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 javax.print.DocFlavor;
31 import javax.print.MultiDocPrintService;
32 import javax.print.PrintService;
33 import javax.print.PrintServiceLookup;
34 import javax.print.attribute.Attribute;
35 import javax.print.attribute.AttributeSet;
36 import javax.print.attribute.HashPrintRequestAttributeSet;
37 import javax.print.attribute.HashPrintServiceAttributeSet;
38 import javax.print.attribute.PrintRequestAttribute;
39 import javax.print.attribute.PrintRequestAttributeSet;
40 import javax.print.attribute.PrintServiceAttribute;
41 import javax.print.attribute.PrintServiceAttributeSet;
42 import javax.print.attribute.standard.PrinterName;
43
44 public class PrintServiceLookupProvider extends PrintServiceLookup {
45
46 private String defaultPrinter;
47 private PrintService defaultPrintService;
48 private String[] printers; /* excludes the default printer */
49 private PrintService[] printServices; /* includes the default printer */
50 private static boolean pollServices = true;
51 private static final int DEFAULT_MINREFRESH = 240; // 4 minutes
52 private static int minRefreshTime = DEFAULT_MINREFRESH;
53
54 static {
55 /* The system property "sun.java2d.print.polling"
56 * can be used to force the printing code to poll or not poll
57 * for PrintServices.
58 */
59 String pollStr = java.security.AccessController.doPrivileged(
60 new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
61
62 if (pollStr != null) {
63 if (pollStr.equalsIgnoreCase("false")) {
64 pollServices = false;
65 }
66 }
67
68 /* The system property "sun.java2d.print.minRefreshTime"
69 * can be used to specify minimum refresh time (in seconds)
70 * for polling PrintServices. The default is 240.
71 */
72 String refreshTimeStr = java.security.AccessController.doPrivileged(
73 new sun.security.action.GetPropertyAction(
74 "sun.java2d.print.minRefreshTime"));
75
76 if (refreshTimeStr != null) {
77 try {
78 minRefreshTime = Integer.parseInt(refreshTimeStr);
79 } catch (NumberFormatException e) {
80 // ignore
81 }
82 if (minRefreshTime < DEFAULT_MINREFRESH) {
83 minRefreshTime = DEFAULT_MINREFRESH;
84 }
85 }
86
87 java.security.AccessController.doPrivileged(
88 new java.security.PrivilegedAction<Void>() {
89 public Void run() {
90 System.loadLibrary("awt");
91 return null;
92 }
93 });
94 }
95
96 /* The singleton win32 print lookup service.
97 * Code that is aware of this field and wants to use it must first
98 * see if its null, and if so instantiate it by calling a method such as
99 * javax.print.PrintServiceLookup.defaultPrintService() so that the
100 * same instance is stored there.
101 */
102 private static PrintServiceLookupProvider win32PrintLUS;
103
104 /* Think carefully before calling this. Preferably don't call it. */
105 public static PrintServiceLookupProvider getWin32PrintLUS() {
106 if (win32PrintLUS == null) {
107 /* This call is internally synchronized.
108 * When it returns an instance of this class will have
109 * been instantiated - else there's a JDK internal error.
110 */
111 PrintServiceLookup.lookupDefaultPrintService();
112 }
113 return win32PrintLUS;
114 }
115
377 }
378
379 /* Windows provides *PrinterChangeNotification* functions that provides
380 information about printer status changes of the local printers but not
381 network printers.
382 Alternatively, Windows provides a way through which one can get the
383 network printer status changes by using WMI, RegistryKeyChange combination,
384 which is a slightly complex mechanism.
385 The Windows WMI offers an async and sync method to read through registry
386 via the WQL query. The async method is considered dangerous as it leaves
387 open a channel until we close it. But the async method has the advantage of
388 being notified of a change in registry by calling callback without polling for it.
389 The sync method uses the polling mechanism to notify.
390 RegistryValueChange cannot be used in combination with WMI to get registry
391 value change notification because of an error that may be generated because the
392 scope of the query would be too big to handle(at times).
393 Hence an alternative mechanism is chosen via the EnumPrinters by polling for the
394 count of printer status changes(add\remove) and based on it update the printers
395 list.
396 */
397 class RemotePrinterChangeListener extends Thread {
398 private String[] prevRemotePrinters;
399
400 RemotePrinterChangeListener() {
401 prevRemotePrinters = getRemotePrintersNames();
402 }
403
404 private boolean doCompare(String[] str1, String[] str2) {
405 if (str1 == null && str2 == null) {
406 return false;
407 } else if (str1 == null || str2 == null) {
408 return true;
409 }
410
411 if (str1.length != str2.length) {
412 return true;
413 } else {
414 for (int i = 0; i < str1.length; i++) {
415 for (int j = 0; j < str2.length; j++) {
416 // skip if both are nulls
417 if (str1[i] == null && str2[j] == null) {
418 continue;
419 }
420
421 // return true if there is a 'difference' but
422 // no need to access the individual string
423 if (str1[i] == null || str2[j] == null) {
424 return true;
425 }
426
427 // do comparison only if they are non-nulls
428 if (!str1[i].equals(str2[j])) {
429 return true;
430 }
431 }
432 }
433 }
434
435 return false;
436 }
437
438 @Override
439 public void run() {
440 // Init the list of remote printers
441 prevRemotePrinters = getRemotePrintersNames();
442
443 while (true) {
444 try {
445 Thread.sleep(minRefreshTime * 1000);
446 } catch (InterruptedException e) {
447 break;
448 }
449
450 String[] currentRemotePrinters = getRemotePrintersNames();
451 if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
452 // The list of remote printers got updated,
453 // so update the cached list printers which
454 // includes both local and network printers
455 refreshServices();
456
457 // store the current data for next comparison
458 prevRemotePrinters = currentRemotePrinters;
459 }
460 }
461 }
462 }
463
464 private native String getDefaultPrinterName();
465 private native String[] getAllPrinterNames();
466 private native long notifyFirstPrinterChange(String printer);
467 private native void notifyClosePrinterChange(long chgObj);
468 private native int notifyPrinterChange(long chgObj);
469 private native String[] getRemotePrintersNames();
470 }
|
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
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 private String[] prevRemotePrinters;
401
402 RemotePrinterChangeListener() {
403 prevRemotePrinters = getRemotePrintersNames();
404 }
405
406 @Override
407 public int compare(String o1, String o2) {
408 return ((o1 == null)
409 ? ((o2 == null) ? 0 : 1)
410 : ((o2 == null) ? -1 : o1.compareTo(o2)));
411 }
412
413 @Override
414 public void run() {
415 // Init the list of remote printers
416 String[] prevRemotePrinters = getRemotePrintersNames();
417 if (prevRemotePrinters != null) {
418 Arrays.sort(prevRemotePrinters, this);
419 }
420
421 while (true) {
422 try {
423 Thread.sleep(refreshTime * 1000);
424 } catch (InterruptedException e) {
425 break;
426 }
427
428 String[] currentRemotePrinters = getRemotePrintersNames();
429 if (currentRemotePrinters != null) {
430 Arrays.sort(currentRemotePrinters, this);
431 }
432 if (!Arrays.equals(prevRemotePrinters, currentRemotePrinters)) {
433 // The list of remote printers got updated,
434 // so update the cached list printers which
435 // includes both local and network printers
436 refreshServices();
437
438 // store the current data for next comparison
439 prevRemotePrinters = currentRemotePrinters;
440 }
441 }
442 }
443 }
444
445 private native String getDefaultPrinterName();
446 private native String[] getAllPrinterNames();
447 private native long notifyFirstPrinterChange(String printer);
448 private native void notifyClosePrinterChange(long chgObj);
449 private native int notifyPrinterChange(long chgObj);
450 private native String[] getRemotePrintersNames();
451 }
|