Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/print/UnixPrintJob.java
32287 views
/*1* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.print;2627import java.net.URI;28import java.net.URL;29import java.io.BufferedInputStream;30import java.io.BufferedOutputStream;31import java.io.BufferedReader;32import java.io.BufferedWriter;33import java.io.File;34import java.io.FileOutputStream;35import java.io.InputStream;36import java.io.InputStreamReader;37import java.io.OutputStream;38import java.io.OutputStreamWriter;39import java.io.IOException;40import java.io.PrintWriter;41import java.io.Reader;42import java.io.StringWriter;43import java.io.UnsupportedEncodingException;44import java.nio.file.Files;45import java.util.Vector;4647import javax.print.CancelablePrintJob;48import javax.print.Doc;49import javax.print.DocFlavor;50import javax.print.DocPrintJob;51import javax.print.PrintService;52import javax.print.PrintException;53import javax.print.event.PrintJobEvent;54import javax.print.event.PrintJobListener;55import javax.print.event.PrintJobAttributeListener;5657import javax.print.attribute.Attribute;58import javax.print.attribute.AttributeSet;59import javax.print.attribute.AttributeSetUtilities;60import javax.print.attribute.DocAttributeSet;61import javax.print.attribute.HashPrintJobAttributeSet;62import javax.print.attribute.HashPrintRequestAttributeSet;63import javax.print.attribute.PrintJobAttribute;64import javax.print.attribute.PrintJobAttributeSet;65import javax.print.attribute.PrintRequestAttribute;66import javax.print.attribute.PrintRequestAttributeSet;67import javax.print.attribute.PrintServiceAttributeSet;68import javax.print.attribute.standard.Copies;69import javax.print.attribute.standard.Destination;70import javax.print.attribute.standard.DocumentName;71import javax.print.attribute.standard.Fidelity;72import javax.print.attribute.standard.JobName;73import javax.print.attribute.standard.JobOriginatingUserName;74import javax.print.attribute.standard.JobSheets;75import javax.print.attribute.standard.Media;76import javax.print.attribute.standard.MediaSize;77import javax.print.attribute.standard.MediaSizeName;78import javax.print.attribute.standard.OrientationRequested;79import javax.print.attribute.standard.PrinterName;80import javax.print.attribute.standard.RequestingUserName;81import javax.print.attribute.standard.NumberUp;82import javax.print.attribute.standard.Sides;83import javax.print.attribute.standard.PrinterIsAcceptingJobs;8485import java.awt.print.*;86878889public class UnixPrintJob implements CancelablePrintJob {90private static String debugPrefix = "UnixPrintJob>> ";9192transient private Vector jobListeners;93transient private Vector attrListeners;94transient private Vector listenedAttributeSets;9596private PrintService service;97private boolean fidelity;98private boolean printing = false;99private boolean printReturned = false;100private PrintRequestAttributeSet reqAttrSet = null;101private PrintJobAttributeSet jobAttrSet = null;102private PrinterJob job;103private Doc doc;104/* these variables used globally to store reference to the print105* data retrieved as a stream. On completion these are always closed106* if non-null.107*/108private InputStream instream = null;109private Reader reader = null;110111/* default values overridden by those extracted from the attributes */112private String jobName = "Java Printing";113private int copies = 1;114private MediaSizeName mediaName = MediaSizeName.NA_LETTER;115private MediaSize mediaSize = MediaSize.NA.LETTER;116private CustomMediaTray customTray = null;117private OrientationRequested orient = OrientationRequested.PORTRAIT;118private NumberUp nUp = null;119private Sides sides = null;120121UnixPrintJob(PrintService service) {122this.service = service;123mDestination = service.getName();124if (PrintServiceLookupProvider.isMac()) {125mDestination = ((IPPPrintService)service).getDest();126}127mDestType = UnixPrintJob.DESTPRINTER;128}129130public PrintService getPrintService() {131return service;132}133134public PrintJobAttributeSet getAttributes() {135synchronized (this) {136if (jobAttrSet == null) {137/* just return an empty set until the job is submitted */138PrintJobAttributeSet jobSet = new HashPrintJobAttributeSet();139return AttributeSetUtilities.unmodifiableView(jobSet);140} else {141return jobAttrSet;142}143}144}145146public void addPrintJobListener(PrintJobListener listener) {147synchronized (this) {148if (listener == null) {149return;150}151if (jobListeners == null) {152jobListeners = new Vector();153}154jobListeners.add(listener);155}156}157158public void removePrintJobListener(PrintJobListener listener) {159synchronized (this) {160if (listener == null || jobListeners == null ) {161return;162}163jobListeners.remove(listener);164if (jobListeners.isEmpty()) {165jobListeners = null;166}167}168}169170171/* Closes any stream already retrieved for the data.172* We want to avoid unnecessarily asking the Doc to create a stream only173* to get a reference in order to close it because the job failed.174* If the representation class is itself a "stream", this175* closes that stream too.176*/177private void closeDataStreams() {178179if (doc == null) {180return;181}182183Object data = null;184185try {186data = doc.getPrintData();187} catch (IOException e) {188return;189}190191if (instream != null) {192try {193instream.close();194} catch (IOException e) {195} finally {196instream = null;197}198}199else if (reader != null) {200try {201reader.close();202} catch (IOException e) {203} finally {204reader = null;205}206}207else if (data instanceof InputStream) {208try {209((InputStream)data).close();210} catch (IOException e) {211}212}213else if (data instanceof Reader) {214try {215((Reader)data).close();216} catch (IOException e) {217}218}219}220221private void notifyEvent(int reason) {222223/* since this method should always get called, here's where224* we will perform the clean up of any data stream supplied.225*/226switch (reason) {227case PrintJobEvent.DATA_TRANSFER_COMPLETE:228case PrintJobEvent.JOB_CANCELED :229case PrintJobEvent.JOB_FAILED :230case PrintJobEvent.NO_MORE_EVENTS :231case PrintJobEvent.JOB_COMPLETE :232closeDataStreams();233}234235synchronized (this) {236if (jobListeners != null) {237PrintJobListener listener;238PrintJobEvent event = new PrintJobEvent(this, reason);239for (int i = 0; i < jobListeners.size(); i++) {240listener = (PrintJobListener)(jobListeners.elementAt(i));241switch (reason) {242243case PrintJobEvent.JOB_CANCELED :244listener.printJobCanceled(event);245break;246247case PrintJobEvent.JOB_FAILED :248listener.printJobFailed(event);249break;250251case PrintJobEvent.DATA_TRANSFER_COMPLETE :252listener.printDataTransferCompleted(event);253break;254255case PrintJobEvent.NO_MORE_EVENTS :256listener.printJobNoMoreEvents(event);257break;258259default:260break;261}262}263}264}265}266267public void addPrintJobAttributeListener(268PrintJobAttributeListener listener,269PrintJobAttributeSet attributes) {270synchronized (this) {271if (listener == null) {272return;273}274if (attrListeners == null) {275attrListeners = new Vector();276listenedAttributeSets = new Vector();277}278attrListeners.add(listener);279if (attributes == null) {280attributes = new HashPrintJobAttributeSet();281}282listenedAttributeSets.add(attributes);283}284}285286public void removePrintJobAttributeListener(287PrintJobAttributeListener listener) {288synchronized (this) {289if (listener == null || attrListeners == null ) {290return;291}292int index = attrListeners.indexOf(listener);293if (index == -1) {294return;295} else {296attrListeners.remove(index);297listenedAttributeSets.remove(index);298if (attrListeners.isEmpty()) {299attrListeners = null;300listenedAttributeSets = null;301}302}303}304}305306public void print(Doc doc, PrintRequestAttributeSet attributes)307throws PrintException {308309synchronized (this) {310if (printing) {311throw new PrintException("already printing");312} else {313printing = true;314}315}316317if ((PrinterIsAcceptingJobs)(service.getAttribute(318PrinterIsAcceptingJobs.class)) ==319PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) {320throw new PrintException("Printer is not accepting job.");321}322323this.doc = doc;324/* check if the parameters are valid before doing much processing */325DocFlavor flavor = doc.getDocFlavor();326327Object data;328329try {330data = doc.getPrintData();331} catch (IOException e) {332notifyEvent(PrintJobEvent.JOB_FAILED);333throw new PrintException("can't get print data: " + e.toString());334}335336if (data == null) {337throw new PrintException("Null print data.");338}339340if (flavor == null || (!service.isDocFlavorSupported(flavor))) {341notifyEvent(PrintJobEvent.JOB_FAILED);342throw new PrintJobFlavorException("invalid flavor", flavor);343}344345initializeAttributeSets(doc, attributes);346347getAttributeValues(flavor);348349// set up mOptions350if ((service instanceof IPPPrintService) &&351CUPSPrinter.isCupsRunning()) {352353IPPPrintService.debug_println(debugPrefix+354"instanceof IPPPrintService");355356if (mediaName != null) {357CustomMediaSizeName customMedia =358((IPPPrintService)service).findCustomMedia(mediaName);359if (customMedia != null) {360mOptions = " media="+ customMedia.getChoiceName();361}362}363364if (customTray != null &&365customTray instanceof CustomMediaTray) {366String choice = customTray.getChoiceName();367if (choice != null) {368mOptions += " media="+choice;369}370}371372if (nUp != null) {373mOptions += " number-up="+nUp.getValue();374}375376if (orient != OrientationRequested.PORTRAIT &&377(flavor != null) &&378!flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {379mOptions += " orientation-requested="+orient.getValue();380}381382if (sides != null) {383mOptions += " sides="+sides;384}385386}387388IPPPrintService.debug_println(debugPrefix+"mOptions "+mOptions);389String repClassName = flavor.getRepresentationClassName();390String val = flavor.getParameter("charset");391String encoding = "us-ascii";392if (val != null && !val.equals("")) {393encoding = val;394}395396if (flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||397flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||398flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||399flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||400flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||401flavor.equals(DocFlavor.BYTE_ARRAY.PNG)) {402try {403instream = doc.getStreamForBytes();404if (instream == null) {405notifyEvent(PrintJobEvent.JOB_FAILED);406throw new PrintException("No stream for data");407}408if (!(service instanceof IPPPrintService &&409((IPPPrintService)service).isIPPSupportedImages(410flavor.getMimeType()))) {411printableJob(new ImagePrinter(instream));412((UnixPrintService)service).wakeNotifier();413return;414}415} catch (ClassCastException cce) {416notifyEvent(PrintJobEvent.JOB_FAILED);417throw new PrintException(cce);418} catch (IOException ioe) {419notifyEvent(PrintJobEvent.JOB_FAILED);420throw new PrintException(ioe);421}422} else if (flavor.equals(DocFlavor.URL.GIF) ||423flavor.equals(DocFlavor.URL.JPEG) ||424flavor.equals(DocFlavor.URL.PNG)) {425try {426URL url = (URL)data;427if ((service instanceof IPPPrintService) &&428((IPPPrintService)service).isIPPSupportedImages(429flavor.getMimeType())) {430instream = url.openStream();431} else {432printableJob(new ImagePrinter(url));433((UnixPrintService)service).wakeNotifier();434return;435}436} catch (ClassCastException cce) {437notifyEvent(PrintJobEvent.JOB_FAILED);438throw new PrintException(cce);439} catch (IOException e) {440notifyEvent(PrintJobEvent.JOB_FAILED);441throw new PrintException(e.toString());442}443} else if (flavor.equals(DocFlavor.CHAR_ARRAY.TEXT_PLAIN) ||444flavor.equals(DocFlavor.READER.TEXT_PLAIN) ||445flavor.equals(DocFlavor.STRING.TEXT_PLAIN)) {446try {447reader = doc.getReaderForText();448if (reader == null) {449notifyEvent(PrintJobEvent.JOB_FAILED);450throw new PrintException("No reader for data");451}452} catch (IOException ioe) {453notifyEvent(PrintJobEvent.JOB_FAILED);454throw new PrintException(ioe.toString());455}456} else if (repClassName.equals("[B") ||457repClassName.equals("java.io.InputStream")) {458try {459instream = doc.getStreamForBytes();460if (instream == null) {461notifyEvent(PrintJobEvent.JOB_FAILED);462throw new PrintException("No stream for data");463}464} catch (IOException ioe) {465notifyEvent(PrintJobEvent.JOB_FAILED);466throw new PrintException(ioe.toString());467}468} else if (repClassName.equals("java.net.URL")) {469/*470* This extracts the data from the URL and passes it the content471* directly to the print service as a file.472* This is appropriate for the current implementation where lp or473* lpr is always used to spool the data. We expect to revise the474* implementation to provide more complete IPP support (ie not just475* CUPS) and at that time the job will be spooled via IPP476* and the URL477* itself should be sent to the IPP print service not the content.478*/479URL url = (URL)data;480try {481instream = url.openStream();482} catch (IOException e) {483notifyEvent(PrintJobEvent.JOB_FAILED);484throw new PrintException(e.toString());485}486} else if (repClassName.equals("java.awt.print.Pageable")) {487try {488pageableJob((Pageable)doc.getPrintData());489if (service instanceof IPPPrintService) {490((IPPPrintService)service).wakeNotifier();491} else {492((UnixPrintService)service).wakeNotifier();493}494return;495} catch (ClassCastException cce) {496notifyEvent(PrintJobEvent.JOB_FAILED);497throw new PrintException(cce);498} catch (IOException ioe) {499notifyEvent(PrintJobEvent.JOB_FAILED);500throw new PrintException(ioe);501}502} else if (repClassName.equals("java.awt.print.Printable")) {503try {504printableJob((Printable)doc.getPrintData());505if (service instanceof IPPPrintService) {506((IPPPrintService)service).wakeNotifier();507} else {508((UnixPrintService)service).wakeNotifier();509}510return;511} catch (ClassCastException cce) {512notifyEvent(PrintJobEvent.JOB_FAILED);513throw new PrintException(cce);514} catch (IOException ioe) {515notifyEvent(PrintJobEvent.JOB_FAILED);516throw new PrintException(ioe);517}518} else {519notifyEvent(PrintJobEvent.JOB_FAILED);520throw new PrintException("unrecognized class: "+repClassName);521}522523// now spool the print data.524PrinterOpener po = new PrinterOpener();525java.security.AccessController.doPrivileged(po);526if (po.pex != null) {527throw po.pex;528}529OutputStream output = po.result;530531/* There are three cases:532* 1) Text data from a Reader, just pass through.533* 2) Text data from an input stream which we must read using the534* correct encoding535* 3) Raw byte data from an InputStream we don't interpret as text,536* just pass through: eg postscript.537*/538539BufferedWriter bw = null;540if ((instream == null && reader != null)) {541BufferedReader br = new BufferedReader(reader);542OutputStreamWriter osw = new OutputStreamWriter(output);543bw = new BufferedWriter(osw);544char []buffer = new char[1024];545int cread;546547try {548while ((cread = br.read(buffer, 0, buffer.length)) >=0) {549bw.write(buffer, 0, cread);550}551br.close();552bw.flush();553bw.close();554} catch (IOException e) {555notifyEvent(PrintJobEvent.JOB_FAILED);556throw new PrintException (e);557}558} else if (instream != null &&559flavor.getMediaType().equalsIgnoreCase("text")) {560try {561562InputStreamReader isr = new InputStreamReader(instream,563encoding);564BufferedReader br = new BufferedReader(isr);565OutputStreamWriter osw = new OutputStreamWriter(output);566bw = new BufferedWriter(osw);567char []buffer = new char[1024];568int cread;569570while ((cread = br.read(buffer, 0, buffer.length)) >=0) {571bw.write(buffer, 0, cread);572}573bw.flush();574} catch (IOException e) {575notifyEvent(PrintJobEvent.JOB_FAILED);576throw new PrintException (e);577} finally {578try {579if (bw != null) {580bw.close();581}582} catch (IOException e) {583}584}585} else if (instream != null) {586BufferedInputStream bin = new BufferedInputStream(instream);587BufferedOutputStream bout = new BufferedOutputStream(output);588byte[] buffer = new byte[1024];589int bread = 0;590591try {592while ((bread = bin.read(buffer)) >= 0) {593bout.write(buffer, 0, bread);594}595bin.close();596bout.flush();597bout.close();598} catch (IOException e) {599notifyEvent(PrintJobEvent.JOB_FAILED);600throw new PrintException (e);601}602}603notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);604605if (mDestType == UnixPrintJob.DESTPRINTER) {606PrinterSpooler spooler = new PrinterSpooler();607java.security.AccessController.doPrivileged(spooler);608if (spooler.pex != null) {609throw spooler.pex;610}611}612notifyEvent(PrintJobEvent.NO_MORE_EVENTS);613if (service instanceof IPPPrintService) {614((IPPPrintService)service).wakeNotifier();615} else {616((UnixPrintService)service).wakeNotifier();617}618}619620public void printableJob(Printable printable) throws PrintException {621try {622synchronized(this) {623if (job != null) { // shouldn't happen624throw new PrintException("already printing");625} else {626job = new PSPrinterJob();627}628}629job.setPrintService(getPrintService());630job.setCopies(copies);631job.setJobName(jobName);632PageFormat pf = new PageFormat();633if (mediaSize != null) {634Paper p = new Paper();635p.setSize(mediaSize.getX(MediaSize.INCH)*72.0,636mediaSize.getY(MediaSize.INCH)*72.0);637p.setImageableArea(72.0, 72.0, p.getWidth()-144.0,638p.getHeight()-144.0);639pf.setPaper(p);640}641if (orient == OrientationRequested.REVERSE_LANDSCAPE) {642pf.setOrientation(PageFormat.REVERSE_LANDSCAPE);643} else if (orient == OrientationRequested.LANDSCAPE) {644pf.setOrientation(PageFormat.LANDSCAPE);645}646job.setPrintable(printable, pf);647job.print(reqAttrSet);648notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);649return;650} catch (PrinterException pe) {651notifyEvent(PrintJobEvent.JOB_FAILED);652throw new PrintException(pe);653} finally {654printReturned = true;655notifyEvent(PrintJobEvent.NO_MORE_EVENTS);656}657}658659public void pageableJob(Pageable pageable) throws PrintException {660try {661synchronized(this) {662if (job != null) { // shouldn't happen663throw new PrintException("already printing");664} else {665job = new PSPrinterJob();666}667}668job.setPrintService(getPrintService());669job.setCopies(copies);670job.setJobName(jobName);671job.setPageable(pageable);672job.print(reqAttrSet);673notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);674return;675} catch (PrinterException pe) {676notifyEvent(PrintJobEvent.JOB_FAILED);677throw new PrintException(pe);678} finally {679printReturned = true;680notifyEvent(PrintJobEvent.NO_MORE_EVENTS);681}682}683/* There's some inefficiency here as the job set is created even though684* it may never be requested.685*/686private synchronized void687initializeAttributeSets(Doc doc, PrintRequestAttributeSet reqSet) {688689reqAttrSet = new HashPrintRequestAttributeSet();690jobAttrSet = new HashPrintJobAttributeSet();691692Attribute[] attrs;693if (reqSet != null) {694reqAttrSet.addAll(reqSet);695attrs = reqSet.toArray();696for (int i=0; i<attrs.length; i++) {697if (attrs[i] instanceof PrintJobAttribute) {698jobAttrSet.add(attrs[i]);699}700}701}702703DocAttributeSet docSet = doc.getAttributes();704if (docSet != null) {705attrs = docSet.toArray();706for (int i=0; i<attrs.length; i++) {707if (attrs[i] instanceof PrintRequestAttribute) {708reqAttrSet.add(attrs[i]);709}710if (attrs[i] instanceof PrintJobAttribute) {711jobAttrSet.add(attrs[i]);712}713}714}715716/* add the user name to the job */717String userName = "";718try {719userName = System.getProperty("user.name");720} catch (SecurityException se) {721}722723if (userName == null || userName.equals("")) {724RequestingUserName ruName =725(RequestingUserName)reqSet.get(RequestingUserName.class);726if (ruName != null) {727jobAttrSet.add(728new JobOriginatingUserName(ruName.getValue(),729ruName.getLocale()));730} else {731jobAttrSet.add(new JobOriginatingUserName("", null));732}733} else {734jobAttrSet.add(new JobOriginatingUserName(userName, null));735}736737/* if no job name supplied use doc name (if supplied), if none and738* its a URL use that, else finally anything .. */739if (jobAttrSet.get(JobName.class) == null) {740JobName jobName;741if (docSet != null && docSet.get(DocumentName.class) != null) {742DocumentName docName =743(DocumentName)docSet.get(DocumentName.class);744jobName = new JobName(docName.getValue(), docName.getLocale());745jobAttrSet.add(jobName);746} else {747String str = "JPS Job:" + doc;748try {749Object printData = doc.getPrintData();750if (printData instanceof URL) {751str = ((URL)(doc.getPrintData())).toString();752}753} catch (IOException e) {754}755jobName = new JobName(str, null);756jobAttrSet.add(jobName);757}758}759760jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet);761}762763private void getAttributeValues(DocFlavor flavor) throws PrintException {764Attribute attr;765Class category;766767if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) {768fidelity = true;769} else {770fidelity = false;771}772773Attribute []attrs = reqAttrSet.toArray();774for (int i=0; i<attrs.length; i++) {775attr = attrs[i];776category = attr.getCategory();777if (fidelity == true) {778if (!service.isAttributeCategorySupported(category)) {779notifyEvent(PrintJobEvent.JOB_FAILED);780throw new PrintJobAttributeException(781"unsupported category: " + category, category, null);782} else if783(!service.isAttributeValueSupported(attr, flavor, null)) {784notifyEvent(PrintJobEvent.JOB_FAILED);785throw new PrintJobAttributeException(786"unsupported attribute: " + attr, null, attr);787}788}789if (category == Destination.class) {790URI uri = ((Destination)attr).getURI();791if (!"file".equals(uri.getScheme())) {792notifyEvent(PrintJobEvent.JOB_FAILED);793throw new PrintException("Not a file: URI");794} else {795try {796mDestType = DESTFILE;797mDestination = (new File(uri)).getPath();798} catch (Exception e) {799throw new PrintException(e);800}801// check write access802SecurityManager security = System.getSecurityManager();803if (security != null) {804try {805security.checkWrite(mDestination);806} catch (SecurityException se) {807notifyEvent(PrintJobEvent.JOB_FAILED);808throw new PrintException(se);809}810}811}812} else if (category == JobSheets.class) {813if ((JobSheets)attr == JobSheets.NONE) {814mNoJobSheet = true;815}816} else if (category == JobName.class) {817jobName = ((JobName)attr).getValue();818} else if (category == Copies.class) {819copies = ((Copies)attr).getValue();820} else if (category == Media.class) {821if (attr instanceof MediaSizeName) {822mediaName = (MediaSizeName)attr;823IPPPrintService.debug_println(debugPrefix+824"mediaName "+mediaName);825if (!service.isAttributeValueSupported(attr, null, null)) {826mediaSize = MediaSize.getMediaSizeForName(mediaName);827}828} else if (attr instanceof CustomMediaTray) {829customTray = (CustomMediaTray)attr;830}831} else if (category == OrientationRequested.class) {832orient = (OrientationRequested)attr;833} else if (category == NumberUp.class) {834nUp = (NumberUp)attr;835} else if (category == Sides.class) {836sides = (Sides)attr;837}838}839}840841private String[] printExecCmd(String printer, String options,842boolean noJobSheet,843String banner, int copies, String spoolFile) {844int PRINTER = 0x1;845int OPTIONS = 0x2;846int BANNER = 0x4;847int COPIES = 0x8;848int NOSHEET = 0x10;849int pFlags = 0;850String execCmd[];851int ncomps = 2; // minimum number of print args852int n = 0;853854// conveniently "lp" is the default destination for both lp and lpr.855if (printer != null && !printer.equals("") && !printer.equals("lp")) {856pFlags |= PRINTER;857ncomps+=1;858}859if (options != null && !options.equals("")) {860pFlags |= OPTIONS;861ncomps+=1;862}863if (banner != null && !banner.equals("")) {864pFlags |= BANNER;865ncomps+=1;866}867if (copies > 1) {868pFlags |= COPIES;869ncomps+=1;870}871if (noJobSheet) {872pFlags |= NOSHEET;873ncomps+=1;874}875if (PrintServiceLookupProvider.osname.equals("SunOS")) {876ncomps+=1; // lp uses 1 more arg than lpr (make a copy)877execCmd = new String[ncomps];878execCmd[n++] = "/usr/bin/lp";879execCmd[n++] = "-c"; // make a copy of the spool file880if ((pFlags & PRINTER) != 0) {881execCmd[n++] = "-d" + printer;882}883if ((pFlags & BANNER) != 0) {884String quoteChar = "\"";885execCmd[n++] = "-t " + quoteChar+banner+quoteChar;886}887if ((pFlags & COPIES) != 0) {888execCmd[n++] = "-n " + copies;889}890if ((pFlags & NOSHEET) != 0) {891execCmd[n++] = "-o nobanner";892}893if ((pFlags & OPTIONS) != 0) {894execCmd[n++] = "-o " + options;895}896} else {897execCmd = new String[ncomps];898execCmd[n++] = "/usr/bin/lpr";899if ((pFlags & PRINTER) != 0) {900execCmd[n++] = "-P" + printer;901}902if ((pFlags & BANNER) != 0) {903execCmd[n++] = "-J " + banner;904}905if ((pFlags & COPIES) != 0) {906execCmd[n++] = "-#" + copies;907}908if ((pFlags & NOSHEET) != 0) {909execCmd[n++] = "-h";910}911if ((pFlags & OPTIONS) != 0) {912execCmd[n++] = "-o" + options;913}914}915execCmd[n++] = spoolFile;916if (IPPPrintService.debugPrint) {917System.out.println("UnixPrintJob>> execCmd");918for (int i=0; i<execCmd.length; i++) {919System.out.print(" "+execCmd[i]);920}921System.out.println();922}923return execCmd;924}925926private static int DESTPRINTER = 1;927private static int DESTFILE = 2;928private int mDestType = DESTPRINTER;929930private File spoolFile;931private String mDestination, mOptions="";932private boolean mNoJobSheet = false;933934// Inner class to run "privileged" to open the printer output stream.935936private class PrinterOpener implements java.security.PrivilegedAction {937PrintException pex;938OutputStream result;939940public Object run() {941try {942if (mDestType == UnixPrintJob.DESTFILE) {943spoolFile = new File(mDestination);944} else {945/* Write to a temporary file which will be spooled to946* the printer then deleted. In the case that the file947* is not removed for some reason, request that it is948* removed when the VM exits.949*/950spoolFile = Files.createTempFile("javaprint", "").toFile();951spoolFile.deleteOnExit();952}953result = new FileOutputStream(spoolFile);954return result;955} catch (IOException ex) {956// If there is an IOError we subvert it to a PrinterException.957notifyEvent(PrintJobEvent.JOB_FAILED);958pex = new PrintException(ex);959}960return null;961}962}963964// Inner class to run "privileged" to invoke the system print command965966private class PrinterSpooler implements java.security.PrivilegedAction {967PrintException pex;968969private void handleProcessFailure(final Process failedProcess,970final String[] execCmd, final int result) throws IOException {971try (StringWriter sw = new StringWriter();972PrintWriter pw = new PrintWriter(sw)) {973pw.append("error=").append(Integer.toString(result));974pw.append(" running:");975for (String arg: execCmd) {976pw.append(" '").append(arg).append("'");977}978try (InputStream is = failedProcess.getErrorStream();979InputStreamReader isr = new InputStreamReader(is);980BufferedReader br = new BufferedReader(isr)) {981while (br.ready()) {982pw.println();983pw.append("\t\t").append(br.readLine());984}985} finally {986pw.flush();987throw new IOException(sw.toString());988}989}990}991992public Object run() {993if (spoolFile == null || !spoolFile.exists()) {994pex = new PrintException("No spool file");995notifyEvent(PrintJobEvent.JOB_FAILED);996return null;997}998try {999/**1000* Spool to the printer.1001*/1002String fileName = spoolFile.getAbsolutePath();1003String execCmd[] = printExecCmd(mDestination, mOptions,1004mNoJobSheet, jobName, copies, fileName);10051006Process process = Runtime.getRuntime().exec(execCmd);1007process.waitFor();1008final int result = process.exitValue();1009if (0 != result) {1010handleProcessFailure(process, execCmd, result);1011}1012notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);1013} catch (IOException ex) {1014notifyEvent(PrintJobEvent.JOB_FAILED);1015// REMIND : 2d printing throws PrinterException1016pex = new PrintException(ex);1017} catch (InterruptedException ie) {1018notifyEvent(PrintJobEvent.JOB_FAILED);1019pex = new PrintException(ie);1020} finally {1021spoolFile.delete();1022notifyEvent(PrintJobEvent.NO_MORE_EVENTS);1023}1024return null;1025}1026}10271028public void cancel() throws PrintException {1029synchronized (this) {1030if (!printing) {1031throw new PrintException("Job is not yet submitted.");1032} else if (job != null && !printReturned) {1033job.cancel();1034notifyEvent(PrintJobEvent.JOB_CANCELED);1035return;1036} else {1037throw new PrintException("Job could not be cancelled.");1038}1039}1040}1041}104210431044