Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/print/UnixPrintJob.java
32287 views
1
/*
2
* Copyright (c) 2000, 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 sun.print;
27
28
import java.net.URI;
29
import java.net.URL;
30
import java.io.BufferedInputStream;
31
import java.io.BufferedOutputStream;
32
import java.io.BufferedReader;
33
import java.io.BufferedWriter;
34
import java.io.File;
35
import java.io.FileOutputStream;
36
import java.io.InputStream;
37
import java.io.InputStreamReader;
38
import java.io.OutputStream;
39
import java.io.OutputStreamWriter;
40
import java.io.IOException;
41
import java.io.PrintWriter;
42
import java.io.Reader;
43
import java.io.StringWriter;
44
import java.io.UnsupportedEncodingException;
45
import java.nio.file.Files;
46
import java.util.Vector;
47
48
import javax.print.CancelablePrintJob;
49
import javax.print.Doc;
50
import javax.print.DocFlavor;
51
import javax.print.DocPrintJob;
52
import javax.print.PrintService;
53
import javax.print.PrintException;
54
import javax.print.event.PrintJobEvent;
55
import javax.print.event.PrintJobListener;
56
import javax.print.event.PrintJobAttributeListener;
57
58
import javax.print.attribute.Attribute;
59
import javax.print.attribute.AttributeSet;
60
import javax.print.attribute.AttributeSetUtilities;
61
import javax.print.attribute.DocAttributeSet;
62
import javax.print.attribute.HashPrintJobAttributeSet;
63
import javax.print.attribute.HashPrintRequestAttributeSet;
64
import javax.print.attribute.PrintJobAttribute;
65
import javax.print.attribute.PrintJobAttributeSet;
66
import javax.print.attribute.PrintRequestAttribute;
67
import javax.print.attribute.PrintRequestAttributeSet;
68
import javax.print.attribute.PrintServiceAttributeSet;
69
import javax.print.attribute.standard.Copies;
70
import javax.print.attribute.standard.Destination;
71
import javax.print.attribute.standard.DocumentName;
72
import javax.print.attribute.standard.Fidelity;
73
import javax.print.attribute.standard.JobName;
74
import javax.print.attribute.standard.JobOriginatingUserName;
75
import javax.print.attribute.standard.JobSheets;
76
import javax.print.attribute.standard.Media;
77
import javax.print.attribute.standard.MediaSize;
78
import javax.print.attribute.standard.MediaSizeName;
79
import javax.print.attribute.standard.OrientationRequested;
80
import javax.print.attribute.standard.PrinterName;
81
import javax.print.attribute.standard.RequestingUserName;
82
import javax.print.attribute.standard.NumberUp;
83
import javax.print.attribute.standard.Sides;
84
import javax.print.attribute.standard.PrinterIsAcceptingJobs;
85
86
import java.awt.print.*;
87
88
89
90
public class UnixPrintJob implements CancelablePrintJob {
91
private static String debugPrefix = "UnixPrintJob>> ";
92
93
transient private Vector jobListeners;
94
transient private Vector attrListeners;
95
transient private Vector listenedAttributeSets;
96
97
private PrintService service;
98
private boolean fidelity;
99
private boolean printing = false;
100
private boolean printReturned = false;
101
private PrintRequestAttributeSet reqAttrSet = null;
102
private PrintJobAttributeSet jobAttrSet = null;
103
private PrinterJob job;
104
private Doc doc;
105
/* these variables used globally to store reference to the print
106
* data retrieved as a stream. On completion these are always closed
107
* if non-null.
108
*/
109
private InputStream instream = null;
110
private Reader reader = null;
111
112
/* default values overridden by those extracted from the attributes */
113
private String jobName = "Java Printing";
114
private int copies = 1;
115
private MediaSizeName mediaName = MediaSizeName.NA_LETTER;
116
private MediaSize mediaSize = MediaSize.NA.LETTER;
117
private CustomMediaTray customTray = null;
118
private OrientationRequested orient = OrientationRequested.PORTRAIT;
119
private NumberUp nUp = null;
120
private Sides sides = null;
121
122
UnixPrintJob(PrintService service) {
123
this.service = service;
124
mDestination = service.getName();
125
if (PrintServiceLookupProvider.isMac()) {
126
mDestination = ((IPPPrintService)service).getDest();
127
}
128
mDestType = UnixPrintJob.DESTPRINTER;
129
}
130
131
public PrintService getPrintService() {
132
return service;
133
}
134
135
public PrintJobAttributeSet getAttributes() {
136
synchronized (this) {
137
if (jobAttrSet == null) {
138
/* just return an empty set until the job is submitted */
139
PrintJobAttributeSet jobSet = new HashPrintJobAttributeSet();
140
return AttributeSetUtilities.unmodifiableView(jobSet);
141
} else {
142
return jobAttrSet;
143
}
144
}
145
}
146
147
public void addPrintJobListener(PrintJobListener listener) {
148
synchronized (this) {
149
if (listener == null) {
150
return;
151
}
152
if (jobListeners == null) {
153
jobListeners = new Vector();
154
}
155
jobListeners.add(listener);
156
}
157
}
158
159
public void removePrintJobListener(PrintJobListener listener) {
160
synchronized (this) {
161
if (listener == null || jobListeners == null ) {
162
return;
163
}
164
jobListeners.remove(listener);
165
if (jobListeners.isEmpty()) {
166
jobListeners = null;
167
}
168
}
169
}
170
171
172
/* Closes any stream already retrieved for the data.
173
* We want to avoid unnecessarily asking the Doc to create a stream only
174
* to get a reference in order to close it because the job failed.
175
* If the representation class is itself a "stream", this
176
* closes that stream too.
177
*/
178
private void closeDataStreams() {
179
180
if (doc == null) {
181
return;
182
}
183
184
Object data = null;
185
186
try {
187
data = doc.getPrintData();
188
} catch (IOException e) {
189
return;
190
}
191
192
if (instream != null) {
193
try {
194
instream.close();
195
} catch (IOException e) {
196
} finally {
197
instream = null;
198
}
199
}
200
else if (reader != null) {
201
try {
202
reader.close();
203
} catch (IOException e) {
204
} finally {
205
reader = null;
206
}
207
}
208
else if (data instanceof InputStream) {
209
try {
210
((InputStream)data).close();
211
} catch (IOException e) {
212
}
213
}
214
else if (data instanceof Reader) {
215
try {
216
((Reader)data).close();
217
} catch (IOException e) {
218
}
219
}
220
}
221
222
private void notifyEvent(int reason) {
223
224
/* since this method should always get called, here's where
225
* we will perform the clean up of any data stream supplied.
226
*/
227
switch (reason) {
228
case PrintJobEvent.DATA_TRANSFER_COMPLETE:
229
case PrintJobEvent.JOB_CANCELED :
230
case PrintJobEvent.JOB_FAILED :
231
case PrintJobEvent.NO_MORE_EVENTS :
232
case PrintJobEvent.JOB_COMPLETE :
233
closeDataStreams();
234
}
235
236
synchronized (this) {
237
if (jobListeners != null) {
238
PrintJobListener listener;
239
PrintJobEvent event = new PrintJobEvent(this, reason);
240
for (int i = 0; i < jobListeners.size(); i++) {
241
listener = (PrintJobListener)(jobListeners.elementAt(i));
242
switch (reason) {
243
244
case PrintJobEvent.JOB_CANCELED :
245
listener.printJobCanceled(event);
246
break;
247
248
case PrintJobEvent.JOB_FAILED :
249
listener.printJobFailed(event);
250
break;
251
252
case PrintJobEvent.DATA_TRANSFER_COMPLETE :
253
listener.printDataTransferCompleted(event);
254
break;
255
256
case PrintJobEvent.NO_MORE_EVENTS :
257
listener.printJobNoMoreEvents(event);
258
break;
259
260
default:
261
break;
262
}
263
}
264
}
265
}
266
}
267
268
public void addPrintJobAttributeListener(
269
PrintJobAttributeListener listener,
270
PrintJobAttributeSet attributes) {
271
synchronized (this) {
272
if (listener == null) {
273
return;
274
}
275
if (attrListeners == null) {
276
attrListeners = new Vector();
277
listenedAttributeSets = new Vector();
278
}
279
attrListeners.add(listener);
280
if (attributes == null) {
281
attributes = new HashPrintJobAttributeSet();
282
}
283
listenedAttributeSets.add(attributes);
284
}
285
}
286
287
public void removePrintJobAttributeListener(
288
PrintJobAttributeListener listener) {
289
synchronized (this) {
290
if (listener == null || attrListeners == null ) {
291
return;
292
}
293
int index = attrListeners.indexOf(listener);
294
if (index == -1) {
295
return;
296
} else {
297
attrListeners.remove(index);
298
listenedAttributeSets.remove(index);
299
if (attrListeners.isEmpty()) {
300
attrListeners = null;
301
listenedAttributeSets = null;
302
}
303
}
304
}
305
}
306
307
public void print(Doc doc, PrintRequestAttributeSet attributes)
308
throws PrintException {
309
310
synchronized (this) {
311
if (printing) {
312
throw new PrintException("already printing");
313
} else {
314
printing = true;
315
}
316
}
317
318
if ((PrinterIsAcceptingJobs)(service.getAttribute(
319
PrinterIsAcceptingJobs.class)) ==
320
PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS) {
321
throw new PrintException("Printer is not accepting job.");
322
}
323
324
this.doc = doc;
325
/* check if the parameters are valid before doing much processing */
326
DocFlavor flavor = doc.getDocFlavor();
327
328
Object data;
329
330
try {
331
data = doc.getPrintData();
332
} catch (IOException e) {
333
notifyEvent(PrintJobEvent.JOB_FAILED);
334
throw new PrintException("can't get print data: " + e.toString());
335
}
336
337
if (data == null) {
338
throw new PrintException("Null print data.");
339
}
340
341
if (flavor == null || (!service.isDocFlavorSupported(flavor))) {
342
notifyEvent(PrintJobEvent.JOB_FAILED);
343
throw new PrintJobFlavorException("invalid flavor", flavor);
344
}
345
346
initializeAttributeSets(doc, attributes);
347
348
getAttributeValues(flavor);
349
350
// set up mOptions
351
if ((service instanceof IPPPrintService) &&
352
CUPSPrinter.isCupsRunning()) {
353
354
IPPPrintService.debug_println(debugPrefix+
355
"instanceof IPPPrintService");
356
357
if (mediaName != null) {
358
CustomMediaSizeName customMedia =
359
((IPPPrintService)service).findCustomMedia(mediaName);
360
if (customMedia != null) {
361
mOptions = " media="+ customMedia.getChoiceName();
362
}
363
}
364
365
if (customTray != null &&
366
customTray instanceof CustomMediaTray) {
367
String choice = customTray.getChoiceName();
368
if (choice != null) {
369
mOptions += " media="+choice;
370
}
371
}
372
373
if (nUp != null) {
374
mOptions += " number-up="+nUp.getValue();
375
}
376
377
if (orient != OrientationRequested.PORTRAIT &&
378
(flavor != null) &&
379
!flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)) {
380
mOptions += " orientation-requested="+orient.getValue();
381
}
382
383
if (sides != null) {
384
mOptions += " sides="+sides;
385
}
386
387
}
388
389
IPPPrintService.debug_println(debugPrefix+"mOptions "+mOptions);
390
String repClassName = flavor.getRepresentationClassName();
391
String val = flavor.getParameter("charset");
392
String encoding = "us-ascii";
393
if (val != null && !val.equals("")) {
394
encoding = val;
395
}
396
397
if (flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
398
flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
399
flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
400
flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
401
flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
402
flavor.equals(DocFlavor.BYTE_ARRAY.PNG)) {
403
try {
404
instream = doc.getStreamForBytes();
405
if (instream == null) {
406
notifyEvent(PrintJobEvent.JOB_FAILED);
407
throw new PrintException("No stream for data");
408
}
409
if (!(service instanceof IPPPrintService &&
410
((IPPPrintService)service).isIPPSupportedImages(
411
flavor.getMimeType()))) {
412
printableJob(new ImagePrinter(instream));
413
((UnixPrintService)service).wakeNotifier();
414
return;
415
}
416
} catch (ClassCastException cce) {
417
notifyEvent(PrintJobEvent.JOB_FAILED);
418
throw new PrintException(cce);
419
} catch (IOException ioe) {
420
notifyEvent(PrintJobEvent.JOB_FAILED);
421
throw new PrintException(ioe);
422
}
423
} else if (flavor.equals(DocFlavor.URL.GIF) ||
424
flavor.equals(DocFlavor.URL.JPEG) ||
425
flavor.equals(DocFlavor.URL.PNG)) {
426
try {
427
URL url = (URL)data;
428
if ((service instanceof IPPPrintService) &&
429
((IPPPrintService)service).isIPPSupportedImages(
430
flavor.getMimeType())) {
431
instream = url.openStream();
432
} else {
433
printableJob(new ImagePrinter(url));
434
((UnixPrintService)service).wakeNotifier();
435
return;
436
}
437
} catch (ClassCastException cce) {
438
notifyEvent(PrintJobEvent.JOB_FAILED);
439
throw new PrintException(cce);
440
} catch (IOException e) {
441
notifyEvent(PrintJobEvent.JOB_FAILED);
442
throw new PrintException(e.toString());
443
}
444
} else if (flavor.equals(DocFlavor.CHAR_ARRAY.TEXT_PLAIN) ||
445
flavor.equals(DocFlavor.READER.TEXT_PLAIN) ||
446
flavor.equals(DocFlavor.STRING.TEXT_PLAIN)) {
447
try {
448
reader = doc.getReaderForText();
449
if (reader == null) {
450
notifyEvent(PrintJobEvent.JOB_FAILED);
451
throw new PrintException("No reader for data");
452
}
453
} catch (IOException ioe) {
454
notifyEvent(PrintJobEvent.JOB_FAILED);
455
throw new PrintException(ioe.toString());
456
}
457
} else if (repClassName.equals("[B") ||
458
repClassName.equals("java.io.InputStream")) {
459
try {
460
instream = doc.getStreamForBytes();
461
if (instream == null) {
462
notifyEvent(PrintJobEvent.JOB_FAILED);
463
throw new PrintException("No stream for data");
464
}
465
} catch (IOException ioe) {
466
notifyEvent(PrintJobEvent.JOB_FAILED);
467
throw new PrintException(ioe.toString());
468
}
469
} else if (repClassName.equals("java.net.URL")) {
470
/*
471
* This extracts the data from the URL and passes it the content
472
* directly to the print service as a file.
473
* This is appropriate for the current implementation where lp or
474
* lpr is always used to spool the data. We expect to revise the
475
* implementation to provide more complete IPP support (ie not just
476
* CUPS) and at that time the job will be spooled via IPP
477
* and the URL
478
* itself should be sent to the IPP print service not the content.
479
*/
480
URL url = (URL)data;
481
try {
482
instream = url.openStream();
483
} catch (IOException e) {
484
notifyEvent(PrintJobEvent.JOB_FAILED);
485
throw new PrintException(e.toString());
486
}
487
} else if (repClassName.equals("java.awt.print.Pageable")) {
488
try {
489
pageableJob((Pageable)doc.getPrintData());
490
if (service instanceof IPPPrintService) {
491
((IPPPrintService)service).wakeNotifier();
492
} else {
493
((UnixPrintService)service).wakeNotifier();
494
}
495
return;
496
} catch (ClassCastException cce) {
497
notifyEvent(PrintJobEvent.JOB_FAILED);
498
throw new PrintException(cce);
499
} catch (IOException ioe) {
500
notifyEvent(PrintJobEvent.JOB_FAILED);
501
throw new PrintException(ioe);
502
}
503
} else if (repClassName.equals("java.awt.print.Printable")) {
504
try {
505
printableJob((Printable)doc.getPrintData());
506
if (service instanceof IPPPrintService) {
507
((IPPPrintService)service).wakeNotifier();
508
} else {
509
((UnixPrintService)service).wakeNotifier();
510
}
511
return;
512
} catch (ClassCastException cce) {
513
notifyEvent(PrintJobEvent.JOB_FAILED);
514
throw new PrintException(cce);
515
} catch (IOException ioe) {
516
notifyEvent(PrintJobEvent.JOB_FAILED);
517
throw new PrintException(ioe);
518
}
519
} else {
520
notifyEvent(PrintJobEvent.JOB_FAILED);
521
throw new PrintException("unrecognized class: "+repClassName);
522
}
523
524
// now spool the print data.
525
PrinterOpener po = new PrinterOpener();
526
java.security.AccessController.doPrivileged(po);
527
if (po.pex != null) {
528
throw po.pex;
529
}
530
OutputStream output = po.result;
531
532
/* There are three cases:
533
* 1) Text data from a Reader, just pass through.
534
* 2) Text data from an input stream which we must read using the
535
* correct encoding
536
* 3) Raw byte data from an InputStream we don't interpret as text,
537
* just pass through: eg postscript.
538
*/
539
540
BufferedWriter bw = null;
541
if ((instream == null && reader != null)) {
542
BufferedReader br = new BufferedReader(reader);
543
OutputStreamWriter osw = new OutputStreamWriter(output);
544
bw = new BufferedWriter(osw);
545
char []buffer = new char[1024];
546
int cread;
547
548
try {
549
while ((cread = br.read(buffer, 0, buffer.length)) >=0) {
550
bw.write(buffer, 0, cread);
551
}
552
br.close();
553
bw.flush();
554
bw.close();
555
} catch (IOException e) {
556
notifyEvent(PrintJobEvent.JOB_FAILED);
557
throw new PrintException (e);
558
}
559
} else if (instream != null &&
560
flavor.getMediaType().equalsIgnoreCase("text")) {
561
try {
562
563
InputStreamReader isr = new InputStreamReader(instream,
564
encoding);
565
BufferedReader br = new BufferedReader(isr);
566
OutputStreamWriter osw = new OutputStreamWriter(output);
567
bw = new BufferedWriter(osw);
568
char []buffer = new char[1024];
569
int cread;
570
571
while ((cread = br.read(buffer, 0, buffer.length)) >=0) {
572
bw.write(buffer, 0, cread);
573
}
574
bw.flush();
575
} catch (IOException e) {
576
notifyEvent(PrintJobEvent.JOB_FAILED);
577
throw new PrintException (e);
578
} finally {
579
try {
580
if (bw != null) {
581
bw.close();
582
}
583
} catch (IOException e) {
584
}
585
}
586
} else if (instream != null) {
587
BufferedInputStream bin = new BufferedInputStream(instream);
588
BufferedOutputStream bout = new BufferedOutputStream(output);
589
byte[] buffer = new byte[1024];
590
int bread = 0;
591
592
try {
593
while ((bread = bin.read(buffer)) >= 0) {
594
bout.write(buffer, 0, bread);
595
}
596
bin.close();
597
bout.flush();
598
bout.close();
599
} catch (IOException e) {
600
notifyEvent(PrintJobEvent.JOB_FAILED);
601
throw new PrintException (e);
602
}
603
}
604
notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
605
606
if (mDestType == UnixPrintJob.DESTPRINTER) {
607
PrinterSpooler spooler = new PrinterSpooler();
608
java.security.AccessController.doPrivileged(spooler);
609
if (spooler.pex != null) {
610
throw spooler.pex;
611
}
612
}
613
notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
614
if (service instanceof IPPPrintService) {
615
((IPPPrintService)service).wakeNotifier();
616
} else {
617
((UnixPrintService)service).wakeNotifier();
618
}
619
}
620
621
public void printableJob(Printable printable) throws PrintException {
622
try {
623
synchronized(this) {
624
if (job != null) { // shouldn't happen
625
throw new PrintException("already printing");
626
} else {
627
job = new PSPrinterJob();
628
}
629
}
630
job.setPrintService(getPrintService());
631
job.setCopies(copies);
632
job.setJobName(jobName);
633
PageFormat pf = new PageFormat();
634
if (mediaSize != null) {
635
Paper p = new Paper();
636
p.setSize(mediaSize.getX(MediaSize.INCH)*72.0,
637
mediaSize.getY(MediaSize.INCH)*72.0);
638
p.setImageableArea(72.0, 72.0, p.getWidth()-144.0,
639
p.getHeight()-144.0);
640
pf.setPaper(p);
641
}
642
if (orient == OrientationRequested.REVERSE_LANDSCAPE) {
643
pf.setOrientation(PageFormat.REVERSE_LANDSCAPE);
644
} else if (orient == OrientationRequested.LANDSCAPE) {
645
pf.setOrientation(PageFormat.LANDSCAPE);
646
}
647
job.setPrintable(printable, pf);
648
job.print(reqAttrSet);
649
notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
650
return;
651
} catch (PrinterException pe) {
652
notifyEvent(PrintJobEvent.JOB_FAILED);
653
throw new PrintException(pe);
654
} finally {
655
printReturned = true;
656
notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
657
}
658
}
659
660
public void pageableJob(Pageable pageable) throws PrintException {
661
try {
662
synchronized(this) {
663
if (job != null) { // shouldn't happen
664
throw new PrintException("already printing");
665
} else {
666
job = new PSPrinterJob();
667
}
668
}
669
job.setPrintService(getPrintService());
670
job.setCopies(copies);
671
job.setJobName(jobName);
672
job.setPageable(pageable);
673
job.print(reqAttrSet);
674
notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
675
return;
676
} catch (PrinterException pe) {
677
notifyEvent(PrintJobEvent.JOB_FAILED);
678
throw new PrintException(pe);
679
} finally {
680
printReturned = true;
681
notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
682
}
683
}
684
/* There's some inefficiency here as the job set is created even though
685
* it may never be requested.
686
*/
687
private synchronized void
688
initializeAttributeSets(Doc doc, PrintRequestAttributeSet reqSet) {
689
690
reqAttrSet = new HashPrintRequestAttributeSet();
691
jobAttrSet = new HashPrintJobAttributeSet();
692
693
Attribute[] attrs;
694
if (reqSet != null) {
695
reqAttrSet.addAll(reqSet);
696
attrs = reqSet.toArray();
697
for (int i=0; i<attrs.length; i++) {
698
if (attrs[i] instanceof PrintJobAttribute) {
699
jobAttrSet.add(attrs[i]);
700
}
701
}
702
}
703
704
DocAttributeSet docSet = doc.getAttributes();
705
if (docSet != null) {
706
attrs = docSet.toArray();
707
for (int i=0; i<attrs.length; i++) {
708
if (attrs[i] instanceof PrintRequestAttribute) {
709
reqAttrSet.add(attrs[i]);
710
}
711
if (attrs[i] instanceof PrintJobAttribute) {
712
jobAttrSet.add(attrs[i]);
713
}
714
}
715
}
716
717
/* add the user name to the job */
718
String userName = "";
719
try {
720
userName = System.getProperty("user.name");
721
} catch (SecurityException se) {
722
}
723
724
if (userName == null || userName.equals("")) {
725
RequestingUserName ruName =
726
(RequestingUserName)reqSet.get(RequestingUserName.class);
727
if (ruName != null) {
728
jobAttrSet.add(
729
new JobOriginatingUserName(ruName.getValue(),
730
ruName.getLocale()));
731
} else {
732
jobAttrSet.add(new JobOriginatingUserName("", null));
733
}
734
} else {
735
jobAttrSet.add(new JobOriginatingUserName(userName, null));
736
}
737
738
/* if no job name supplied use doc name (if supplied), if none and
739
* its a URL use that, else finally anything .. */
740
if (jobAttrSet.get(JobName.class) == null) {
741
JobName jobName;
742
if (docSet != null && docSet.get(DocumentName.class) != null) {
743
DocumentName docName =
744
(DocumentName)docSet.get(DocumentName.class);
745
jobName = new JobName(docName.getValue(), docName.getLocale());
746
jobAttrSet.add(jobName);
747
} else {
748
String str = "JPS Job:" + doc;
749
try {
750
Object printData = doc.getPrintData();
751
if (printData instanceof URL) {
752
str = ((URL)(doc.getPrintData())).toString();
753
}
754
} catch (IOException e) {
755
}
756
jobName = new JobName(str, null);
757
jobAttrSet.add(jobName);
758
}
759
}
760
761
jobAttrSet = AttributeSetUtilities.unmodifiableView(jobAttrSet);
762
}
763
764
private void getAttributeValues(DocFlavor flavor) throws PrintException {
765
Attribute attr;
766
Class category;
767
768
if (reqAttrSet.get(Fidelity.class) == Fidelity.FIDELITY_TRUE) {
769
fidelity = true;
770
} else {
771
fidelity = false;
772
}
773
774
Attribute []attrs = reqAttrSet.toArray();
775
for (int i=0; i<attrs.length; i++) {
776
attr = attrs[i];
777
category = attr.getCategory();
778
if (fidelity == true) {
779
if (!service.isAttributeCategorySupported(category)) {
780
notifyEvent(PrintJobEvent.JOB_FAILED);
781
throw new PrintJobAttributeException(
782
"unsupported category: " + category, category, null);
783
} else if
784
(!service.isAttributeValueSupported(attr, flavor, null)) {
785
notifyEvent(PrintJobEvent.JOB_FAILED);
786
throw new PrintJobAttributeException(
787
"unsupported attribute: " + attr, null, attr);
788
}
789
}
790
if (category == Destination.class) {
791
URI uri = ((Destination)attr).getURI();
792
if (!"file".equals(uri.getScheme())) {
793
notifyEvent(PrintJobEvent.JOB_FAILED);
794
throw new PrintException("Not a file: URI");
795
} else {
796
try {
797
mDestType = DESTFILE;
798
mDestination = (new File(uri)).getPath();
799
} catch (Exception e) {
800
throw new PrintException(e);
801
}
802
// check write access
803
SecurityManager security = System.getSecurityManager();
804
if (security != null) {
805
try {
806
security.checkWrite(mDestination);
807
} catch (SecurityException se) {
808
notifyEvent(PrintJobEvent.JOB_FAILED);
809
throw new PrintException(se);
810
}
811
}
812
}
813
} else if (category == JobSheets.class) {
814
if ((JobSheets)attr == JobSheets.NONE) {
815
mNoJobSheet = true;
816
}
817
} else if (category == JobName.class) {
818
jobName = ((JobName)attr).getValue();
819
} else if (category == Copies.class) {
820
copies = ((Copies)attr).getValue();
821
} else if (category == Media.class) {
822
if (attr instanceof MediaSizeName) {
823
mediaName = (MediaSizeName)attr;
824
IPPPrintService.debug_println(debugPrefix+
825
"mediaName "+mediaName);
826
if (!service.isAttributeValueSupported(attr, null, null)) {
827
mediaSize = MediaSize.getMediaSizeForName(mediaName);
828
}
829
} else if (attr instanceof CustomMediaTray) {
830
customTray = (CustomMediaTray)attr;
831
}
832
} else if (category == OrientationRequested.class) {
833
orient = (OrientationRequested)attr;
834
} else if (category == NumberUp.class) {
835
nUp = (NumberUp)attr;
836
} else if (category == Sides.class) {
837
sides = (Sides)attr;
838
}
839
}
840
}
841
842
private String[] printExecCmd(String printer, String options,
843
boolean noJobSheet,
844
String banner, int copies, String spoolFile) {
845
int PRINTER = 0x1;
846
int OPTIONS = 0x2;
847
int BANNER = 0x4;
848
int COPIES = 0x8;
849
int NOSHEET = 0x10;
850
int pFlags = 0;
851
String execCmd[];
852
int ncomps = 2; // minimum number of print args
853
int n = 0;
854
855
// conveniently "lp" is the default destination for both lp and lpr.
856
if (printer != null && !printer.equals("") && !printer.equals("lp")) {
857
pFlags |= PRINTER;
858
ncomps+=1;
859
}
860
if (options != null && !options.equals("")) {
861
pFlags |= OPTIONS;
862
ncomps+=1;
863
}
864
if (banner != null && !banner.equals("")) {
865
pFlags |= BANNER;
866
ncomps+=1;
867
}
868
if (copies > 1) {
869
pFlags |= COPIES;
870
ncomps+=1;
871
}
872
if (noJobSheet) {
873
pFlags |= NOSHEET;
874
ncomps+=1;
875
}
876
if (PrintServiceLookupProvider.osname.equals("SunOS")) {
877
ncomps+=1; // lp uses 1 more arg than lpr (make a copy)
878
execCmd = new String[ncomps];
879
execCmd[n++] = "/usr/bin/lp";
880
execCmd[n++] = "-c"; // make a copy of the spool file
881
if ((pFlags & PRINTER) != 0) {
882
execCmd[n++] = "-d" + printer;
883
}
884
if ((pFlags & BANNER) != 0) {
885
String quoteChar = "\"";
886
execCmd[n++] = "-t " + quoteChar+banner+quoteChar;
887
}
888
if ((pFlags & COPIES) != 0) {
889
execCmd[n++] = "-n " + copies;
890
}
891
if ((pFlags & NOSHEET) != 0) {
892
execCmd[n++] = "-o nobanner";
893
}
894
if ((pFlags & OPTIONS) != 0) {
895
execCmd[n++] = "-o " + options;
896
}
897
} else {
898
execCmd = new String[ncomps];
899
execCmd[n++] = "/usr/bin/lpr";
900
if ((pFlags & PRINTER) != 0) {
901
execCmd[n++] = "-P" + printer;
902
}
903
if ((pFlags & BANNER) != 0) {
904
execCmd[n++] = "-J " + banner;
905
}
906
if ((pFlags & COPIES) != 0) {
907
execCmd[n++] = "-#" + copies;
908
}
909
if ((pFlags & NOSHEET) != 0) {
910
execCmd[n++] = "-h";
911
}
912
if ((pFlags & OPTIONS) != 0) {
913
execCmd[n++] = "-o" + options;
914
}
915
}
916
execCmd[n++] = spoolFile;
917
if (IPPPrintService.debugPrint) {
918
System.out.println("UnixPrintJob>> execCmd");
919
for (int i=0; i<execCmd.length; i++) {
920
System.out.print(" "+execCmd[i]);
921
}
922
System.out.println();
923
}
924
return execCmd;
925
}
926
927
private static int DESTPRINTER = 1;
928
private static int DESTFILE = 2;
929
private int mDestType = DESTPRINTER;
930
931
private File spoolFile;
932
private String mDestination, mOptions="";
933
private boolean mNoJobSheet = false;
934
935
// Inner class to run "privileged" to open the printer output stream.
936
937
private class PrinterOpener implements java.security.PrivilegedAction {
938
PrintException pex;
939
OutputStream result;
940
941
public Object run() {
942
try {
943
if (mDestType == UnixPrintJob.DESTFILE) {
944
spoolFile = new File(mDestination);
945
} else {
946
/* Write to a temporary file which will be spooled to
947
* the printer then deleted. In the case that the file
948
* is not removed for some reason, request that it is
949
* removed when the VM exits.
950
*/
951
spoolFile = Files.createTempFile("javaprint", "").toFile();
952
spoolFile.deleteOnExit();
953
}
954
result = new FileOutputStream(spoolFile);
955
return result;
956
} catch (IOException ex) {
957
// If there is an IOError we subvert it to a PrinterException.
958
notifyEvent(PrintJobEvent.JOB_FAILED);
959
pex = new PrintException(ex);
960
}
961
return null;
962
}
963
}
964
965
// Inner class to run "privileged" to invoke the system print command
966
967
private class PrinterSpooler implements java.security.PrivilegedAction {
968
PrintException pex;
969
970
private void handleProcessFailure(final Process failedProcess,
971
final String[] execCmd, final int result) throws IOException {
972
try (StringWriter sw = new StringWriter();
973
PrintWriter pw = new PrintWriter(sw)) {
974
pw.append("error=").append(Integer.toString(result));
975
pw.append(" running:");
976
for (String arg: execCmd) {
977
pw.append(" '").append(arg).append("'");
978
}
979
try (InputStream is = failedProcess.getErrorStream();
980
InputStreamReader isr = new InputStreamReader(is);
981
BufferedReader br = new BufferedReader(isr)) {
982
while (br.ready()) {
983
pw.println();
984
pw.append("\t\t").append(br.readLine());
985
}
986
} finally {
987
pw.flush();
988
throw new IOException(sw.toString());
989
}
990
}
991
}
992
993
public Object run() {
994
if (spoolFile == null || !spoolFile.exists()) {
995
pex = new PrintException("No spool file");
996
notifyEvent(PrintJobEvent.JOB_FAILED);
997
return null;
998
}
999
try {
1000
/**
1001
* Spool to the printer.
1002
*/
1003
String fileName = spoolFile.getAbsolutePath();
1004
String execCmd[] = printExecCmd(mDestination, mOptions,
1005
mNoJobSheet, jobName, copies, fileName);
1006
1007
Process process = Runtime.getRuntime().exec(execCmd);
1008
process.waitFor();
1009
final int result = process.exitValue();
1010
if (0 != result) {
1011
handleProcessFailure(process, execCmd, result);
1012
}
1013
notifyEvent(PrintJobEvent.DATA_TRANSFER_COMPLETE);
1014
} catch (IOException ex) {
1015
notifyEvent(PrintJobEvent.JOB_FAILED);
1016
// REMIND : 2d printing throws PrinterException
1017
pex = new PrintException(ex);
1018
} catch (InterruptedException ie) {
1019
notifyEvent(PrintJobEvent.JOB_FAILED);
1020
pex = new PrintException(ie);
1021
} finally {
1022
spoolFile.delete();
1023
notifyEvent(PrintJobEvent.NO_MORE_EVENTS);
1024
}
1025
return null;
1026
}
1027
}
1028
1029
public void cancel() throws PrintException {
1030
synchronized (this) {
1031
if (!printing) {
1032
throw new PrintException("Job is not yet submitted.");
1033
} else if (job != null && !printReturned) {
1034
job.cancel();
1035
notifyEvent(PrintJobEvent.JOB_CANCELED);
1036
return;
1037
} else {
1038
throw new PrintException("Job could not be cancelled.");
1039
}
1040
}
1041
}
1042
}
1043
1044