1 /*
2 * Copyright (c) 2000, 2015, 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.awt.Dimension;
29 import java.awt.Frame;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.PrintJob;
33 import java.awt.JobAttributes;
34 import java.awt.JobAttributes.*;
35 import java.awt.PageAttributes;
36 import java.awt.PageAttributes.*;
37
38 import java.awt.print.PageFormat;
39 import java.awt.print.Paper;
40 import java.awt.print.Printable;
41 import java.awt.print.PrinterException;
42 import java.awt.print.PrinterJob;
43
44 import java.io.File;
45 import java.io.FilePermission;
46 import java.io.IOException;
47
48 import java.net.URI;
49 import java.net.URISyntaxException;
50
51 import java.util.ArrayList;
52 import java.util.Properties;
53
54 import javax.print.PrintService;
55 import javax.print.attribute.HashPrintRequestAttributeSet;
56 import javax.print.attribute.PrintRequestAttributeSet;
57 import javax.print.attribute.ResolutionSyntax;
58 import javax.print.attribute.Size2DSyntax;
59 import javax.print.attribute.standard.Chromaticity;
60 import javax.print.attribute.standard.Copies;
61 import javax.print.attribute.standard.Destination;
62 import javax.print.attribute.standard.DialogTypeSelection;
63 import javax.print.attribute.standard.JobName;
64 import javax.print.attribute.standard.MediaSize;
65 import javax.print.attribute.standard.PrintQuality;
66 import javax.print.attribute.standard.PrinterResolution;
67 import javax.print.attribute.standard.SheetCollate;
68 import javax.print.attribute.standard.Sides;
69 import javax.print.attribute.standard.Media;
70 import javax.print.attribute.standard.OrientationRequested;
71 import javax.print.attribute.standard.MediaSizeName;
72 import javax.print.attribute.standard.PageRanges;
73
74 import sun.misc.ManagedLocalsThread;
75 import sun.print.SunPageSelection;
76 import sun.print.SunMinMaxPage;
77
78 /**
79 * A class which initiates and executes a print job using
80 * the underlying PrinterJob graphics conversions.
81 *
82 * @see java.awt.Toolkit#getPrintJob
83 *
84 */
85 public class PrintJob2D extends PrintJob implements Printable, Runnable {
86
87 private static final MediaType SIZES[] = {
88 MediaType.ISO_4A0, MediaType.ISO_2A0, MediaType.ISO_A0,
89 MediaType.ISO_A1, MediaType.ISO_A2, MediaType.ISO_A3,
90 MediaType.ISO_A4, MediaType.ISO_A5, MediaType.ISO_A6,
91 MediaType.ISO_A7, MediaType.ISO_A8, MediaType.ISO_A9,
92 MediaType.ISO_A10, MediaType.ISO_B0, MediaType.ISO_B1,
93 MediaType.ISO_B2, MediaType.ISO_B3, MediaType.ISO_B4,
94 MediaType.ISO_B5, MediaType.ISO_B6, MediaType.ISO_B7,
95 MediaType.ISO_B8, MediaType.ISO_B9, MediaType.ISO_B10,
96 MediaType.JIS_B0, MediaType.JIS_B1, MediaType.JIS_B2,
97 MediaType.JIS_B3, MediaType.JIS_B4, MediaType.JIS_B5,
98 MediaType.JIS_B6, MediaType.JIS_B7, MediaType.JIS_B8,
99 MediaType.JIS_B9, MediaType.JIS_B10, MediaType.ISO_C0,
100 MediaType.ISO_C1, MediaType.ISO_C2, MediaType.ISO_C3,
101 MediaType.ISO_C4, MediaType.ISO_C5, MediaType.ISO_C6,
102 MediaType.ISO_C7, MediaType.ISO_C8, MediaType.ISO_C9,
103 MediaType.ISO_C10, MediaType.ISO_DESIGNATED_LONG,
104 MediaType.EXECUTIVE, MediaType.FOLIO, MediaType.INVOICE,
105 MediaType.LEDGER, MediaType.NA_LETTER, MediaType.NA_LEGAL,
106 MediaType.QUARTO, MediaType.A, MediaType.B,
107 MediaType.C, MediaType.D, MediaType.E,
108 MediaType.NA_10X15_ENVELOPE, MediaType.NA_10X14_ENVELOPE,
109 MediaType.NA_10X13_ENVELOPE, MediaType.NA_9X12_ENVELOPE,
110 MediaType.NA_9X11_ENVELOPE, MediaType.NA_7X9_ENVELOPE,
111 MediaType.NA_6X9_ENVELOPE, MediaType.NA_NUMBER_9_ENVELOPE,
112 MediaType.NA_NUMBER_10_ENVELOPE, MediaType.NA_NUMBER_11_ENVELOPE,
113 MediaType.NA_NUMBER_12_ENVELOPE, MediaType.NA_NUMBER_14_ENVELOPE,
114 MediaType.INVITE_ENVELOPE, MediaType.ITALY_ENVELOPE,
115 MediaType.MONARCH_ENVELOPE, MediaType.PERSONAL_ENVELOPE
116 };
117
118 /* This array maps the above array to the objects used by the
119 * javax.print APIs
120 */
121 private static final MediaSizeName JAVAXSIZES[] = {
122 null, null, MediaSizeName.ISO_A0,
123 MediaSizeName.ISO_A1, MediaSizeName.ISO_A2, MediaSizeName.ISO_A3,
124 MediaSizeName.ISO_A4, MediaSizeName.ISO_A5, MediaSizeName.ISO_A6,
125 MediaSizeName.ISO_A7, MediaSizeName.ISO_A8, MediaSizeName.ISO_A9,
126 MediaSizeName.ISO_A10, MediaSizeName.ISO_B0, MediaSizeName.ISO_B1,
127 MediaSizeName.ISO_B2, MediaSizeName.ISO_B3, MediaSizeName.ISO_B4,
128 MediaSizeName.ISO_B5, MediaSizeName.ISO_B6, MediaSizeName.ISO_B7,
129 MediaSizeName.ISO_B8, MediaSizeName.ISO_B9, MediaSizeName.ISO_B10,
130 MediaSizeName.JIS_B0, MediaSizeName.JIS_B1, MediaSizeName.JIS_B2,
131 MediaSizeName.JIS_B3, MediaSizeName.JIS_B4, MediaSizeName.JIS_B5,
132 MediaSizeName.JIS_B6, MediaSizeName.JIS_B7, MediaSizeName.JIS_B8,
133 MediaSizeName.JIS_B9, MediaSizeName.JIS_B10, MediaSizeName.ISO_C0,
134 MediaSizeName.ISO_C1, MediaSizeName.ISO_C2, MediaSizeName.ISO_C3,
135 MediaSizeName.ISO_C4, MediaSizeName.ISO_C5, MediaSizeName.ISO_C6,
136 null, null, null, null,
137 MediaSizeName.ISO_DESIGNATED_LONG, MediaSizeName.EXECUTIVE,
138 MediaSizeName.FOLIO, MediaSizeName.INVOICE, MediaSizeName.LEDGER,
139 MediaSizeName.NA_LETTER, MediaSizeName.NA_LEGAL,
140 MediaSizeName.QUARTO, MediaSizeName.A, MediaSizeName.B,
141 MediaSizeName.C, MediaSizeName.D, MediaSizeName.E,
142 MediaSizeName.NA_10X15_ENVELOPE, MediaSizeName.NA_10X14_ENVELOPE,
143 MediaSizeName.NA_10X13_ENVELOPE, MediaSizeName.NA_9X12_ENVELOPE,
144 MediaSizeName.NA_9X11_ENVELOPE, MediaSizeName.NA_7X9_ENVELOPE,
145 MediaSizeName.NA_6X9_ENVELOPE,
146 MediaSizeName.NA_NUMBER_9_ENVELOPE,
147 MediaSizeName.NA_NUMBER_10_ENVELOPE,
148 MediaSizeName.NA_NUMBER_11_ENVELOPE,
149 MediaSizeName.NA_NUMBER_12_ENVELOPE,
150 MediaSizeName.NA_NUMBER_14_ENVELOPE,
151 null, MediaSizeName.ITALY_ENVELOPE,
152 MediaSizeName.MONARCH_ENVELOPE, MediaSizeName.PERSONAL_ENVELOPE,
153 };
154
155
156 // widths and lengths in PostScript points (1/72 in.)
157 private static final int WIDTHS[] = {
158 /*iso-4a0*/ 4768, /*iso-2a0*/ 3370, /*iso-a0*/ 2384, /*iso-a1*/ 1684,
159 /*iso-a2*/ 1191, /*iso-a3*/ 842, /*iso-a4*/ 595, /*iso-a5*/ 420,
160 /*iso-a6*/ 298, /*iso-a7*/ 210, /*iso-a8*/ 147, /*iso-a9*/ 105,
161 /*iso-a10*/ 74, /*iso-b0*/ 2835, /*iso-b1*/ 2004, /*iso-b2*/ 1417,
162 /*iso-b3*/ 1001, /*iso-b4*/ 709, /*iso-b5*/ 499, /*iso-b6*/ 354,
163 /*iso-b7*/ 249, /*iso-b8*/ 176, /*iso-b9*/ 125, /*iso-b10*/ 88,
164 /*jis-b0*/ 2920, /*jis-b1*/ 2064, /*jis-b2*/ 1460, /*jis-b3*/ 1032,
165 /*jis-b4*/ 729, /*jis-b5*/ 516, /*jis-b6*/ 363, /*jis-b7*/ 258,
166 /*jis-b8*/ 181, /*jis-b9*/ 128, /*jis-b10*/ 91, /*iso-c0*/ 2599,
167 /*iso-c1*/ 1837, /*iso-c2*/ 1298, /*iso-c3*/ 918, /*iso-c4*/ 649,
168 /*iso-c5*/ 459, /*iso-c6*/ 323, /*iso-c7*/ 230, /*iso-c8*/ 162,
169 /*iso-c9*/ 113, /*iso-c10*/ 79, /*iso-designated-long*/ 312,
170 /*executive*/ 522, /*folio*/ 612, /*invoice*/ 396, /*ledger*/ 792,
171 /*na-letter*/ 612, /*na-legal*/ 612, /*quarto*/ 609, /*a*/ 612,
172 /*b*/ 792, /*c*/ 1224, /*d*/ 1584, /*e*/ 2448,
173 /*na-10x15-envelope*/ 720, /*na-10x14-envelope*/ 720,
174 /*na-10x13-envelope*/ 720, /*na-9x12-envelope*/ 648,
175 /*na-9x11-envelope*/ 648, /*na-7x9-envelope*/ 504,
176 /*na-6x9-envelope*/ 432, /*na-number-9-envelope*/ 279,
177 /*na-number-10-envelope*/ 297, /*na-number-11-envelope*/ 324,
178 /*na-number-12-envelope*/ 342, /*na-number-14-envelope*/ 360,
179 /*invite-envelope*/ 624, /*italy-envelope*/ 312,
180 /*monarch-envelope*/ 279, /*personal-envelope*/ 261
181 };
182 private static final int LENGTHS[] = {
183 /*iso-4a0*/ 6741, /*iso-2a0*/ 4768, /*iso-a0*/ 3370, /*iso-a1*/ 2384,
184 /*iso-a2*/ 1684, /*iso-a3*/ 1191, /*iso-a4*/ 842, /*iso-a5*/ 595,
185 /*iso-a6*/ 420, /*iso-a7*/ 298, /*iso-a8*/ 210, /*iso-a9*/ 147,
186 /*iso-a10*/ 105, /*iso-b0*/ 4008, /*iso-b1*/ 2835, /*iso-b2*/ 2004,
187 /*iso-b3*/ 1417, /*iso-b4*/ 1001, /*iso-b5*/ 729, /*iso-b6*/ 499,
188 /*iso-b7*/ 354, /*iso-b8*/ 249, /*iso-b9*/ 176, /*iso-b10*/ 125,
189 /*jis-b0*/ 4127, /*jis-b1*/ 2920, /*jis-b2*/ 2064, /*jis-b3*/ 1460,
190 /*jis-b4*/ 1032, /*jis-b5*/ 729, /*jis-b6*/ 516, /*jis-b7*/ 363,
191 /*jis-b8*/ 258, /*jis-b9*/ 181, /*jis-b10*/ 128, /*iso-c0*/ 3677,
192 /*iso-c1*/ 2599, /*iso-c2*/ 1837, /*iso-c3*/ 1298, /*iso-c4*/ 918,
193 /*iso-c5*/ 649, /*iso-c6*/ 459, /*iso-c7*/ 323, /*iso-c8*/ 230,
194 /*iso-c9*/ 162, /*iso-c10*/ 113, /*iso-designated-long*/ 624,
195 /*executive*/ 756, /*folio*/ 936, /*invoice*/ 612, /*ledger*/ 1224,
196 /*na-letter*/ 792, /*na-legal*/ 1008, /*quarto*/ 780, /*a*/ 792,
197 /*b*/ 1224, /*c*/ 1584, /*d*/ 2448, /*e*/ 3168,
198 /*na-10x15-envelope*/ 1080, /*na-10x14-envelope*/ 1008,
199 /*na-10x13-envelope*/ 936, /*na-9x12-envelope*/ 864,
200 /*na-9x11-envelope*/ 792, /*na-7x9-envelope*/ 648,
201 /*na-6x9-envelope*/ 648, /*na-number-9-envelope*/ 639,
202 /*na-number-10-envelope*/ 684, /*na-number-11-envelope*/ 747,
203 /*na-number-12-envelope*/ 792, /*na-number-14-envelope*/ 828,
204 /*invite-envelope*/ 624, /*italy-envelope*/ 652,
205 /*monarch-envelope*/ 540, /*personal-envelope*/ 468
206 };
207
208
209 private Frame frame;
210 private String docTitle = "";
211 private JobAttributes jobAttributes;
212 private PageAttributes pageAttributes;
213 private PrintRequestAttributeSet attributes;
214
215 /*
216 * Displays the native or cross-platform dialog and allows the
217 * user to update job & page attributes
218 */
219
220 /**
221 * The PrinterJob being uses to implement the PrintJob.
222 */
223 private PrinterJob printerJob;
224
225 /**
226 * The size of the page being used for the PrintJob.
227 */
228 private PageFormat pageFormat;
229
230 /**
231 * The PrinterJob and the application run on different
232 * threads and communicate through a pair of message
233 * queues. This queue is the list of Graphics that
234 * the PrinterJob has requested rendering for, but
235 * for which the application has not yet called getGraphics().
236 * In practice the length of this message queue is always
237 * 0 or 1.
238 */
239 private MessageQ graphicsToBeDrawn = new MessageQ("tobedrawn");
240
241 /**
242 * Used to communicate between the application's thread
243 * and the PrinterJob's thread this message queue holds
244 * the list of Graphics into which the application has
245 * finished drawing, but that have not yet been returned
246 * to the PrinterJob thread. Again, in practice, the
247 * length of this message queue is always 0 or 1.
248 */
249 private MessageQ graphicsDrawn = new MessageQ("drawn");
250
251 /**
252 * The last Graphics returned to the application via
253 * getGraphics. This is the Graphics into which the
254 * application is currently drawing.
255 */
256 private Graphics2D currentGraphics;
257
258 /**
259 * The zero based index of the page currently being rendered
260 * by the application.
261 */
262 private int pageIndex = -1;
263
264 // The following Strings are maintained for backward-compatibility with
265 // Properties based print control.
266 private static final String DEST_PROP = "awt.print.destination";
267 private static final String PRINTER = "printer";
268 private static final String FILE = "file";
269
270 private static final String PRINTER_PROP = "awt.print.printer";
271
272 private static final String FILENAME_PROP = "awt.print.fileName";
273
274 private static final String NUMCOPIES_PROP = "awt.print.numCopies";
275
276 private static final String OPTIONS_PROP = "awt.print.options";
277
278 private static final String ORIENT_PROP = "awt.print.orientation";
279 private static final String PORTRAIT = "portrait";
280 private static final String LANDSCAPE = "landscape";
281
282 private static final String PAPERSIZE_PROP = "awt.print.paperSize";
283 private static final String LETTER = "letter";
284 private static final String LEGAL = "legal";
285 private static final String EXECUTIVE = "executive";
286 private static final String A4 = "a4";
287
288 private Properties props;
289
290 private String options = ""; // REMIND: needs implementation
291
292 /**
293 * The thread on which PrinterJob is running.
294 * This is different than the applications thread.
295 */
296 private Thread printerJobThread;
297
298 public PrintJob2D(Frame frame, String doctitle,
299 final Properties props) {
300 this.props = props;
301 this.jobAttributes = new JobAttributes();
302 this.pageAttributes = new PageAttributes();
303 translateInputProps();
304 initPrintJob2D(frame, doctitle,
305 this.jobAttributes, this.pageAttributes);
306 }
307
308 public PrintJob2D(Frame frame, String doctitle,
309 JobAttributes jobAttributes,
310 PageAttributes pageAttributes) {
311 initPrintJob2D(frame, doctitle, jobAttributes, pageAttributes);
312 }
313
314 private void initPrintJob2D(Frame frame, String doctitle,
315 JobAttributes jobAttributes,
316 PageAttributes pageAttributes) {
317
318 SecurityManager security = System.getSecurityManager();
319 if (security != null) {
320 security.checkPrintJobAccess();
321 }
322
323 if (frame == null &&
324 (jobAttributes == null ||
325 jobAttributes.getDialog() == DialogType.NATIVE)) {
326 throw new NullPointerException("Frame must not be null");
327 }
328 this.frame = frame;
329
330 this.docTitle = (doctitle == null) ? "" : doctitle;
331 this.jobAttributes = (jobAttributes != null)
332 ? jobAttributes : new JobAttributes();
333 this.pageAttributes = (pageAttributes != null)
334 ? pageAttributes : new PageAttributes();
335
336 // Currently, we always reduce page ranges to xxx or xxx-xxx
337 int[][] pageRanges = this.jobAttributes.getPageRanges();
338 int first = pageRanges[0][0];
339 int last = pageRanges[pageRanges.length - 1][1];
340 this.jobAttributes.setPageRanges(new int[][] {
341 new int[] { first, last }
342 });
343 this.jobAttributes.setToPage(last);
344 this.jobAttributes.setFromPage(first);
345
346
347 // Verify that the cross feed and feed resolutions are the same
348 int[] res = this.pageAttributes.getPrinterResolution();
349 if (res[0] != res[1]) {
350 throw new IllegalArgumentException("Differing cross feed and feed"+
351 " resolutions not supported.");
352 }
353
354 // Verify that the app has access to the file system
355 DestinationType dest= this.jobAttributes.getDestination();
356 if (dest == DestinationType.FILE) {
357 throwPrintToFile();
358
359 // check if given filename is valid
360 String destStr = jobAttributes.getFileName();
361 if ((destStr != null) &&
362 (jobAttributes.getDialog() == JobAttributes.DialogType.NONE)) {
363
364 File f = new File(destStr);
365 try {
366 // check if this is a new file and if filename chars are valid
367 // createNewFile returns false if file exists
368 if (f.createNewFile()) {
369 f.delete();
370 }
371 } catch (IOException ioe) {
372 throw new IllegalArgumentException("Cannot write to file:"+
373 destStr);
374 } catch (SecurityException se) {
375 //There is already file read/write access so at this point
376 // only delete access is denied. Just ignore it because in
377 // most cases the file created in createNewFile gets overwritten
378 // anyway.
379 }
380
381 File pFile = f.getParentFile();
382 if ((f.exists() &&
383 (!f.isFile() || !f.canWrite())) ||
384 ((pFile != null) &&
385 (!pFile.exists() || (pFile.exists() && !pFile.canWrite())))) {
386 throw new IllegalArgumentException("Cannot write to file:"+
387 destStr);
388 }
389 }
390 }
391 }
392
393 public boolean printDialog() {
394
395 boolean proceedWithPrint = false;
396
397 printerJob = PrinterJob.getPrinterJob();
398 if (printerJob == null) {
399 return false;
400 }
401 DialogType d = this.jobAttributes.getDialog();
402 PrintService pServ = printerJob.getPrintService();
403 if ((pServ == null) && (d == DialogType.NONE)){
404 return false;
405 }
406 copyAttributes(pServ);
407
408 DefaultSelectionType select =
409 this.jobAttributes.getDefaultSelection();
410 if (select == DefaultSelectionType.RANGE) {
411 attributes.add(SunPageSelection.RANGE);
412 } else if (select == DefaultSelectionType.SELECTION) {
413 attributes.add(SunPageSelection.SELECTION);
414 } else {
415 attributes.add(SunPageSelection.ALL);
416 }
417
418 if (frame != null) {
419 attributes.add(new DialogOwner(frame));
420 }
421
422 if ( d == DialogType.NONE) {
423 proceedWithPrint = true;
424 } else {
425 if (d == DialogType.NATIVE) {
426 attributes.add(DialogTypeSelection.NATIVE);
427 } else { // (d == DialogType.COMMON)
428 attributes.add(DialogTypeSelection.COMMON);
429 }
430 if (proceedWithPrint = printerJob.printDialog(attributes)) {
431 if (pServ == null) {
432 // Windows gives an option to install a service
433 // when it detects there are no printers so
434 // we make sure we get the updated print service.
435 pServ = printerJob.getPrintService();
436 if (pServ == null) {
437 return false;
438 }
439 }
440 updateAttributes();
441 translateOutputProps();
442 }
443 }
444
445 if (proceedWithPrint) {
446
447 JobName jname = (JobName)attributes.get(JobName.class);
448 if (jname != null) {
449 printerJob.setJobName(jname.toString());
450 }
451
452 pageFormat = new PageFormat();
453
454 Media media = (Media)attributes.get(Media.class);
455 MediaSize mediaSize = null;
456 if (media != null && media instanceof MediaSizeName) {
457 mediaSize = MediaSize.getMediaSizeForName((MediaSizeName)media);
458 }
459
460 Paper p = pageFormat.getPaper();
461 if (mediaSize != null) {
462 p.setSize(mediaSize.getX(MediaSize.INCH)*72.0,
463 mediaSize.getY(MediaSize.INCH)*72.0);
464 }
465
466 if (pageAttributes.getOrigin()==OriginType.PRINTABLE) {
467 // AWT uses 1/4" borders by default
468 p.setImageableArea(18.0, 18.0,
469 p.getWidth()-36.0,
470 p.getHeight()-36.0);
471 } else {
472 p.setImageableArea(0.0,0.0,p.getWidth(),p.getHeight());
473 }
474
475 pageFormat.setPaper(p);
476
477 OrientationRequested orient =
478 (OrientationRequested)attributes.get(OrientationRequested.class);
479 if (orient!= null &&
480 orient == OrientationRequested.REVERSE_LANDSCAPE) {
481 pageFormat.setOrientation(PageFormat.REVERSE_LANDSCAPE);
482 } else if (orient == OrientationRequested.LANDSCAPE) {
483 pageFormat.setOrientation(PageFormat.LANDSCAPE);
484 } else {
485 pageFormat.setOrientation(PageFormat.PORTRAIT);
486 }
487
488 printerJob.setPrintable(this, pageFormat);
489
490 }
491
492 return proceedWithPrint;
493 }
494
495 private void updateAttributes() {
496 Copies c = (Copies)attributes.get(Copies.class);
497 jobAttributes.setCopies(c.getValue());
498
499 SunPageSelection sel =
500 (SunPageSelection)attributes.get(SunPageSelection.class);
501 if (sel == SunPageSelection.RANGE) {
502 jobAttributes.setDefaultSelection(DefaultSelectionType.RANGE);
503 } else if (sel == SunPageSelection.SELECTION) {
504 jobAttributes.setDefaultSelection(DefaultSelectionType.SELECTION);
505 } else {
506 jobAttributes.setDefaultSelection(DefaultSelectionType.ALL);
507 }
508
509 Destination dest = (Destination)attributes.get(Destination.class);
510 if (dest != null) {
511 jobAttributes.setDestination(DestinationType.FILE);
512 jobAttributes.setFileName(dest.getURI().getPath());
513 } else {
514 jobAttributes.setDestination(DestinationType.PRINTER);
515 }
516
517 PrintService serv = printerJob.getPrintService();
518 if (serv != null) {
519 jobAttributes.setPrinter(serv.getName());
520 }
521
522 PageRanges range = (PageRanges)attributes.get(PageRanges.class);
523 int[][] members = range.getMembers();
524 jobAttributes.setPageRanges(members);
525
526 SheetCollate collation =
527 (SheetCollate)attributes.get(SheetCollate.class);
528 if (collation == SheetCollate.COLLATED) {
529 jobAttributes.setMultipleDocumentHandling(
530 MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_COLLATED_COPIES);
531 } else {
532 jobAttributes.setMultipleDocumentHandling(
533 MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_UNCOLLATED_COPIES);
534 }
535
536 Sides sides = (Sides)attributes.get(Sides.class);
537 if (sides == Sides.TWO_SIDED_LONG_EDGE) {
538 jobAttributes.setSides(SidesType.TWO_SIDED_LONG_EDGE);
539 } else if (sides == Sides.TWO_SIDED_SHORT_EDGE) {
540 jobAttributes.setSides(SidesType.TWO_SIDED_SHORT_EDGE);
541 } else {
542 jobAttributes.setSides(SidesType.ONE_SIDED);
543 }
544
545 // PageAttributes
546
547 Chromaticity color =
548 (Chromaticity)attributes.get(Chromaticity.class);
549 if (color == Chromaticity.COLOR) {
550 pageAttributes.setColor(ColorType.COLOR);
551 } else {
552 pageAttributes.setColor(ColorType.MONOCHROME);
553 }
554
555 OrientationRequested orient =
556 (OrientationRequested)attributes.get(OrientationRequested.class);
557 if (orient == OrientationRequested.LANDSCAPE) {
558 pageAttributes.setOrientationRequested(
559 OrientationRequestedType.LANDSCAPE);
560 } else {
561 pageAttributes.setOrientationRequested(
562 OrientationRequestedType.PORTRAIT);
563 }
564
565 PrintQuality qual = (PrintQuality)attributes.get(PrintQuality.class);
566 if (qual == PrintQuality.DRAFT) {
567 pageAttributes.setPrintQuality(PrintQualityType.DRAFT);
568 } else if (qual == PrintQuality.HIGH) {
569 pageAttributes.setPrintQuality(PrintQualityType.HIGH);
570 } else { // NORMAL
571 pageAttributes.setPrintQuality(PrintQualityType.NORMAL);
572 }
573
574 Media msn = (Media)attributes.get(Media.class);
575 if (msn != null && msn instanceof MediaSizeName) {
576 MediaType mType = unMapMedia((MediaSizeName)msn);
577
578 if (mType != null) {
579 pageAttributes.setMedia(mType);
580 }
581 }
582 debugPrintAttributes(false, false);
583 }
584
585 private void debugPrintAttributes(boolean ja, boolean pa ) {
586 if (ja) {
587 System.out.println("new Attributes\ncopies = "+
588 jobAttributes.getCopies()+
589 "\nselection = "+
590 jobAttributes.getDefaultSelection()+
591 "\ndest "+jobAttributes.getDestination()+
592 "\nfile "+jobAttributes.getFileName()+
593 "\nfromPage "+jobAttributes.getFromPage()+
594 "\ntoPage "+jobAttributes.getToPage()+
595 "\ncollation "+
596 jobAttributes.getMultipleDocumentHandling()+
597 "\nPrinter "+jobAttributes.getPrinter()+
598 "\nSides2 "+jobAttributes.getSides()
599 );
600 }
601
602 if (pa) {
603 System.out.println("new Attributes\ncolor = "+
604 pageAttributes.getColor()+
605 "\norientation = "+
606 pageAttributes.getOrientationRequested()+
607 "\nquality "+pageAttributes.getPrintQuality()+
608 "\nMedia2 "+pageAttributes.getMedia()
609 );
610 }
611 }
612
613
614 /* From JobAttributes we will copy job name and duplex printing
615 * and destination.
616 * The majority of the rest of the attributes are reflected
617 * attributes.
618 *
619 * From PageAttributes we copy color, media size, orientation,
620 * origin type, resolution and print quality.
621 * We use the media, orientation in creating the page format, and
622 * the origin type to set its imageable area.
623 *
624 * REMIND: Interpretation of resolution, additional media sizes.
625 */
626 private void copyAttributes(PrintService printServ) {
627
628 attributes = new HashPrintRequestAttributeSet();
629 attributes.add(new JobName(docTitle, null));
630 PrintService pServ = printServ;
631
632 String printerName = jobAttributes.getPrinter();
633 if (printerName != null && printerName != ""
634 && pServ != null && !printerName.equals(pServ.getName())) {
635
636 // Search for the given printerName in the list of PrintServices
637 PrintService []services = PrinterJob.lookupPrintServices();
638 try {
639 for (int i=0; i<services.length; i++) {
640 if (printerName.equals(services[i].getName())) {
641 printerJob.setPrintService(services[i]);
642 pServ = services[i];
643 break;
644 }
645 }
646 } catch (PrinterException pe) {
647 }
648 }
649
650 DestinationType dest = jobAttributes.getDestination();
651 if (dest == DestinationType.FILE && pServ != null &&
652 pServ.isAttributeCategorySupported(Destination.class)) {
653
654 String fileName = jobAttributes.getFileName();
655
656 Destination defaultDest;
657 if (fileName == null && (defaultDest = (Destination)pServ.
658 getDefaultAttributeValue(Destination.class)) != null) {
659 attributes.add(defaultDest);
660 } else {
661 URI uri = null;
662 try {
663 if (fileName != null) {
664 if (fileName.equals("")) {
665 fileName = ".";
666 }
667 } else {
668 // defaultDest should not be null. The following code
669 // is only added to safeguard against a possible
670 // buggy implementation of a PrintService having a
671 // null default Destination.
672 fileName = "out.prn";
673 }
674 uri = (new File(fileName)).toURI();
675 } catch (SecurityException se) {
676 try {
677 // '\\' file separator is illegal character in opaque
678 // part and causes URISyntaxException, so we replace
679 // it with '/'
680 fileName = fileName.replace('\\', '/');
681 uri = new URI("file:"+fileName);
682 } catch (URISyntaxException e) {
683 }
684 }
685 if (uri != null) {
686 attributes.add(new Destination(uri));
687 }
688 }
689 }
690 attributes.add(new SunMinMaxPage(jobAttributes.getMinPage(),
691 jobAttributes.getMaxPage()));
692 SidesType sType = jobAttributes.getSides();
693 if (sType == SidesType.TWO_SIDED_LONG_EDGE) {
694 attributes.add(Sides.TWO_SIDED_LONG_EDGE);
695 } else if (sType == SidesType.TWO_SIDED_SHORT_EDGE) {
696 attributes.add(Sides.TWO_SIDED_SHORT_EDGE);
697 } else if (sType == SidesType.ONE_SIDED) {
698 attributes.add(Sides.ONE_SIDED);
699 }
700
701 MultipleDocumentHandlingType hType =
702 jobAttributes.getMultipleDocumentHandling();
703 if (hType ==
704 MultipleDocumentHandlingType.SEPARATE_DOCUMENTS_COLLATED_COPIES) {
705 attributes.add(SheetCollate.COLLATED);
706 } else {
707 attributes.add(SheetCollate.UNCOLLATED);
708 }
709
710 attributes.add(new Copies(jobAttributes.getCopies()));
711
712 attributes.add(new PageRanges(jobAttributes.getFromPage(),
713 jobAttributes.getToPage()));
714
715 if (pageAttributes.getColor() == ColorType.COLOR) {
716 attributes.add(Chromaticity.COLOR);
717 } else {
718 attributes.add(Chromaticity.MONOCHROME);
719 }
720
721 pageFormat = printerJob.defaultPage();
722 if (pageAttributes.getOrientationRequested() ==
723 OrientationRequestedType.LANDSCAPE) {
724 pageFormat.setOrientation(PageFormat.LANDSCAPE);
725 attributes.add(OrientationRequested.LANDSCAPE);
726 } else {
727 pageFormat.setOrientation(PageFormat.PORTRAIT);
728 attributes.add(OrientationRequested.PORTRAIT);
729 }
730
731 MediaType media = pageAttributes.getMedia();
732 MediaSizeName msn = mapMedia(media);
733 if (msn != null) {
734 attributes.add(msn);
735 }
736
737 PrintQualityType qType =
738 pageAttributes.getPrintQuality();
739 if (qType == PrintQualityType.DRAFT) {
740 attributes.add(PrintQuality.DRAFT);
741 } else if (qType == PrintQualityType.NORMAL) {
742 attributes.add(PrintQuality.NORMAL);
743 } else if (qType == PrintQualityType.HIGH) {
744 attributes.add(PrintQuality.HIGH);
745 }
746 }
747
748 /**
749 * Gets a Graphics object that will draw to the next page.
750 * The page is sent to the printer when the graphics
751 * object is disposed. This graphics object will also implement
752 * the PrintGraphics interface.
753 * @see java.awt.PrintGraphics
754 */
755 public Graphics getGraphics() {
756
757 Graphics printGraphics = null;
758
759 synchronized (this) {
760 ++pageIndex;
761
762 // Thread should not be created after end has been called.
763 // One way to detect this is if any of the graphics queue
764 // has been closed.
765 if (pageIndex == 0 && !graphicsToBeDrawn.isClosed()) {
766
767 /* We start a thread on which the PrinterJob will run.
768 * The PrinterJob will ask for pages on that thread
769 * and will use a message queue to fulfill the application's
770 * requests for a Graphics on the application's
771 * thread.
772 */
773
774 startPrinterJobThread();
775
776 }
777 notify();
778 }
779
780 /* If the application has already been handed back
781 * a graphics then we need to put that graphics into
782 * the drawn queue so that the PrinterJob thread can
783 * return to the print system.
784 */
785 if (currentGraphics != null) {
786 graphicsDrawn.append(currentGraphics);
787 currentGraphics = null;
788 }
789
790 /* We'll block here until a new graphics becomes
791 * available.
792 */
793
794 currentGraphics = graphicsToBeDrawn.pop();
795
796 if (currentGraphics instanceof PeekGraphics) {
797 ( (PeekGraphics) currentGraphics).setAWTDrawingOnly();
798 graphicsDrawn.append(currentGraphics);
799 currentGraphics = graphicsToBeDrawn.pop();
800 }
801
802
803 if (currentGraphics != null) {
804
805 /* In the PrintJob API, the origin is at the upper-
806 * left of the imageable area when using the new "printable"
807 * origin attribute, otherwise its the physical origin (for
808 * backwards compatibility. We emulate this by createing
809 * a PageFormat which matches and then performing the
810 * translate to the origin. This is a no-op if physical
811 * origin is specified.
812 */
813 currentGraphics.translate(pageFormat.getImageableX(),
814 pageFormat.getImageableY());
815
816 /* Scale to accommodate AWT's notion of printer resolution */
817 double awtScale = 72.0/getPageResolutionInternal();
818 currentGraphics.scale(awtScale, awtScale);
819
820 /* The caller wants a Graphics instance but we do
821 * not want them to make 2D calls. We can't hand
822 * back a Graphics2D. The returned Graphics also
823 * needs to implement PrintGraphics, so we wrap
824 * the Graphics2D instance. The PrintJob API has
825 * the application dispose of the Graphics so
826 * we create a copy of the one returned by PrinterJob.
827 */
828 printGraphics = new ProxyPrintGraphics(currentGraphics.create(),
829 this);
830
831 }
832
833 return printGraphics;
834 }
835
836 /**
837 * Returns the dimensions of the page in pixels.
838 * The resolution of the page is chosen so that it
839 * is similar to the screen resolution.
840 * Except (since 1.3) when the application specifies a resolution.
841 * In that case it is scaled accordingly.
842 */
843 public Dimension getPageDimension() {
844 double wid, hgt, scale;
845 if (pageAttributes != null &&
846 pageAttributes.getOrigin()==OriginType.PRINTABLE) {
847 wid = pageFormat.getImageableWidth();
848 hgt = pageFormat.getImageableHeight();
849 } else {
850 wid = pageFormat.getWidth();
851 hgt = pageFormat.getHeight();
852 }
853 scale = getPageResolutionInternal() / 72.0;
854 return new Dimension((int)(wid * scale), (int)(hgt * scale));
855 }
856
857 private double getPageResolutionInternal() {
858 if (pageAttributes != null) {
859 int []res = pageAttributes.getPrinterResolution();
860 if (res[2] == 3) {
861 return res[0];
862 } else /* if (res[2] == 4) */ {
863 return (res[0] * 2.54);
864 }
865 } else {
866 return 72.0;
867 }
868 }
869
870 /**
871 * Returns the resolution of the page in pixels per inch.
872 * Note that this doesn't have to correspond to the physical
873 * resolution of the printer.
874 */
875 public int getPageResolution() {
876 return (int)getPageResolutionInternal();
877 }
878
879 /**
880 * Returns true if the last page will be printed first.
881 */
882 public boolean lastPageFirst() {
883 return false;
884 }
885
886 /**
887 * Ends the print job and does any necessary cleanup.
888 */
889 public synchronized void end() {
890
891 /* Prevent the PrinterJob thread from appending any more
892 * graphics to the to-be-drawn queue
893 */
894 graphicsToBeDrawn.close();
895
896 /* If we have a currentGraphics it was the last one returned to the
897 * PrintJob client. Append it to the drawn queue so that print()
898 * will return allowing the page to be flushed.
899 * This really ought to happen in dispose() but for whatever reason
900 * that isn't how the old PrintJob worked even though its spec
901 * said dispose() flushed the page.
902 */
903 if (currentGraphics != null) {
904 graphicsDrawn.append(currentGraphics);
905 }
906 graphicsDrawn.closeWhenEmpty();
907
908 /* Wait for the PrinterJob.print() thread to terminate, ensuring
909 * that RasterPrinterJob has made its end doc call, and resources
910 * are released, files closed etc.
911 */
912 if( printerJobThread != null && printerJobThread.isAlive() ){
913 try {
914 printerJobThread.join();
915 } catch (InterruptedException e) {
916 }
917 }
918 }
919
920 /**
921 * Ends this print job once it is no longer referenced.
922 * @see #end
923 */
924 public void finalize() {
925 end();
926 }
927
928 /**
929 * Prints the page at the specified index into the specified
930 * {@link Graphics} context in the specified
931 * format. A {@code PrinterJob} calls the
932 * {@code Printable} interface to request that a page be
933 * rendered into the context specified by
934 * {@code graphics}. The format of the page to be drawn is
935 * specified by {@code pageFormat}. The zero based index
936 * of the requested page is specified by {@code pageIndex}.
937 * If the requested page does not exist then this method returns
938 * NO_SUCH_PAGE; otherwise PAGE_EXISTS is returned.
939 * The {@code Graphics} class or subclass implements the
940 * {@link java.awt.PrintGraphics} interface to provide additional
941 * information. If the {@code Printable} object
942 * aborts the print job then it throws a {@link PrinterException}.
943 * @param graphics the context into which the page is drawn
944 * @param pageFormat the size and orientation of the page being drawn
945 * @param pageIndex the zero based index of the page to be drawn
946 * @return PAGE_EXISTS if the page is rendered successfully
947 * or NO_SUCH_PAGE if {@code pageIndex} specifies a
948 * non-existent page.
949 * @exception java.awt.print.PrinterException
950 * thrown when the print job is terminated.
951 */
952 public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
953 throws PrinterException {
954
955 int result;
956
957 /* This method will be called by the PrinterJob on a thread other
958 * that the application's thread. We hold on to the graphics
959 * until we can rendevous with the application's thread and
960 * hand over the graphics. The application then does all the
961 * drawing. When the application is done drawing we rendevous
962 * again with the PrinterJob thread and release the Graphics
963 * so that it knows we are done.
964 */
965
966 /* Add the graphics to the message queue of graphics to
967 * be rendered. This is really a one slot queue. The
968 * application's thread will come along and remove the
969 * graphics from the queue when the app asks for a graphics.
970 */
971 graphicsToBeDrawn.append( (Graphics2D) graphics);
972
973 /* We now wait for the app's thread to finish drawing on
974 * the Graphics. This thread will sleep until the application
975 * release the graphics by placing it in the graphics drawn
976 * message queue. If the application signals that it is
977 * finished drawing the entire document then we'll get null
978 * returned when we try and pop a finished graphic.
979 */
980 if (graphicsDrawn.pop() != null) {
981 result = PAGE_EXISTS;
982 } else {
983 result = NO_SUCH_PAGE;
984 }
985
986 return result;
987 }
988
989 private void startPrinterJobThread() {
990 printerJobThread = new ManagedLocalsThread(this, "printerJobThread");
991 printerJobThread.start();
992 }
993
994
995 public void run() {
996
997 try {
998 attributes.remove(PageRanges.class);
999 printerJob.print(attributes);
1000 } catch (PrinterException e) {
1001 //REMIND: need to store this away and not rethrow it.
1002 }
1003
1004 /* Close the message queues so that nobody is stuck
1005 * waiting for one.
1006 */
1007 graphicsToBeDrawn.closeWhenEmpty();
1008 graphicsDrawn.close();
1009 }
1010
1011 private class MessageQ {
1012
1013 private String qid="noname";
1014
1015 private ArrayList<Graphics2D> queue = new ArrayList<>();
1016
1017 MessageQ(String id) {
1018 qid = id;
1019 }
1020
1021 synchronized void closeWhenEmpty() {
1022
1023 while (queue != null && queue.size() > 0) {
1024 try {
1025 wait(1000);
1026 } catch (InterruptedException e) {
1027 // do nothing.
1028 }
1029 }
1030
1031 queue = null;
1032 notifyAll();
1033 }
1034
1035 synchronized void close() {
1036 queue = null;
1037 notifyAll();
1038 }
1039
1040 synchronized boolean append(Graphics2D g) {
1041
1042 boolean queued = false;
1043
1044 if (queue != null) {
1045 queue.add(g);
1046 queued = true;
1047 notify();
1048 }
1049
1050 return queued;
1051 }
1052
1053 synchronized Graphics2D pop() {
1054 Graphics2D g = null;
1055
1056 while (g == null && queue != null) {
1057
1058 if (queue.size() > 0) {
1059 g = queue.remove(0);
1060 notify();
1061
1062 } else {
1063 try {
1064 wait(2000);
1065 } catch (InterruptedException e) {
1066 // do nothing.
1067 }
1068 }
1069 }
1070
1071 return g;
1072 }
1073
1074 synchronized boolean isClosed() {
1075 return queue == null;
1076 }
1077
1078 }
1079
1080
1081 private static int[] getSize(MediaType mType) {
1082 int []dim = new int[2];
1083 dim[0] = 612;
1084 dim[1] = 792;
1085
1086 for (int i=0; i < SIZES.length; i++) {
1087 if (SIZES[i] == mType) {
1088 dim[0] = WIDTHS[i];
1089 dim[1] = LENGTHS[i];
1090 break;
1091 }
1092 }
1093 return dim;
1094 }
1095
1096 public static MediaSizeName mapMedia(MediaType mType) {
1097 MediaSizeName media = null;
1098
1099 // JAVAXSIZES.length and SIZES.length must be equal!
1100 // Attempt to recover by getting the smaller size.
1101 int length = Math.min(SIZES.length, JAVAXSIZES.length);
1102
1103 for (int i=0; i < length; i++) {
1104 if (SIZES[i] == mType) {
1105 if ((JAVAXSIZES[i] != null) &&
1106 MediaSize.getMediaSizeForName(JAVAXSIZES[i]) != null) {
1107 media = JAVAXSIZES[i];
1108 break;
1109 } else {
1110 /* create Custom Media */
1111 media = new CustomMediaSizeName(SIZES[i].toString());
1112
1113 float w = (float)Math.rint(WIDTHS[i] / 72.0);
1114 float h = (float)Math.rint(LENGTHS[i] / 72.0);
1115 if (w > 0.0 && h > 0.0) {
1116 // add new created MediaSize to our static map
1117 // so it will be found when we call findMedia
1118 new MediaSize(w, h, Size2DSyntax.INCH, media);
1119 }
1120
1121 break;
1122 }
1123 }
1124 }
1125 return media;
1126 }
1127
1128
1129 public static MediaType unMapMedia(MediaSizeName mSize) {
1130 MediaType media = null;
1131
1132 // JAVAXSIZES.length and SIZES.length must be equal!
1133 // Attempt to recover by getting the smaller size.
1134 int length = Math.min(SIZES.length, JAVAXSIZES.length);
1135
1136 for (int i=0; i < length; i++) {
1137 if (JAVAXSIZES[i] == mSize) {
1138 if (SIZES[i] != null) {
1139 media = SIZES[i];
1140 break;
1141 }
1142 }
1143 }
1144 return media;
1145 }
1146
1147 private void translateInputProps() {
1148 if (props == null) {
1149 return;
1150 }
1151
1152 String str;
1153
1154 str = props.getProperty(DEST_PROP);
1155 if (str != null) {
1156 if (str.equals(PRINTER)) {
1157 jobAttributes.setDestination(DestinationType.PRINTER);
1158 } else if (str.equals(FILE)) {
1159 jobAttributes.setDestination(DestinationType.FILE);
1160 }
1161 }
1162 str = props.getProperty(PRINTER_PROP);
1163 if (str != null) {
1164 jobAttributes.setPrinter(str);
1165 }
1166 str = props.getProperty(FILENAME_PROP);
1167 if (str != null) {
1168 jobAttributes.setFileName(str);
1169 }
1170 str = props.getProperty(NUMCOPIES_PROP);
1171 if (str != null) {
1172 jobAttributes.setCopies(Integer.parseInt(str));
1173 }
1174
1175 this.options = props.getProperty(OPTIONS_PROP, "");
1176
1177 str = props.getProperty(ORIENT_PROP);
1178 if (str != null) {
1179 if (str.equals(PORTRAIT)) {
1180 pageAttributes.setOrientationRequested(
1181 OrientationRequestedType.PORTRAIT);
1182 } else if (str.equals(LANDSCAPE)) {
1183 pageAttributes.setOrientationRequested(
1184 OrientationRequestedType.LANDSCAPE);
1185 }
1186 }
1187 str = props.getProperty(PAPERSIZE_PROP);
1188 if (str != null) {
1189 if (str.equals(LETTER)) {
1190 pageAttributes.setMedia(SIZES[MediaType.LETTER.hashCode()]);
1191 } else if (str.equals(LEGAL)) {
1192 pageAttributes.setMedia(SIZES[MediaType.LEGAL.hashCode()]);
1193 } else if (str.equals(EXECUTIVE)) {
1194 pageAttributes.setMedia(SIZES[MediaType.EXECUTIVE.hashCode()]);
1195 } else if (str.equals(A4)) {
1196 pageAttributes.setMedia(SIZES[MediaType.A4.hashCode()]);
1197 }
1198 }
1199 }
1200
1201 private void translateOutputProps() {
1202 if (props == null) {
1203 return;
1204 }
1205
1206 String str;
1207
1208 props.setProperty(DEST_PROP,
1209 (jobAttributes.getDestination() == DestinationType.PRINTER) ?
1210 PRINTER : FILE);
1211 str = jobAttributes.getPrinter();
1212 if (str != null && !str.equals("")) {
1213 props.setProperty(PRINTER_PROP, str);
1214 }
1215 str = jobAttributes.getFileName();
1216 if (str != null && !str.equals("")) {
1217 props.setProperty(FILENAME_PROP, str);
1218 }
1219 int copies = jobAttributes.getCopies();
1220 if (copies > 0) {
1221 props.setProperty(NUMCOPIES_PROP, "" + copies);
1222 }
1223 str = this.options;
1224 if (str != null && !str.equals("")) {
1225 props.setProperty(OPTIONS_PROP, str);
1226 }
1227 props.setProperty(ORIENT_PROP,
1228 (pageAttributes.getOrientationRequested() ==
1229 OrientationRequestedType.PORTRAIT)
1230 ? PORTRAIT : LANDSCAPE);
1231 MediaType media = SIZES[pageAttributes.getMedia().hashCode()];
1232 if (media == MediaType.LETTER) {
1233 str = LETTER;
1234 } else if (media == MediaType.LEGAL) {
1235 str = LEGAL;
1236 } else if (media == MediaType.EXECUTIVE) {
1237 str = EXECUTIVE;
1238 } else if (media == MediaType.A4) {
1239 str = A4;
1240 } else {
1241 str = media.toString();
1242 }
1243 props.setProperty(PAPERSIZE_PROP, str);
1244 }
1245
1246 private void throwPrintToFile() {
1247 SecurityManager security = System.getSecurityManager();
1248 FilePermission printToFilePermission = null;
1249 if (security != null) {
1250 if (printToFilePermission == null) {
1251 printToFilePermission =
1252 new FilePermission("<<ALL FILES>>", "read,write");
1253 }
1254 security.checkPermission(printToFilePermission);
1255 }
1256 }
1257
1258 }
--- EOF ---