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