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