1 /* 2 * Copyright (c) 1997, 2017, 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 java.awt.print; 27 28 import java.awt.AWTError; 29 import java.awt.HeadlessException; 30 31 import javax.print.DocFlavor; 32 import javax.print.PrintService; 33 import javax.print.PrintServiceLookup; 34 import javax.print.StreamPrintServiceFactory; 35 import javax.print.attribute.AttributeSet; 36 import javax.print.attribute.PrintRequestAttributeSet; 37 import javax.print.attribute.standard.Media; 38 import javax.print.attribute.standard.MediaPrintableArea; 39 import javax.print.attribute.standard.MediaSize; 40 import javax.print.attribute.standard.MediaSizeName; 41 import javax.print.attribute.standard.OrientationRequested; 42 43 /** 44 * The {@code PrinterJob} class is the principal class that controls 45 * printing. An application calls methods in this class to set up a job, 46 * optionally to invoke a print dialog with the user, and then to print 47 * the pages of the job. 48 */ 49 public abstract class PrinterJob { 50 51 /* Public Class Methods */ 52 53 /** 54 * Creates and returns a {@code PrinterJob} which is initially 55 * associated with the default printer. 56 * If no printers are available on the system, a PrinterJob will still 57 * be returned from this method, but {@code getPrintService()} 58 * will return {@code null}, and calling 59 * {@link #print() print} with this {@code PrinterJob} might 60 * generate an exception. Applications that need to determine if 61 * there are suitable printers before creating a {@code PrinterJob} 62 * should ensure that the array returned from 63 * {@link #lookupPrintServices() lookupPrintServices} is not empty. 64 * @return a new {@code PrinterJob}. 65 * 66 * @throws SecurityException if a security manager exists and its 67 * {@link java.lang.SecurityManager#checkPrintJobAccess} 68 * method disallows this thread from creating a print job request 69 */ 70 public static PrinterJob getPrinterJob() { 71 SecurityManager security = System.getSecurityManager(); 72 if (security != null) { 73 security.checkPrintJobAccess(); 74 } 75 return sun.print.PlatformPrinterJobProxy.getPrinterJob(); 76 } 77 78 /** 79 * A convenience method which looks up 2D print services. 80 * Services returned from this method may be installed on 81 * {@code PrinterJob}s which support print services. 82 * Calling this method is equivalent to calling 83 * {@link javax.print.PrintServiceLookup#lookupPrintServices( 84 * DocFlavor, AttributeSet) 85 * PrintServiceLookup.lookupPrintServices()} 86 * and specifying a Pageable DocFlavor. 87 * @return a possibly empty array of 2D print services. 88 * @since 1.4 89 */ 90 public static PrintService[] lookupPrintServices() { 91 return PrintServiceLookup. 92 lookupPrintServices(DocFlavor.SERVICE_FORMATTED.PAGEABLE, null); 93 } 94 95 96 /** 97 * A convenience method which locates factories for stream print 98 * services which can image 2D graphics. 99 * Sample usage : 100 * <pre>{@code 101 * FileOutputStream outstream; 102 * StreamPrintService psPrinter; 103 * String psMimeType = "application/postscript"; 104 * PrinterJob pj = PrinterJob.getPrinterJob(); 105 * 106 * StreamPrintServiceFactory[] factories = 107 * PrinterJob.lookupStreamPrintServices(psMimeType); 108 * if (factories.length > 0) { 109 * try { 110 * outstream = new File("out.ps"); 111 * psPrinter = factories[0].getPrintService(outstream); 112 * // psPrinter can now be set as the service on a PrinterJob 113 * pj.setPrintService(psPrinter) 114 * } catch (Exception e) { 115 * e.printStackTrace(); 116 * } 117 * } 118 * }</pre> 119 * Services returned from this method may be installed on 120 * {@code PrinterJob} instances which support print services. 121 * Calling this method is equivalent to calling 122 * {@link javax.print.StreamPrintServiceFactory#lookupStreamPrintServiceFactories(DocFlavor, String) 123 * StreamPrintServiceFactory.lookupStreamPrintServiceFactories() 124 * } and specifying a Pageable DocFlavor. 125 * 126 * @param mimeType the required output format, or null to mean any format. 127 * @return a possibly empty array of 2D stream print service factories. 128 * @since 1.4 129 */ 130 public static StreamPrintServiceFactory[] 131 lookupStreamPrintServices(String mimeType) { 132 return StreamPrintServiceFactory.lookupStreamPrintServiceFactories( 133 DocFlavor.SERVICE_FORMATTED.PAGEABLE, 134 mimeType); 135 } 136 137 138 /* Public Methods */ 139 140 /** 141 * A {@code PrinterJob} object should be created using the 142 * static {@link #getPrinterJob() getPrinterJob} method. 143 */ 144 public PrinterJob() { 145 } 146 147 /** 148 * Returns the service (printer) for this printer job. 149 * Implementations of this class which do not support print services 150 * may return null. null will also be returned if no printers are 151 * available. 152 * @return the service for this printer job. 153 * @see #setPrintService(PrintService) 154 * @see #getPrinterJob() 155 * @since 1.4 156 */ 157 public PrintService getPrintService() { 158 return null; 159 } 160 161 /** 162 * Associate this PrinterJob with a new PrintService. 163 * This method is overridden by subclasses which support 164 * specifying a Print Service. 165 * 166 * Throws {@code PrinterException} if the specified service 167 * cannot support the {@code Pageable} and 168 * {@code Printable} interfaces necessary to support 2D printing. 169 * @param service a print service that supports 2D printing 170 * @exception PrinterException if the specified service does not support 171 * 2D printing, or this PrinterJob class does not support 172 * setting a 2D print service, or the specified service is 173 * otherwise not a valid print service. 174 * @see #getPrintService 175 * @since 1.4 176 */ 177 public void setPrintService(PrintService service) 178 throws PrinterException { 179 throw new PrinterException( 180 "Setting a service is not supported on this class"); 181 } 182 183 /** 184 * Calls {@code painter} to render the pages. The pages in the 185 * document to be printed by this 186 * {@code PrinterJob} are rendered by the {@link Printable} 187 * object, {@code painter}. The {@link PageFormat} for each page 188 * is the default page format. 189 * @param painter the {@code Printable} that renders each page of 190 * the document. 191 */ 192 public abstract void setPrintable(Printable painter); 193 194 /** 195 * Calls {@code painter} to render the pages in the specified 196 * {@code format}. The pages in the document to be printed by 197 * this {@code PrinterJob} are rendered by the 198 * {@code Printable} object, {@code painter}. The 199 * {@code PageFormat} of each page is {@code format}. 200 * @param painter the {@code Printable} called to render 201 * each page of the document 202 * @param format the size and orientation of each page to 203 * be printed 204 */ 205 public abstract void setPrintable(Printable painter, PageFormat format); 206 207 /** 208 * Queries {@code document} for the number of pages and 209 * the {@code PageFormat} and {@code Printable} for each 210 * page held in the {@code Pageable} instance, 211 * {@code document}. 212 * @param document the pages to be printed. It can not be 213 * {@code null}. 214 * @exception NullPointerException the {@code Pageable} passed in 215 * was {@code null}. 216 * @see PageFormat 217 * @see Printable 218 */ 219 public abstract void setPageable(Pageable document) 220 throws NullPointerException; 221 222 /** 223 * Presents a dialog to the user for changing the properties of 224 * the print job. 225 * This method will display a native dialog if a native print 226 * service is selected, and user choice of printers will be restricted 227 * to these native print services. 228 * To present the cross platform print dialog for all services, 229 * including native ones instead use 230 * {@code printDialog(PrintRequestAttributeSet)}. 231 * <p> 232 * PrinterJob implementations which can use PrintService's will update 233 * the PrintService for this PrinterJob to reflect the new service 234 * selected by the user. 235 * @return {@code true} if the user does not cancel the dialog; 236 * {@code false} otherwise. 237 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 238 * returns true. 239 * @see java.awt.GraphicsEnvironment#isHeadless 240 */ 241 public abstract boolean printDialog() throws HeadlessException; 242 243 /** 244 * A convenience method which displays a cross-platform print dialog 245 * for all services which are capable of printing 2D graphics using the 246 * {@code Pageable} interface. The selected printer when the 247 * dialog is initially displayed will reflect the print service currently 248 * attached to this print job. 249 * If the user changes the print service, the PrinterJob will be 250 * updated to reflect this, unless the user cancels the dialog. 251 * As well as allowing the user to select the destination printer, 252 * the user can also select values of various print request attributes. 253 * <p> 254 * The attributes parameter on input will reflect the applications 255 * required initial selections in the user dialog. Attributes not 256 * specified display using the default for the service. On return it 257 * will reflect the user's choices. Selections may be updated by 258 * the implementation to be consistent with the supported values 259 * for the currently selected print service. 260 * <p> 261 * As the user scrolls to a new print service selection, the values 262 * copied are based on the settings for the previous service, together 263 * with any user changes. The values are not based on the original 264 * settings supplied by the client. 265 * <p> 266 * With the exception of selected printer, the PrinterJob state is 267 * not updated to reflect the user's changes. 268 * For the selections to affect a printer job, the attributes must 269 * be specified in the call to the 270 * {@code print(PrintRequestAttributeSet)} method. If using 271 * the Pageable interface, clients which intend to use media selected 272 * by the user must create a PageFormat derived from the user's 273 * selections. 274 * If the user cancels the dialog, the attributes will not reflect 275 * any changes made by the user. 276 * @param attributes on input is application supplied attributes, 277 * on output the contents are updated to reflect user choices. 278 * This parameter may not be null. 279 * @return {@code true} if the user does not cancel the dialog; 280 * {@code false} otherwise. 281 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 282 * returns true. 283 * @exception NullPointerException if {@code attributes} parameter 284 * is null. 285 * @see java.awt.GraphicsEnvironment#isHeadless 286 * @since 1.4 287 * 288 */ 289 public boolean printDialog(PrintRequestAttributeSet attributes) 290 throws HeadlessException { 291 292 if (attributes == null) { 293 throw new NullPointerException("attributes"); 294 } 295 return printDialog(); 296 } 297 298 /** 299 * Displays a dialog that allows modification of a 300 * {@code PageFormat} instance. 301 * The {@code page} argument is used to initialize controls 302 * in the page setup dialog. 303 * If the user cancels the dialog then this method returns the 304 * original {@code page} object unmodified. 305 * If the user okays the dialog then this method returns a new 306 * {@code PageFormat} object with the indicated changes. 307 * In either case, the original {@code page} object is 308 * not modified. 309 * @param page the default {@code PageFormat} presented to the 310 * user for modification 311 * @return the original {@code page} object if the dialog 312 * is cancelled; a new {@code PageFormat} object 313 * containing the format indicated by the user if the 314 * dialog is acknowledged. 315 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 316 * returns true. 317 * @see java.awt.GraphicsEnvironment#isHeadless 318 * @since 1.2 319 */ 320 public abstract PageFormat pageDialog(PageFormat page) 321 throws HeadlessException; 322 323 /** 324 * A convenience method which displays a cross-platform page setup dialog. 325 * The choices available will reflect the print service currently 326 * set on this PrinterJob. 327 * <p> 328 * The attributes parameter on input will reflect the client's 329 * required initial selections in the user dialog. Attributes which are 330 * not specified display using the default for the service. On return it 331 * will reflect the user's choices. Selections may be updated by 332 * the implementation to be consistent with the supported values 333 * for the currently selected print service. 334 * <p> 335 * The return value will be a PageFormat equivalent to the 336 * selections in the PrintRequestAttributeSet. 337 * If the user cancels the dialog, the attributes will not reflect 338 * any changes made by the user, and the return value will be null. 339 * @param attributes on input is application supplied attributes, 340 * on output the contents are updated to reflect user choices. 341 * This parameter may not be null. 342 * @return a page format if the user does not cancel the dialog; 343 * {@code null} otherwise. 344 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 345 * returns true. 346 * @exception NullPointerException if {@code attributes} parameter 347 * is null. 348 * @see java.awt.GraphicsEnvironment#isHeadless 349 * @since 1.4 350 * 351 */ 352 public PageFormat pageDialog(PrintRequestAttributeSet attributes) 353 throws HeadlessException { 354 355 if (attributes == null) { 356 throw new NullPointerException("attributes"); 357 } 358 return pageDialog(defaultPage()); 359 } 360 361 /** 362 * Clones the {@code PageFormat} argument and alters the 363 * clone to describe a default page size and orientation. 364 * @param page the {@code PageFormat} to be cloned and altered 365 * @return clone of {@code page}, altered to describe a default 366 * {@code PageFormat}. 367 */ 368 public abstract PageFormat defaultPage(PageFormat page); 369 370 /** 371 * Creates a new {@code PageFormat} instance and 372 * sets it to a default size and orientation. 373 * @return a {@code PageFormat} set to a default size and 374 * orientation. 375 */ 376 public PageFormat defaultPage() { 377 return defaultPage(new PageFormat()); 378 } 379 380 /** 381 * Calculates a {@code PageFormat} with values consistent with those 382 * supported by the current {@code PrintService} for this job 383 * (ie the value returned by {@code getPrintService()}) and media, 384 * printable area and orientation contained in {@code attributes}. 385 * <p> 386 * Calling this method does not update the job. 387 * It is useful for clients that have a set of attributes obtained from 388 * {@code printDialog(PrintRequestAttributeSet attributes)} 389 * and need a PageFormat to print a Pageable object. 390 * @param attributes a set of printing attributes, for example obtained 391 * from calling printDialog. If {@code attributes} is null a default 392 * PageFormat is returned. 393 * @return a {@code PageFormat} whose settings conform with 394 * those of the current service and the specified attributes. 395 * @since 1.6 396 */ 397 public PageFormat getPageFormat(PrintRequestAttributeSet attributes) { 398 399 PrintService service = getPrintService(); 400 PageFormat pf = defaultPage(); 401 402 if (service == null || attributes == null) { 403 return pf; 404 } 405 406 Media media = (Media)attributes.get(Media.class); 407 MediaPrintableArea mpa = 408 (MediaPrintableArea)attributes.get(MediaPrintableArea.class); 409 OrientationRequested orientReq = 410 (OrientationRequested)attributes.get(OrientationRequested.class); 411 412 if (media == null && mpa == null && orientReq == null) { 413 return pf; 414 } 415 Paper paper = pf.getPaper(); 416 417 /* If there's a media but no media printable area, we can try 418 * to retrieve the default value for mpa and use that. 419 */ 420 if (mpa == null && media != null && 421 service.isAttributeCategorySupported(MediaPrintableArea.class)) { 422 Object mpaVals = 423 service.getSupportedAttributeValues(MediaPrintableArea.class, 424 null, attributes); 425 if (mpaVals instanceof MediaPrintableArea[] && 426 ((MediaPrintableArea[])mpaVals).length > 0) { 427 mpa = ((MediaPrintableArea[])mpaVals)[0]; 428 } 429 } 430 431 if (media != null && 432 service.isAttributeValueSupported(media, null, attributes)) { 433 if (media instanceof MediaSizeName) { 434 MediaSizeName msn = (MediaSizeName)media; 435 MediaSize msz = MediaSize.getMediaSizeForName(msn); 436 if (msz != null) { 437 double inch = 72.0; 438 double paperWid = msz.getX(MediaSize.INCH) * inch; 439 double paperHgt = msz.getY(MediaSize.INCH) * inch; 440 paper.setSize(paperWid, paperHgt); 441 if (mpa == null) { 442 paper.setImageableArea(inch, inch, 443 paperWid-2*inch, 444 paperHgt-2*inch); 445 } 446 } 447 } 448 } 449 450 if (mpa != null && 451 service.isAttributeValueSupported(mpa, null, attributes)) { 452 float [] printableArea = 453 mpa.getPrintableArea(MediaPrintableArea.INCH); 454 for (int i=0; i < printableArea.length; i++) { 455 printableArea[i] = printableArea[i]*72.0f; 456 } 457 paper.setImageableArea(printableArea[0], printableArea[1], 458 printableArea[2], printableArea[3]); 459 } 460 461 if (orientReq != null && 462 service.isAttributeValueSupported(orientReq, null, attributes)) { 463 int orient; 464 if (orientReq.equals(OrientationRequested.REVERSE_LANDSCAPE)) { 465 orient = PageFormat.REVERSE_LANDSCAPE; 466 } else if (orientReq.equals(OrientationRequested.LANDSCAPE)) { 467 orient = PageFormat.LANDSCAPE; 468 } else { 469 orient = PageFormat.PORTRAIT; 470 } 471 pf.setOrientation(orient); 472 } 473 474 pf.setPaper(paper); 475 pf = validatePage(pf); 476 return pf; 477 } 478 479 /** 480 * Returns the clone of {@code page} with its settings 481 * adjusted to be compatible with the current printer of this 482 * {@code PrinterJob}. For example, the returned 483 * {@code PageFormat} could have its imageable area 484 * adjusted to fit within the physical area of the paper that 485 * is used by the current printer. 486 * @param page the {@code PageFormat} that is cloned and 487 * whose settings are changed to be compatible with 488 * the current printer 489 * @return a {@code PageFormat} that is cloned from 490 * {@code page} and whose settings are changed 491 * to conform with this {@code PrinterJob}. 492 */ 493 public abstract PageFormat validatePage(PageFormat page); 494 495 /** 496 * Prints a set of pages. 497 * @exception PrinterException an error in the print system 498 * caused the job to be aborted. 499 * @see Book 500 * @see Pageable 501 * @see Printable 502 */ 503 public abstract void print() throws PrinterException; 504 505 /** 506 * Prints a set of pages using the settings in the attribute 507 * set. The default implementation ignores the attribute set. 508 * <p> 509 * Note that some attributes may be set directly on the PrinterJob 510 * by equivalent method calls, (for example), copies: 511 * {@code setCopies(int)}, job name: {@code setJobName(String)} 512 * and specifying media size and orientation though the 513 * {@code PageFormat} object. 514 * <p> 515 * If a supported attribute-value is specified in this attribute set, 516 * it will take precedence over the API settings for this print() 517 * operation only. 518 * The following behaviour is specified for PageFormat: 519 * If a client uses the Printable interface, then the 520 * {@code attributes} parameter to this method is examined 521 * for attributes which specify media (by size), orientation, and 522 * imageable area, and those are used to construct a new PageFormat 523 * which is passed to the Printable object's print() method. 524 * See {@link Printable} for an explanation of the required 525 * behaviour of a Printable to ensure optimal printing via PrinterJob. 526 * For clients of the Pageable interface, the PageFormat will always 527 * be as supplied by that interface, on a per page basis. 528 * <p> 529 * These behaviours allow an application to directly pass the 530 * user settings returned from 531 * {@code printDialog(PrintRequestAttributeSet attributes} to 532 * this print() method. 533 * 534 * @param attributes a set of attributes for the job 535 * @exception PrinterException an error in the print system 536 * caused the job to be aborted. 537 * @see Book 538 * @see Pageable 539 * @see Printable 540 * @since 1.4 541 */ 542 public void print(PrintRequestAttributeSet attributes) 543 throws PrinterException { 544 print(); 545 } 546 547 /** 548 * Sets the number of copies to be printed. 549 * @param copies the number of copies to be printed 550 * @see #getCopies 551 */ 552 public abstract void setCopies(int copies); 553 554 /** 555 * Gets the number of copies to be printed. 556 * @return the number of copies to be printed. 557 * @see #setCopies 558 */ 559 public abstract int getCopies(); 560 561 /** 562 * Gets the name of the printing user. 563 * @return the name of the printing user 564 * @throws SecurityException if a security manager exists and 565 * PropertyPermission - user.name is not given in the policy file 566 */ 567 public abstract String getUserName(); 568 569 /** 570 * Sets the name of the document to be printed. 571 * The document name can not be {@code null}. 572 * @param jobName the name of the document to be printed 573 * @see #getJobName 574 */ 575 public abstract void setJobName(String jobName); 576 577 /** 578 * Gets the name of the document to be printed. 579 * @return the name of the document to be printed. 580 * @see #setJobName 581 */ 582 public abstract String getJobName(); 583 584 /** 585 * Cancels a print job that is in progress. If 586 * {@link #print() print} has been called but has not 587 * returned then this method signals 588 * that the job should be cancelled at the next 589 * chance. If there is no print job in progress then 590 * this call does nothing. 591 */ 592 public abstract void cancel(); 593 594 /** 595 * Returns {@code true} if a print job is 596 * in progress, but is going to be cancelled 597 * at the next opportunity; otherwise returns 598 * {@code false}. 599 * @return {@code true} if the job in progress 600 * is going to be cancelled; {@code false} otherwise. 601 */ 602 public abstract boolean isCancelled(); 603 604 }