1 /* 2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.print; 27 28 import java.net.URI; 29 import java.io.BufferedInputStream; 30 import java.io.BufferedOutputStream; 31 import java.io.File; 32 import java.io.FileOutputStream; 33 import java.io.InputStream; 34 import java.io.OutputStream; 35 import java.io.InputStream; 36 import java.io.IOException; 37 import java.io.FileNotFoundException; 38 import java.io.Reader; 39 import java.net.URL; 40 import java.util.Vector; 41 42 import javax.print.CancelablePrintJob; 43 import javax.print.Doc; 44 import javax.print.DocFlavor; 45 import javax.print.DocPrintJob; 46 import javax.print.PrintService; 47 import javax.print.PrintException; 48 import javax.print.event.PrintJobEvent; 49 import javax.print.event.PrintJobListener; 50 import javax.print.event.PrintJobAttributeListener; 51 52 import javax.print.attribute.Attribute; 53 import javax.print.attribute.AttributeSet; 54 import javax.print.attribute.AttributeSetUtilities; 55 import javax.print.attribute.DocAttributeSet; 56 import javax.print.attribute.HashPrintJobAttributeSet; 57 import javax.print.attribute.HashPrintRequestAttributeSet; 58 import javax.print.attribute.PrintJobAttribute; 59 import javax.print.attribute.PrintJobAttributeSet; 60 import javax.print.attribute.PrintRequestAttribute; 61 import javax.print.attribute.PrintRequestAttributeSet; 62 import javax.print.attribute.standard.Copies; 63 import javax.print.attribute.standard.DocumentName; 64 import javax.print.attribute.standard.Fidelity; 65 import javax.print.attribute.standard.JobName; 66 import javax.print.attribute.standard.JobOriginatingUserName; 67 import javax.print.attribute.standard.Media; 68 import javax.print.attribute.standard.MediaSize; 69 import javax.print.attribute.standard.MediaSizeName; 70 import javax.print.attribute.standard.OrientationRequested; 71 import javax.print.attribute.standard.RequestingUserName; 72 import javax.print.attribute.standard.Destination; 73 import javax.print.attribute.standard.PrinterIsAcceptingJobs; 74 import javax.print.attribute.standard.PrinterState; 75 import javax.print.attribute.standard.PrinterStateReason; 76 import javax.print.attribute.standard.PrinterStateReasons; 77 78 import java.awt.print.*; 79 80 public class Win32PrintJob implements CancelablePrintJob { 81 82 transient private Vector jobListeners; 83 transient private Vector attrListeners; 84 transient private Vector listenedAttributeSets; 85 86 private Win32PrintService service; 87 private boolean fidelity; 88 private boolean printing = false; 89 private boolean printReturned = false; 90 private PrintRequestAttributeSet reqAttrSet = null; 91 private PrintJobAttributeSet jobAttrSet = null; 92 private PrinterJob job; 93 private Doc doc; 94 private String mDestination = null; 95 96 /* these variables used globally to store reference to the print 97 * data retrieved as a stream. On completion these are always closed 98 * if non-null. 99 */ 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 161 /* Closes any stream already retrieved for the data. 162 * We want to avoid unnecessarily asking the Doc to create a stream only 163 * to get a reference in order to close it because the job failed. 164 * If the representation class is itself a "stream", this 165 * closes that stream too. 166 */ 167 private void closeDataStreams() { 168 169 if (doc == null) { 170 return; 171 } 172 173 Object data = null; 174 175 try { 176 data = doc.getPrintData(); 177 } catch (IOException e) { 178 return; 179 } 180 181 if (instream != null) { 182 try { 183 instream.close(); 184 } catch (IOException e) { 185 } finally { 186 instream = null; 187 } 188 } 189 else if (reader != null) { 190 try { 191 reader.close(); 192 } catch (IOException e) { 193 } finally { 194 reader = null; 195 } 196 } 197 else if (data instanceof InputStream) { 198 try { 199 ((InputStream)data).close(); 200 } catch (IOException e) { 201 } 202 } 203 else if (data instanceof Reader) { 204 try { 205 ((Reader)data).close(); 206 } catch (IOException e) { 207 } 208 } 209 } 210 211 private void notifyEvent(int reason) { 212 213 /* since this method should always get called, here's where 214 * we will perform the clean up of any data stream supplied. 215 */ 216 switch (reason) { 217 case PrintJobEvent.DATA_TRANSFER_COMPLETE: 218 case PrintJobEvent.JOB_CANCELED : 219 case PrintJobEvent.JOB_FAILED : 220 case PrintJobEvent.NO_MORE_EVENTS : 221 case PrintJobEvent.JOB_COMPLETE : 222 closeDataStreams(); 223 } 224 225 synchronized (this) { 226 if (jobListeners != null) { 227 PrintJobListener listener; 228 PrintJobEvent event = new PrintJobEvent(this, reason); 229 for (int i = 0; i < jobListeners.size(); i++) { 230 listener = (PrintJobListener)(jobListeners.elementAt(i)); 231 switch (reason) { 232 233 case PrintJobEvent.JOB_COMPLETE : 234 listener.printJobCompleted(event); 235 break; 236 237 case PrintJobEvent.JOB_CANCELED : 238 listener.printJobCanceled(event); 239 break; 240 241 case PrintJobEvent.JOB_FAILED : 242 listener.printJobFailed(event); 243 break; 244 245 case PrintJobEvent.DATA_TRANSFER_COMPLETE : 246 listener.printDataTransferCompleted(event); 247 break; 248 249 case PrintJobEvent.NO_MORE_EVENTS : 250 listener.printJobNoMoreEvents(event); 251 break; 252 253 default: 254 break; 255 } 256 } 257 } 258 } 259 } 260 261 public void addPrintJobAttributeListener( 262 PrintJobAttributeListener listener, 263 PrintJobAttributeSet attributes) { 264 synchronized (this) { 265 if (listener == null) { 266 return; 267 } 268 if (attrListeners == null) { 269 attrListeners = new Vector(); 270 listenedAttributeSets = new Vector(); 271 } 272 attrListeners.add(listener); 273 if (attributes == null) { 274 attributes = new HashPrintJobAttributeSet(); 275 } 276 listenedAttributeSets.add(attributes); 277 } 278 } 279 280 public void removePrintJobAttributeListener( 281 PrintJobAttributeListener listener) { 282 synchronized (this) { 283 if (listener == null || attrListeners == null ) { 284 return; 285 } 286 int index = attrListeners.indexOf(listener); 287 if (index == -1) { 288 return; 289 } else { 290 attrListeners.remove(index); 291 listenedAttributeSets.remove(index); 292 if (attrListeners.isEmpty()) { 293 attrListeners = null; 294 listenedAttributeSets = null; 295 } 296 } 297 } 298 } 299 300 public void print(Doc doc, PrintRequestAttributeSet attributes) 301 throws PrintException { 302 303 synchronized (this) { 304 if (printing) { 305 throw new PrintException("already printing"); 306 } else { 307 printing = true; 308 } 309 } 310 311 PrinterState prnState = (PrinterState)service.getAttribute( 312 PrinterState.class); 313 if (prnState == PrinterState.STOPPED) { 314 PrinterStateReasons prnStateReasons = 315 (PrinterStateReasons)service.getAttribute( 316 PrinterStateReasons.class); 317 if ((prnStateReasons != null) && 318 (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN))) 319 { 320 throw new PrintException("PrintService is no longer available."); 321 } 322 } 323 324 if ((PrinterIsAcceptingJobs)(service.getAttribute( 325 PrinterIsAcceptingJobs.class)) == 326 PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) { 327 throw new PrintException("Printer is not accepting job."); 328 } 329 330 331 this.doc = doc; 332 /* check if the parameters are valid before doing much processing */ 333 DocFlavor flavor = doc.getDocFlavor(); 334 Object data; 335 336 try { 337 data = doc.getPrintData(); 338 } catch (IOException e) { 339 notifyEvent(PrintJobEvent.JOB_FAILED); 340 throw new PrintException("can't get print data: " + e.toString()); 341 } 342 343 if (data == null) { 344 throw new PrintException("Null print data."); 345 } 346 347 if (flavor == null || (!service.isDocFlavorSupported(flavor))) { 348 notifyEvent(PrintJobEvent.JOB_FAILED); 349 throw new PrintJobFlavorException("invalid flavor", flavor); 350 } 351 352 initializeAttributeSets(doc, attributes); 353 354 getAttributeValues(flavor); 355 356 String repClassName = flavor.getRepresentationClassName(); 357 358 if (flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 359 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 360 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 361 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 362 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 363 flavor.equals(DocFlavor.BYTE_ARRAY.PNG)) { 364 try { 365 instream = doc.getStreamForBytes(); 366 if (instream == null) { 367 notifyEvent(PrintJobEvent.JOB_FAILED); 368 throw new PrintException("No stream for data"); 369 } 370 printableJob(new ImagePrinter(instream)); 371 service.wakeNotifier(); 372 return; 373 } catch (ClassCastException cce) { 374 notifyEvent(PrintJobEvent.JOB_FAILED); 375 throw new PrintException(cce); 376 } catch (IOException ioe) { 377 notifyEvent(PrintJobEvent.JOB_FAILED); 378 throw new PrintException(ioe); 379 } 380 } else if (flavor.equals(DocFlavor.URL.GIF) || 381 flavor.equals(DocFlavor.URL.JPEG) || 382 flavor.equals(DocFlavor.URL.PNG)) { 383 try { 384 printableJob(new ImagePrinter((URL)data)); 385 service.wakeNotifier(); 386 return; 387 } catch (ClassCastException cce) { 388 notifyEvent(PrintJobEvent.JOB_FAILED); 389 throw new PrintException(cce); 390 } 391 } else if (repClassName.equals("java.awt.print.Pageable")) { 392 try { 393 pageableJob((Pageable)doc.getPrintData()); 394 service.wakeNotifier(); 395 return; 396 } catch (ClassCastException cce) { 397 notifyEvent(PrintJobEvent.JOB_FAILED); 398 throw new PrintException(cce); 399 } catch (IOException ioe) { 400 notifyEvent(PrintJobEvent.JOB_FAILED); 401 throw new PrintException(ioe); 402 } 403 } else if (repClassName.equals("java.awt.print.Printable")) { 404 try { 405 printableJob((Printable)doc.getPrintData()); 406 service.wakeNotifier(); 407 return; 408 } catch (ClassCastException cce) { 409 notifyEvent(PrintJobEvent.JOB_FAILED); 410 throw new PrintException(cce); 411 } catch (IOException ioe) { 412 notifyEvent(PrintJobEvent.JOB_FAILED); 413 throw new PrintException(ioe); 414 } 415 } else if (repClassName.equals("[B") || 416 repClassName.equals("java.io.InputStream") || 417 repClassName.equals("java.net.URL")) { 418 419 if (repClassName.equals("java.net.URL")) { 420 URL url = (URL)data; 421 try { 422 instream = url.openStream(); 423 } catch (IOException e) { 424 notifyEvent(PrintJobEvent.JOB_FAILED); 425 throw new PrintException(e.toString()); 426 } 427 } else { 428 try { 429 instream = doc.getStreamForBytes(); 430 } catch (IOException ioe) { 431 notifyEvent(PrintJobEvent.JOB_FAILED); 432 throw new PrintException(ioe.toString()); 433 } 434 } 435 436 if (instream == null) { 437 notifyEvent(PrintJobEvent.JOB_FAILED); 438 throw new PrintException("No stream for data"); 439 } 440 441 if (mDestination != null) { // if destination attribute is set 442 try { 443 FileOutputStream fos = new FileOutputStream(mDestination); 444 byte []buffer = new byte[1024]; 445 int cread; 446 447 while ((cread = instream.read(buffer, 0, buffer.length)) >=0) { 448 fos.write(buffer, 0, cread); 449 } 450 fos.flush(); 451 fos.close(); 452 } catch (FileNotFoundException fnfe) { 453 notifyEvent(PrintJobEvent.JOB_FAILED); 454 throw new PrintException(fnfe.toString()); 455 } catch (IOException ioe) { 456 notifyEvent(PrintJobEvent.JOB_FAILED); 457 throw new PrintException(ioe.toString()); 458 } 459 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 460 notifyEvent(PrintJobEvent.JOB_COMPLETE); 461 service.wakeNotifier(); 462 return; 463 } 464 465 if (!startPrintRawData(service.getName(), jobName)) { 466 notifyEvent(PrintJobEvent.JOB_FAILED); 467 throw new PrintException("Print job failed to start."); 468 } 469 BufferedInputStream bin = new BufferedInputStream(instream); 470 int bread = 0; 471 try { 472 byte[] buffer = new byte[PRINTBUFFERLEN]; 473 474 while ((bread = bin.read(buffer, 0, PRINTBUFFERLEN)) >=0) { 475 if (!printRawData(buffer, bread)) { 476 bin.close(); 477 notifyEvent(PrintJobEvent.JOB_FAILED); 478 throw new PrintException ("Problem while spooling data"); 479 } 480 } 481 bin.close(); 482 if (!endPrintRawData()) { 483 notifyEvent(PrintJobEvent.JOB_FAILED); 484 throw new PrintException("Print job failed to close properly."); 485 } 486 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 487 } catch (IOException e) { 488 notifyEvent(PrintJobEvent.JOB_FAILED); 489 throw new PrintException (e.toString()); 490 } finally { 491 notifyEvent(PrintJobEvent.NO_MORE_EVENTS); 492 } 493 } else { 494 notifyEvent(PrintJobEvent.JOB_FAILED); 495 throw new PrintException("unrecognized class: "+repClassName); 496 } 497 service.wakeNotifier(); 498 } 499 500 public void printableJob(Printable printable) throws PrintException { 501 try { 502 synchronized(this) { 503 if (job != null) { // shouldn't happen 504 throw new PrintException("already printing"); 505 } else { 506 job = new sun.awt.windows.WPrinterJob(); 507 } 508 } 509 PrintService svc = getPrintService(); 510 job.setPrintService(svc); 511 if (copies == 0) { 512 Copies c = (Copies)svc.getDefaultAttributeValue(Copies.class); 513 copies = c.getValue(); 514 } 515 516 if (mediaName == null) { 517 Object media = svc.getDefaultAttributeValue(Media.class); 518 if (media instanceof MediaSizeName) { 519 mediaName = (MediaSizeName) media; 520 mediaSize = MediaSize.getMediaSizeForName(mediaName); 521 } 522 } 523 524 if (orient == null) { 525 orient = 526 (OrientationRequested)svc.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, 537 p.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.getDefaultAttributeValue(Copies.class); 571 copies = c.getValue(); 572 } 573 job.setCopies(copies); 574 job.setJobName(jobName); 575 job.setPageable(pageable); 576 job.print(reqAttrSet); 577 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 578 return; 579 } catch (PrinterException pe) { 580 notifyEvent(PrintJobEvent.JOB_FAILED); 581 throw new PrintException(pe); 582 } finally { 583 printReturned = true; 584 notifyEvent(PrintJobEvent.NO_MORE_EVENTS); 585 } 586 } 587 588 /* There's some inefficiency here as the job set is created even though 589 * it may never be requested. 590 */ 591 private synchronized void 592 initializeAttributeSets(Doc doc, PrintRequestAttributeSet reqSet) { 593 594 reqAttrSet = new HashPrintRequestAttributeSet(); 595 jobAttrSet = new HashPrintJobAttributeSet(); 596 597 Attribute[] attrs; 598 if (reqSet != null) { 599 reqAttrSet.addAll(reqSet); 600 attrs = reqSet.toArray(); 601 for (int i=0; i<attrs.length; i++) { 602 if (attrs[i] instanceof PrintJobAttribute) { 603 jobAttrSet.add(attrs[i]); 604 } 605 } 606 } 607 608 DocAttributeSet docSet = doc.getAttributes(); 609 if (docSet != null) { 610 attrs = docSet.toArray(); 611 for (int i=0; i<attrs.length; i++) { 612 if (attrs[i] instanceof PrintRequestAttribute) { 613 reqAttrSet.add(attrs[i]); 614 } 615 if (attrs[i] instanceof PrintJobAttribute) { 616 jobAttrSet.add(attrs[i]); 617 } 618 } 619 } 620 621 /* add the user name to the job */ 622 String userName = ""; 623 try { 624 userName = System.getProperty("user.name"); 625 } catch (SecurityException se) { 626 } 627 628 if (userName == null || userName.equals("")) { 629 RequestingUserName ruName = 630 (RequestingUserName)reqSet.get(RequestingUserName.class); 631 if (ruName != null) { 632 jobAttrSet.add( 633 new JobOriginatingUserName(ruName.getValue(), 634 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 && docSet.get(DocumentName.class) != null) { 647 DocumentName docName = 648 (DocumentName)docSet.get(DocumentName.class); 649 jobName = new JobName(docName.getValue(), docName.getLocale()); 650 jobAttrSet.add(jobName); 651 } else { 652 String str = "JPS Job:" + doc; 653 try { 654 Object printData = doc.getPrintData(); 655 if (printData instanceof URL) { 656 str = ((URL)(doc.getPrintData())).toString(); 657 } 658 } catch (IOException e) { 659 } 660 jobName = new JobName(str, null); 661 jobAttrSet.add(jobName); 662 } 663 } 664 665 jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet); 666 } 667 668 private void getAttributeValues(DocFlavor flavor) throws PrintException { 669 670 if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) { 671 fidelity = true; 672 } else { 673 fidelity = false; 674 } 675 676 Class category; 677 Attribute [] attrs = reqAttrSet.toArray(); 678 for (int i=0; i<attrs.length; i++) { 679 Attribute attr = attrs[i]; 680 category = attr.getCategory(); 681 if (fidelity == true) { 682 if (!service.isAttributeCategorySupported(category)) { 683 notifyEvent(PrintJobEvent.JOB_FAILED); 684 throw new PrintJobAttributeException( 685 "unsupported category: " + category, category, null); 686 } else if 687 (!service.isAttributeValueSupported(attr, flavor, null)) { 688 notifyEvent(PrintJobEvent.JOB_FAILED); 689 throw new PrintJobAttributeException( 690 "unsupported attribute: " + attr, null, attr); 691 } 692 } 693 if (category == Destination.class) { 694 URI uri = ((Destination)attr).getURI(); 695 if (!"file".equals(uri.getScheme())) { 696 notifyEvent(PrintJobEvent.JOB_FAILED); 697 throw new PrintException("Not a file: URI"); 698 } else { 699 try { 700 mDestination = (new File(uri)).getPath(); 701 } catch (Exception e) { 702 throw new PrintException(e); 703 } 704 // check write access 705 SecurityManager security = System.getSecurityManager(); 706 if (security != null) { 707 try { 708 security.checkWrite(mDestination); 709 } catch (SecurityException se) { 710 notifyEvent(PrintJobEvent.JOB_FAILED); 711 throw new PrintException(se); 712 } 713 } 714 } 715 } else if (category == JobName.class) { 716 jobName = ((JobName)attr).getValue(); 717 } else if (category == Copies.class) { 718 copies = ((Copies)attr).getValue(); 719 } else if (category == Media.class) { 720 if (attr instanceof MediaSizeName) { 721 mediaName = (MediaSizeName)attr; 722 // If requested MediaSizeName is not supported, 723 // get the corresponding media size - this will 724 // be used to create a new PageFormat. 725 if (!service.isAttributeValueSupported(attr, null, null)) { 726 mediaSize = MediaSize.getMediaSizeForName(mediaName); 727 } 728 } 729 } else if (category == OrientationRequested.class) { 730 orient = (OrientationRequested)attr; 731 } 732 } 733 } 734 735 private native boolean startPrintRawData(String printerName, 736 String jobName); 737 private native boolean printRawData(byte[] data, int count); 738 private native boolean endPrintRawData(); 739 740 /* Cancel PrinterJob jobs that haven't yet completed. */ 741 public void cancel() throws PrintException { 742 synchronized (this) { 743 if (!printing) { 744 throw new PrintException("Job is not yet submitted."); 745 } else if (job != null && !printReturned) { 746 job.cancel(); 747 notifyEvent(PrintJobEvent.JOB_CANCELED); 748 return; 749 } else { 750 throw new PrintException("Job could not be cancelled."); 751 } 752 } 753 } 754 }