Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/print/IPPPrintService.java
41152 views
1
/*
2
* Copyright (c) 2003, 2021, 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.GraphicsEnvironment;
29
import java.awt.Toolkit;
30
import javax.print.attribute.*;
31
import javax.print.attribute.standard.*;
32
import javax.print.DocFlavor;
33
import javax.print.DocPrintJob;
34
import javax.print.PrintService;
35
import javax.print.ServiceUIFactory;
36
import java.util.ArrayList;
37
import java.util.HashMap;
38
import java.util.Locale;
39
import java.util.Date;
40
import java.util.Arrays;
41
import java.security.AccessController;
42
import java.security.PrivilegedActionException;
43
import java.security.PrivilegedExceptionAction;
44
import javax.print.event.PrintServiceAttributeListener;
45
46
import java.net.URI;
47
import java.net.URISyntaxException;
48
import java.net.URL;
49
import java.net.URLConnection;
50
import java.net.HttpURLConnection;
51
import java.io.File;
52
import java.io.InputStream;
53
import java.io.OutputStream;
54
import java.io.OutputStreamWriter;
55
import java.io.DataInputStream;
56
import java.io.ByteArrayOutputStream;
57
import java.io.ByteArrayInputStream;
58
import java.io.BufferedReader;
59
import java.io.InputStreamReader;
60
import java.nio.charset.Charset;
61
62
import java.util.Iterator;
63
import java.util.HashSet;
64
import java.util.Map;
65
66
67
public class IPPPrintService implements PrintService, SunPrinterJobService {
68
69
public static final boolean debugPrint;
70
private static final String debugPrefix = "IPPPrintService>> ";
71
protected static void debug_println(String str) {
72
if (debugPrint) {
73
System.out.println(str);
74
}
75
}
76
77
private static final String FORCE_PIPE_PROP = "sun.print.ippdebug";
78
79
static {
80
@SuppressWarnings("removal")
81
String debugStr = java.security.AccessController.doPrivileged(
82
new sun.security.action.GetPropertyAction(FORCE_PIPE_PROP));
83
84
debugPrint = "true".equalsIgnoreCase(debugStr);
85
}
86
87
private String printer;
88
private URI myURI;
89
private URL myURL;
90
private transient ServiceNotifier notifier = null;
91
92
private static int MAXCOPIES = 1000;
93
private static short MAX_ATTRIBUTE_LENGTH = 255;
94
95
private CUPSPrinter cps;
96
private HttpURLConnection urlConnection = null;
97
private DocFlavor[] supportedDocFlavors;
98
private Class<?>[] supportedCats;
99
private MediaTray[] mediaTrays;
100
private MediaSizeName[] mediaSizeNames;
101
private CustomMediaSizeName[] customMediaSizeNames;
102
private int defaultMediaIndex;
103
private int[] rawResolutions = null;
104
private PrinterResolution[] printerResolutions = null;
105
private boolean isCupsPrinter;
106
private boolean init;
107
private Boolean isPS;
108
private HashMap<String, AttributeClass> getAttMap;
109
private boolean pngImagesAdded = false;
110
private boolean gifImagesAdded = false;
111
private boolean jpgImagesAdded = false;
112
113
114
/**
115
* IPP Status Codes
116
*/
117
private static final byte STATUSCODE_SUCCESS = 0x00;
118
119
/**
120
* IPP Group Tags. Each tag is used once before the first attribute
121
* of that group.
122
*/
123
// operation attributes group
124
private static final byte GRPTAG_OP_ATTRIBUTES = 0x01;
125
// job attributes group
126
private static final byte GRPTAG_JOB_ATTRIBUTES = 0x02;
127
// printer attributes group
128
private static final byte GRPTAG_PRINTER_ATTRIBUTES = 0x04;
129
// used as the last tag in an IPP message.
130
private static final byte GRPTAG_END_ATTRIBUTES = 0x03;
131
132
/**
133
* IPP Operation codes
134
*/
135
// gets the attributes for a printer
136
public static final String OP_GET_ATTRIBUTES = "000B";
137
// gets the default printer
138
public static final String OP_CUPS_GET_DEFAULT = "4001";
139
// gets the list of printers
140
public static final String OP_CUPS_GET_PRINTERS = "4002";
141
142
143
/**
144
* List of all PrintRequestAttributes. This is used
145
* for looping through all the IPP attribute name.
146
*/
147
private static Object[] printReqAttribDefault = {
148
Chromaticity.COLOR,
149
new Copies(1),
150
Fidelity.FIDELITY_FALSE,
151
Finishings.NONE,
152
//new JobHoldUntil(new Date()),
153
//new JobImpressions(0),
154
//JobImpressions,
155
//JobKOctets,
156
//JobMediaSheets,
157
new JobName("", Locale.getDefault()),
158
//JobPriority,
159
JobSheets.NONE,
160
(Media)MediaSizeName.NA_LETTER,
161
//MediaPrintableArea.class, // not an IPP attribute
162
//MultipleDocumentHandling.SINGLE_DOCUMENT,
163
new NumberUp(1),
164
OrientationRequested.PORTRAIT,
165
new PageRanges(1),
166
//PresentationDirection,
167
// CUPS does not supply printer-resolution attribute
168
//new PrinterResolution(300, 300, PrinterResolution.DPI),
169
//PrintQuality.NORMAL,
170
new RequestingUserName("", Locale.getDefault()),
171
//SheetCollate.UNCOLLATED, //CUPS has no sheet collate?
172
Sides.ONE_SIDED,
173
};
174
175
176
/**
177
* List of all PrintServiceAttributes. This is used
178
* for looping through all the IPP attribute name.
179
*/
180
private static Object[][] serviceAttributes = {
181
{ColorSupported.class, "color-supported"},
182
{PagesPerMinute.class, "pages-per-minute"},
183
{PagesPerMinuteColor.class, "pages-per-minute-color"},
184
{PDLOverrideSupported.class, "pdl-override-supported"},
185
{PrinterInfo.class, "printer-info"},
186
{PrinterIsAcceptingJobs.class, "printer-is-accepting-jobs"},
187
{PrinterLocation.class, "printer-location"},
188
{PrinterMakeAndModel.class, "printer-make-and-model"},
189
{PrinterMessageFromOperator.class, "printer-message-from-operator"},
190
{PrinterMoreInfo.class, "printer-more-info"},
191
{PrinterMoreInfoManufacturer.class, "printer-more-info-manufacturer"},
192
{PrinterName.class, "printer-name"},
193
{PrinterState.class, "printer-state"},
194
{PrinterStateReasons.class, "printer-state-reasons"},
195
{PrinterURI.class, "printer-uri"},
196
{QueuedJobCount.class, "queued-job-count"}
197
};
198
199
200
/**
201
* List of DocFlavors, grouped based on matching mime-type.
202
* NOTE: For any change in the predefined DocFlavors, it must be reflected
203
* here also.
204
*/
205
// PDF DocFlavors
206
private static DocFlavor[] appPDF = {
207
DocFlavor.BYTE_ARRAY.PDF,
208
DocFlavor.INPUT_STREAM.PDF,
209
DocFlavor.URL.PDF
210
};
211
212
// Postscript DocFlavors
213
private static DocFlavor[] appPostScript = {
214
DocFlavor.BYTE_ARRAY.POSTSCRIPT,
215
DocFlavor.INPUT_STREAM.POSTSCRIPT,
216
DocFlavor.URL.POSTSCRIPT
217
};
218
219
// Autosense DocFlavors
220
private static DocFlavor[] appOctetStream = {
221
DocFlavor.BYTE_ARRAY.AUTOSENSE,
222
DocFlavor.INPUT_STREAM.AUTOSENSE,
223
DocFlavor.URL.AUTOSENSE
224
};
225
226
// Text DocFlavors
227
private static DocFlavor[] textPlain = {
228
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8,
229
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16,
230
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE,
231
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE,
232
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII,
233
DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8,
234
DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16,
235
DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE,
236
DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE,
237
DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII,
238
DocFlavor.URL.TEXT_PLAIN_UTF_8,
239
DocFlavor.URL.TEXT_PLAIN_UTF_16,
240
DocFlavor.URL.TEXT_PLAIN_UTF_16BE,
241
DocFlavor.URL.TEXT_PLAIN_UTF_16LE,
242
DocFlavor.URL.TEXT_PLAIN_US_ASCII,
243
DocFlavor.CHAR_ARRAY.TEXT_PLAIN,
244
DocFlavor.STRING.TEXT_PLAIN,
245
DocFlavor.READER.TEXT_PLAIN
246
};
247
248
private static DocFlavor[] textPlainHost = {
249
DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST,
250
DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,
251
DocFlavor.URL.TEXT_PLAIN_HOST
252
};
253
254
// JPG DocFlavors
255
private static DocFlavor[] imageJPG = {
256
DocFlavor.BYTE_ARRAY.JPEG,
257
DocFlavor.INPUT_STREAM.JPEG,
258
DocFlavor.URL.JPEG
259
};
260
261
// GIF DocFlavors
262
private static DocFlavor[] imageGIF = {
263
DocFlavor.BYTE_ARRAY.GIF,
264
DocFlavor.INPUT_STREAM.GIF,
265
DocFlavor.URL.GIF
266
};
267
268
// PNG DocFlavors
269
private static DocFlavor[] imagePNG = {
270
DocFlavor.BYTE_ARRAY.PNG,
271
DocFlavor.INPUT_STREAM.PNG,
272
DocFlavor.URL.PNG
273
};
274
275
// HTML DocFlavors
276
private static DocFlavor[] textHtml = {
277
DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_8,
278
DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16,
279
DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16BE,
280
DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16LE,
281
DocFlavor.BYTE_ARRAY.TEXT_HTML_US_ASCII,
282
DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_8,
283
DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16,
284
DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16BE,
285
DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16LE,
286
DocFlavor.INPUT_STREAM.TEXT_HTML_US_ASCII,
287
DocFlavor.URL.TEXT_HTML_UTF_8,
288
DocFlavor.URL.TEXT_HTML_UTF_16,
289
DocFlavor.URL.TEXT_HTML_UTF_16BE,
290
DocFlavor.URL.TEXT_HTML_UTF_16LE,
291
DocFlavor.URL.TEXT_HTML_US_ASCII,
292
// These are not handled in UnixPrintJob so commenting these
293
// for now.
294
/*
295
DocFlavor.CHAR_ARRAY.TEXT_HTML,
296
DocFlavor.STRING.TEXT_HTML,
297
DocFlavor.READER.TEXT_HTML,
298
*/
299
};
300
301
private static DocFlavor[] textHtmlHost = {
302
DocFlavor.BYTE_ARRAY.TEXT_HTML_HOST,
303
DocFlavor.INPUT_STREAM.TEXT_HTML_HOST,
304
DocFlavor.URL.TEXT_HTML_HOST,
305
};
306
307
308
// PCL DocFlavors
309
private static DocFlavor[] appPCL = {
310
DocFlavor.BYTE_ARRAY.PCL,
311
DocFlavor.INPUT_STREAM.PCL,
312
DocFlavor.URL.PCL
313
};
314
315
// List of all DocFlavors, used in looping
316
// through all supported mime-types
317
private static Object[] allDocFlavors = {
318
appPDF, appPostScript, appOctetStream,
319
textPlain, imageJPG, imageGIF, imagePNG,
320
textHtml, appPCL,
321
};
322
323
324
IPPPrintService(String name, URL url) {
325
if ((name == null) || (url == null)){
326
throw new IllegalArgumentException("null uri or printer name");
327
}
328
try {
329
printer = java.net.URLDecoder.decode(name, "UTF-8");
330
} catch (java.io.UnsupportedEncodingException e) {
331
printer = name;
332
}
333
supportedDocFlavors = null;
334
supportedCats = null;
335
mediaSizeNames = null;
336
customMediaSizeNames = null;
337
mediaTrays = null;
338
myURL = url;
339
cps = null;
340
isCupsPrinter = false;
341
init = false;
342
defaultMediaIndex = -1;
343
344
String host = myURL.getHost();
345
if (host!=null && host.equals(CUPSPrinter.getServer())) {
346
isCupsPrinter = true;
347
try {
348
myURI = new URI("ipp://"+host+
349
"/printers/"+printer);
350
debug_println(debugPrefix+"IPPPrintService myURI : "+myURI);
351
} catch (java.net.URISyntaxException e) {
352
throw new IllegalArgumentException("invalid url");
353
}
354
}
355
}
356
357
358
IPPPrintService(String name, String uriStr, boolean isCups) {
359
if ((name == null) || (uriStr == null)){
360
throw new IllegalArgumentException("null uri or printer name");
361
}
362
try {
363
printer = java.net.URLDecoder.decode(name, "UTF-8");
364
} catch (java.io.UnsupportedEncodingException e) {
365
printer = name;
366
}
367
supportedDocFlavors = null;
368
supportedCats = null;
369
mediaSizeNames = null;
370
customMediaSizeNames = null;
371
mediaTrays = null;
372
cps = null;
373
init = false;
374
defaultMediaIndex = -1;
375
try {
376
myURL =
377
new URL(uriStr.replaceFirst("ipp", "http"));
378
} catch (Exception e) {
379
IPPPrintService.debug_println(debugPrefix+
380
" IPPPrintService, myURL="+
381
myURL+" Exception= "+
382
e);
383
throw new IllegalArgumentException("invalid url");
384
}
385
386
isCupsPrinter = isCups;
387
try {
388
myURI = new URI(uriStr);
389
debug_println(debugPrefix+"IPPPrintService myURI : "+myURI);
390
} catch (java.net.URISyntaxException e) {
391
throw new IllegalArgumentException("invalid uri");
392
}
393
}
394
395
396
/*
397
* Initialize mediaSizeNames, mediaTrays and other attributes.
398
* Media size/trays are initialized to non-null values, may be 0-length
399
* array.
400
* NOTE: Must be called from a synchronized block only.
401
*/
402
private void initAttributes() {
403
if (!init) {
404
// init customMediaSizeNames
405
customMediaSizeNames = new CustomMediaSizeName[0];
406
407
if ((urlConnection = getIPPConnection(myURL)) == null) {
408
mediaSizeNames = new MediaSizeName[0];
409
mediaTrays = new MediaTray[0];
410
debug_println(debugPrefix+"initAttributes, NULL urlConnection ");
411
init = true;
412
return;
413
}
414
415
// get all supported attributes through IPP
416
opGetAttributes();
417
418
if (isCupsPrinter) {
419
// note, it is possible to query media in CUPS using IPP
420
// right now we always get it from PPD.
421
// maybe use "&& (usePPD)" later?
422
// Another reason why we use PPD is because
423
// IPP currently does not support it but PPD does.
424
425
try {
426
cps = new CUPSPrinter(printer);
427
mediaSizeNames = cps.getMediaSizeNames();
428
mediaTrays = cps.getMediaTrays();
429
customMediaSizeNames = cps.getCustomMediaSizeNames();
430
defaultMediaIndex = cps.getDefaultMediaIndex();
431
rawResolutions = cps.getRawResolutions();
432
urlConnection.disconnect();
433
init = true;
434
return;
435
} catch (Exception e) {
436
IPPPrintService.debug_println(debugPrefix+
437
"initAttributes, error creating CUPSPrinter e="+e);
438
}
439
}
440
441
// use IPP to get all media,
442
Media[] allMedia = getSupportedMedia();
443
ArrayList<Media> sizeList = new ArrayList<>();
444
ArrayList<Media> trayList = new ArrayList<>();
445
for (int i=0; i<allMedia.length; i++) {
446
if (allMedia[i] instanceof MediaSizeName) {
447
sizeList.add(allMedia[i]);
448
} else if (allMedia[i] instanceof MediaTray) {
449
trayList.add(allMedia[i]);
450
}
451
}
452
453
if (sizeList != null) {
454
mediaSizeNames = new MediaSizeName[sizeList.size()];
455
mediaSizeNames = sizeList.toArray(mediaSizeNames);
456
}
457
if (trayList != null) {
458
mediaTrays = new MediaTray[trayList.size()];
459
mediaTrays = trayList.toArray(mediaTrays);
460
}
461
urlConnection.disconnect();
462
463
init = true;
464
}
465
}
466
467
468
public DocPrintJob createPrintJob() {
469
@SuppressWarnings("removal")
470
SecurityManager security = System.getSecurityManager();
471
if (security != null) {
472
security.checkPrintJobAccess();
473
}
474
// REMIND: create IPPPrintJob
475
return new UnixPrintJob(this);
476
}
477
478
479
public synchronized Object
480
getSupportedAttributeValues(Class<? extends Attribute> category,
481
DocFlavor flavor,
482
AttributeSet attributes)
483
{
484
if (category == null) {
485
throw new NullPointerException("null category");
486
}
487
if (!Attribute.class.isAssignableFrom(category)) {
488
throw new IllegalArgumentException(category +
489
" does not implement Attribute");
490
}
491
if (flavor != null) {
492
if (!isDocFlavorSupported(flavor)) {
493
throw new IllegalArgumentException(flavor +
494
" is an unsupported flavor");
495
} else if (isAutoSense(flavor)) {
496
return null;
497
}
498
499
}
500
501
if (!isAttributeCategorySupported(category)) {
502
return null;
503
}
504
505
/* Test if the flavor is compatible with the attributes */
506
if (!isDestinationSupported(flavor, attributes)) {
507
return null;
508
}
509
510
initAttributes();
511
512
/* Test if the flavor is compatible with the category */
513
if ((category == Copies.class) ||
514
(category == CopiesSupported.class)) {
515
if (flavor == null ||
516
!(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
517
flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
518
flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
519
CopiesSupported cs = new CopiesSupported(1, MAXCOPIES);
520
AttributeClass attribClass = (getAttMap != null) ?
521
getAttMap.get(cs.getName()) : null;
522
if (attribClass != null) {
523
int[] range = attribClass.getIntRangeValue();
524
cs = new CopiesSupported(range[0], range[1]);
525
}
526
return cs;
527
} else {
528
return null;
529
}
530
} else if (category == Chromaticity.class) {
531
if (flavor == null ||
532
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
533
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
534
!isIPPSupportedImages(flavor.getMimeType())) {
535
Chromaticity[]arr = new Chromaticity[1];
536
arr[0] = Chromaticity.COLOR;
537
return (arr);
538
} else {
539
return null;
540
}
541
} else if (category == Destination.class) {
542
if (flavor == null ||
543
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
544
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
545
try {
546
return new Destination((new File("out.ps")).toURI());
547
} catch (SecurityException se) {
548
try {
549
return new Destination(new URI("file:out.ps"));
550
} catch (URISyntaxException e) {
551
return null;
552
}
553
}
554
}
555
return null;
556
} else if (category == Fidelity.class) {
557
Fidelity []arr = new Fidelity[2];
558
arr[0] = Fidelity.FIDELITY_FALSE;
559
arr[1] = Fidelity.FIDELITY_TRUE;
560
return arr;
561
} else if (category == Finishings.class) {
562
AttributeClass attribClass = (getAttMap != null) ?
563
getAttMap.get("finishings-supported")
564
: null;
565
if (attribClass != null) {
566
int[] finArray = attribClass.getArrayOfIntValues();
567
if ((finArray != null) && (finArray.length > 0)) {
568
Finishings[] finSup = new Finishings[finArray.length];
569
for (int i=0; i<finArray.length; i++) {
570
finSup[i] = Finishings.NONE;
571
Finishings[] fAll = (Finishings[])
572
(new ExtFinishing(100)).getAll();
573
for (int j=0; j<fAll.length; j++) {
574
if (fAll[j] == null) {
575
continue;
576
}
577
if (finArray[i] == fAll[j].getValue()) {
578
finSup[i] = fAll[j];
579
break;
580
}
581
}
582
}
583
return finSup;
584
}
585
}
586
} else if (category == JobName.class) {
587
return new JobName("Java Printing", null);
588
} else if (category == JobSheets.class) {
589
JobSheets[] arr = new JobSheets[2];
590
arr[0] = JobSheets.NONE;
591
arr[1] = JobSheets.STANDARD;
592
return arr;
593
594
} else if (category == Media.class) {
595
Media[] allMedia = new Media[mediaSizeNames.length+
596
mediaTrays.length];
597
598
for (int i=0; i<mediaSizeNames.length; i++) {
599
allMedia[i] = mediaSizeNames[i];
600
}
601
602
for (int i=0; i<mediaTrays.length; i++) {
603
allMedia[i+mediaSizeNames.length] = mediaTrays[i];
604
}
605
606
if (allMedia.length == 0) {
607
allMedia = new Media[1];
608
allMedia[0] = (Media)getDefaultAttributeValue(Media.class);
609
}
610
611
return allMedia;
612
} else if (category == MediaPrintableArea.class) {
613
MediaPrintableArea[] mpas = null;
614
if (cps != null) {
615
mpas = cps.getMediaPrintableArea();
616
}
617
618
if (mpas == null) {
619
mpas = new MediaPrintableArea[1];
620
mpas[0] = (MediaPrintableArea)
621
getDefaultAttributeValue(MediaPrintableArea.class);
622
}
623
624
if ((attributes == null) || (attributes.size() == 0)) {
625
ArrayList<MediaPrintableArea> printableList =
626
new ArrayList<MediaPrintableArea>();
627
628
for (int i=0; i<mpas.length; i++) {
629
if (mpas[i] != null) {
630
printableList.add(mpas[i]);
631
}
632
}
633
if (printableList.size() > 0) {
634
mpas = new MediaPrintableArea[printableList.size()];
635
printableList.toArray(mpas);
636
}
637
return mpas;
638
}
639
640
int match = -1;
641
Media media = (Media)attributes.get(Media.class);
642
if (media != null && media instanceof MediaSizeName) {
643
MediaSizeName msn = (MediaSizeName)media;
644
645
// case when no supported mediasizenames are reported
646
// check given media against the default
647
if (mediaSizeNames.length == 0 &&
648
msn.equals(getDefaultAttributeValue(Media.class))) {
649
//default printable area is that of default mediasize
650
return mpas;
651
}
652
653
for (int i=0; i<mediaSizeNames.length; i++) {
654
if (msn.equals(mediaSizeNames[i])) {
655
match = i;
656
}
657
}
658
}
659
660
if (match == -1) {
661
return null;
662
} else {
663
MediaPrintableArea []arr = new MediaPrintableArea[1];
664
arr[0] = mpas[match];
665
return arr;
666
}
667
} else if (category == NumberUp.class) {
668
AttributeClass attribClass = (getAttMap != null) ?
669
getAttMap.get("number-up-supported") : null;
670
if (attribClass != null) {
671
int[] values = attribClass.getArrayOfIntValues();
672
if (values != null) {
673
NumberUp[] nUp = new NumberUp[values.length];
674
for (int i=0; i<values.length; i++) {
675
nUp[i] = new NumberUp(values[i]);
676
}
677
return nUp;
678
} else {
679
return null;
680
}
681
}
682
} else if (category == OrientationRequested.class) {
683
if ((flavor != null) &&
684
(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
685
flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
686
flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {
687
return null;
688
}
689
690
boolean revPort = false;
691
OrientationRequested[] orientSup = null;
692
693
AttributeClass attribClass = (getAttMap != null) ?
694
getAttMap.get("orientation-requested-supported")
695
: null;
696
if (attribClass != null) {
697
int[] orientArray = attribClass.getArrayOfIntValues();
698
if ((orientArray != null) && (orientArray.length > 0)) {
699
orientSup =
700
new OrientationRequested[orientArray.length];
701
for (int i=0; i<orientArray.length; i++) {
702
switch (orientArray[i]) {
703
default:
704
case 3 :
705
orientSup[i] = OrientationRequested.PORTRAIT;
706
break;
707
case 4:
708
orientSup[i] = OrientationRequested.LANDSCAPE;
709
break;
710
case 5:
711
orientSup[i] =
712
OrientationRequested.REVERSE_LANDSCAPE;
713
break;
714
case 6:
715
orientSup[i] =
716
OrientationRequested.REVERSE_PORTRAIT;
717
revPort = true;
718
break;
719
}
720
}
721
}
722
}
723
if (flavor == null ||
724
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
725
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
726
727
if (revPort && flavor == null) {
728
OrientationRequested []orSup = new OrientationRequested[4];
729
orSup[0] = OrientationRequested.PORTRAIT;
730
orSup[1] = OrientationRequested.LANDSCAPE;
731
orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
732
orSup[3] = OrientationRequested.REVERSE_PORTRAIT;
733
return orSup;
734
} else {
735
OrientationRequested []orSup = new OrientationRequested[3];
736
orSup[0] = OrientationRequested.PORTRAIT;
737
orSup[1] = OrientationRequested.LANDSCAPE;
738
orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
739
return orSup;
740
}
741
} else {
742
return orientSup;
743
}
744
} else if (category == PageRanges.class) {
745
if (flavor == null ||
746
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
747
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
748
PageRanges []arr = new PageRanges[1];
749
arr[0] = new PageRanges(1, Integer.MAX_VALUE);
750
return arr;
751
} else {
752
// Returning null as this is not yet supported in UnixPrintJob.
753
return null;
754
}
755
} else if (category == RequestingUserName.class) {
756
String userName = "";
757
try {
758
userName = System.getProperty("user.name", "");
759
} catch (SecurityException se) {
760
}
761
return new RequestingUserName(userName, null);
762
} else if (category == Sides.class) {
763
// The printer takes care of Sides so if short-edge
764
// is chosen in a job, the rotation is done by the printer.
765
// Orientation is rotated by emulation if pageable
766
// or printable so if the document is in Landscape, this may
767
// result in double rotation.
768
AttributeClass attribClass = (getAttMap != null) ?
769
getAttMap.get("sides-supported")
770
: null;
771
if (attribClass != null) {
772
String[] sidesArray = attribClass.getArrayOfStringValues();
773
if ((sidesArray != null) && (sidesArray.length > 0)) {
774
Sides[] sidesSup = new Sides[sidesArray.length];
775
for (int i=0; i<sidesArray.length; i++) {
776
if (sidesArray[i].endsWith("long-edge")) {
777
sidesSup[i] = Sides.TWO_SIDED_LONG_EDGE;
778
} else if (sidesArray[i].endsWith("short-edge")) {
779
sidesSup[i] = Sides.TWO_SIDED_SHORT_EDGE;
780
} else {
781
sidesSup[i] = Sides.ONE_SIDED;
782
}
783
}
784
return sidesSup;
785
}
786
}
787
} else if (category == PrinterResolution.class) {
788
PrinterResolution[] supportedRes = getPrintResolutions();
789
if (supportedRes == null) {
790
return null;
791
}
792
PrinterResolution []arr =
793
new PrinterResolution[supportedRes.length];
794
System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length);
795
return arr;
796
}
797
798
return null;
799
}
800
801
//This class is for getting all pre-defined Finishings
802
@SuppressWarnings("serial") // JDK implementation class
803
private class ExtFinishing extends Finishings {
804
ExtFinishing(int value) {
805
super(100); // 100 to avoid any conflicts with predefined values.
806
}
807
808
EnumSyntax[] getAll() {
809
EnumSyntax[] es = super.getEnumValueTable();
810
return es;
811
}
812
}
813
814
815
public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
816
AttributeSet attributes) {
817
if (flavor != null && !isDocFlavorSupported(flavor)) {
818
throw new IllegalArgumentException("flavor " + flavor +
819
"is not supported");
820
}
821
822
if (attributes == null) {
823
return null;
824
}
825
826
Attribute attr;
827
AttributeSet unsupp = new HashAttributeSet();
828
Attribute []attrs = attributes.toArray();
829
for (int i=0; i<attrs.length; i++) {
830
try {
831
attr = attrs[i];
832
if (!isAttributeCategorySupported(attr.getCategory())) {
833
unsupp.add(attr);
834
} else if (!isAttributeValueSupported(attr, flavor,
835
attributes)) {
836
unsupp.add(attr);
837
}
838
} catch (ClassCastException e) {
839
}
840
}
841
if (unsupp.isEmpty()) {
842
return null;
843
} else {
844
return unsupp;
845
}
846
}
847
848
849
public synchronized DocFlavor[] getSupportedDocFlavors() {
850
851
if (supportedDocFlavors != null) {
852
int len = supportedDocFlavors.length;
853
DocFlavor[] copyflavors = new DocFlavor[len];
854
System.arraycopy(supportedDocFlavors, 0, copyflavors, 0, len);
855
return copyflavors;
856
}
857
initAttributes();
858
859
if ((getAttMap != null) &&
860
getAttMap.containsKey("document-format-supported")) {
861
862
AttributeClass attribClass =
863
getAttMap.get("document-format-supported");
864
if (attribClass != null) {
865
String mimeType;
866
boolean psSupported = false;
867
String[] docFlavors = attribClass.getArrayOfStringValues();
868
DocFlavor[] flavors;
869
HashSet<Object> docList = new HashSet<>();
870
int j;
871
String hostEnc = DocFlavor.hostEncoding.
872
toLowerCase(Locale.ENGLISH);
873
boolean addHostEncoding = !hostEnc.equals("utf-8") &&
874
!hostEnc.equals("utf-16") && !hostEnc.equals("utf-16be") &&
875
!hostEnc.equals("utf-16le") && !hostEnc.equals("us-ascii");
876
877
for (int i = 0; i < docFlavors.length; i++) {
878
for (j=0; j<allDocFlavors.length; j++) {
879
flavors = (DocFlavor[])allDocFlavors[j];
880
881
mimeType = flavors[0].getMimeType();
882
if (mimeType.startsWith(docFlavors[i])) {
883
884
docList.addAll(Arrays.asList(flavors));
885
886
if (mimeType.equals("text/plain") &&
887
addHostEncoding) {
888
docList.add(Arrays.asList(textPlainHost));
889
} else if (mimeType.equals("text/html") &&
890
addHostEncoding) {
891
docList.add(Arrays.asList(textHtmlHost));
892
} else if (mimeType.equals("image/png")) {
893
pngImagesAdded = true;
894
} else if (mimeType.equals("image/gif")) {
895
gifImagesAdded = true;
896
} else if (mimeType.equals("image/jpeg")) {
897
jpgImagesAdded = true;
898
} else if (mimeType.indexOf("postscript") != -1) {
899
psSupported = true;
900
}
901
break;
902
}
903
}
904
905
// Not added? Create new DocFlavors
906
if (j == allDocFlavors.length) {
907
// make new DocFlavors
908
docList.add(new DocFlavor.BYTE_ARRAY(docFlavors[i]));
909
docList.add(new DocFlavor.INPUT_STREAM(docFlavors[i]));
910
docList.add(new DocFlavor.URL(docFlavors[i]));
911
}
912
}
913
914
// check if we need to add image DocFlavors
915
// and Pageable/Printable flavors
916
if (psSupported || isCupsPrinter) {
917
/*
918
Always add Pageable and Printable for CUPS
919
since it uses Filters to convert from Postscript
920
to device printer language.
921
*/
922
docList.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE);
923
docList.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
924
925
docList.addAll(Arrays.asList(imageJPG));
926
docList.addAll(Arrays.asList(imagePNG));
927
docList.addAll(Arrays.asList(imageGIF));
928
}
929
supportedDocFlavors = new DocFlavor[docList.size()];
930
docList.toArray(supportedDocFlavors);
931
int len = supportedDocFlavors.length;
932
DocFlavor[] copyflavors = new DocFlavor[len];
933
System.arraycopy(supportedDocFlavors, 0, copyflavors, 0, len);
934
return copyflavors;
935
}
936
}
937
DocFlavor[] flavor = new DocFlavor[2];
938
flavor[0] = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
939
flavor[1] = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
940
supportedDocFlavors = flavor;
941
return flavor;
942
}
943
944
945
public boolean isDocFlavorSupported(DocFlavor flavor) {
946
if (supportedDocFlavors == null) {
947
getSupportedDocFlavors();
948
}
949
if (supportedDocFlavors != null) {
950
for (int f=0; f<supportedDocFlavors.length; f++) {
951
if (flavor.equals(supportedDocFlavors[f])) {
952
return true;
953
}
954
}
955
}
956
return false;
957
}
958
959
960
/**
961
* Finds matching CustomMediaSizeName of given media.
962
*/
963
public CustomMediaSizeName findCustomMedia(MediaSizeName media) {
964
if (customMediaSizeNames == null) {
965
return null;
966
}
967
for (int i=0; i< customMediaSizeNames.length; i++) {
968
CustomMediaSizeName custom = customMediaSizeNames[i];
969
MediaSizeName msn = custom.getStandardMedia();
970
if (media.equals(msn)) {
971
return customMediaSizeNames[i];
972
}
973
}
974
return null;
975
}
976
977
978
/**
979
* Returns the matching standard Media using string comparison of names.
980
*/
981
private Media getIPPMedia(String mediaName) {
982
CustomMediaSizeName sampleSize = new CustomMediaSizeName("sample", "",
983
0, 0);
984
Media[] sizes = sampleSize.getSuperEnumTable();
985
for (int i=0; i<sizes.length; i++) {
986
if (mediaName.equals(""+sizes[i])) {
987
return sizes[i];
988
}
989
}
990
CustomMediaTray sampleTray = new CustomMediaTray("sample", "");
991
Media[] trays = sampleTray.getSuperEnumTable();
992
for (int i=0; i<trays.length; i++) {
993
if (mediaName.equals(""+trays[i])) {
994
return trays[i];
995
}
996
}
997
return null;
998
}
999
1000
private Media[] getSupportedMedia() {
1001
if ((getAttMap != null) &&
1002
getAttMap.containsKey("media-supported")) {
1003
1004
AttributeClass attribClass = getAttMap.get("media-supported");
1005
1006
if (attribClass != null) {
1007
String[] mediaVals = attribClass.getArrayOfStringValues();
1008
Media msn;
1009
Media[] mediaNames =
1010
new Media[mediaVals.length];
1011
for (int i=0; i<mediaVals.length; i++) {
1012
msn = getIPPMedia(mediaVals[i]);
1013
//REMIND: if null, create custom?
1014
mediaNames[i] = msn;
1015
}
1016
return mediaNames;
1017
}
1018
}
1019
return new Media[0];
1020
}
1021
1022
1023
public synchronized Class<?>[] getSupportedAttributeCategories() {
1024
if (supportedCats != null) {
1025
Class<?> [] copyCats = new Class<?>[supportedCats.length];
1026
System.arraycopy(supportedCats, 0, copyCats, 0, copyCats.length);
1027
return copyCats;
1028
}
1029
1030
initAttributes();
1031
1032
ArrayList<Class<?>> catList = new ArrayList<>();
1033
1034
for (int i=0; i < printReqAttribDefault.length; i++) {
1035
PrintRequestAttribute pra =
1036
(PrintRequestAttribute)printReqAttribDefault[i];
1037
if (getAttMap != null &&
1038
getAttMap.containsKey(pra.getName()+"-supported")) {
1039
catList.add(pra.getCategory());
1040
}
1041
}
1042
1043
// Some IPP printers like lexc710 do not have list of supported media
1044
// but CUPS can get the media from PPD, so we still report as
1045
// supported category.
1046
if (isCupsPrinter) {
1047
if (!catList.contains(Media.class)) {
1048
catList.add(Media.class);
1049
}
1050
1051
// Always add MediaPrintable for cups,
1052
// because we can get it from PPD.
1053
catList.add(MediaPrintableArea.class);
1054
1055
// this is already supported in UnixPrintJob
1056
catList.add(Destination.class);
1057
1058
// It is unfortunate that CUPS doesn't provide a way to query
1059
// if printer supports collation but since most printers
1060
// now supports collation and that most OS has a way
1061
// of setting it, it is a safe assumption to just always
1062
// include SheetCollate as supported attribute.
1063
1064
catList.add(SheetCollate.class);
1065
1066
}
1067
1068
// With the assumption that Chromaticity is equivalent to
1069
// ColorSupported.
1070
if (getAttMap != null && getAttMap.containsKey("color-supported")) {
1071
catList.add(Chromaticity.class);
1072
}
1073
1074
// CUPS does not report printer resolution via IPP but it
1075
// may be gleaned from the PPD.
1076
PrinterResolution[] supportedRes = getPrintResolutions();
1077
if (supportedRes != null && (supportedRes.length > 0)) {
1078
catList.add(PrinterResolution.class);
1079
}
1080
1081
if (GraphicsEnvironment.isHeadless() == false) {
1082
catList.add(DialogOwner.class);
1083
catList.add(DialogTypeSelection.class);
1084
}
1085
1086
supportedCats = new Class<?>[catList.size()];
1087
catList.toArray(supportedCats);
1088
Class<?>[] copyCats = new Class<?>[supportedCats.length];
1089
System.arraycopy(supportedCats, 0, copyCats, 0, copyCats.length);
1090
return copyCats;
1091
}
1092
1093
1094
public boolean
1095
isAttributeCategorySupported(Class<? extends Attribute> category)
1096
{
1097
if (category == null) {
1098
throw new NullPointerException("null category");
1099
}
1100
if (!(Attribute.class.isAssignableFrom(category))) {
1101
throw new IllegalArgumentException(category +
1102
" is not an Attribute");
1103
}
1104
1105
if (supportedCats == null) {
1106
getSupportedAttributeCategories();
1107
}
1108
1109
// It is safe to assume that Orientation is always supported
1110
// and even if CUPS or an IPP device reports it as not,
1111
// our renderer can do portrait, landscape and
1112
// reverse landscape.
1113
if (category == OrientationRequested.class) {
1114
return true;
1115
}
1116
1117
for (int i=0;i<supportedCats.length;i++) {
1118
if (category == supportedCats[i]) {
1119
return true;
1120
}
1121
}
1122
1123
return false;
1124
}
1125
1126
@SuppressWarnings("unchecked")
1127
public synchronized <T extends PrintServiceAttribute>
1128
T getAttribute(Class<T> category)
1129
{
1130
if (category == null) {
1131
throw new NullPointerException("category");
1132
}
1133
if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {
1134
throw new IllegalArgumentException("Not a PrintServiceAttribute");
1135
}
1136
1137
initAttributes();
1138
1139
if (category == PrinterName.class) {
1140
return (T)(new PrinterName(printer, null));
1141
} else if (category == PrinterInfo.class) {
1142
PrinterInfo pInfo = new PrinterInfo(printer, null);
1143
AttributeClass ac = (getAttMap != null) ?
1144
getAttMap.get(pInfo.getName())
1145
: null;
1146
if (ac != null) {
1147
return (T)(new PrinterInfo(ac.getStringValue(), null));
1148
}
1149
return (T)pInfo;
1150
} else if (category == QueuedJobCount.class) {
1151
QueuedJobCount qjc = new QueuedJobCount(0);
1152
AttributeClass ac = (getAttMap != null) ?
1153
getAttMap.get(qjc.getName())
1154
: null;
1155
if (ac != null) {
1156
qjc = new QueuedJobCount(ac.getIntValue());
1157
}
1158
return (T)qjc;
1159
} else if (category == PrinterIsAcceptingJobs.class) {
1160
PrinterIsAcceptingJobs accJob =
1161
PrinterIsAcceptingJobs.ACCEPTING_JOBS;
1162
AttributeClass ac = (getAttMap != null) ?
1163
getAttMap.get(accJob.getName())
1164
: null;
1165
if ((ac != null) && (ac.getByteValue() == 0)) {
1166
accJob = PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
1167
}
1168
return (T)accJob;
1169
} else if (category == ColorSupported.class) {
1170
ColorSupported cs = ColorSupported.SUPPORTED;
1171
AttributeClass ac = (getAttMap != null) ?
1172
getAttMap.get(cs.getName())
1173
: null;
1174
if ((ac != null) && (ac.getByteValue() == 0)) {
1175
cs = ColorSupported.NOT_SUPPORTED;
1176
}
1177
return (T)cs;
1178
} else if (category == PDLOverrideSupported.class) {
1179
1180
if (isCupsPrinter) {
1181
// Documented: For CUPS this will always be false
1182
return (T)PDLOverrideSupported.NOT_ATTEMPTED;
1183
} else {
1184
// REMIND: check attribute values
1185
return (T)PDLOverrideSupported.NOT_ATTEMPTED;
1186
}
1187
} else if (category == PrinterURI.class) {
1188
return (T)(new PrinterURI(myURI));
1189
} else {
1190
return null;
1191
}
1192
}
1193
1194
1195
public synchronized PrintServiceAttributeSet getAttributes() {
1196
// update getAttMap by sending again get-attributes IPP request
1197
init = false;
1198
initAttributes();
1199
1200
HashPrintServiceAttributeSet attrs =
1201
new HashPrintServiceAttributeSet();
1202
1203
for (int i=0; i < serviceAttributes.length; i++) {
1204
String name = (String)serviceAttributes[i][1];
1205
if (getAttMap != null && getAttMap.containsKey(name)) {
1206
@SuppressWarnings("unchecked")
1207
Class<PrintServiceAttribute> c = (Class<PrintServiceAttribute>)serviceAttributes[i][0];
1208
PrintServiceAttribute psa = getAttribute(c);
1209
if (psa != null) {
1210
attrs.add(psa);
1211
}
1212
}
1213
}
1214
return AttributeSetUtilities.unmodifiableView(attrs);
1215
}
1216
1217
public boolean isIPPSupportedImages(String mimeType) {
1218
if (supportedDocFlavors == null) {
1219
getSupportedDocFlavors();
1220
}
1221
1222
if (mimeType.equals("image/png") && pngImagesAdded) {
1223
return true;
1224
} else if (mimeType.equals("image/gif") && gifImagesAdded) {
1225
return true;
1226
} else if (mimeType.equals("image/jpeg") && jpgImagesAdded) {
1227
return true;
1228
}
1229
1230
return false;
1231
}
1232
1233
1234
private boolean isSupportedCopies(Copies copies) {
1235
CopiesSupported cs = (CopiesSupported)
1236
getSupportedAttributeValues(Copies.class, null, null);
1237
int[][] members = cs.getMembers();
1238
int min, max;
1239
if ((members.length > 0) && (members[0].length > 0)) {
1240
min = members[0][0];
1241
max = members[0][1];
1242
} else {
1243
min = 1;
1244
max = MAXCOPIES;
1245
}
1246
1247
int value = copies.getValue();
1248
return (value >= min && value <= max);
1249
}
1250
1251
private boolean isAutoSense(DocFlavor flavor) {
1252
if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) ||
1253
flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) ||
1254
flavor.equals(DocFlavor.URL.AUTOSENSE)) {
1255
return true;
1256
}
1257
else {
1258
return false;
1259
}
1260
}
1261
1262
private synchronized boolean isSupportedMediaTray(MediaTray msn) {
1263
initAttributes();
1264
1265
if (mediaTrays != null) {
1266
for (int i=0; i<mediaTrays.length; i++) {
1267
if (msn.equals(mediaTrays[i])) {
1268
return true;
1269
}
1270
}
1271
}
1272
return false;
1273
}
1274
1275
private synchronized boolean isSupportedMedia(MediaSizeName msn) {
1276
initAttributes();
1277
1278
if (msn.equals((Media)getDefaultAttributeValue(Media.class))) {
1279
return true;
1280
}
1281
for (int i=0; i<mediaSizeNames.length; i++) {
1282
debug_println(debugPrefix+"isSupportedMedia, mediaSizeNames[i] "+mediaSizeNames[i]);
1283
if (msn.equals(mediaSizeNames[i])) {
1284
return true;
1285
}
1286
}
1287
return false;
1288
}
1289
1290
/* Return false if flavor is not null, pageable, nor printable and
1291
* Destination is part of attributes.
1292
*/
1293
private boolean
1294
isDestinationSupported(DocFlavor flavor, AttributeSet attributes) {
1295
1296
if ((attributes != null) &&
1297
(attributes.get(Destination.class) != null) &&
1298
!(flavor == null ||
1299
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1300
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1301
return false;
1302
}
1303
return true;
1304
}
1305
1306
1307
public boolean isAttributeValueSupported(Attribute attr,
1308
DocFlavor flavor,
1309
AttributeSet attributes) {
1310
if (attr == null) {
1311
throw new NullPointerException("null attribute");
1312
}
1313
if (flavor != null) {
1314
if (!isDocFlavorSupported(flavor)) {
1315
throw new IllegalArgumentException(flavor +
1316
" is an unsupported flavor");
1317
} else if (isAutoSense(flavor)) {
1318
return false;
1319
}
1320
}
1321
Class<? extends Attribute> category = attr.getCategory();
1322
if (!isAttributeCategorySupported(category)) {
1323
return false;
1324
}
1325
1326
/* Test if the flavor is compatible with the attributes */
1327
if (!isDestinationSupported(flavor, attributes)) {
1328
return false;
1329
}
1330
1331
/* Test if the flavor is compatible with the category */
1332
if (attr.getCategory() == Chromaticity.class) {
1333
if ((flavor == null) ||
1334
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1335
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1336
!isIPPSupportedImages(flavor.getMimeType())) {
1337
return attr == Chromaticity.COLOR;
1338
} else {
1339
return false;
1340
}
1341
} else if (attr.getCategory() == Copies.class) {
1342
return (flavor == null ||
1343
!(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
1344
flavor.equals(DocFlavor.URL.POSTSCRIPT) ||
1345
flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) &&
1346
isSupportedCopies((Copies)attr);
1347
1348
} else if (attr.getCategory() == Destination.class) {
1349
if (flavor == null ||
1350
flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1351
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
1352
URI uri = ((Destination)attr).getURI();
1353
if ("file".equals(uri.getScheme()) &&
1354
!uri.getSchemeSpecificPart().isEmpty()) {
1355
return true;
1356
}
1357
}
1358
return false;
1359
} else if (attr.getCategory() == Media.class) {
1360
if (attr instanceof MediaSizeName) {
1361
return isSupportedMedia((MediaSizeName)attr);
1362
}
1363
if (attr instanceof MediaTray) {
1364
return isSupportedMediaTray((MediaTray)attr);
1365
}
1366
} else if (attr.getCategory() == PageRanges.class) {
1367
if (flavor != null &&
1368
!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1369
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1370
return false;
1371
}
1372
} else if (attr.getCategory() == SheetCollate.class) {
1373
if (flavor != null &&
1374
!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1375
flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1376
return false;
1377
}
1378
} else if (attr.getCategory() == Sides.class) {
1379
Sides[] sidesArray = (Sides[])getSupportedAttributeValues(
1380
Sides.class,
1381
flavor,
1382
attributes);
1383
1384
if (sidesArray != null) {
1385
for (int i=0; i<sidesArray.length; i++) {
1386
if (sidesArray[i] == (Sides)attr) {
1387
return true;
1388
}
1389
}
1390
}
1391
return false;
1392
} else if (attr.getCategory() == OrientationRequested.class) {
1393
OrientationRequested[] orientArray =
1394
(OrientationRequested[])getSupportedAttributeValues(
1395
OrientationRequested.class,
1396
flavor,
1397
attributes);
1398
1399
if (orientArray != null) {
1400
for (int i=0; i<orientArray.length; i++) {
1401
if (orientArray[i] == (OrientationRequested)attr) {
1402
return true;
1403
}
1404
}
1405
}
1406
return false;
1407
} else if (attr.getCategory() == PrinterResolution.class) {
1408
if (attr instanceof PrinterResolution) {
1409
return isSupportedResolution((PrinterResolution)attr);
1410
}
1411
} else if (attr.getCategory() == DialogOwner.class) {
1412
DialogOwner owner = (DialogOwner)attr;
1413
// ID not supported on any dialog type on Unix platforms.
1414
if (DialogOwnerAccessor.getID(owner) != 0) {
1415
return false;
1416
}
1417
// On Mac we have no control over the native dialog.
1418
DialogTypeSelection dst = (attributes == null) ? null :
1419
(DialogTypeSelection)attributes.get(DialogTypeSelection.class);
1420
if (PrintServiceLookupProvider.isMac() &&
1421
dst == DialogTypeSelection.NATIVE) {
1422
return false;
1423
}
1424
// The other case is always a Swing dialog on all Unix platforms.
1425
// So we only need to check that the toolkit supports
1426
// always on top.
1427
if (owner.getOwner() != null) {
1428
return true;
1429
} else {
1430
return Toolkit.getDefaultToolkit().isAlwaysOnTopSupported();
1431
}
1432
} else if (attr.getCategory() == DialogTypeSelection.class) {
1433
if (PrintServiceLookupProvider.isMac()) {
1434
return true;
1435
} else {
1436
DialogTypeSelection dst = (DialogTypeSelection)attr;
1437
return attr == DialogTypeSelection.COMMON;
1438
}
1439
}
1440
return true;
1441
}
1442
1443
1444
public synchronized Object
1445
getDefaultAttributeValue(Class<? extends Attribute> category)
1446
{
1447
if (category == null) {
1448
throw new NullPointerException("null category");
1449
}
1450
if (!Attribute.class.isAssignableFrom(category)) {
1451
throw new IllegalArgumentException(category +
1452
" is not an Attribute");
1453
}
1454
if (!isAttributeCategorySupported(category)) {
1455
return null;
1456
}
1457
1458
initAttributes();
1459
1460
String catName = null;
1461
for (int i=0; i < printReqAttribDefault.length; i++) {
1462
PrintRequestAttribute pra =
1463
(PrintRequestAttribute)printReqAttribDefault[i];
1464
if (pra.getCategory() == category) {
1465
catName = pra.getName();
1466
break;
1467
}
1468
}
1469
String attribName = catName+"-default";
1470
AttributeClass attribClass = (getAttMap != null) ?
1471
getAttMap.get(attribName) : null;
1472
1473
if (category == Copies.class) {
1474
if (attribClass != null) {
1475
return new Copies(attribClass.getIntValue());
1476
} else {
1477
return new Copies(1);
1478
}
1479
} else if (category == Chromaticity.class) {
1480
return Chromaticity.COLOR;
1481
} else if (category == Destination.class) {
1482
try {
1483
return new Destination((new File("out.ps")).toURI());
1484
} catch (SecurityException se) {
1485
try {
1486
return new Destination(new URI("file:out.ps"));
1487
} catch (URISyntaxException e) {
1488
return null;
1489
}
1490
}
1491
} else if (category == Fidelity.class) {
1492
return Fidelity.FIDELITY_FALSE;
1493
} else if (category == Finishings.class) {
1494
return Finishings.NONE;
1495
} else if (category == JobName.class) {
1496
return new JobName("Java Printing", null);
1497
} else if (category == JobSheets.class) {
1498
if (attribClass != null &&
1499
attribClass.getStringValue().equals("none")) {
1500
return JobSheets.NONE;
1501
} else {
1502
return JobSheets.STANDARD;
1503
}
1504
} else if (category == Media.class) {
1505
if (defaultMediaIndex == -1) {
1506
defaultMediaIndex = 0;
1507
}
1508
if (mediaSizeNames.length == 0) {
1509
String defaultCountry = Locale.getDefault().getCountry();
1510
if (defaultCountry != null &&
1511
(defaultCountry.isEmpty() ||
1512
defaultCountry.equals(Locale.US.getCountry()) ||
1513
defaultCountry.equals(Locale.CANADA.getCountry()))) {
1514
return MediaSizeName.NA_LETTER;
1515
} else {
1516
return MediaSizeName.ISO_A4;
1517
}
1518
}
1519
1520
if (attribClass != null) {
1521
String name = attribClass.getStringValue();
1522
if (isCupsPrinter) {
1523
return mediaSizeNames[defaultMediaIndex];
1524
} else {
1525
for (int i=0; i< mediaSizeNames.length; i++) {
1526
if (mediaSizeNames[i].toString().indexOf(name) != -1) {
1527
defaultMediaIndex = i;
1528
return mediaSizeNames[defaultMediaIndex];
1529
}
1530
}
1531
}
1532
}
1533
return mediaSizeNames[defaultMediaIndex];
1534
1535
} else if (category == MediaPrintableArea.class) {
1536
MediaPrintableArea[] mpas;
1537
if ((cps != null) &&
1538
((mpas = cps.getMediaPrintableArea()) != null)) {
1539
if (defaultMediaIndex == -1) {
1540
// initializes value of defaultMediaIndex
1541
getDefaultAttributeValue(Media.class);
1542
}
1543
return mpas[defaultMediaIndex];
1544
} else {
1545
String defaultCountry = Locale.getDefault().getCountry();
1546
float iw, ih;
1547
if (defaultCountry != null &&
1548
(defaultCountry.isEmpty() ||
1549
defaultCountry.equals(Locale.US.getCountry()) ||
1550
defaultCountry.equals(Locale.CANADA.getCountry()))) {
1551
iw = MediaSize.NA.LETTER.getX(Size2DSyntax.INCH) - 0.5f;
1552
ih = MediaSize.NA.LETTER.getY(Size2DSyntax.INCH) - 0.5f;
1553
} else {
1554
iw = MediaSize.ISO.A4.getX(Size2DSyntax.INCH) - 0.5f;
1555
ih = MediaSize.ISO.A4.getY(Size2DSyntax.INCH) - 0.5f;
1556
}
1557
return new MediaPrintableArea(0.25f, 0.25f, iw, ih,
1558
MediaPrintableArea.INCH);
1559
}
1560
} else if (category == NumberUp.class) {
1561
return new NumberUp(1); // for CUPS this is always 1
1562
} else if (category == OrientationRequested.class) {
1563
if (attribClass != null) {
1564
switch (attribClass.getIntValue()) {
1565
default:
1566
case 3: return OrientationRequested.PORTRAIT;
1567
case 4: return OrientationRequested.LANDSCAPE;
1568
case 5: return OrientationRequested.REVERSE_LANDSCAPE;
1569
case 6: return OrientationRequested.REVERSE_PORTRAIT;
1570
}
1571
} else {
1572
return OrientationRequested.PORTRAIT;
1573
}
1574
} else if (category == PageRanges.class) {
1575
if (attribClass != null) {
1576
int[] range = attribClass.getIntRangeValue();
1577
return new PageRanges(range[0], range[1]);
1578
} else {
1579
return new PageRanges(1, Integer.MAX_VALUE);
1580
}
1581
} else if (category == RequestingUserName.class) {
1582
String userName = "";
1583
try {
1584
userName = System.getProperty("user.name", "");
1585
} catch (SecurityException se) {
1586
}
1587
return new RequestingUserName(userName, null);
1588
} else if (category == SheetCollate.class) {
1589
return SheetCollate.UNCOLLATED;
1590
} else if (category == Sides.class) {
1591
if (attribClass != null) {
1592
if (attribClass.getStringValue().endsWith("long-edge")) {
1593
return Sides.TWO_SIDED_LONG_EDGE;
1594
} else if (attribClass.getStringValue().endsWith(
1595
"short-edge")) {
1596
return Sides.TWO_SIDED_SHORT_EDGE;
1597
}
1598
}
1599
return Sides.ONE_SIDED;
1600
} else if (category == PrinterResolution.class) {
1601
PrinterResolution[] supportedRes = getPrintResolutions();
1602
if ((supportedRes != null) && (supportedRes.length > 0)) {
1603
return supportedRes[0];
1604
} else {
1605
return new PrinterResolution(300, 300, PrinterResolution.DPI);
1606
}
1607
}
1608
1609
return null;
1610
}
1611
1612
private PrinterResolution[] getPrintResolutions() {
1613
if (printerResolutions == null) {
1614
if (rawResolutions == null) {
1615
printerResolutions = new PrinterResolution[0];
1616
} else {
1617
int numRes = rawResolutions.length / 2;
1618
PrinterResolution[] pres = new PrinterResolution[numRes];
1619
for (int i=0; i < numRes; i++) {
1620
pres[i] = new PrinterResolution(rawResolutions[i*2],
1621
rawResolutions[i*2+1],
1622
PrinterResolution.DPI);
1623
}
1624
printerResolutions = pres;
1625
}
1626
}
1627
return printerResolutions;
1628
}
1629
1630
private boolean isSupportedResolution(PrinterResolution res) {
1631
PrinterResolution[] supportedRes = getPrintResolutions();
1632
if (supportedRes != null) {
1633
for (int i=0; i<supportedRes.length; i++) {
1634
if (res.equals(supportedRes[i])) {
1635
return true;
1636
}
1637
}
1638
}
1639
return false;
1640
}
1641
1642
public ServiceUIFactory getServiceUIFactory() {
1643
return null;
1644
}
1645
1646
public void wakeNotifier() {
1647
synchronized (this) {
1648
if (notifier != null) {
1649
notifier.wake();
1650
}
1651
}
1652
}
1653
1654
public void addPrintServiceAttributeListener(
1655
PrintServiceAttributeListener listener) {
1656
synchronized (this) {
1657
if (listener == null) {
1658
return;
1659
}
1660
if (notifier == null) {
1661
notifier = new ServiceNotifier(this);
1662
}
1663
notifier.addListener(listener);
1664
}
1665
}
1666
1667
public void removePrintServiceAttributeListener(
1668
PrintServiceAttributeListener listener) {
1669
synchronized (this) {
1670
if (listener == null || notifier == null ) {
1671
return;
1672
}
1673
notifier.removeListener(listener);
1674
if (notifier.isEmpty()) {
1675
notifier.stopNotifier();
1676
notifier = null;
1677
}
1678
}
1679
}
1680
1681
String getDest() {
1682
return printer;
1683
}
1684
1685
public String getName() {
1686
/*
1687
* Mac is using printer-info IPP attribute for its human-readable printer
1688
* name and is also the identifier used in NSPrintInfo:setPrinter.
1689
*/
1690
if (PrintServiceLookupProvider.isMac()) {
1691
PrintServiceAttributeSet psaSet = this.getAttributes();
1692
if (psaSet != null) {
1693
PrinterInfo pName = (PrinterInfo)psaSet.get(PrinterInfo.class);
1694
if (pName != null) {
1695
return pName.toString();
1696
}
1697
}
1698
}
1699
return printer;
1700
}
1701
1702
1703
public boolean usesClass(Class<?> c) {
1704
return (c == sun.print.PSPrinterJob.class);
1705
}
1706
1707
1708
public static HttpURLConnection getIPPConnection(URL url) {
1709
HttpURLConnection connection;
1710
URLConnection urlc;
1711
try {
1712
urlc = url.openConnection();
1713
} catch (java.io.IOException ioe) {
1714
return null;
1715
}
1716
if (!(urlc instanceof HttpURLConnection)) {
1717
return null;
1718
}
1719
connection = (HttpURLConnection)urlc;
1720
connection.setUseCaches(false);
1721
connection.setDoInput(true);
1722
connection.setDoOutput(true);
1723
connection.setRequestProperty("Content-type", "application/ipp");
1724
return connection;
1725
}
1726
1727
1728
public synchronized boolean isPostscript() {
1729
if (isPS == null) {
1730
isPS = Boolean.TRUE;
1731
if (isCupsPrinter) {
1732
try {
1733
urlConnection = getIPPConnection(
1734
new URL(myURL+".ppd"));
1735
1736
InputStream is = urlConnection.getInputStream();
1737
if (is != null) {
1738
BufferedReader d =
1739
new BufferedReader(new InputStreamReader(is,
1740
Charset.forName("ISO-8859-1")));
1741
String lineStr;
1742
while ((lineStr = d.readLine()) != null) {
1743
if (lineStr.startsWith("*cupsFilter:")) {
1744
isPS = Boolean.FALSE;
1745
break;
1746
}
1747
}
1748
}
1749
} catch (java.io.IOException e) {
1750
debug_println(" isPostscript, e= "+e);
1751
/* if PPD is not found, this may be a raw printer
1752
and in this case it is assumed that it is a
1753
Postscript printer */
1754
// do nothing
1755
}
1756
}
1757
}
1758
return isPS.booleanValue();
1759
}
1760
1761
1762
private void opGetAttributes() {
1763
try {
1764
debug_println(debugPrefix+"opGetAttributes myURI "+myURI+" myURL "+myURL);
1765
1766
AttributeClass[] attClNoUri = {
1767
AttributeClass.ATTRIBUTES_CHARSET,
1768
AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE};
1769
1770
AttributeClass[] attCl = {
1771
AttributeClass.ATTRIBUTES_CHARSET,
1772
AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
1773
new AttributeClass("printer-uri",
1774
AttributeClass.TAG_URI,
1775
""+myURI)};
1776
1777
@SuppressWarnings("removal")
1778
OutputStream os = java.security.AccessController.
1779
doPrivileged(new java.security.PrivilegedAction<OutputStream>() {
1780
public OutputStream run() {
1781
try {
1782
return urlConnection.getOutputStream();
1783
} catch (Exception e) {
1784
}
1785
return null;
1786
}
1787
});
1788
1789
if (os == null) {
1790
return;
1791
}
1792
1793
boolean success = (myURI == null) ?
1794
writeIPPRequest(os, OP_GET_ATTRIBUTES, attClNoUri) :
1795
writeIPPRequest(os, OP_GET_ATTRIBUTES, attCl);
1796
if (success) {
1797
InputStream is = null;
1798
if ((is = urlConnection.getInputStream())!=null) {
1799
HashMap<String, AttributeClass>[] responseMap = readIPPResponse(is);
1800
1801
if (responseMap != null && responseMap.length > 0) {
1802
getAttMap = responseMap[0];
1803
// If there is extra hashmap created due to duplicate
1804
// key/attribute present in IPPresponse, then use that
1805
// map too by appending to getAttMap after removing the
1806
// duplicate key/value
1807
if (responseMap.length > 1) {
1808
for (int i = 1; i < responseMap.length; i++) {
1809
for (Map.Entry<String, AttributeClass> entry : responseMap[i].entrySet()) {
1810
if (!getAttMap.containsKey(entry.getValue())) {
1811
getAttMap.put(entry.getKey(), entry.getValue());
1812
}
1813
}
1814
}
1815
}
1816
}
1817
} else {
1818
debug_println(debugPrefix+"opGetAttributes - null input stream");
1819
}
1820
is.close();
1821
}
1822
os.close();
1823
} catch (java.io.IOException e) {
1824
debug_println(debugPrefix+"opGetAttributes - input/output stream: "+e);
1825
}
1826
}
1827
1828
1829
public static boolean writeIPPRequest(OutputStream os,
1830
String operCode,
1831
AttributeClass[] attCl) {
1832
OutputStreamWriter osw;
1833
try {
1834
osw = new OutputStreamWriter(os, "UTF-8");
1835
} catch (java.io.UnsupportedEncodingException exc) {
1836
debug_println(debugPrefix+"writeIPPRequest, UTF-8 not supported? Exception: "+exc);
1837
return false;
1838
}
1839
debug_println(debugPrefix+"writeIPPRequest, op code= "+operCode);
1840
char[] opCode = new char[2];
1841
opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16);
1842
opCode[1] = (char)Byte.parseByte(operCode.substring(2,4), 16);
1843
char[] bytes = {0x01, 0x01, 0x00, 0x01};
1844
try {
1845
osw.write(bytes, 0, 2); // version number
1846
osw.write(opCode, 0, 2); // operation code
1847
bytes[0] = 0x00; bytes[1] = 0x00;
1848
osw.write(bytes, 0, 4); // request ID #1
1849
1850
bytes[0] = 0x01; // operation-group-tag
1851
osw.write(bytes[0]);
1852
1853
String valStr;
1854
char[] lenStr;
1855
1856
AttributeClass ac;
1857
for (int i=0; i < attCl.length; i++) {
1858
ac = attCl[i];
1859
osw.write(ac.getType()); // value tag
1860
1861
lenStr = ac.getLenChars();
1862
osw.write(lenStr, 0, 2); // length
1863
osw.write(""+ac, 0, ac.getName().length());
1864
1865
// check if string range (0x35 -> 0x49)
1866
if (ac.getType() >= AttributeClass.TAG_TEXT_LANGUAGE &&
1867
ac.getType() <= AttributeClass.TAG_MIME_MEDIATYPE){
1868
valStr = (String)ac.getObjectValue();
1869
bytes[0] = 0; bytes[1] = (char)valStr.length();
1870
osw.write(bytes, 0, 2);
1871
osw.write(valStr, 0, valStr.length());
1872
} // REMIND: need to support other value tags but for CUPS
1873
// string is all we need.
1874
}
1875
1876
osw.write(GRPTAG_END_ATTRIBUTES);
1877
osw.flush();
1878
osw.close();
1879
} catch (java.io.IOException ioe) {
1880
debug_println(debugPrefix+"writeIPPRequest, IPPPrintService Exception in writeIPPRequest: "+ioe);
1881
return false;
1882
}
1883
return true;
1884
}
1885
1886
1887
public static HashMap<String, AttributeClass>[] readIPPResponse(InputStream inputStream) {
1888
1889
if (inputStream == null) {
1890
return null;
1891
}
1892
1893
byte[] response = new byte[MAX_ATTRIBUTE_LENGTH];
1894
try {
1895
1896
DataInputStream ois = new DataInputStream(inputStream);
1897
1898
// read status and ID
1899
if ((ois.read(response, 0, 8) > -1) &&
1900
(response[2] == STATUSCODE_SUCCESS)) {
1901
1902
ByteArrayOutputStream outObj;
1903
int counter=0;
1904
short len = 0;
1905
String attribStr = null;
1906
// assign default value
1907
byte valTagByte = AttributeClass.TAG_KEYWORD;
1908
ArrayList<HashMap<String, AttributeClass>> respList = new ArrayList<>();
1909
HashMap<String, AttributeClass> responseMap = new HashMap<>();
1910
1911
response[0] = ois.readByte();
1912
1913
// check for group tags
1914
while ((response[0] >= GRPTAG_OP_ATTRIBUTES) &&
1915
(response[0] <= GRPTAG_PRINTER_ATTRIBUTES)
1916
&& (response[0] != GRPTAG_END_ATTRIBUTES)) {
1917
debug_println(debugPrefix+"readIPPResponse, checking group tag, response[0]= "+
1918
response[0]);
1919
1920
outObj = new ByteArrayOutputStream();
1921
//make sure counter and attribStr are re-initialized
1922
counter = 0;
1923
attribStr = null;
1924
1925
// read value tag
1926
response[0] = ois.readByte();
1927
while (response[0] >= AttributeClass.TAG_UNSUPPORTED_VALUE &&
1928
response[0] <= AttributeClass.TAG_MEMBER_ATTRNAME) {
1929
// read name length
1930
len = ois.readShort();
1931
1932
// If current value is not part of previous attribute
1933
// then close stream and add it to HashMap.
1934
// It is part of previous attribute if name length=0.
1935
if ((len != 0) && (attribStr != null)) {
1936
//last byte is the total # of values
1937
outObj.write(counter);
1938
outObj.flush();
1939
outObj.close();
1940
byte[] outArray = outObj.toByteArray();
1941
1942
// if key exists, new HashMap
1943
if (responseMap.containsKey(attribStr)) {
1944
respList.add(responseMap);
1945
responseMap = new HashMap<>();
1946
}
1947
1948
// exclude those that are unknown
1949
if (valTagByte >= AttributeClass.TAG_INT) {
1950
AttributeClass ac =
1951
new AttributeClass(attribStr,
1952
valTagByte,
1953
outArray);
1954
1955
responseMap.put(ac.getName(), ac);
1956
debug_println(debugPrefix+ "readIPPResponse "+ac);
1957
}
1958
1959
outObj = new ByteArrayOutputStream();
1960
counter = 0; //reset counter
1961
}
1962
//check if this is new value tag
1963
if (counter == 0) {
1964
valTagByte = response[0];
1965
}
1966
// read attribute name
1967
if (len != 0) {
1968
// read "len" characters
1969
// make sure it doesn't exceed the maximum
1970
if (len > MAX_ATTRIBUTE_LENGTH) {
1971
response = new byte[len]; // expand as needed
1972
}
1973
ois.read(response, 0, len);
1974
attribStr = new String(response, 0, len);
1975
}
1976
// read value length
1977
len = ois.readShort();
1978
// write name length
1979
outObj.write(len);
1980
// read value, make sure it doesn't exceed the maximum
1981
if (len > MAX_ATTRIBUTE_LENGTH) {
1982
response = new byte[len]; // expand as needed
1983
}
1984
ois.read(response, 0, len);
1985
// write value of "len" length
1986
outObj.write(response, 0, len);
1987
counter++;
1988
// read next byte
1989
response[0] = ois.readByte();
1990
}
1991
1992
if (attribStr != null) {
1993
outObj.write(counter);
1994
outObj.flush();
1995
outObj.close();
1996
1997
// if key exists in old HashMap, new HashMap
1998
if ((counter != 0) &&
1999
responseMap.containsKey(attribStr)) {
2000
respList.add(responseMap);
2001
responseMap = new HashMap<>();
2002
}
2003
2004
byte[] outArray = outObj.toByteArray();
2005
2006
AttributeClass ac =
2007
new AttributeClass(attribStr,
2008
valTagByte,
2009
outArray);
2010
responseMap.put(ac.getName(), ac);
2011
}
2012
}
2013
ois.close();
2014
if ((responseMap != null) && (responseMap.size() > 0)) {
2015
respList.add(responseMap);
2016
}
2017
@SuppressWarnings({"unchecked", "rawtypes"})
2018
HashMap<String, AttributeClass>[] tmp =
2019
respList.toArray((HashMap<String, AttributeClass>[])new HashMap[respList.size()]);
2020
return tmp;
2021
} else {
2022
debug_println(debugPrefix+
2023
"readIPPResponse client error, IPP status code: 0x"+
2024
toHex(response[2]) + toHex(response[3]));
2025
return null;
2026
}
2027
2028
} catch (java.io.IOException e) {
2029
debug_println(debugPrefix+"readIPPResponse: "+e);
2030
if (debugPrint) {
2031
e.printStackTrace();
2032
}
2033
return null;
2034
}
2035
}
2036
2037
private static String toHex(byte v) {
2038
String s = Integer.toHexString(v&0xff);
2039
return (s.length() == 2) ? s : "0"+s;
2040
}
2041
2042
public String toString() {
2043
return "IPP Printer : " + getName();
2044
}
2045
2046
public boolean equals(Object obj) {
2047
return (obj == this ||
2048
(obj instanceof IPPPrintService &&
2049
((IPPPrintService)obj).getName().equals(getName())));
2050
}
2051
2052
public int hashCode() {
2053
return this.getClass().hashCode()+getName().hashCode();
2054
}
2055
}
2056
2057