Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
41152 views
1
/*
2
* Copyright (c) 2000, 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.io.BufferedReader;
29
import java.io.FileInputStream;
30
import java.io.InputStream;
31
import java.io.InputStreamReader;
32
import java.io.IOException;
33
import java.util.ArrayList;
34
import java.util.Vector;
35
import java.security.AccessController;
36
import java.security.PrivilegedActionException;
37
import java.security.PrivilegedExceptionAction;
38
import javax.print.DocFlavor;
39
import javax.print.MultiDocPrintService;
40
import javax.print.PrintService;
41
import javax.print.PrintServiceLookup;
42
import javax.print.attribute.Attribute;
43
import javax.print.attribute.AttributeSet;
44
import javax.print.attribute.HashPrintRequestAttributeSet;
45
import javax.print.attribute.HashPrintServiceAttributeSet;
46
import javax.print.attribute.PrintRequestAttribute;
47
import javax.print.attribute.PrintRequestAttributeSet;
48
import javax.print.attribute.PrintServiceAttribute;
49
import javax.print.attribute.PrintServiceAttributeSet;
50
import javax.print.attribute.standard.PrinterName;
51
import javax.print.attribute.standard.PrinterURI;
52
import java.io.File;
53
import java.io.FileReader;
54
import java.net.URL;
55
import java.nio.file.Files;
56
57
/*
58
* Remind: This class uses solaris commands. We also need a linux
59
* version
60
*/
61
@SuppressWarnings("removal")
62
public class PrintServiceLookupProvider extends PrintServiceLookup
63
implements BackgroundServiceLookup, Runnable {
64
65
/* Remind: the current implementation is static, as its assumed
66
* its preferable to minimize creation of PrintService instances.
67
* Later we should add logic to add/remove services on the fly which
68
* will take a hit of needing to regather the list of services.
69
*/
70
private String defaultPrinter;
71
private PrintService defaultPrintService;
72
private PrintService[] printServices; /* includes the default printer */
73
private Vector<BackgroundLookupListener> lookupListeners = null;
74
private static String debugPrefix = "PrintServiceLookupProvider>> ";
75
private static boolean pollServices = true;
76
private static final int DEFAULT_MINREFRESH = 120; // 2 minutes
77
private static int minRefreshTime = DEFAULT_MINREFRESH;
78
79
80
static String osname;
81
82
// List of commands used to deal with the printer queues on AIX
83
String[] lpNameComAix = {
84
"/usr/bin/lsallq",
85
"/usr/bin/lpstat -W -p|/usr/bin/expand|/usr/bin/cut -f1 -d' '",
86
"/usr/bin/lpstat -W -d|/usr/bin/expand|/usr/bin/cut -f1 -d' '",
87
"/usr/bin/lpstat -W -v"
88
};
89
private static final int aix_lsallq = 0;
90
private static final int aix_lpstat_p = 1;
91
private static final int aix_lpstat_d = 2;
92
private static final int aix_lpstat_v = 3;
93
private static int aix_defaultPrinterEnumeration = aix_lsallq;
94
95
static {
96
/* The system property "sun.java2d.print.polling"
97
* can be used to force the printing code to poll or not poll
98
* for PrintServices.
99
*/
100
String pollStr = java.security.AccessController.doPrivileged(
101
new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
102
103
if (pollStr != null) {
104
if (pollStr.equalsIgnoreCase("true")) {
105
pollServices = true;
106
} else if (pollStr.equalsIgnoreCase("false")) {
107
pollServices = false;
108
}
109
}
110
111
/* The system property "sun.java2d.print.minRefreshTime"
112
* can be used to specify minimum refresh time (in seconds)
113
* for polling PrintServices. The default is 120.
114
*/
115
String refreshTimeStr = java.security.AccessController.doPrivileged(
116
new sun.security.action.GetPropertyAction(
117
"sun.java2d.print.minRefreshTime"));
118
119
if (refreshTimeStr != null) {
120
try {
121
minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
122
} catch (NumberFormatException e) {
123
}
124
if (minRefreshTime < DEFAULT_MINREFRESH) {
125
minRefreshTime = DEFAULT_MINREFRESH;
126
}
127
}
128
129
osname = java.security.AccessController.doPrivileged(
130
new sun.security.action.GetPropertyAction("os.name"));
131
132
/* The system property "sun.java2d.print.aix.lpstat"
133
* can be used to force the usage of 'lpstat -p' to enumerate all
134
* printer queues. By default we use 'lsallq', because 'lpstat -p' can
135
* take lots of time if thousands of printers are attached to a server.
136
*/
137
if (isAIX()) {
138
String aixPrinterEnumerator = java.security.AccessController.doPrivileged(
139
new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat"));
140
141
if (aixPrinterEnumerator != null) {
142
if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) {
143
aix_defaultPrinterEnumeration = aix_lpstat_p;
144
} else if (aixPrinterEnumerator.equalsIgnoreCase("lsallq")) {
145
aix_defaultPrinterEnumeration = aix_lsallq;
146
}
147
}
148
}
149
}
150
151
static boolean isMac() {
152
return osname.startsWith("Mac");
153
}
154
155
static boolean isLinux() {
156
return (osname.equals("Linux"));
157
}
158
159
static boolean isBSD() {
160
return (osname.equals("Linux") ||
161
osname.contains("OS X"));
162
}
163
164
static boolean isAIX() {
165
return osname.equals("AIX");
166
}
167
168
static final int UNINITIALIZED = -1;
169
static final int BSD_LPD = 0;
170
static final int BSD_LPD_NG = 1;
171
172
static int cmdIndex = UNINITIALIZED;
173
174
String[] lpcFirstCom = {
175
"/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'",
176
"/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'"
177
};
178
179
String[] lpcAllCom = {
180
"/usr/sbin/lpc status all | grep : | sed -e 's/://'",
181
"/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort"
182
};
183
184
String[] lpcNameCom = {
185
"| grep : | sed -ne 's/://p'",
186
"| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'"
187
};
188
189
190
static int getBSDCommandIndex() {
191
String command = "/usr/sbin/lpc status all";
192
String[] names = execCmd(command);
193
194
if ((names == null) || (names.length == 0)) {
195
return BSD_LPD_NG;
196
}
197
198
for (int i=0; i<names.length; i++) {
199
if (names[i].indexOf('@') != -1) {
200
return BSD_LPD_NG;
201
}
202
}
203
204
return BSD_LPD;
205
}
206
207
208
public PrintServiceLookupProvider() {
209
// start the printer listener thread
210
if (pollServices) {
211
Thread thr = new Thread(null, new PrinterChangeListener(),
212
"PrinterListener", 0, false);
213
thr.setDaemon(true);
214
thr.start();
215
IPPPrintService.debug_println(debugPrefix+"polling turned on");
216
}
217
}
218
219
/* Want the PrintService which is default print service to have
220
* equality of reference with the equivalent in list of print services
221
* This isn't required by the API and there's a risk doing this will
222
* lead people to assume its guaranteed.
223
*/
224
public synchronized PrintService[] getPrintServices() {
225
SecurityManager security = System.getSecurityManager();
226
if (security != null) {
227
security.checkPrintJobAccess();
228
}
229
230
if (printServices == null || !pollServices) {
231
refreshServices();
232
}
233
if (printServices == null) {
234
return new PrintService[0];
235
} else {
236
return printServices.clone();
237
}
238
}
239
240
private int addPrintServiceToList(ArrayList<PrintService> printerList, PrintService ps) {
241
int index = printerList.indexOf(ps);
242
// Check if PrintService with same name is already in the list.
243
if (CUPSPrinter.isCupsRunning() && index != -1) {
244
// Bug in Linux: Duplicate entry of a remote printer
245
// and treats it as local printer but it is returning wrong
246
// information when queried using IPP. Workaround is to remove it.
247
// Even CUPS ignores these entries as shown in lpstat or using
248
// their web configuration.
249
PrinterURI uri = ps.getAttribute(PrinterURI.class);
250
if (uri.getURI().getHost().equals("localhost")) {
251
IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps);
252
return index; // Do not add this.
253
}
254
PrintService oldPS = printerList.get(index);
255
uri = oldPS.getAttribute(PrinterURI.class);
256
if (uri.getURI().getHost().equals("localhost")) {
257
IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS);
258
printerList.remove(oldPS);
259
} else {
260
return index;
261
}
262
}
263
printerList.add(ps);
264
return (printerList.size() - 1);
265
}
266
267
268
// refreshes "printServices"
269
public synchronized void refreshServices() {
270
/* excludes the default printer */
271
String[] printers = null; // array of printer names
272
String[] printerURIs = null; //array of printer URIs
273
274
try {
275
getDefaultPrintService();
276
} catch (Throwable t) {
277
IPPPrintService.debug_println(debugPrefix+
278
"Exception getting default printer : " + t);
279
}
280
if (CUPSPrinter.isCupsRunning()) {
281
try {
282
printerURIs = CUPSPrinter.getAllPrinters();
283
IPPPrintService.debug_println("CUPS URIs = " + printerURIs);
284
if (printerURIs != null) {
285
for (int p = 0; p < printerURIs.length; p++) {
286
IPPPrintService.debug_println("URI="+printerURIs[p]);
287
}
288
}
289
} catch (Throwable t) {
290
IPPPrintService.debug_println(debugPrefix+
291
"Exception getting all CUPS printers : " + t);
292
}
293
if ((printerURIs != null) && (printerURIs.length > 0)) {
294
printers = new String[printerURIs.length];
295
for (int i=0; i<printerURIs.length; i++) {
296
int lastIndex = printerURIs[i].lastIndexOf("/");
297
printers[i] = printerURIs[i].substring(lastIndex+1);
298
}
299
}
300
} else {
301
if (isMac()) {
302
printers = getAllPrinterNamesSysV();
303
} else if (isAIX()) {
304
printers = getAllPrinterNamesAIX();
305
} else { //BSD
306
printers = getAllPrinterNamesBSD();
307
}
308
}
309
310
if (printers == null) {
311
if (defaultPrintService != null) {
312
printServices = new PrintService[1];
313
printServices[0] = defaultPrintService;
314
} else {
315
printServices = null;
316
}
317
return;
318
}
319
320
ArrayList<PrintService> printerList = new ArrayList<>();
321
int defaultIndex = -1;
322
for (int p=0; p<printers.length; p++) {
323
if (printers[p] == null) {
324
continue;
325
}
326
if ((defaultPrintService != null)
327
&& printers[p].equals(getPrinterDestName(defaultPrintService))) {
328
defaultIndex = addPrintServiceToList(printerList, defaultPrintService);
329
} else {
330
if (printServices == null) {
331
IPPPrintService.debug_println(debugPrefix+
332
"total# of printers = "+printers.length);
333
334
if (CUPSPrinter.isCupsRunning()) {
335
try {
336
addPrintServiceToList(printerList,
337
new IPPPrintService(printers[p],
338
printerURIs[p],
339
true));
340
} catch (Exception e) {
341
IPPPrintService.debug_println(debugPrefix+
342
" getAllPrinters Exception "+
343
e);
344
345
}
346
} else {
347
printerList.add(new UnixPrintService(printers[p]));
348
}
349
} else {
350
int j;
351
for (j=0; j<printServices.length; j++) {
352
if (printServices[j] != null) {
353
if (printers[p].equals(getPrinterDestName(printServices[j]))) {
354
printerList.add(printServices[j]);
355
printServices[j] = null;
356
break;
357
}
358
}
359
}
360
361
if (j == printServices.length) { // not found?
362
if (CUPSPrinter.isCupsRunning()) {
363
try {
364
addPrintServiceToList(printerList,
365
new IPPPrintService(printers[p],
366
printerURIs[p],
367
true));
368
} catch (Exception e) {
369
IPPPrintService.debug_println(debugPrefix+
370
" getAllPrinters Exception "+
371
e);
372
373
}
374
} else {
375
printerList.add(new UnixPrintService(printers[p]));
376
}
377
}
378
}
379
}
380
}
381
382
// Look for deleted services and invalidate these
383
if (printServices != null) {
384
for (int j=0; j < printServices.length; j++) {
385
if ((printServices[j] instanceof UnixPrintService) &&
386
(!printServices[j].equals(defaultPrintService))) {
387
((UnixPrintService)printServices[j]).invalidateService();
388
}
389
}
390
}
391
392
//if defaultService is not found in printerList
393
if (defaultIndex == -1 && defaultPrintService != null) {
394
defaultIndex = addPrintServiceToList(printerList, defaultPrintService);
395
}
396
397
printServices = printerList.toArray(new PrintService[] {});
398
399
// swap default with the first in the list
400
if (defaultIndex > 0) {
401
PrintService saveService = printServices[0];
402
printServices[0] = printServices[defaultIndex];
403
printServices[defaultIndex] = saveService;
404
}
405
}
406
407
private boolean matchesAttributes(PrintService service,
408
PrintServiceAttributeSet attributes) {
409
410
Attribute [] attrs = attributes.toArray();
411
for (int i=0; i<attrs.length; i++) {
412
@SuppressWarnings("unchecked")
413
Attribute serviceAttr
414
= service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());
415
if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {
416
return false;
417
}
418
}
419
return true;
420
}
421
422
/* This checks for validity of the printer name before passing as
423
* parameter to a shell command.
424
*/
425
private boolean checkPrinterName(String s) {
426
char c;
427
428
for (int i=0; i < s.length(); i++) {
429
c = s.charAt(i);
430
if (Character.isLetterOrDigit(c) ||
431
c == '-' || c == '_' || c == '.' || c == '/') {
432
continue;
433
} else {
434
return false;
435
}
436
}
437
return true;
438
}
439
440
/*
441
* Gets the printer name compatible with the list of printers returned by
442
* the system when we query default or all the available printers.
443
*/
444
private String getPrinterDestName(PrintService ps) {
445
if (isMac()) {
446
return ((IPPPrintService)ps).getDest();
447
}
448
return ps.getName();
449
}
450
451
/* On a network with many (hundreds) of network printers, it
452
* can save several seconds if you know all you want is a particular
453
* printer, to ask for that printer rather than retrieving all printers.
454
*/
455
private PrintService getServiceByName(PrinterName nameAttr) {
456
String name = nameAttr.getValue();
457
if (name == null || name.isEmpty() || !checkPrinterName(name)) {
458
return null;
459
}
460
/* check if all printers are already available */
461
if (printServices != null) {
462
for (PrintService printService : printServices) {
463
PrinterName printerName = printService.getAttribute(PrinterName.class);
464
if (printerName.getValue().equals(name)) {
465
return printService;
466
}
467
}
468
}
469
/* take CUPS into account first */
470
if (CUPSPrinter.isCupsRunning()) {
471
try {
472
return new IPPPrintService(name,
473
new URL("http://"+
474
CUPSPrinter.getServer()+":"+
475
CUPSPrinter.getPort()+"/"+
476
name));
477
} catch (Exception e) {
478
IPPPrintService.debug_println(debugPrefix+
479
" getServiceByName Exception "+
480
e);
481
}
482
}
483
/* fallback if nothing not having a printer at this point */
484
PrintService printer = null;
485
if (isMac()) {
486
printer = getNamedPrinterNameSysV(name);
487
} else if (isAIX()) {
488
printer = getNamedPrinterNameAIX(name);
489
} else {
490
printer = getNamedPrinterNameBSD(name);
491
}
492
return printer;
493
}
494
495
private PrintService[]
496
getPrintServices(PrintServiceAttributeSet serviceSet) {
497
498
if (serviceSet == null || serviceSet.isEmpty()) {
499
return getPrintServices();
500
}
501
502
/* Typically expect that if a service attribute is specified that
503
* its a printer name and there ought to be only one match.
504
* Directly retrieve that service and confirm
505
* that it meets the other requirements.
506
* If printer name isn't mentioned then go a slow path checking
507
* all printers if they meet the reqiremements.
508
*/
509
PrintService[] services;
510
PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);
511
PrintService defService;
512
if (name != null && (defService = getDefaultPrintService()) != null) {
513
/* To avoid execing a unix command see if the client is asking
514
* for the default printer by name, since we already have that
515
* initialised.
516
*/
517
518
PrinterName defName = defService.getAttribute(PrinterName.class);
519
520
if (defName != null && name.equals(defName)) {
521
if (matchesAttributes(defService, serviceSet)) {
522
services = new PrintService[1];
523
services[0] = defService;
524
return services;
525
} else {
526
return new PrintService[0];
527
}
528
} else {
529
/* Its not the default service */
530
PrintService service = getServiceByName(name);
531
if (service != null &&
532
matchesAttributes(service, serviceSet)) {
533
services = new PrintService[1];
534
services[0] = service;
535
return services;
536
} else {
537
return new PrintService[0];
538
}
539
}
540
} else {
541
/* specified service attributes don't include a name.*/
542
Vector<PrintService> matchedServices = new Vector<>();
543
services = getPrintServices();
544
for (int i = 0; i< services.length; i++) {
545
if (matchesAttributes(services[i], serviceSet)) {
546
matchedServices.add(services[i]);
547
}
548
}
549
services = new PrintService[matchedServices.size()];
550
for (int i = 0; i< services.length; i++) {
551
services[i] = matchedServices.elementAt(i);
552
}
553
return services;
554
}
555
}
556
557
/*
558
* If service attributes are specified then there must be additional
559
* filtering.
560
*/
561
public PrintService[] getPrintServices(DocFlavor flavor,
562
AttributeSet attributes) {
563
SecurityManager security = System.getSecurityManager();
564
if (security != null) {
565
security.checkPrintJobAccess();
566
}
567
PrintRequestAttributeSet requestSet = null;
568
PrintServiceAttributeSet serviceSet = null;
569
570
if (attributes != null && !attributes.isEmpty()) {
571
572
requestSet = new HashPrintRequestAttributeSet();
573
serviceSet = new HashPrintServiceAttributeSet();
574
575
Attribute[] attrs = attributes.toArray();
576
for (int i=0; i<attrs.length; i++) {
577
if (attrs[i] instanceof PrintRequestAttribute) {
578
requestSet.add(attrs[i]);
579
} else if (attrs[i] instanceof PrintServiceAttribute) {
580
serviceSet.add(attrs[i]);
581
}
582
}
583
}
584
585
PrintService[] services = getPrintServices(serviceSet);
586
if (services.length == 0) {
587
return services;
588
}
589
590
if (CUPSPrinter.isCupsRunning()) {
591
ArrayList<PrintService> matchingServices = new ArrayList<>();
592
for (int i=0; i<services.length; i++) {
593
try {
594
if (services[i].
595
getUnsupportedAttributes(flavor, requestSet) == null) {
596
matchingServices.add(services[i]);
597
}
598
} catch (IllegalArgumentException e) {
599
}
600
}
601
services = new PrintService[matchingServices.size()];
602
return matchingServices.toArray(services);
603
604
} else {
605
// We only need to compare 1 PrintService because all
606
// UnixPrintServices are the same anyway. We will not use
607
// default PrintService because it might be null.
608
PrintService service = services[0];
609
if ((flavor == null ||
610
service.isDocFlavorSupported(flavor)) &&
611
service.getUnsupportedAttributes(flavor, requestSet) == null)
612
{
613
return services;
614
} else {
615
return new PrintService[0];
616
}
617
}
618
}
619
620
/*
621
* return empty array as don't support multi docs
622
*/
623
public MultiDocPrintService[]
624
getMultiDocPrintServices(DocFlavor[] flavors,
625
AttributeSet attributes) {
626
SecurityManager security = System.getSecurityManager();
627
if (security != null) {
628
security.checkPrintJobAccess();
629
}
630
return new MultiDocPrintService[0];
631
}
632
633
634
public synchronized PrintService getDefaultPrintService() {
635
SecurityManager security = System.getSecurityManager();
636
if (security != null) {
637
security.checkPrintJobAccess();
638
}
639
640
// clear defaultPrintService
641
defaultPrintService = null;
642
String psuri = null;
643
644
IPPPrintService.debug_println("isRunning ? "+
645
(CUPSPrinter.isCupsRunning()));
646
if (CUPSPrinter.isCupsRunning()) {
647
String[] printerInfo = CUPSPrinter.getDefaultPrinter();
648
if (printerInfo != null && printerInfo.length >= 2) {
649
defaultPrinter = printerInfo[0];
650
psuri = printerInfo[1];
651
}
652
} else {
653
if (isMac()) {
654
defaultPrinter = getDefaultPrinterNameSysV();
655
} else if (isAIX()) {
656
defaultPrinter = getDefaultPrinterNameAIX();
657
} else {
658
defaultPrinter = getDefaultPrinterNameBSD();
659
}
660
}
661
if (defaultPrinter == null) {
662
return null;
663
}
664
defaultPrintService = null;
665
if (printServices != null) {
666
for (int j=0; j<printServices.length; j++) {
667
if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) {
668
defaultPrintService = printServices[j];
669
break;
670
}
671
}
672
}
673
if (defaultPrintService == null) {
674
if (CUPSPrinter.isCupsRunning()) {
675
try {
676
PrintService defaultPS;
677
if ((psuri != null) && !psuri.startsWith("file")) {
678
defaultPS = new IPPPrintService(defaultPrinter,
679
psuri, true);
680
} else {
681
defaultPS = new IPPPrintService(defaultPrinter,
682
new URL("http://"+
683
CUPSPrinter.getServer()+":"+
684
CUPSPrinter.getPort()+"/"+
685
defaultPrinter));
686
}
687
defaultPrintService = defaultPS;
688
} catch (Exception e) {
689
}
690
} else {
691
defaultPrintService = new UnixPrintService(defaultPrinter);
692
}
693
}
694
695
return defaultPrintService;
696
}
697
698
public synchronized void
699
getServicesInbackground(BackgroundLookupListener listener) {
700
if (printServices != null) {
701
listener.notifyServices(printServices);
702
} else {
703
if (lookupListeners == null) {
704
lookupListeners = new Vector<>();
705
lookupListeners.add(listener);
706
Thread lookupThread = new Thread(this);
707
lookupThread.start();
708
} else {
709
lookupListeners.add(listener);
710
}
711
}
712
}
713
714
/* This method isn't used in most cases because we rely on code in
715
* javax.print.PrintServiceLookup. This is needed just for the cases
716
* where those interfaces are by-passed.
717
*/
718
private PrintService[] copyOf(PrintService[] inArr) {
719
if (inArr == null || inArr.length == 0) {
720
return inArr;
721
} else {
722
PrintService []outArr = new PrintService[inArr.length];
723
System.arraycopy(inArr, 0, outArr, 0, inArr.length);
724
return outArr;
725
}
726
}
727
728
public void run() {
729
PrintService[] services = getPrintServices();
730
synchronized (this) {
731
BackgroundLookupListener listener;
732
for (int i=0; i<lookupListeners.size(); i++) {
733
listener = lookupListeners.elementAt(i);
734
listener.notifyServices(copyOf(services));
735
}
736
lookupListeners = null;
737
}
738
}
739
740
private String getDefaultPrinterNameBSD() {
741
if (cmdIndex == UNINITIALIZED) {
742
cmdIndex = getBSDCommandIndex();
743
}
744
String[] names = execCmd(lpcFirstCom[cmdIndex]);
745
if (names == null || names.length == 0) {
746
return null;
747
}
748
749
if ((cmdIndex==BSD_LPD_NG) &&
750
(names[0].startsWith("missingprinter"))) {
751
return null;
752
}
753
return names[0];
754
}
755
756
private PrintService getNamedPrinterNameBSD(String name) {
757
if (cmdIndex == UNINITIALIZED) {
758
cmdIndex = getBSDCommandIndex();
759
}
760
String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex];
761
String[] result = execCmd(command);
762
763
if (result == null || !(result[0].equals(name))) {
764
return null;
765
}
766
return new UnixPrintService(name);
767
}
768
769
private String[] getAllPrinterNamesBSD() {
770
if (cmdIndex == UNINITIALIZED) {
771
cmdIndex = getBSDCommandIndex();
772
}
773
String[] names = execCmd(lpcAllCom[cmdIndex]);
774
if (names == null || names.length == 0) {
775
return null;
776
}
777
return names;
778
}
779
780
static String getDefaultPrinterNameSysV() {
781
String defaultPrinter = "lp";
782
String command = "/usr/bin/lpstat -d";
783
784
String [] names = execCmd(command);
785
if (names == null || names.length == 0) {
786
return defaultPrinter;
787
} else {
788
int index = names[0].indexOf(":");
789
if (index == -1 || (names[0].length() <= index+1)) {
790
return null;
791
} else {
792
String name = names[0].substring(index+1).trim();
793
if (name.length() == 0) {
794
return null;
795
} else {
796
return name;
797
}
798
}
799
}
800
}
801
802
private PrintService getNamedPrinterNameSysV(String name) {
803
804
String command = "/usr/bin/lpstat -v " + name;
805
String []result = execCmd(command);
806
807
if (result == null || result[0].indexOf("unknown printer") > 0) {
808
return null;
809
} else {
810
return new UnixPrintService(name);
811
}
812
}
813
814
private String[] getAllPrinterNamesSysV() {
815
String defaultPrinter = "lp";
816
String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort";
817
818
String [] names = execCmd(command);
819
ArrayList<String> printerNames = new ArrayList<>();
820
for (int i=0; i < names.length; i++) {
821
if (!names[i].equals("_default") &&
822
!names[i].equals(defaultPrinter) &&
823
!names[i].isEmpty()) {
824
printerNames.add(names[i]);
825
}
826
}
827
return printerNames.toArray(new String[printerNames.size()]);
828
}
829
830
private String getDefaultPrinterNameAIX() {
831
String[] names = execCmd(lpNameComAix[aix_lpstat_d]);
832
// Remove headers and bogus entries added by remote printers.
833
names = UnixPrintService.filterPrinterNamesAIX(names);
834
if (names == null || names.length != 1) {
835
// No default printer found
836
return null;
837
} else {
838
return names[0];
839
}
840
}
841
842
private PrintService getNamedPrinterNameAIX(String name) {
843
// On AIX there should be no blank after '-v'.
844
String[] result = execCmd(lpNameComAix[aix_lpstat_v] + name);
845
// Remove headers and bogus entries added by remote printers.
846
result = UnixPrintService.filterPrinterNamesAIX(result);
847
if (result == null || result.length != 1) {
848
return null;
849
} else {
850
return new UnixPrintService(name);
851
}
852
}
853
854
private String[] getAllPrinterNamesAIX() {
855
// Determine all printers of the system.
856
String [] names = execCmd(lpNameComAix[aix_defaultPrinterEnumeration]);
857
858
// Remove headers and bogus entries added by remote printers.
859
names = UnixPrintService.filterPrinterNamesAIX(names);
860
861
ArrayList<String> printerNames = new ArrayList<String>();
862
for ( int i=0; i < names.length; i++) {
863
printerNames.add(names[i]);
864
}
865
return printerNames.toArray(new String[printerNames.size()]);
866
}
867
868
static String[] execCmd(final String command) {
869
ArrayList<String> results = null;
870
try {
871
final String[] cmd = new String[3];
872
if (isAIX()) {
873
cmd[0] = "/usr/bin/sh";
874
cmd[1] = "-c";
875
cmd[2] = "env LC_ALL=C " + command;
876
} else {
877
cmd[0] = "/bin/sh";
878
cmd[1] = "-c";
879
cmd[2] = "LC_ALL=C " + command;
880
}
881
882
results = AccessController.doPrivileged(
883
new PrivilegedExceptionAction<ArrayList<String>>() {
884
public ArrayList<String> run() throws IOException {
885
886
Process proc;
887
BufferedReader bufferedReader = null;
888
File f = Files.createTempFile("prn","xc").toFile();
889
cmd[2] = cmd[2]+">"+f.getAbsolutePath();
890
891
proc = Runtime.getRuntime().exec(cmd);
892
try {
893
boolean done = false; // in case of interrupt.
894
while (!done) {
895
try {
896
proc.waitFor();
897
done = true;
898
} catch (InterruptedException e) {
899
}
900
}
901
902
if (proc.exitValue() == 0) {
903
FileReader reader = new FileReader(f);
904
bufferedReader = new BufferedReader(reader);
905
String line;
906
ArrayList<String> results = new ArrayList<>();
907
while ((line = bufferedReader.readLine())
908
!= null) {
909
results.add(line);
910
}
911
return results;
912
}
913
} finally {
914
f.delete();
915
// promptly close all streams.
916
if (bufferedReader != null) {
917
bufferedReader.close();
918
}
919
proc.getInputStream().close();
920
proc.getErrorStream().close();
921
proc.getOutputStream().close();
922
}
923
return null;
924
}
925
});
926
} catch (PrivilegedActionException e) {
927
}
928
if (results == null) {
929
return new String[0];
930
} else {
931
return results.toArray(new String[results.size()]);
932
}
933
}
934
935
private class PrinterChangeListener implements Runnable {
936
937
@Override
938
public void run() {
939
int refreshSecs;
940
while (true) {
941
try {
942
refreshServices();
943
} catch (Exception se) {
944
IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread.");
945
break;
946
}
947
948
if ((printServices != null) &&
949
(printServices.length > minRefreshTime)) {
950
// compute new refresh time 1 printer = 1 sec
951
refreshSecs = printServices.length;
952
} else {
953
refreshSecs = minRefreshTime;
954
}
955
try {
956
Thread.sleep(refreshSecs * 1000);
957
} catch (InterruptedException e) {
958
break;
959
}
960
}
961
}
962
}
963
}
964
965