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 PrinterChangeListener thr = new PrinterChangeListener();
101 thr.setDaemon(true);
102 thr.start();
103 } /* else condition ought to never happen! */
104 }
105
106 /* Want the PrintService which is default print service to have
107 * equality of reference with the equivalent in list of print services
108 * This isn't required by the API and there's a risk doing this will
109 * lead people to assume its guaranteed.
110 */
111 public synchronized PrintService[] getPrintServices() {
112 SecurityManager security = System.getSecurityManager();
113 if (security != null) {
114 security.checkPrintJobAccess();
115 }
116 if (printServices == null) {
117 refreshServices();
118 }
119 return printServices;
120 }
121
122 private synchronized void refreshServices() {
324
325 public void run() {
326 if (chgObj != -1) {
327 while (true) {
328 // wait for configuration to change
329 if (notifyPrinterChange(chgObj) != 0) {
330 try {
331 refreshServices();
332 } catch (SecurityException se) {
333 break;
334 }
335 } else {
336 notifyClosePrinterChange(chgObj);
337 break;
338 }
339 }
340 }
341 }
342 }
343
344 private native String getDefaultPrinterName();
345 private native String[] getAllPrinterNames();
346 private native long notifyFirstPrinterChange(String printer);
347 private native void notifyClosePrinterChange(long chgObj);
348 private native int notifyPrinterChange(long chgObj);
349 }
|
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);
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);
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() {
367
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 }
|