< prev index next >

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

Print this page




  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             Thread thr = new Thread(null, new PrinterChangeListener(),
 101                                     "PrinterListener", 0, false);
 102             thr.setDaemon(true);
 103             thr.start();








 104         } /* else condition ought to never happen! */
 105     }
 106 
 107     /* Want the PrintService which is default print service to have
 108      * equality of reference with the equivalent in list of print services
 109      * This isn't required by the API and there's a risk doing this will
 110      * lead people to assume its guaranteed.
 111      */
 112     public synchronized PrintService[] getPrintServices() {
 113         SecurityManager security = System.getSecurityManager();
 114         if (security != null) {
 115             security.checkPrintJobAccess();
 116         }
 117         if (printServices == null) {
 118             refreshServices();
 119         }
 120         return printServices;
 121     }
 122 
 123     private synchronized void refreshServices() {


 299 
 300          // Not the same as default so proceed to get new PrintService.
 301 
 302         // clear defaultPrintService
 303         defaultPrintService = null;
 304 
 305         if (printServices != null) {
 306             for (int j=0; j<printServices.length; j++) {
 307                 if (defaultPrinter.equals(printServices[j].getName())) {
 308                     defaultPrintService = printServices[j];
 309                     break;
 310                 }
 311             }
 312         }
 313 
 314         if (defaultPrintService == null) {
 315             defaultPrintService = new Win32PrintService(defaultPrinter);
 316         }
 317         return defaultPrintService;
 318     }
 319 
 320     class PrinterChangeListener implements Runnable {
 321         long chgObj;
 322         PrinterChangeListener() {
 323             chgObj = notifyFirstPrinterChange(null);
 324         }
 325 
 326         @Override
 327         public void run() {
 328             if (chgObj != -1) {
 329                 while (true) {
 330                     // wait for configuration to change
 331                     if (notifyPrinterChange(chgObj) != 0) {
 332                         try {
 333                             refreshServices();
 334                         } catch (SecurityException se) {
 335                             break;
 336                         }
 337                     } else {
 338                         notifyClosePrinterChange(chgObj);
 339                         break;
 340                     }
 341                 }
 342             }
 343         }
 344     }
 345 
































































 346     private native String getDefaultPrinterName();
 347     private native String[] getAllPrinterNames();
 348     private native long notifyFirstPrinterChange(String printer);
 349     private native void notifyClosePrinterChange(long chgObj);
 350     private native int notifyPrinterChange(long chgObj);

 351 }


  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, false);
 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, false);
 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() {


 341 
 342          // Not the same as default so proceed to get new PrintService.
 343 
 344         // clear defaultPrintService
 345         defaultPrintService = null;
 346 
 347         if (printServices != null) {
 348             for (int j=0; j<printServices.length; j++) {
 349                 if (defaultPrinter.equals(printServices[j].getName())) {
 350                     defaultPrintService = printServices[j];
 351                     break;
 352                 }
 353             }
 354         }
 355 
 356         if (defaultPrintService == null) {
 357             defaultPrintService = new Win32PrintService(defaultPrinter);
 358         }
 359         return defaultPrintService;
 360     }

 361     class PrinterChangeListener implements Runnable {
 362         long chgObj;
 363         PrinterChangeListener() {
 364             chgObj = notifyFirstPrinterChange(null);
 365         }
 366 
 367         @Override
 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 >