< 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 = 120;  // 2 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("true")) {
  70                 pollServices = true;
  71             } else if (pollStr.equalsIgnoreCase("false")) {
  72                 pollServices = false;
  73             }
  74         }
  75 
  76         /* The system property "sun.java2d.print.minRefreshTime"
  77          * can be used to specify minimum refresh time (in seconds)
  78          * for polling PrintServices.  The default is 120.
  79          */
  80         String refreshTimeStr = java.security.AccessController.doPrivileged(
  81             new sun.security.action.GetPropertyAction(
  82                 "sun.java2d.print.minRefreshTime"));
  83 
  84         if (refreshTimeStr != null) {
  85             try {
  86                 minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
  87             } catch (NumberFormatException e) {
  88             }
  89             if (minRefreshTime < DEFAULT_MINREFRESH) {
  90                 minRefreshTime = DEFAULT_MINREFRESH;
  91             }
  92         }
  93 
  94         java.security.AccessController.doPrivileged(
  95             new java.security.PrivilegedAction<Void>() {
  96                 public Void run() {
  97                     System.loadLibrary("awt");
  98                     return null;
  99                 }
 100             });
 101     }
 102 
 103     /* The singleton win32 print lookup service.
 104      * Code that is aware of this field and wants to use it must first
 105      * see if its null, and if so instantiate it by calling a method such as
 106      * javax.print.PrintServiceLookup.defaultPrintService() so that the
 107      * same instance is stored there.
 108      */
 109     private static PrintServiceLookupProvider win32PrintLUS;
 110 
 111     /* Think carefully before calling this. Preferably don't call it. */
 112     public static PrintServiceLookupProvider getWin32PrintLUS() {
 113         if (win32PrintLUS == null) {


 115              * When it returns an instance of this class will have
 116              * been instantiated - else there's a JDK internal error.
 117              */
 118             PrintServiceLookup.lookupDefaultPrintService();
 119         }
 120         return win32PrintLUS;
 121     }
 122 
 123     public PrintServiceLookupProvider() {
 124 
 125         if (win32PrintLUS == null) {
 126             win32PrintLUS = this;
 127 
 128             String osName = AccessController.doPrivileged(
 129                 new sun.security.action.GetPropertyAction("os.name"));
 130             // There's no capability for Win98 to refresh printers.
 131             // See "OpenPrinter" for more info.
 132             if (osName != null && osName.startsWith("Windows 98")) {
 133                 return;
 134             }
 135             // start the local printer listener thread
 136             Thread thr = new Thread(null, new PrinterChangeListener(),
 137                                     "PrinterListener", 0, false);
 138             thr.setDaemon(true);
 139             thr.start();
 140 
 141             if (pollServices) {
 142                 // start the remote printer listener thread
 143                 Thread remThr = new Thread(null, new RemotePrinterChangeListener(),
 144                                         "RemotePrinterListener", 0, false);
 145                 remThr.setDaemon(true);
 146                 remThr.start();
 147             }
 148         } /* else condition ought to never happen! */
 149     }
 150 
 151     /* Want the PrintService which is default print service to have
 152      * equality of reference with the equivalent in list of print services
 153      * This isn't required by the API and there's a risk doing this will
 154      * lead people to assume its guaranteed.
 155      */
 156     public synchronized PrintService[] getPrintServices() {
 157         SecurityManager security = System.getSecurityManager();
 158         if (security != null) {
 159             security.checkPrintJobAccess();
 160         }
 161         if (printServices == null) {
 162             refreshServices();
 163         }
 164         return printServices;
 165     }
 166 
 167     private synchronized void refreshServices() {


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

 363     class PrinterChangeListener implements Runnable {
 364         long chgObj;
 365         PrinterChangeListener() {
 366             chgObj = notifyFirstPrinterChange(null);
 367         }
 368 
 369         @Override
 370         public void run() {
 371             if (chgObj != -1) {
 372                 while (true) {
 373                     // wait for configuration to change
 374                     if (notifyPrinterChange(chgObj) != 0) {
 375                         try {
 376                             refreshServices();
 377                         } catch (SecurityException se) {
 378                             break;
 379                         }
 380                     } else {
 381                         notifyClosePrinterChange(chgObj);
 382                         break;
 383                     }
 384                 }
 385             }
 386         }
 387     }    
 388 
 389     /* Windows provides *PrinterChangeNotification* functions that provides 
 390        information about printer status changes of the local printers but not
 391        network printers.
 392        Alternatively, Windows provides a way thro' which one can get the
 393        network printer status changes by using WMI, RegistryKeyChange combination,
 394        which is a slightly complex mechanism. 
 395        The Windows WMI offers an async and sync method to read thro' registry 
 396        via the WQL query. The async method is considered dangerous as it leaves 
 397        open a channel until we close it. But the async method has the advantage of 
 398        being notified of a change in registry by calling callback without polling for it.
 399        The sync method uses the polling mechanism to notify.
 400        RegistryValueChange cannot be used in combination with WMI to get registry
 401        value change notification because of an error that may be generated because the
 402        scope of the query would be too big to handle(at times).
 403        Hence an alternative mechanism is choosen via the EnumPrinters by polling for the
 404        count of printer status changes(add\remove) and based on it update the printers
 405        list.
 406     */
 407     class RemotePrinterChangeListener implements Runnable {
 408         private String[] prevRemotePrinters;
 409 
 410         RemotePrinterChangeListener() {
 411             prevRemotePrinters = GetRemotePrintersNames();
 412         }
 413 
 414         boolean doCompare(String[] str1, String[] str2) {
 415             if (str1.length != str2.length) {
 416                 return true;
 417             } else {
 418                 for (int i = 0;i < str1.length;i++) {
 419                     for (int j = 0;j < str2.length;j++) {
 420                         if (!str1[i].equals(str2[j])) {
 421                             return true;
 422                         }
 423                     }
 424                 }
 425             }
 426 
 427             return false;
 428         }
 429 
 430         @Override
 431         public void run() {
 432             while(true) {
 433                 String[] currentRemotePrinters = GetRemotePrintersNames();
 434                 if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
 435 
 436                     // updated the printers data
 437                     // printers list now contains both local and network printer data
 438                     refreshServices();
 439 
 440                     // store the current data for next comparison
 441                     prevRemotePrinters = currentRemotePrinters;
 442                 }
 443 
 444                 try {
 445                     Thread.sleep(minRefreshTime * 1000);
 446                 } catch (InterruptedException e) {
 447                     break;
 448                 }
 449             }
 450         }
 451     }
 452 
 453     private native String getDefaultPrinterName();
 454     private native String[] getAllPrinterNames();
 455     private native long notifyFirstPrinterChange(String printer);
 456     private native void notifyClosePrinterChange(long chgObj);
 457     private native int notifyPrinterChange(long chgObj);
 458     private native String[] GetRemotePrintersNames();
 459 }
< prev index next >