1 /* 2 * Copyright (c) 2000, 2014, 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 = service.getAttribute(PrinterState.class); 312 if (prnState == PrinterState.STOPPED) { 313 PrinterStateReasons prnStateReasons = 314 service.getAttribute(PrinterStateReasons.class); 315 if ((prnStateReasons != null) && 316 (prnStateReasons.containsKey(PrinterStateReason.SHUTDOWN))) 317 { 318 throw new PrintException("PrintService is no longer available."); 319 } 320 } 321 322 if (service.getAttribute(PrinterIsAcceptingJobs.class) == 323 PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) { 324 throw new PrintException("Printer is not accepting job."); 325 } 326 327 328 this.doc = doc; 329 /* check if the parameters are valid before doing much processing */ 330 DocFlavor flavor = doc.getDocFlavor(); 331 Object data; 332 333 try { 334 data = doc.getPrintData(); 335 } catch (IOException e) { 336 notifyEvent(PrintJobEvent.JOB_FAILED); 337 throw new PrintException("can't get print data: " + e.toString()); 338 } 339 340 if (data == null) { 341 throw new PrintException("Null print data."); 342 } 343 344 if (flavor == null || (!service.isDocFlavorSupported(flavor))) { 345 notifyEvent(PrintJobEvent.JOB_FAILED); 346 throw new PrintJobFlavorException("invalid flavor", flavor); 347 } 348 349 initializeAttributeSets(doc, attributes); 350 351 getAttributeValues(flavor); 352 353 String repClassName = flavor.getRepresentationClassName(); 354 355 if (flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 356 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 357 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 358 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 359 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 360 flavor.equals(DocFlavor.BYTE_ARRAY.PNG)) { 361 try { 362 instream = doc.getStreamForBytes(); 363 if (instream == null) { 364 notifyEvent(PrintJobEvent.JOB_FAILED); 365 throw new PrintException("No stream for data"); 366 } 367 printableJob(new ImagePrinter(instream)); 368 service.wakeNotifier(); 369 return; 370 } catch (ClassCastException cce) { 371 notifyEvent(PrintJobEvent.JOB_FAILED); 372 throw new PrintException(cce); 373 } catch (IOException ioe) { 374 notifyEvent(PrintJobEvent.JOB_FAILED); 375 throw new PrintException(ioe); 376 } 377 } else if (flavor.equals(DocFlavor.URL.GIF) || 378 flavor.equals(DocFlavor.URL.JPEG) || 379 flavor.equals(DocFlavor.URL.PNG)) { 380 try { 381 printableJob(new ImagePrinter((URL)data)); 382 service.wakeNotifier(); 383 return; 384 } catch (ClassCastException cce) { 385 notifyEvent(PrintJobEvent.JOB_FAILED); 386 throw new PrintException(cce); 387 } 388 } else if (repClassName.equals("java.awt.print.Pageable")) { 389 try { 390 pageableJob((Pageable)doc.getPrintData()); 391 service.wakeNotifier(); 392 return; 393 } catch (ClassCastException cce) { 394 notifyEvent(PrintJobEvent.JOB_FAILED); 395 throw new PrintException(cce); 396 } catch (IOException ioe) { 397 notifyEvent(PrintJobEvent.JOB_FAILED); 398 throw new PrintException(ioe); 399 } 400 } else if (repClassName.equals("java.awt.print.Printable")) { 401 try { 402 printableJob((Printable)doc.getPrintData()); 403 service.wakeNotifier(); 404 return; 405 } catch (ClassCastException cce) { 406 notifyEvent(PrintJobEvent.JOB_FAILED); 407 throw new PrintException(cce); 408 } catch (IOException ioe) { 409 notifyEvent(PrintJobEvent.JOB_FAILED); 410 throw new PrintException(ioe); 411 } 412 } else if (repClassName.equals("[B") || 413 repClassName.equals("java.io.InputStream") || 414 repClassName.equals("java.net.URL")) { 415 416 if (repClassName.equals("java.net.URL")) { 417 URL url = (URL)data; 418 try { 419 instream = url.openStream(); 420 } catch (IOException e) { 421 notifyEvent(PrintJobEvent.JOB_FAILED); 422 throw new PrintException(e.toString()); 423 } 424 } else { 425 try { 426 instream = doc.getStreamForBytes(); 427 } catch (IOException ioe) { 428 notifyEvent(PrintJobEvent.JOB_FAILED); 429 throw new PrintException(ioe.toString()); 430 } 431 } 432 433 if (instream == null) { 434 notifyEvent(PrintJobEvent.JOB_FAILED); 435 throw new PrintException("No stream for data"); 436 } 437 438 if (mDestination != null) { // if destination attribute is set 439 try { 440 FileOutputStream fos = new FileOutputStream(mDestination); 441 byte []buffer = new byte[1024]; 442 int cread; 443 444 while ((cread = instream.read(buffer, 0, buffer.length)) >=0) { 445 fos.write(buffer, 0, cread); 446 } 447 fos.flush(); 448 fos.close(); 449 } catch (FileNotFoundException fnfe) { 450 notifyEvent(PrintJobEvent.JOB_FAILED); 451 throw new PrintException(fnfe.toString()); 452 } catch (IOException ioe) { 453 notifyEvent(PrintJobEvent.JOB_FAILED); 454 throw new PrintException(ioe.toString()); 455 } 456 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 457 notifyEvent(PrintJobEvent.JOB_COMPLETE); 458 service.wakeNotifier(); 459 return; 460 } 461 462 if (!startPrintRawData(service.getName(), jobName)) { 463 notifyEvent(PrintJobEvent.JOB_FAILED); 464 throw new PrintException("Print job failed to start."); 465 } 466 BufferedInputStream bin = new BufferedInputStream(instream); 467 int bread = 0; 468 try { 469 byte[] buffer = new byte[PRINTBUFFERLEN]; 470 471 while ((bread = bin.read(buffer, 0, PRINTBUFFERLEN)) >=0) { 472 if (!printRawData(buffer, bread)) { 473 bin.close(); 474 notifyEvent(PrintJobEvent.JOB_FAILED); 475 throw new PrintException ("Problem while spooling data"); 476 } 477 } 478 bin.close(); 479 if (!endPrintRawData()) { 480 notifyEvent(PrintJobEvent.JOB_FAILED); 481 throw new PrintException("Print job failed to close properly."); 482 } 483 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 484 } catch (IOException e) { 485 notifyEvent(PrintJobEvent.JOB_FAILED); 486 throw new PrintException (e.toString()); 487 } finally { 488 notifyEvent(PrintJobEvent.NO_MORE_EVENTS); 489 } 490 } else { 491 notifyEvent(PrintJobEvent.JOB_FAILED); 492 throw new PrintException("unrecognized class: "+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.getDefaultAttributeValue(Copies.class); 510 copies = c.getValue(); 511 } 512 513 if (mediaName == null) { 514 Object media = svc.getDefaultAttributeValue(Media.class); 515 if (media instanceof MediaSizeName) { 516 mediaName = (MediaSizeName) media; 517 mediaSize = MediaSize.getMediaSizeForName(mediaName); 518 } 519 } 520 521 if (orient == null) { 522 orient = 523 (OrientationRequested)svc.getDefaultAttributeValue(OrientationRequested.class); 524 } 525 526 job.setCopies(copies); 527 job.setJobName(jobName); 528 PageFormat pf = new PageFormat(); 529 if (mediaSize != null) { 530 Paper p = new Paper(); 531 p.setSize(mediaSize.getX(MediaSize.INCH)*72.0, 532 mediaSize.getY(MediaSize.INCH)*72.0); 533 p.setImageableArea(72.0, 72.0, p.getWidth()-144.0, 534 p.getHeight()-144.0); 535 pf.setPaper(p); 536 } 537 if (orient == OrientationRequested.REVERSE_LANDSCAPE) { 538 pf.setOrientation(PageFormat.REVERSE_LANDSCAPE); 539 } else if (orient == OrientationRequested.LANDSCAPE) { 540 pf.setOrientation(PageFormat.LANDSCAPE); 541 } 542 job.setPrintable(printable, pf); 543 job.print(reqAttrSet); 544 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 545 return; 546 } catch (PrinterException pe) { 547 notifyEvent(PrintJobEvent.JOB_FAILED); 548 throw new PrintException(pe); 549 } finally { 550 printReturned = true; 551 notifyEvent(PrintJobEvent.NO_MORE_EVENTS); 552 } 553 } 554 555 public void pageableJob(Pageable pageable) throws PrintException { 556 try { 557 synchronized(this) { 558 if (job != null) { // shouldn't happen 559 throw new PrintException("already printing"); 560 } else { 561 job = new sun.awt.windows.WPrinterJob(); 562 } 563 } 564 PrintService svc = getPrintService(); 565 job.setPrintService(svc); 566 if (copies == 0) { 567 Copies c = (Copies)svc.getDefaultAttributeValue(Copies.class); 568 copies = c.getValue(); 569 } 570 job.setCopies(copies); 571 job.setJobName(jobName); 572 job.setPageable(pageable); 573 job.print(reqAttrSet); 574 notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE); 575 return; 576 } catch (PrinterException pe) { 577 notifyEvent(PrintJobEvent.JOB_FAILED); 578 throw new PrintException(pe); 579 } finally { 580 printReturned = true; 581 notifyEvent(PrintJobEvent.NO_MORE_EVENTS); 582 } 583 } 584 585 /* There's some inefficiency here as the job set is created even though 586 * it may never be requested. 587 */ 588 private synchronized void 589 initializeAttributeSets(Doc doc, PrintRequestAttributeSet reqSet) { 590 591 reqAttrSet = new HashPrintRequestAttributeSet(); 592 jobAttrSet = new HashPrintJobAttributeSet(); 593 594 Attribute[] attrs; 595 if (reqSet != null) { 596 reqAttrSet.addAll(reqSet); 597 attrs = reqSet.toArray(); 598 for (int i=0; i<attrs.length; i++) { 599 if (attrs[i] instanceof PrintJobAttribute) { 600 jobAttrSet.add(attrs[i]); 601 } 602 } 603 } 604 605 DocAttributeSet docSet = doc.getAttributes(); 606 if (docSet != null) { 607 attrs = docSet.toArray(); 608 for (int i=0; i<attrs.length; i++) { 609 if (attrs[i] instanceof PrintRequestAttribute) { 610 reqAttrSet.add(attrs[i]); 611 } 612 if (attrs[i] instanceof PrintJobAttribute) { 613 jobAttrSet.add(attrs[i]); 614 } 615 } 616 } 617 618 /* add the user name to the job */ 619 String userName = ""; 620 try { 621 userName = System.getProperty("user.name"); 622 } catch (SecurityException se) { 623 } 624 625 if (userName == null || userName.equals("")) { 626 RequestingUserName ruName = 627 (RequestingUserName)reqSet.get(RequestingUserName.class); 628 if (ruName != null) { 629 jobAttrSet.add( 630 new JobOriginatingUserName(ruName.getValue(), 631 ruName.getLocale())); 632 } else { 633 jobAttrSet.add(new JobOriginatingUserName("", null)); 634 } 635 } else { 636 jobAttrSet.add(new JobOriginatingUserName(userName, null)); 637 } 638 639 /* if no job name supplied use doc name (if supplied), if none and 640 * its a URL use that, else finally anything .. */ 641 if (jobAttrSet.get(JobName.class) == null) { 642 JobName jobName; 643 if (docSet != null && docSet.get(DocumentName.class) != null) { 644 DocumentName docName = 645 (DocumentName)docSet.get(DocumentName.class); 646 jobName = new JobName(docName.getValue(), docName.getLocale()); 647 jobAttrSet.add(jobName); 648 } else { 649 String str = "JPS Job:" + doc; 650 try { 651 Object printData = doc.getPrintData(); 652 if (printData instanceof URL) { 653 str = ((URL)(doc.getPrintData())).toString(); 654 } 655 } catch (IOException e) { 656 } 657 jobName = new JobName(str, null); 658 jobAttrSet.add(jobName); 659 } 660 } 661 662 jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet); 663 } 664 665 private void getAttributeValues(DocFlavor flavor) throws PrintException { 666 667 if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) { 668 fidelity = true; 669 } else { 670 fidelity = false; 671 } 672 673 Class category; 674 Attribute [] attrs = reqAttrSet.toArray(); 675 for (int i=0; i<attrs.length; i++) { 676 Attribute attr = attrs[i]; 677 category = attr.getCategory(); 678 if (fidelity == true) { 679 if (!service.isAttributeCategorySupported(category)) { 680 notifyEvent(PrintJobEvent.JOB_FAILED); 681 throw new PrintJobAttributeException( 682 "unsupported category: " + category, category, null); 683 } else if 684 (!service.isAttributeValueSupported(attr, flavor, null)) { 685 notifyEvent(PrintJobEvent.JOB_FAILED); 686 throw new PrintJobAttributeException( 687 "unsupported attribute: " + attr, null, attr); 688 } 689 } 690 if (category == Destination.class) { 691 URI uri = ((Destination)attr).getURI(); 692 if (!"file".equals(uri.getScheme())) { 693 notifyEvent(PrintJobEvent.JOB_FAILED); 694 throw new PrintException("Not a file: URI"); 695 } else { 696 try { 697 mDestination = (new File(uri)).getPath(); 698 } catch (Exception e) { 699 throw new PrintException(e); 700 } 701 // check write access 702 SecurityManager security = System.getSecurityManager(); 703 if (security != null) { 704 try { 705 security.checkWrite(mDestination); 706 } catch (SecurityException se) { 707 notifyEvent(PrintJobEvent.JOB_FAILED); 708 throw new PrintException(se); 709 } 710 } 711 } 712 } else if (category == JobName.class) { 713 jobName = ((JobName)attr).getValue(); 714 } else if (category == Copies.class) { 715 copies = ((Copies)attr).getValue(); 716 } else if (category == Media.class) { 717 if (attr instanceof MediaSizeName) { 718 mediaName = (MediaSizeName)attr; 719 // If requested MediaSizeName is not supported, 720 // get the corresponding media size - this will 721 // be used to create a new PageFormat. 722 if (!service.isAttributeValueSupported(attr, null, null)) { 723 mediaSize = MediaSize.getMediaSizeForName(mediaName); 724 } 725 } 726 } else if (category == OrientationRequested.class) { 727 orient = (OrientationRequested)attr; 728 } 729 } 730 } 731 732 private native boolean startPrintRawData(String printerName, 733 String jobName); 734 private native boolean printRawData(byte[] data, int count); 735 private native boolean endPrintRawData(); 736 737 /* Cancel PrinterJob jobs that haven't yet completed. */ 738 public void cancel() throws PrintException { 739 synchronized (this) { 740 if (!printing) { 741 throw new PrintException("Job is not yet submitted."); 742 } else if (job != null && !printReturned) { 743 job.cancel(); 744 notifyEvent(PrintJobEvent.JOB_CANCELED); 745 return; 746 } else { 747 throw new PrintException("Job could not be cancelled."); 748 } 749 } 750 } 751 }