36 import javax.print.DocFlavor;
37 import javax.print.MultiDocPrintService;
38 import javax.print.PrintService;
39 import javax.print.PrintServiceLookup;
40 import javax.print.attribute.Attribute;
41 import javax.print.attribute.AttributeSet;
42 import javax.print.attribute.HashPrintRequestAttributeSet;
43 import javax.print.attribute.HashPrintServiceAttributeSet;
44 import javax.print.attribute.PrintRequestAttribute;
45 import javax.print.attribute.PrintRequestAttributeSet;
46 import javax.print.attribute.PrintServiceAttribute;
47 import javax.print.attribute.PrintServiceAttributeSet;
48 import javax.print.attribute.standard.PrinterName;
49
50 public class PrintServiceLookupProvider extends PrintServiceLookup {
51
52 private String defaultPrinter;
53 private PrintService defaultPrintService;
54 private String[] printers; /* excludes the default printer */
55 private PrintService[] printServices; /* includes the default printer */
56
57 static {
58 java.security.AccessController.doPrivileged(
59 new java.security.PrivilegedAction<Void>() {
60 public Void run() {
61 System.loadLibrary("awt");
62 return null;
63 }
64 });
65 }
66
67 /* The singleton win32 print lookup service.
68 * Code that is aware of this field and wants to use it must first
69 * see if its null, and if so instantiate it by calling a method such as
70 * javax.print.PrintServiceLookup.defaultPrintService() so that the
71 * same instance is stored there.
72 */
73 private static PrintServiceLookupProvider win32PrintLUS;
74
75 /* Think carefully before calling this. Preferably don't call it. */
76 public static PrintServiceLookupProvider getWin32PrintLUS() {
77 if (win32PrintLUS == null) {
79 * When it returns an instance of this class will have
80 * been instantiated - else there's a JDK internal error.
81 */
82 PrintServiceLookup.lookupDefaultPrintService();
83 }
84 return win32PrintLUS;
85 }
86
87 public PrintServiceLookupProvider() {
88
89 if (win32PrintLUS == null) {
90 win32PrintLUS = this;
91
92 String osName = AccessController.doPrivileged(
93 new sun.security.action.GetPropertyAction("os.name"));
94 // There's no capability for Win98 to refresh printers.
95 // See "OpenPrinter" for more info.
96 if (osName != null && osName.startsWith("Windows 98")) {
97 return;
98 }
99 // start the printer listener thread
100 Thread thr = new Thread(null, new PrinterChangeListener(),
101 "PrinterListener", 0, false);
102 thr.setDaemon(true);
103 thr.start();
104 } /* else condition ought to never happen! */
105 }
106
107 /* Want the PrintService which is default print service to have
108 * equality of reference with the equivalent in list of print services
109 * This isn't required by the API and there's a risk doing this will
110 * lead people to assume its guaranteed.
111 */
112 public synchronized PrintService[] getPrintServices() {
113 SecurityManager security = System.getSecurityManager();
114 if (security != null) {
115 security.checkPrintJobAccess();
116 }
117 if (printServices == null) {
118 refreshServices();
119 }
120 return printServices;
121 }
122
123 private synchronized void refreshServices() {
299
300 // Not the same as default so proceed to get new PrintService.
301
302 // clear defaultPrintService
303 defaultPrintService = null;
304
305 if (printServices != null) {
306 for (int j=0; j<printServices.length; j++) {
307 if (defaultPrinter.equals(printServices[j].getName())) {
308 defaultPrintService = printServices[j];
309 break;
310 }
311 }
312 }
313
314 if (defaultPrintService == null) {
315 defaultPrintService = new Win32PrintService(defaultPrinter);
316 }
317 return defaultPrintService;
318 }
319
320 class PrinterChangeListener implements Runnable {
321 long chgObj;
322 PrinterChangeListener() {
323 chgObj = notifyFirstPrinterChange(null);
324 }
325
326 @Override
327 public void run() {
328 if (chgObj != -1) {
329 while (true) {
330 // wait for configuration to change
331 if (notifyPrinterChange(chgObj) != 0) {
332 try {
333 refreshServices();
334 } catch (SecurityException se) {
335 break;
336 }
337 } else {
338 notifyClosePrinterChange(chgObj);
339 break;
340 }
341 }
342 }
343 }
344 }
345
346 private native String getDefaultPrinterName();
347 private native String[] getAllPrinterNames();
348 private native long notifyFirstPrinterChange(String printer);
349 private native void notifyClosePrinterChange(long chgObj);
350 private native int notifyPrinterChange(long chgObj);
351 }
|
36 import javax.print.DocFlavor;
37 import javax.print.MultiDocPrintService;
38 import javax.print.PrintService;
39 import javax.print.PrintServiceLookup;
40 import javax.print.attribute.Attribute;
41 import javax.print.attribute.AttributeSet;
42 import javax.print.attribute.HashPrintRequestAttributeSet;
43 import javax.print.attribute.HashPrintServiceAttributeSet;
44 import javax.print.attribute.PrintRequestAttribute;
45 import javax.print.attribute.PrintRequestAttributeSet;
46 import javax.print.attribute.PrintServiceAttribute;
47 import javax.print.attribute.PrintServiceAttributeSet;
48 import javax.print.attribute.standard.PrinterName;
49
50 public class PrintServiceLookupProvider extends PrintServiceLookup {
51
52 private String defaultPrinter;
53 private PrintService defaultPrintService;
54 private String[] printers; /* excludes the default printer */
55 private PrintService[] printServices; /* includes the default printer */
56 private static boolean pollServices = true;
57 private static final int DEFAULT_MINREFRESH = 120; // 2 minutes
58 private static int minRefreshTime = DEFAULT_MINREFRESH;
59
60 static {
61 /* The system property "sun.java2d.print.polling"
62 * can be used to force the printing code to poll or not poll
63 * for PrintServices.
64 */
65 String pollStr = java.security.AccessController.doPrivileged(
66 new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
67
68 if (pollStr != null) {
69 if (pollStr.equalsIgnoreCase("true")) {
70 pollServices = true;
71 } else if (pollStr.equalsIgnoreCase("false")) {
72 pollServices = false;
73 }
74 }
75
76 /* The system property "sun.java2d.print.minRefreshTime"
77 * can be used to specify minimum refresh time (in seconds)
78 * for polling PrintServices. The default is 120.
79 */
80 String refreshTimeStr = java.security.AccessController.doPrivileged(
81 new sun.security.action.GetPropertyAction(
82 "sun.java2d.print.minRefreshTime"));
83
84 if (refreshTimeStr != null) {
85 try {
86 minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
87 } catch (NumberFormatException e) {
88 }
89 if (minRefreshTime < DEFAULT_MINREFRESH) {
90 minRefreshTime = DEFAULT_MINREFRESH;
91 }
92 }
93
94 java.security.AccessController.doPrivileged(
95 new java.security.PrivilegedAction<Void>() {
96 public Void run() {
97 System.loadLibrary("awt");
98 return null;
99 }
100 });
101 }
102
103 /* The singleton win32 print lookup service.
104 * Code that is aware of this field and wants to use it must first
105 * see if its null, and if so instantiate it by calling a method such as
106 * javax.print.PrintServiceLookup.defaultPrintService() so that the
107 * same instance is stored there.
108 */
109 private static PrintServiceLookupProvider win32PrintLUS;
110
111 /* Think carefully before calling this. Preferably don't call it. */
112 public static PrintServiceLookupProvider getWin32PrintLUS() {
113 if (win32PrintLUS == null) {
115 * When it returns an instance of this class will have
116 * been instantiated - else there's a JDK internal error.
117 */
118 PrintServiceLookup.lookupDefaultPrintService();
119 }
120 return win32PrintLUS;
121 }
122
123 public PrintServiceLookupProvider() {
124
125 if (win32PrintLUS == null) {
126 win32PrintLUS = this;
127
128 String osName = AccessController.doPrivileged(
129 new sun.security.action.GetPropertyAction("os.name"));
130 // There's no capability for Win98 to refresh printers.
131 // See "OpenPrinter" for more info.
132 if (osName != null && osName.startsWith("Windows 98")) {
133 return;
134 }
135 // start the local printer listener thread
136 Thread thr = new Thread(null, new PrinterChangeListener(),
137 "PrinterListener", 0, false);
138 thr.setDaemon(true);
139 thr.start();
140
141 if (pollServices) {
142 // start the remote printer listener thread
143 Thread remThr = new Thread(null, new RemotePrinterChangeListener(),
144 "RemotePrinterListener", 0, false);
145 remThr.setDaemon(true);
146 remThr.start();
147 }
148 } /* else condition ought to never happen! */
149 }
150
151 /* Want the PrintService which is default print service to have
152 * equality of reference with the equivalent in list of print services
153 * This isn't required by the API and there's a risk doing this will
154 * lead people to assume its guaranteed.
155 */
156 public synchronized PrintService[] getPrintServices() {
157 SecurityManager security = System.getSecurityManager();
158 if (security != null) {
159 security.checkPrintJobAccess();
160 }
161 if (printServices == null) {
162 refreshServices();
163 }
164 return printServices;
165 }
166
167 private synchronized void refreshServices() {
343
344 // Not the same as default so proceed to get new PrintService.
345
346 // clear defaultPrintService
347 defaultPrintService = null;
348
349 if (printServices != null) {
350 for (int j=0; j<printServices.length; j++) {
351 if (defaultPrinter.equals(printServices[j].getName())) {
352 defaultPrintService = printServices[j];
353 break;
354 }
355 }
356 }
357
358 if (defaultPrintService == null) {
359 defaultPrintService = new Win32PrintService(defaultPrinter);
360 }
361 return defaultPrintService;
362 }
363 class PrinterChangeListener implements Runnable {
364 long chgObj;
365 PrinterChangeListener() {
366 chgObj = notifyFirstPrinterChange(null);
367 }
368
369 @Override
370 public void run() {
371 if (chgObj != -1) {
372 while (true) {
373 // wait for configuration to change
374 if (notifyPrinterChange(chgObj) != 0) {
375 try {
376 refreshServices();
377 } catch (SecurityException se) {
378 break;
379 }
380 } else {
381 notifyClosePrinterChange(chgObj);
382 break;
383 }
384 }
385 }
386 }
387 }
388
389 /* Windows provides *PrinterChangeNotification* functions that provides
390 information about printer status changes of the local printers but not
391 network printers.
392 Alternatively, Windows provides a way thro' which one can get the
393 network printer status changes by using WMI, RegistryKeyChange combination,
394 which is a slightly complex mechanism.
395 The Windows WMI offers an async and sync method to read thro' registry
396 via the WQL query. The async method is considered dangerous as it leaves
397 open a channel until we close it. But the async method has the advantage of
398 being notified of a change in registry by calling callback without polling for it.
399 The sync method uses the polling mechanism to notify.
400 RegistryValueChange cannot be used in combination with WMI to get registry
401 value change notification because of an error that may be generated because the
402 scope of the query would be too big to handle(at times).
403 Hence an alternative mechanism is choosen via the EnumPrinters by polling for the
404 count of printer status changes(add\remove) and based on it update the printers
405 list.
406 */
407 class RemotePrinterChangeListener implements Runnable {
408 private String[] prevRemotePrinters;
409
410 RemotePrinterChangeListener() {
411 prevRemotePrinters = GetRemotePrintersNames();
412 }
413
414 boolean doCompare(String[] str1, String[] str2) {
415 if (str1.length != str2.length) {
416 return true;
417 } else {
418 for (int i = 0;i < str1.length;i++) {
419 for (int j = 0;j < str2.length;j++) {
420 if (!str1[i].equals(str2[j])) {
421 return true;
422 }
423 }
424 }
425 }
426
427 return false;
428 }
429
430 @Override
431 public void run() {
432 while(true) {
433 String[] currentRemotePrinters = GetRemotePrintersNames();
434 if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
435
436 // updated the printers data
437 // printers list now contains both local and network printer data
438 refreshServices();
439
440 // store the current data for next comparison
441 prevRemotePrinters = currentRemotePrinters;
442 }
443
444 try {
445 Thread.sleep(minRefreshTime * 1000);
446 } catch (InterruptedException e) {
447 break;
448 }
449 }
450 }
451 }
452
453 private native String getDefaultPrinterName();
454 private native String[] getAllPrinterNames();
455 private native long notifyFirstPrinterChange(String printer);
456 private native void notifyClosePrinterChange(long chgObj);
457 private native int notifyPrinterChange(long chgObj);
458 private native String[] GetRemotePrintersNames();
459 }
|