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