< prev index next >

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

Print this page




  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 


 381     }
 382 
 383     /* Windows provides *PrinterChangeNotification* functions that provides
 384        information about printer status changes of the local printers but not
 385        network printers.
 386        Alternatively, Windows provides a way through which one can get the
 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 java.util.Comparator;
  32 import javax.print.DocFlavor;
  33 import javax.print.MultiDocPrintService;
  34 import javax.print.PrintService;
  35 import javax.print.PrintServiceLookup;
  36 import javax.print.attribute.Attribute;
  37 import javax.print.attribute.AttributeSet;
  38 import javax.print.attribute.HashPrintRequestAttributeSet;
  39 import javax.print.attribute.HashPrintServiceAttributeSet;
  40 import javax.print.attribute.PrintRequestAttribute;
  41 import javax.print.attribute.PrintRequestAttributeSet;
  42 import javax.print.attribute.PrintServiceAttribute;
  43 import javax.print.attribute.PrintServiceAttributeSet;
  44 import javax.print.attribute.standard.PrinterName;
  45 
  46 public class PrintServiceLookupProvider extends PrintServiceLookup {
  47 
  48     private String defaultPrinter;
  49     private PrintService defaultPrintService;
  50     private String[] printers; /* excludes the default printer */
  51     private PrintService[] printServices; /* includes the default printer */
  52 
  53     private static final int DEFAULT_REFRESH_TIME = 240;  // 4 minutes
  54     private static final int MINIMUM_REFRESH_TIME = 120;  // 2 minutes
  55     private static final boolean pollServices;
  56     private static final int refreshTime;
  57 
  58     static {
  59         /* The system property "sun.java2d.print.polling"
  60          * can be used to force the printing code to poll or not poll
  61          * for PrintServices.
  62          */
  63         String pollStr = java.security.AccessController.doPrivileged(
  64             new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
  65         pollServices = !("false".equalsIgnoreCase(pollStr));





  66 
  67         /* The system property "sun.java2d.print.minRefreshTime"
  68          * can be used to specify minimum refresh time (in seconds)
  69          * for polling PrintServices.  The default is 240.
  70          */
  71         String refreshTimeStr = java.security.AccessController.doPrivileged(
  72             new sun.security.action.GetPropertyAction(
  73                 "sun.java2d.print.minRefreshTime"));
  74         refreshTime = (refreshTimeStr != null)
  75                       ? getRefreshTime(refreshTimeStr)
  76                       : DEFAULT_REFRESH_TIME;








  77 
  78         java.security.AccessController.doPrivileged(
  79             new java.security.PrivilegedAction<Void>() {
  80                 public Void run() {
  81                     System.loadLibrary("awt");
  82                     return null;
  83                 }
  84             });
  85     }
  86 
  87     private static int getRefreshTime(final String refreshTimeStr) {
  88         try {
  89             int minRefreshTime = Integer.parseInt(refreshTimeStr);
  90             return (minRefreshTime < MINIMUM_REFRESH_TIME)
  91                    ? MINIMUM_REFRESH_TIME
  92                    : minRefreshTime;
  93         } catch (NumberFormatException e) {
  94             return DEFAULT_REFRESH_TIME;
  95         }
  96     }
  97 
  98     /* The singleton win32 print lookup service.
  99      * Code that is aware of this field and wants to use it must first
 100      * see if its null, and if so instantiate it by calling a method such as
 101      * javax.print.PrintServiceLookup.defaultPrintService() so that the
 102      * same instance is stored there.
 103      */
 104     private static PrintServiceLookupProvider win32PrintLUS;
 105 
 106     /* Think carefully before calling this. Preferably don't call it. */
 107     public static PrintServiceLookupProvider getWin32PrintLUS() {
 108         if (win32PrintLUS == null) {
 109             /* This call is internally synchronized.
 110              * When it returns an instance of this class will have
 111              * been instantiated - else there's a JDK internal error.
 112              */
 113             PrintServiceLookup.lookupDefaultPrintService();
 114         }
 115         return win32PrintLUS;
 116     }
 117 


 383     }
 384 
 385     /* Windows provides *PrinterChangeNotification* functions that provides
 386        information about printer status changes of the local printers but not
 387        network printers.
 388        Alternatively, Windows provides a way through which one can get the
 389        network printer status changes by using WMI, RegistryKeyChange combination,
 390        which is a slightly complex mechanism.
 391        The Windows WMI offers an async and sync method to read through registry
 392        via the WQL query. The async method is considered dangerous as it leaves
 393        open a channel until we close it. But the async method has the advantage of
 394        being notified of a change in registry by calling callback without polling for it.
 395        The sync method uses the polling mechanism to notify.
 396        RegistryValueChange cannot be used in combination with WMI to get registry
 397        value change notification because of an error that may be generated because the
 398        scope of the query would be too big to handle(at times).
 399        Hence an alternative mechanism is chosen via the EnumPrinters by polling for the
 400        count of printer status changes(add\remove) and based on it update the printers
 401        list.
 402     */
 403     class RemotePrinterChangeListener implements Comparator<String>, Runnable {

 404 
 405         RemotePrinterChangeListener() {
 406         }
 407 
 408         @Override
 409         public int compare(String o1, String o2) {
 410             return ((o1 == null)
 411                     ? ((o2 == null) ? 0 : 1)
 412                     : ((o2 == null) ? -1 : o1.compareTo(o2)));



























 413         }
 414 
 415         @Override
 416         public void run() {
 417             // Init the list of remote printers
 418             String[] prevRemotePrinters = getRemotePrintersNames();
 419             if (prevRemotePrinters != null) {
 420                 Arrays.sort(prevRemotePrinters, this);
 421             }
 422 
 423             while (true) {
 424                 try {
 425                     Thread.sleep(refreshTime * 1000);
 426                 } catch (InterruptedException e) {
 427                     break;
 428                 }
 429 
 430                 String[] currentRemotePrinters = getRemotePrintersNames();
 431                 if (currentRemotePrinters != null) {
 432                     Arrays.sort(currentRemotePrinters, this);
 433                 }
 434                 if (!Arrays.equals(prevRemotePrinters, currentRemotePrinters)) {
 435                     // The list of remote printers got updated,
 436                     // so update the cached list printers which
 437                     // includes both local and network printers
 438                     refreshServices();
 439 
 440                     // store the current data for next comparison
 441                     prevRemotePrinters = currentRemotePrinters;
 442                 }
 443             }
 444         }
 445     }
 446 
 447     private native String getDefaultPrinterName();
 448     private native String[] getAllPrinterNames();
 449     private native long notifyFirstPrinterChange(String printer);
 450     private native void notifyClosePrinterChange(long chgObj);
 451     private native int notifyPrinterChange(long chgObj);
 452     private native String[] getRemotePrintersNames();
 453 }
< prev index next >