< prev index next >

src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java

Print this page

        

@@ -94,15 +94,21 @@
             // There's no capability for Win98 to refresh printers.
             // See "OpenPrinter" for more info.
             if (osName != null && osName.startsWith("Windows 98")) {
                 return;
             }
-            // start the printer listener thread
+            // start the local printer listener thread
             Thread thr = new Thread(null, new PrinterChangeListener(),
                                     "PrinterListener", 0, false);
             thr.setDaemon(true);
             thr.start();
+
+            // start the remote printer listener thread
+            Thread remThr = new Thread(null, new RemotePrinterChangeListener(),
+                                    "RemotePrinterListener", 0, false);
+            remThr.setDaemon(true);
+            remThr.start();
         } /* else condition ought to never happen! */
     }
 
     /* Want the PrintService which is default print service to have
      * equality of reference with the equivalent in list of print services

@@ -314,11 +320,10 @@
         if (defaultPrintService == null) {
             defaultPrintService = new Win32PrintService(defaultPrinter);
         }
         return defaultPrintService;
     }
-
     class PrinterChangeListener implements Runnable {
         long chgObj;
         PrinterChangeListener() {
             chgObj = notifyFirstPrinterChange(null);
         }

@@ -341,11 +346,77 @@
                 }
             }
         }
     }
 
+    /* Windows provides *PrinterChangeNotification* functions that provides 
+       information about printer status changes of the local printers but not
+       network printers.
+       Alternatively, Windows provides a way thro' which one can get the
+       network printer status changes by using WMI, RegistryKeyChange combination,
+       which is a slightly complex mechanism. 
+       The Windows WMI offers an async and sync method to read thro' registry 
+       via the WQL query. The async method is considered dangerous as it leaves 
+       open a channel until we close it. But the async method has the advantage of 
+       being notified of a change in registry by calling callback without polling for it.
+       The sync method uses the polling mechanism to notify.
+       RegistryValueChange cannot be used in combination with WMI to get registry
+       value change notification because of an error that may be generated because the
+       scope of the query would be too big to handle(at times).
+       Hence an alternative mechanism is choosen via the EnumPrinters by polling for the
+       count of printer status changes(add\remove) and based on it update the printers
+       list.
+    */
+    class RemotePrinterChangeListener implements Runnable {
+        private static final long DELAY = 1000 * 60 * 4; // 4 min pooling
+        private String[] prevRemotePrinters;
+
+        RemotePrinterChangeListener() {
+            prevRemotePrinters = GetRemotePrintersNames();
+        }
+
+        boolean doCompare(String[] str1, String[] str2) {
+            if(str1.length != str2.length) {
+                return true;
+            } else {
+                for(int i = 0;i < str1.length;i++) {
+                    for(int j = 0;j < str2.length;j++) {
+                        if(!str1[i].equals(str2[j])) {
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        @Override
+        public void run() {
+            while(true) {
+                String[] currentRemotePrinters = GetRemotePrintersNames();
+                if(doCompare(prevRemotePrinters, currentRemotePrinters)) {
+
+                    // updated the printers data
+                    // printers list now contains both local and network printer data
+                    refreshServices();
+
+                    // store the current data for next comparison
+                    prevRemotePrinters = currentRemotePrinters;
+                }
+
+                try {
+                    Thread.sleep(DELAY);
+                } catch (InterruptedException e) {
+                    break;
+                }
+            }
+        }
+    }
+
     private native String getDefaultPrinterName();
     private native String[] getAllPrinterNames();
     private native long notifyFirstPrinterChange(String printer);
     private native void notifyClosePrinterChange(long chgObj);
     private native int notifyPrinterChange(long chgObj);
+    private native String[] GetRemotePrintersNames();
 }
< prev index next >