Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/print/PrintServiceLookupProvider.java
32287 views
1
/*
2
* Copyright (c) 2000, 2019, 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.security.AccessController;
29
import java.util.ArrayList;
30
import java.util.Arrays;
31
import java.util.Comparator;
32
import javax.print.DocFlavor;
33
import javax.print.MultiDocPrintService;
34
import javax.print.PrintService;
35
import javax.print.PrintServiceLookup;
36
import javax.print.attribute.Attribute;
37
import javax.print.attribute.AttributeSet;
38
import javax.print.attribute.HashPrintRequestAttributeSet;
39
import javax.print.attribute.HashPrintServiceAttributeSet;
40
import javax.print.attribute.PrintRequestAttribute;
41
import javax.print.attribute.PrintRequestAttributeSet;
42
import javax.print.attribute.PrintServiceAttribute;
43
import javax.print.attribute.PrintServiceAttributeSet;
44
import javax.print.attribute.standard.PrinterName;
45
46
public class PrintServiceLookupProvider extends PrintServiceLookup {
47
48
private String defaultPrinter;
49
private PrintService defaultPrintService;
50
private String[] printers; /* excludes the default printer */
51
private PrintService[] printServices; /* includes the default printer */
52
53
private static final int DEFAULT_REFRESH_TIME = 240; // 4 minutes
54
private static final int MINIMUM_REFRESH_TIME = 120; // 2 minutes
55
private static final boolean pollServices;
56
private static final int refreshTime;
57
58
static {
59
/* The system property "sun.java2d.print.polling"
60
* can be used to force the printing code to poll or not poll
61
* for PrintServices.
62
*/
63
String pollStr = java.security.AccessController.doPrivileged(
64
new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
65
pollServices = !("false".equalsIgnoreCase(pollStr));
66
67
/* The system property "sun.java2d.print.minRefreshTime"
68
* can be used to specify minimum refresh time (in seconds)
69
* for polling PrintServices. The default is 240.
70
*/
71
String refreshTimeStr = java.security.AccessController.doPrivileged(
72
new sun.security.action.GetPropertyAction(
73
"sun.java2d.print.minRefreshTime"));
74
refreshTime = (refreshTimeStr != null)
75
? getRefreshTime(refreshTimeStr)
76
: DEFAULT_REFRESH_TIME;
77
78
java.security.AccessController.doPrivileged(
79
new java.security.PrivilegedAction<Void>() {
80
public Void run() {
81
System.loadLibrary("awt");
82
return null;
83
}
84
});
85
}
86
87
private static int getRefreshTime(final String refreshTimeStr) {
88
try {
89
int minRefreshTime = Integer.parseInt(refreshTimeStr);
90
return (minRefreshTime < MINIMUM_REFRESH_TIME)
91
? MINIMUM_REFRESH_TIME
92
: minRefreshTime;
93
} catch (NumberFormatException e) {
94
return DEFAULT_REFRESH_TIME;
95
}
96
}
97
98
/* The singleton win32 print lookup service.
99
* Code that is aware of this field and wants to use it must first
100
* see if its null, and if so instantiate it by calling a method such as
101
* javax.print.PrintServiceLookup.defaultPrintService() so that the
102
* same instance is stored there.
103
*/
104
private static PrintServiceLookupProvider win32PrintLUS;
105
106
/* Think carefully before calling this. Preferably don't call it. */
107
public static PrintServiceLookupProvider getWin32PrintLUS() {
108
if (win32PrintLUS == null) {
109
/* This call is internally synchronized.
110
* When it returns an instance of this class will have
111
* been instantiated - else there's a JDK internal error.
112
*/
113
PrintServiceLookup.lookupDefaultPrintService();
114
}
115
return win32PrintLUS;
116
}
117
118
public PrintServiceLookupProvider() {
119
120
if (win32PrintLUS == null) {
121
win32PrintLUS = this;
122
123
String osName = AccessController.doPrivileged(
124
new sun.security.action.GetPropertyAction("os.name"));
125
// There's no capability for Win98 to refresh printers.
126
// See "OpenPrinter" for more info.
127
if (osName != null && osName.startsWith("Windows 98")) {
128
return;
129
}
130
// start the local printer listener thread
131
Thread thr = new PrinterChangeListener();
132
thr.setDaemon(true);
133
thr.start();
134
135
if (pollServices) {
136
// start the remote printer listener thread
137
Thread remThr = new RemotePrinterChangeListener();
138
remThr.setDaemon(true);
139
remThr.start();
140
}
141
} /* else condition ought to never happen! */
142
}
143
144
/* Want the PrintService which is default print service to have
145
* equality of reference with the equivalent in list of print services
146
* This isn't required by the API and there's a risk doing this will
147
* lead people to assume its guaranteed.
148
*/
149
public synchronized PrintService[] getPrintServices() {
150
SecurityManager security = System.getSecurityManager();
151
if (security != null) {
152
security.checkPrintJobAccess();
153
}
154
if (printServices == null) {
155
refreshServices();
156
}
157
return printServices;
158
}
159
160
private synchronized void refreshServices() {
161
printers = getAllPrinterNames();
162
if (printers == null) {
163
// In Windows it is safe to assume no default if printers == null so we
164
// don't get the default.
165
printServices = new PrintService[0];
166
return;
167
}
168
169
PrintService[] newServices = new PrintService[printers.length];
170
PrintService defService = getDefaultPrintService();
171
for (int p = 0; p < printers.length; p++) {
172
if (defService != null &&
173
printers[p].equals(defService.getName())) {
174
newServices[p] = defService;
175
} else {
176
if (printServices == null) {
177
newServices[p] = new Win32PrintService(printers[p]);
178
} else {
179
int j;
180
for (j = 0; j < printServices.length; j++) {
181
if ((printServices[j]!= null) &&
182
(printers[p].equals(printServices[j].getName()))) {
183
newServices[p] = printServices[j];
184
printServices[j] = null;
185
break;
186
}
187
}
188
if (j == printServices.length) {
189
newServices[p] = new Win32PrintService(printers[p]);
190
}
191
}
192
}
193
}
194
195
// Look for deleted services and invalidate these
196
if (printServices != null) {
197
for (int j=0; j < printServices.length; j++) {
198
if ((printServices[j] instanceof Win32PrintService) &&
199
(!printServices[j].equals(defaultPrintService))) {
200
((Win32PrintService)printServices[j]).invalidateService();
201
}
202
}
203
}
204
printServices = newServices;
205
}
206
207
208
public synchronized PrintService getPrintServiceByName(String name) {
209
210
if (name == null || name.equals("")) {
211
return null;
212
} else {
213
/* getPrintServices() is now very fast. */
214
PrintService[] printServices = getPrintServices();
215
for (int i=0; i<printServices.length; i++) {
216
if (printServices[i].getName().equals(name)) {
217
return printServices[i];
218
}
219
}
220
return null;
221
}
222
}
223
224
boolean matchingService(PrintService service,
225
PrintServiceAttributeSet serviceSet) {
226
if (serviceSet != null) {
227
Attribute [] attrs = serviceSet.toArray();
228
Attribute serviceAttr;
229
for (int i=0; i<attrs.length; i++) {
230
serviceAttr
231
= service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());
232
if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {
233
return false;
234
}
235
}
236
}
237
return true;
238
}
239
240
public PrintService[] getPrintServices(DocFlavor flavor,
241
AttributeSet attributes) {
242
243
SecurityManager security = System.getSecurityManager();
244
if (security != null) {
245
security.checkPrintJobAccess();
246
}
247
PrintRequestAttributeSet requestSet = null;
248
PrintServiceAttributeSet serviceSet = null;
249
250
if (attributes != null && !attributes.isEmpty()) {
251
252
requestSet = new HashPrintRequestAttributeSet();
253
serviceSet = new HashPrintServiceAttributeSet();
254
255
Attribute[] attrs = attributes.toArray();
256
for (int i=0; i<attrs.length; i++) {
257
if (attrs[i] instanceof PrintRequestAttribute) {
258
requestSet.add(attrs[i]);
259
} else if (attrs[i] instanceof PrintServiceAttribute) {
260
serviceSet.add(attrs[i]);
261
}
262
}
263
}
264
265
/*
266
* Special case: If client is asking for a particular printer
267
* (by name) then we can save time by getting just that service
268
* to check against the rest of the specified attributes.
269
*/
270
PrintService[] services = null;
271
if (serviceSet != null && serviceSet.get(PrinterName.class) != null) {
272
PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);
273
PrintService service = getPrintServiceByName(name.getValue());
274
if (service == null || !matchingService(service, serviceSet)) {
275
services = new PrintService[0];
276
} else {
277
services = new PrintService[1];
278
services[0] = service;
279
}
280
} else {
281
services = getPrintServices();
282
}
283
284
if (services.length == 0) {
285
return services;
286
} else {
287
ArrayList matchingServices = new ArrayList();
288
for (int i=0; i<services.length; i++) {
289
try {
290
if (services[i].
291
getUnsupportedAttributes(flavor, requestSet) == null) {
292
matchingServices.add(services[i]);
293
}
294
} catch (IllegalArgumentException e) {
295
}
296
}
297
services = new PrintService[matchingServices.size()];
298
return (PrintService[])matchingServices.toArray(services);
299
}
300
}
301
302
/*
303
* return empty array as don't support multi docs
304
*/
305
public MultiDocPrintService[]
306
getMultiDocPrintServices(DocFlavor[] flavors,
307
AttributeSet attributes) {
308
SecurityManager security = System.getSecurityManager();
309
if (security != null) {
310
security.checkPrintJobAccess();
311
}
312
return new MultiDocPrintService[0];
313
}
314
315
316
public synchronized PrintService getDefaultPrintService() {
317
SecurityManager security = System.getSecurityManager();
318
if (security != null) {
319
security.checkPrintJobAccess();
320
}
321
322
323
// Windows does not have notification for a change in default
324
// so we always get the latest.
325
defaultPrinter = getDefaultPrinterName();
326
if (defaultPrinter == null) {
327
return null;
328
}
329
330
if ((defaultPrintService != null) &&
331
defaultPrintService.getName().equals(defaultPrinter)) {
332
333
return defaultPrintService;
334
}
335
336
// Not the same as default so proceed to get new PrintService.
337
338
// clear defaultPrintService
339
defaultPrintService = null;
340
341
if (printServices != null) {
342
for (int j=0; j<printServices.length; j++) {
343
if (defaultPrinter.equals(printServices[j].getName())) {
344
defaultPrintService = printServices[j];
345
break;
346
}
347
}
348
}
349
350
if (defaultPrintService == null) {
351
defaultPrintService = new Win32PrintService(defaultPrinter);
352
}
353
return defaultPrintService;
354
}
355
356
class PrinterChangeListener extends Thread {
357
long chgObj;
358
PrinterChangeListener() {
359
chgObj = notifyFirstPrinterChange(null);
360
}
361
362
public void run() {
363
if (chgObj != -1) {
364
while (true) {
365
// wait for configuration to change
366
if (notifyPrinterChange(chgObj) != 0) {
367
try {
368
refreshServices();
369
} catch (SecurityException se) {
370
break;
371
}
372
} else {
373
notifyClosePrinterChange(chgObj);
374
break;
375
}
376
}
377
}
378
}
379
}
380
381
/* Windows provides *PrinterChangeNotification* functions that provides
382
information about printer status changes of the local printers but not
383
network printers.
384
Alternatively, Windows provides a way through which one can get the
385
network printer status changes by using WMI, RegistryKeyChange combination,
386
which is a slightly complex mechanism.
387
The Windows WMI offers an async and sync method to read through registry
388
via the WQL query. The async method is considered dangerous as it leaves
389
open a channel until we close it. But the async method has the advantage of
390
being notified of a change in registry by calling callback without polling for it.
391
The sync method uses the polling mechanism to notify.
392
RegistryValueChange cannot be used in combination with WMI to get registry
393
value change notification because of an error that may be generated because the
394
scope of the query would be too big to handle(at times).
395
Hence an alternative mechanism is chosen via the EnumPrinters by polling for the
396
count of printer status changes(add\remove) and based on it update the printers
397
list.
398
*/
399
class RemotePrinterChangeListener extends Thread implements Comparator<String>{
400
RemotePrinterChangeListener() {
401
}
402
403
@Override
404
public int compare(String o1, String o2) {
405
return ((o1 == null)
406
? ((o2 == null) ? 0 : 1)
407
: ((o2 == null) ? -1 : o1.compareTo(o2)));
408
}
409
410
@Override
411
public void run() {
412
// Init the list of remote printers
413
String[] prevRemotePrinters = getRemotePrintersNames();
414
if (prevRemotePrinters != null) {
415
Arrays.sort(prevRemotePrinters, this);
416
}
417
418
while (true) {
419
try {
420
Thread.sleep(refreshTime * 1000);
421
} catch (InterruptedException e) {
422
break;
423
}
424
425
String[] currentRemotePrinters = getRemotePrintersNames();
426
if (currentRemotePrinters != null) {
427
Arrays.sort(currentRemotePrinters, this);
428
}
429
if (!Arrays.equals(prevRemotePrinters, currentRemotePrinters)) {
430
// The list of remote printers got updated,
431
// so update the cached list printers which
432
// includes both local and network printers
433
refreshServices();
434
435
// store the current data for next comparison
436
prevRemotePrinters = currentRemotePrinters;
437
}
438
}
439
}
440
}
441
442
private native String getDefaultPrinterName();
443
private native String[] getAllPrinterNames();
444
private native long notifyFirstPrinterChange(String printer);
445
private native void notifyClosePrinterChange(long chgObj);
446
private native int notifyPrinterChange(long chgObj);
447
private native String[] getRemotePrintersNames();
448
}
449
450