< prev index next >

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

Print this page
rev 13547 : 8055705: Rename UnixPrintServiceLookup and Win32PrintServiceLookup as a platform neutral class name
Reviewed-by: jgodinez, bae
rev 13548 : 8153732: Windows remote printer changes do not reflect in lookupPrintServices()
Reviewed-by: prr, psadhukhan


  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 }
< prev index next >