001: /*
002: * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.print;
027:
028: import java.net.URI;
029: import java.io.BufferedInputStream;
030: import java.io.BufferedOutputStream;
031: import java.io.File;
032: import java.io.FileOutputStream;
033: import java.io.InputStream;
034: import java.io.OutputStream;
035: import java.io.InputStream;
036: import java.io.IOException;
037: import java.io.FileNotFoundException;
038: import java.io.Reader;
039: import java.net.URL;
040: import java.util.Vector;
041:
042: import javax.print.CancelablePrintJob;
043: import javax.print.Doc;
044: import javax.print.DocFlavor;
045: import javax.print.DocPrintJob;
046: import javax.print.PrintService;
047: import javax.print.PrintException;
048: import javax.print.event.PrintJobEvent;
049: import javax.print.event.PrintJobListener;
050: import javax.print.event.PrintJobAttributeListener;
051:
052: import javax.print.attribute.Attribute;
053: import javax.print.attribute.AttributeSet;
054: import javax.print.attribute.AttributeSetUtilities;
055: import javax.print.attribute.DocAttributeSet;
056: import javax.print.attribute.HashPrintJobAttributeSet;
057: import javax.print.attribute.HashPrintRequestAttributeSet;
058: import javax.print.attribute.PrintJobAttribute;
059: import javax.print.attribute.PrintJobAttributeSet;
060: import javax.print.attribute.PrintRequestAttribute;
061: import javax.print.attribute.PrintRequestAttributeSet;
062: import javax.print.attribute.standard.Copies;
063: import javax.print.attribute.standard.DocumentName;
064: import javax.print.attribute.standard.Fidelity;
065: import javax.print.attribute.standard.JobName;
066: import javax.print.attribute.standard.JobOriginatingUserName;
067: import javax.print.attribute.standard.Media;
068: import javax.print.attribute.standard.MediaSize;
069: import javax.print.attribute.standard.MediaSizeName;
070: import javax.print.attribute.standard.OrientationRequested;
071: import javax.print.attribute.standard.RequestingUserName;
072: import javax.print.attribute.standard.Destination;
073: import javax.print.attribute.standard.PrinterIsAcceptingJobs;
074: import javax.print.attribute.standard.PrinterState;
075: import javax.print.attribute.standard.PrinterStateReason;
076: import javax.print.attribute.standard.PrinterStateReasons;
077:
078: import java.awt.print.*;
079:
080: public class Win32PrintJob implements CancelablePrintJob {
081:
082: transient private Vector jobListeners;
083: transient private Vector attrListeners;
084: transient private Vector listenedAttributeSets;
085:
086: private Win32PrintService service;
087: private boolean fidelity;
088: private boolean printing = false;
089: private boolean printReturned = false;
090: private PrintRequestAttributeSet reqAttrSet = null;
091: private PrintJobAttributeSet jobAttrSet = null;
092: private PrinterJob job;
093: private Doc doc;
094: private String mDestination = null;
095:
096: /* these variables used globally to store reference to the print
097: * data retrieved as a stream. On completion these are always closed
098: * if non-null.
099: */
100: private InputStream instream = null;
101: private Reader reader = null;
102:
103: /* default values overridden by those extracted from the attributes */
104: private String jobName = "Java Printing";
105: private int copies = 0;
106: private MediaSizeName mediaName = null;
107: private MediaSize mediaSize = null;
108: private OrientationRequested orient = null;
109:
110: /* print job handle used by native code */
111: private long hPrintJob;
112:
113: /* buffer length for printing raw data */
114: private static final int PRINTBUFFERLEN = 8192;
115:
116: Win32PrintJob(Win32PrintService service) {
117: this .service = service;
118: }
119:
120: public PrintService getPrintService() {
121: return service;
122: }
123:
124: public PrintJobAttributeSet getAttributes() {
125: synchronized (this ) {
126: if (jobAttrSet == null) {
127: /* just return an empty set until the job is submitted */
128: PrintJobAttributeSet jobSet = new HashPrintJobAttributeSet();
129: return AttributeSetUtilities.unmodifiableView(jobSet);
130: } else {
131: return jobAttrSet;
132: }
133: }
134: }
135:
136: public void addPrintJobListener(PrintJobListener listener) {
137: synchronized (this ) {
138: if (listener == null) {
139: return;
140: }
141: if (jobListeners == null) {
142: jobListeners = new Vector();
143: }
144: jobListeners.add(listener);
145: }
146: }
147:
148: public void removePrintJobListener(PrintJobListener listener) {
149: synchronized (this ) {
150: if (listener == null || jobListeners == null) {
151: return;
152: }
153: jobListeners.remove(listener);
154: if (jobListeners.isEmpty()) {
155: jobListeners = null;
156: }
157: }
158: }
159:
160: /* Closes any stream already retrieved for the data.
161: * We want to avoid unnecessarily asking the Doc to create a stream only
162: * to get a reference in order to close it because the job failed.
163: * If the representation class is itself a "stream", this
164: * closes that stream too.
165: */
166: private void closeDataStreams() {
167:
168: if (doc == null) {
169: return;
170: }
171:
172: Object data = null;
173:
174: try {
175: data = doc.getPrintData();
176: } catch (IOException e) {
177: return;
178: }
179:
180: if (instream != null) {
181: try {
182: instream.close();
183: } catch (IOException e) {
184: } finally {
185: instream = null;
186: }
187: } else if (reader != null) {
188: try {
189: reader.close();
190: } catch (IOException e) {
191: } finally {
192: reader = null;
193: }
194: } else if (data instanceof InputStream) {
195: try {
196: ((InputStream) data).close();
197: } catch (IOException e) {
198: }
199: } else if (data instanceof Reader) {
200: try {
201: ((Reader) data).close();
202: } catch (IOException e) {
203: }
204: }
205: }
206:
207: private void notifyEvent(int reason) {
208:
209: /* since this method should always get called, here's where
210: * we will perform the clean up of any data stream supplied.
211: */
212: switch (reason) {
213: case PrintJobEvent.DATA_TRANSFER_COMPLETE:
214: case PrintJobEvent.JOB_CANCELED:
215: case PrintJobEvent.JOB_FAILED:
216: case PrintJobEvent.NO_MORE_EVENTS:
217: case PrintJobEvent.JOB_COMPLETE:
218: closeDataStreams();
219: }
220:
221: synchronized (this ) {
222: if (jobListeners != null) {
223: PrintJobListener listener;
224: PrintJobEvent event = new PrintJobEvent(this , reason);
225: for (int i = 0; i < jobListeners.size(); i++) {
226: listener = (PrintJobListener) (jobListeners
227: .elementAt(i));
228: switch (reason) {
229:
230: case PrintJobEvent.JOB_COMPLETE:
231: listener.printJobCompleted(event);
232: break;
233:
234: case PrintJobEvent.JOB_CANCELED:
235: listener.printJobCanceled(event);
236: break;
237:
238: case PrintJobEvent.JOB_FAILED:
239: listener.printJobFailed(event);
240: break;
241:
242: case PrintJobEvent.DATA_TRANSFER_COMPLETE:
243: listener.printDataTransferCompleted(event);
244: break;
245:
246: case PrintJobEvent.NO_MORE_EVENTS:
247: listener.printJobNoMoreEvents(event);
248: break;
249:
250: default:
251: break;
252: }
253: }
254: }
255: }
256: }
257:
258: public void addPrintJobAttributeListener(
259: PrintJobAttributeListener listener,
260: PrintJobAttributeSet attributes) {
261: synchronized (this ) {
262: if (listener == null) {
263: return;
264: }
265: if (attrListeners == null) {
266: attrListeners = new Vector();
267: listenedAttributeSets = new Vector();
268: }
269: attrListeners.add(listener);
270: if (attributes == null) {
271: attributes = new HashPrintJobAttributeSet();
272: }
273: listenedAttributeSets.add(attributes);
274: }
275: }
276:
277: public void removePrintJobAttributeListener(
278: PrintJobAttributeListener listener) {
279: synchronized (this ) {
280: if (listener == null || attrListeners == null) {
281: return;
282: }
283: int index = attrListeners.indexOf(listener);
284: if (index == -1) {
285: return;
286: } else {
287: attrListeners.remove(index);
288: listenedAttributeSets.remove(index);
289: if (attrListeners.isEmpty()) {
290: attrListeners = null;
291: listenedAttributeSets = null;
292: }
293: }
294: }
295: }
296:
297: public void print(Doc doc, PrintRequestAttributeSet attributes)
298: throws PrintException {
299:
300: synchronized (this ) {
301: if (printing) {
302: throw new PrintException("already printing");
303: } else {
304: printing = true;
305: }
306: }
307:
308: PrinterState prnState = (PrinterState) service
309: .getAttribute(PrinterState.class);
310: if (prnState == PrinterState.STOPPED) {
311: PrinterStateReasons prnStateReasons = (PrinterStateReasons) service
312: .getAttribute(PrinterStateReasons.class);
313: if ((prnStateReasons != null)
314: && (prnStateReasons
315: .containsKey(PrinterStateReason.SHUTDOWN))) {
316: throw new PrintException(
317: "PrintService is no longer available.");
318: }
319: }
320:
321: if ((PrinterIsAcceptingJobs) (service
322: .getAttribute(PrinterIsAcceptingJobs.class)) == PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) {
323: throw new PrintException("Printer is not accepting job.");
324: }
325:
326: this .doc = doc;
327: /* check if the parameters are valid before doing much processing */
328: DocFlavor flavor = doc.getDocFlavor();
329: Object data;
330:
331: try {
332: data = doc.getPrintData();
333: } catch (IOException e) {
334: notifyEvent(PrintJobEvent.JOB_FAILED);
335: throw new PrintException("can't get print data: "
336: + e.toString());
337: }
338:
339: if (flavor == null || (!service.isDocFlavorSupported(flavor))) {
340: notifyEvent(PrintJobEvent.JOB_FAILED);
341: throw new PrintJobFlavorException("invalid flavor", flavor);
342: }
343:
344: initializeAttributeSets(doc, attributes);
345:
346: getAttributeValues(flavor);
347:
348: String repClassName = flavor.getRepresentationClassName();
349:
350: if (flavor.equals(DocFlavor.INPUT_STREAM.GIF)
351: || flavor.equals(DocFlavor.INPUT_STREAM.JPEG)
352: || flavor.equals(DocFlavor.INPUT_STREAM.PNG)
353: || flavor.equals(DocFlavor.BYTE_ARRAY.GIF)
354: || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG)
355: || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)) {
356: try {
357: instream = doc.getStreamForBytes();
358: if (instream == null) {
359: notifyEvent(PrintJobEvent.JOB_FAILED);
360: throw new PrintException("No stream for data");
361: }
362: printableJob(new ImagePrinter(instream));
363: service.wakeNotifier();
364: return;
365: } catch (ClassCastException cce) {
366: notifyEvent(PrintJobEvent.JOB_FAILED);
367: throw new PrintException(cce);
368: } catch (IOException ioe) {
369: notifyEvent(PrintJobEvent.JOB_FAILED);
370: throw new PrintException(ioe);
371: }
372: } else if (flavor.equals(DocFlavor.URL.GIF)
373: || flavor.equals(DocFlavor.URL.JPEG)
374: || flavor.equals(DocFlavor.URL.PNG)) {
375: try {
376: printableJob(new ImagePrinter((URL) data));
377: service.wakeNotifier();
378: return;
379: } catch (ClassCastException cce) {
380: notifyEvent(PrintJobEvent.JOB_FAILED);
381: throw new PrintException(cce);
382: }
383: } else if (repClassName.equals("java.awt.print.Pageable")) {
384: try {
385: pageableJob((Pageable) doc.getPrintData());
386: service.wakeNotifier();
387: return;
388: } catch (ClassCastException cce) {
389: notifyEvent(PrintJobEvent.JOB_FAILED);
390: throw new PrintException(cce);
391: } catch (IOException ioe) {
392: notifyEvent(PrintJobEvent.JOB_FAILED);
393: throw new PrintException(ioe);
394: }
395: } else if (repClassName.equals("java.awt.print.Printable")) {
396: try {
397: printableJob((Printable) doc.getPrintData());
398: service.wakeNotifier();
399: return;
400: } catch (ClassCastException cce) {
401: notifyEvent(PrintJobEvent.JOB_FAILED);
402: throw new PrintException(cce);
403: } catch (IOException ioe) {
404: notifyEvent(PrintJobEvent.JOB_FAILED);
405: throw new PrintException(ioe);
406: }
407: } else if (repClassName.equals("[B")
408: || repClassName.equals("java.io.InputStream")
409: || repClassName.equals("java.net.URL")) {
410:
411: if (repClassName.equals("java.net.URL")) {
412: URL url = (URL) data;
413: try {
414: instream = url.openStream();
415: } catch (IOException e) {
416: notifyEvent(PrintJobEvent.JOB_FAILED);
417: throw new PrintException(e.toString());
418: }
419: } else {
420: try {
421: instream = doc.getStreamForBytes();
422: } catch (IOException ioe) {
423: notifyEvent(PrintJobEvent.JOB_FAILED);
424: throw new PrintException(ioe.toString());
425: }
426: }
427:
428: if (instream == null) {
429: notifyEvent(PrintJobEvent.JOB_FAILED);
430: throw new PrintException("No stream for data");
431: }
432:
433: if (mDestination != null) { // if destination attribute is set
434: try {
435: FileOutputStream fos = new FileOutputStream(
436: mDestination);
437: byte[] buffer = new byte[1024];
438: int cread;
439:
440: while ((cread = instream.read(buffer, 0,
441: buffer.length)) >= 0) {
442: fos.write(buffer, 0, cread);
443: }
444: fos.flush();
445: fos.close();
446: } catch (FileNotFoundException fnfe) {
447: notifyEvent(PrintJobEvent.JOB_FAILED);
448: throw new PrintException(fnfe.toString());
449: } catch (IOException ioe) {
450: notifyEvent(PrintJobEvent.JOB_FAILED);
451: throw new PrintException(ioe.toString());
452: }
453: notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
454: notifyEvent(PrintJobEvent.JOB_COMPLETE);
455: service.wakeNotifier();
456: return;
457: }
458:
459: if (!startPrintRawData(service.getName(), jobName)) {
460: notifyEvent(PrintJobEvent.JOB_FAILED);
461: throw new PrintException("Print job failed to start.");
462: }
463: BufferedInputStream bin = new BufferedInputStream(instream);
464: int bread = 0;
465: try {
466: byte[] buffer = new byte[PRINTBUFFERLEN];
467:
468: while ((bread = bin.read(buffer, 0, PRINTBUFFERLEN)) >= 0) {
469: if (!printRawData(buffer, bread)) {
470: bin.close();
471: notifyEvent(PrintJobEvent.JOB_FAILED);
472: throw new PrintException(
473: "Problem while spooling data");
474: }
475: }
476: bin.close();
477: if (!endPrintRawData()) {
478: notifyEvent(PrintJobEvent.JOB_FAILED);
479: throw new PrintException(
480: "Print job failed to close properly.");
481: }
482: notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
483: } catch (IOException e) {
484: notifyEvent(PrintJobEvent.JOB_FAILED);
485: throw new PrintException(e.toString());
486: } finally {
487: notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
488: }
489: } else {
490: notifyEvent(PrintJobEvent.JOB_FAILED);
491: throw new PrintException("unrecognized class: "
492: + repClassName);
493: }
494: service.wakeNotifier();
495: }
496:
497: public void printableJob(Printable printable) throws PrintException {
498: try {
499: synchronized (this ) {
500: if (job != null) { // shouldn't happen
501: throw new PrintException("already printing");
502: } else {
503: job = new sun.awt.windows.WPrinterJob();
504: }
505: }
506: PrintService svc = getPrintService();
507: job.setPrintService(svc);
508: if (copies == 0) {
509: Copies c = (Copies) svc
510: .getDefaultAttributeValue(Copies.class);
511: copies = c.getValue();
512: }
513:
514: if (mediaName == null) {
515: Object media = svc
516: .getDefaultAttributeValue(Media.class);
517: if (media instanceof MediaSizeName) {
518: mediaName = (MediaSizeName) media;
519: mediaSize = MediaSize
520: .getMediaSizeForName(mediaName);
521: }
522: }
523:
524: if (orient == null) {
525: orient = (OrientationRequested) svc
526: .getDefaultAttributeValue(OrientationRequested.class);
527: }
528:
529: job.setCopies(copies);
530: job.setJobName(jobName);
531: PageFormat pf = new PageFormat();
532: if (mediaSize != null) {
533: Paper p = new Paper();
534: p.setSize(mediaSize.getX(MediaSize.INCH) * 72.0,
535: mediaSize.getY(MediaSize.INCH) * 72.0);
536: p.setImageableArea(72.0, 72.0, p.getWidth() - 144.0, p
537: .getHeight() - 144.0);
538: pf.setPaper(p);
539: }
540: if (orient == OrientationRequested.REVERSE_LANDSCAPE) {
541: pf.setOrientation(PageFormat.REVERSE_LANDSCAPE);
542: } else if (orient == OrientationRequested.LANDSCAPE) {
543: pf.setOrientation(PageFormat.LANDSCAPE);
544: }
545: job.setPrintable(printable, pf);
546: job.print(reqAttrSet);
547: notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
548: return;
549: } catch (PrinterException pe) {
550: notifyEvent(PrintJobEvent.JOB_FAILED);
551: throw new PrintException(pe);
552: } finally {
553: printReturned = true;
554: notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
555: }
556: }
557:
558: public void pageableJob(Pageable pageable) throws PrintException {
559: try {
560: synchronized (this ) {
561: if (job != null) { // shouldn't happen
562: throw new PrintException("already printing");
563: } else {
564: job = new sun.awt.windows.WPrinterJob();
565: }
566: }
567: PrintService svc = getPrintService();
568: job.setPrintService(svc);
569: if (copies == 0) {
570: Copies c = (Copies) svc
571: .getDefaultAttributeValue(Copies.class);
572: copies = c.getValue();
573: }
574: job.setCopies(copies);
575: job.setJobName(jobName);
576: job.setPageable(pageable);
577: job.print(reqAttrSet);
578: notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
579: return;
580: } catch (PrinterException pe) {
581: notifyEvent(PrintJobEvent.JOB_FAILED);
582: throw new PrintException(pe);
583: } finally {
584: printReturned = true;
585: notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
586: }
587: }
588:
589: /* There's some inefficiency here as the job set is created even though
590: * it may never be requested.
591: */
592: private synchronized void initializeAttributeSets(Doc doc,
593: PrintRequestAttributeSet reqSet) {
594:
595: reqAttrSet = new HashPrintRequestAttributeSet();
596: jobAttrSet = new HashPrintJobAttributeSet();
597:
598: Attribute[] attrs;
599: if (reqSet != null) {
600: reqAttrSet.addAll(reqSet);
601: attrs = reqSet.toArray();
602: for (int i = 0; i < attrs.length; i++) {
603: if (attrs[i] instanceof PrintJobAttribute) {
604: jobAttrSet.add(attrs[i]);
605: }
606: }
607: }
608:
609: DocAttributeSet docSet = doc.getAttributes();
610: if (docSet != null) {
611: attrs = docSet.toArray();
612: for (int i = 0; i < attrs.length; i++) {
613: if (attrs[i] instanceof PrintRequestAttribute) {
614: reqAttrSet.add(attrs[i]);
615: }
616: if (attrs[i] instanceof PrintJobAttribute) {
617: jobAttrSet.add(attrs[i]);
618: }
619: }
620: }
621:
622: /* add the user name to the job */
623: String userName = "";
624: try {
625: userName = System.getProperty("user.name");
626: } catch (SecurityException se) {
627: }
628:
629: if (userName == null || userName.equals("")) {
630: RequestingUserName ruName = (RequestingUserName) reqSet
631: .get(RequestingUserName.class);
632: if (ruName != null) {
633: jobAttrSet.add(new JobOriginatingUserName(ruName
634: .getValue(), ruName.getLocale()));
635: } else {
636: jobAttrSet.add(new JobOriginatingUserName("", null));
637: }
638: } else {
639: jobAttrSet.add(new JobOriginatingUserName(userName, null));
640: }
641:
642: /* if no job name supplied use doc name (if supplied), if none and
643: * its a URL use that, else finally anything .. */
644: if (jobAttrSet.get(JobName.class) == null) {
645: JobName jobName;
646: if (docSet != null
647: && docSet.get(DocumentName.class) != null) {
648: DocumentName docName = (DocumentName) docSet
649: .get(DocumentName.class);
650: jobName = new JobName(docName.getValue(), docName
651: .getLocale());
652: jobAttrSet.add(jobName);
653: } else {
654: String str = "JPS Job:" + doc;
655: try {
656: Object printData = doc.getPrintData();
657: if (printData instanceof URL) {
658: str = ((URL) (doc.getPrintData())).toString();
659: }
660: } catch (IOException e) {
661: }
662: jobName = new JobName(str, null);
663: jobAttrSet.add(jobName);
664: }
665: }
666:
667: jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet);
668: }
669:
670: private void getAttributeValues(DocFlavor flavor)
671: throws PrintException {
672:
673: if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) {
674: fidelity = true;
675: } else {
676: fidelity = false;
677: }
678:
679: Class category;
680: Attribute[] attrs = reqAttrSet.toArray();
681: for (int i = 0; i < attrs.length; i++) {
682: Attribute attr = attrs[i];
683: category = attr.getCategory();
684: if (fidelity == true) {
685: if (!service.isAttributeCategorySupported(category)) {
686: notifyEvent(PrintJobEvent.JOB_FAILED);
687: throw new PrintJobAttributeException(
688: "unsupported category: " + category,
689: category, null);
690: } else if (!service.isAttributeValueSupported(attr,
691: flavor, null)) {
692: notifyEvent(PrintJobEvent.JOB_FAILED);
693: throw new PrintJobAttributeException(
694: "unsupported attribute: " + attr, null,
695: attr);
696: }
697: }
698: if (category == Destination.class) {
699: URI uri = ((Destination) attr).getURI();
700: if (!"file".equals(uri.getScheme())) {
701: notifyEvent(PrintJobEvent.JOB_FAILED);
702: throw new PrintException("Not a file: URI");
703: } else {
704: try {
705: mDestination = (new File(uri)).getPath();
706: } catch (Exception e) {
707: throw new PrintException(e);
708: }
709: // check write access
710: SecurityManager security = System
711: .getSecurityManager();
712: if (security != null) {
713: try {
714: security.checkWrite(mDestination);
715: } catch (SecurityException se) {
716: notifyEvent(PrintJobEvent.JOB_FAILED);
717: throw new PrintException(se);
718: }
719: }
720: }
721: } else if (category == JobName.class) {
722: jobName = ((JobName) attr).getValue();
723: } else if (category == Copies.class) {
724: copies = ((Copies) attr).getValue();
725: } else if (category == Media.class) {
726: if (attr instanceof MediaSizeName) {
727: mediaName = (MediaSizeName) attr;
728: // If requested MediaSizeName is not supported,
729: // get the corresponding media size - this will
730: // be used to create a new PageFormat.
731: if (!service.isAttributeValueSupported(attr, null,
732: null)) {
733: mediaSize = MediaSize
734: .getMediaSizeForName(mediaName);
735: }
736: }
737: } else if (category == OrientationRequested.class) {
738: orient = (OrientationRequested) attr;
739: }
740: }
741: }
742:
743: private native boolean startPrintRawData(String printerName,
744: String jobName);
745:
746: private native boolean printRawData(byte[] data, int count);
747:
748: private native boolean endPrintRawData();
749:
750: /* Cancel PrinterJob jobs that haven't yet completed. */
751: public void cancel() throws PrintException {
752: synchronized (this ) {
753: if (!printing) {
754: throw new PrintException("Job is not yet submitted.");
755: } else if (job != null && !printReturned) {
756: job.cancel();
757: notifyEvent(PrintJobEvent.JOB_CANCELED);
758: return;
759: } else {
760: throw new PrintException("Job could not be cancelled.");
761: }
762: }
763: }
764: }
|