|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  |  | 
|  | package javax.print; | 
|  |  | 
|  | import java.util.ArrayList; | 
|  | import java.util.Iterator; | 
|  | import javax.print.attribute.AttributeSet; | 
|  |  | 
|  | import sun.awt.AppContext; | 
|  | import java.util.ServiceLoader; | 
|  | import java.util.ServiceConfigurationError; | 
|  |  | 
|  | /** Implementations of this class provide lookup services for | 
|  |   * print services (typically equivalent to printers) of a particular type. | 
|  |   * <p> | 
|  |   * Multiple implementations may be installed concurrently. | 
|  |   * All implementations must be able to describe the located printers | 
|  |   * as instances of a PrintService. | 
|  |   * Typically implementations of this service class are located | 
|  |   * automatically in JAR files (see the SPI JAR file specification). | 
|  |   * These classes must be instantiable using a default constructor. | 
|  |   * Alternatively applications may explicitly register instances | 
|  |   * at runtime. | 
|  |   * <p> | 
|  |   * Applications use only the static methods of this abstract class. | 
|  |   * The instance methods are implemented by a service provider in a subclass | 
|  |   * and the unification of the results from all installed lookup classes | 
|  |   * are reported by the static methods of this class when called by | 
|  |   * the application. | 
|  |   * <p> | 
|  |   * A PrintServiceLookup implementor is recommended to check for the | 
|  |   * SecurityManager.checkPrintJobAccess() to deny access to untrusted code. | 
|  |   * Following this recommended policy means that untrusted code may not | 
|  |   * be able to locate any print services. Downloaded applets are the most | 
|  |   * common example of untrusted code. | 
|  |   * <p> | 
|  |   * This check is made on a per lookup service basis to allow flexibility in | 
|  |   * the policy to reflect the needs of different lookup services. | 
|  |   * <p> | 
|  |   * Services which are registered by registerService(PrintService) | 
|  |   * will not be included in lookup results if a security manager is | 
|  |   * installed and its checkPrintJobAccess() method denies access. | 
|  |   */ | 
|  |  | 
|  | public abstract class PrintServiceLookup { | 
|  |  | 
|  |     static class Services { | 
|  |         private ArrayList listOfLookupServices = null; | 
|  |         private ArrayList registeredServices = null; | 
|  |     } | 
|  |  | 
|  |     private static Services getServicesForContext() { | 
|  |         Services services = | 
|  |             (Services)AppContext.getAppContext().get(Services.class); | 
|  |         if (services == null) { | 
|  |             services = new Services(); | 
|  |             AppContext.getAppContext().put(Services.class, services); | 
|  |         } | 
|  |         return services; | 
|  |     } | 
|  |  | 
|  |     private static ArrayList getListOfLookupServices() { | 
|  |         return getServicesForContext().listOfLookupServices; | 
|  |     } | 
|  |  | 
|  |     private static ArrayList initListOfLookupServices() { | 
|  |         ArrayList listOfLookupServices = new ArrayList(); | 
|  |         getServicesForContext().listOfLookupServices = listOfLookupServices; | 
|  |         return listOfLookupServices; | 
|  |     } | 
|  |  | 
|  |  | 
|  |     private static ArrayList getRegisteredServices() { | 
|  |         return getServicesForContext().registeredServices; | 
|  |     } | 
|  |  | 
|  |     private static ArrayList initRegisteredServices() { | 
|  |         ArrayList registeredServices = new ArrayList(); | 
|  |         getServicesForContext().registeredServices = registeredServices; | 
|  |         return registeredServices; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static final PrintService[] | 
|  |         lookupPrintServices(DocFlavor flavor, | 
|  |                             AttributeSet attributes) { | 
|  |         ArrayList list = getServices(flavor, attributes); | 
|  |         return (PrintService[])(list.toArray(new PrintService[list.size()])); | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static final MultiDocPrintService[] | 
|  |         lookupMultiDocPrintServices(DocFlavor[] flavors, | 
|  |                                     AttributeSet attributes) { | 
|  |         ArrayList list = getMultiDocServices(flavors, attributes); | 
|  |         return (MultiDocPrintService[]) | 
|  |             list.toArray(new MultiDocPrintService[list.size()]); | 
|  |     } | 
|  |  | 
|  |  | 
|  |     /** | 
|  |      * Locates the default print service for this environment. | 
|  |      * This may return null. | 
|  |      * If multiple lookup services each specify a default, the | 
|  |      * chosen service is not precisely defined, but a | 
|  |      * platform native service, rather than an installed service, | 
|  |      * is usually returned as the default.  If there is no clearly | 
|  |      * identifiable | 
|  |      * platform native default print service, the default is the first | 
|  |      * to be located in an implementation-dependent manner. | 
|  |      * <p> | 
|  |      * This may include making use of any preferences API that is available | 
|  |      * as part of the Java or native platform. | 
|  |      * This algorithm may be overridden by a user setting the property | 
|  |      * javax.print.defaultPrinter. | 
|  |      * A service specified must be discovered to be valid and currently | 
|  |      * available to be returned as the default. | 
|  |      * | 
|  |      * @return the default PrintService. | 
|  |      */ | 
|  |  | 
|  |     public static final PrintService lookupDefaultPrintService() { | 
|  |  | 
|  |         Iterator psIterator = getAllLookupServices().iterator(); | 
|  |         while (psIterator.hasNext()) { | 
|  |             try { | 
|  |                 PrintServiceLookup lus = (PrintServiceLookup)psIterator.next(); | 
|  |                 PrintService service = lus.getDefaultPrintService(); | 
|  |                 if (service != null) { | 
|  |                     return service; | 
|  |                 } | 
|  |             } catch (Exception e) { | 
|  |             } | 
|  |         } | 
|  |         return null; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public static boolean registerServiceProvider(PrintServiceLookup sp) { | 
|  |         synchronized (PrintServiceLookup.class) { | 
|  |             Iterator psIterator = getAllLookupServices().iterator(); | 
|  |             while (psIterator.hasNext()) { | 
|  |                 try { | 
|  |                     Object lus = psIterator.next(); | 
|  |                     if (lus.getClass() == sp.getClass()) { | 
|  |                         return false; | 
|  |                     } | 
|  |                 } catch (Exception e) { | 
|  |                 } | 
|  |             } | 
|  |             getListOfLookupServices().add(sp); | 
|  |             return true; | 
|  |         } | 
|  |  | 
|  |     } | 
|  |  | 
|  |  | 
|  |     /** | 
|  |      * Allows an application to directly register an instance of a | 
|  |      * class which implements a print service. | 
|  |      * The lookup operations for this service will be | 
|  |      * performed by the PrintServiceLookup class using the attribute | 
|  |      * values and classes reported by the service. | 
|  |      * This may be less efficient than a lookup | 
|  |      * service tuned for that service. | 
|  |      * Therefore registering a <code>PrintServiceLookup</code> instance | 
|  |      * instead is recommended. | 
|  |      * The method returns true if this service is not previously | 
|  |      * registered and is now successfully registered. | 
|  |      * This method should not be called with StreamPrintService instances. | 
|  |      * They will always fail to register and the method will return false. | 
|  |      * @param service an implementation of a print service. | 
|  |      * @return <code>true</code> if the service is newly | 
|  |      *         registered; <code>false</code> otherwise. | 
|  |      */ | 
|  |  | 
|  |     public static boolean registerService(PrintService service) { | 
|  |         synchronized (PrintServiceLookup.class) { | 
|  |             if (service instanceof StreamPrintService) { | 
|  |                 return false; | 
|  |             } | 
|  |             ArrayList registeredServices = getRegisteredServices(); | 
|  |             if (registeredServices == null) { | 
|  |                 registeredServices = initRegisteredServices(); | 
|  |             } | 
|  |             else { | 
|  |               if (registeredServices.contains(service)) { | 
|  |                 return false; | 
|  |               } | 
|  |             } | 
|  |             registeredServices.add(service); | 
|  |             return true; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |  | 
|  |     | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |     */ | 
|  |     public abstract PrintService[] getPrintServices(DocFlavor flavor, | 
|  |                                                     AttributeSet attributes); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public abstract PrintService[] getPrintServices() ; | 
|  |  | 
|  |  | 
|  |     | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |     */ | 
|  |     public abstract MultiDocPrintService[] | 
|  |         getMultiDocPrintServices(DocFlavor[] flavors, | 
|  |                                  AttributeSet attributes); | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public abstract PrintService getDefaultPrintService(); | 
|  |  | 
|  |     private static ArrayList getAllLookupServices() { | 
|  |         synchronized (PrintServiceLookup.class) { | 
|  |             ArrayList listOfLookupServices = getListOfLookupServices(); | 
|  |             if (listOfLookupServices != null) { | 
|  |                 return listOfLookupServices; | 
|  |             } else { | 
|  |                 listOfLookupServices = initListOfLookupServices(); | 
|  |             } | 
|  |             try { | 
|  |                 java.security.AccessController.doPrivileged( | 
|  |                      new java.security.PrivilegedExceptionAction() { | 
|  |                         public Object run() { | 
|  |                             Iterator<PrintServiceLookup> iterator = | 
|  |                                 ServiceLoader.load(PrintServiceLookup.class). | 
|  |                                 iterator(); | 
|  |                             ArrayList los = getListOfLookupServices(); | 
|  |                             while (iterator.hasNext()) { | 
|  |                                 try { | 
|  |                                     los.add(iterator.next()); | 
|  |                                 }  catch (ServiceConfigurationError err) { | 
|  |                                      | 
|  |                                     if (System.getSecurityManager() != null) { | 
|  |                                         err.printStackTrace(); | 
|  |                                     } else { | 
|  |                                         throw err; | 
|  |                                     } | 
|  |                                 } | 
|  |                             } | 
|  |                             return null; | 
|  |                         } | 
|  |                 }); | 
|  |             } catch (java.security.PrivilegedActionException e) { | 
|  |             } | 
|  |  | 
|  |             return listOfLookupServices; | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     private static ArrayList getServices(DocFlavor flavor, | 
|  |                                          AttributeSet attributes) { | 
|  |  | 
|  |         ArrayList listOfServices = new ArrayList(); | 
|  |         Iterator psIterator = getAllLookupServices().iterator(); | 
|  |         while (psIterator.hasNext()) { | 
|  |             try { | 
|  |                 PrintServiceLookup lus = (PrintServiceLookup)psIterator.next(); | 
|  |                 PrintService[] services=null; | 
|  |                 if (flavor == null && attributes == null) { | 
|  |                     try { | 
|  |                     services = lus.getPrintServices(); | 
|  |                     } catch (Throwable tr) { | 
|  |                     } | 
|  |                 } else { | 
|  |                     services = lus.getPrintServices(flavor, attributes); | 
|  |                 } | 
|  |                 if (services == null) { | 
|  |                     continue; | 
|  |                 } | 
|  |                 for (int i=0; i<services.length; i++) { | 
|  |                     listOfServices.add(services[i]); | 
|  |                 } | 
|  |             } catch (Exception e) { | 
|  |             } | 
|  |         } | 
|  |          | 
|  |         ArrayList registeredServices = null; | 
|  |         try { | 
|  |           SecurityManager security = System.getSecurityManager(); | 
|  |           if (security != null) { | 
|  |             security.checkPrintJobAccess(); | 
|  |           } | 
|  |           registeredServices = getRegisteredServices(); | 
|  |         } catch (SecurityException se) { | 
|  |         } | 
|  |         if (registeredServices != null) { | 
|  |             PrintService[] services = (PrintService[]) | 
|  |                 registeredServices.toArray( | 
|  |                            new PrintService[registeredServices.size()]); | 
|  |             for (int i=0; i<services.length; i++) { | 
|  |                 if (!listOfServices.contains(services[i])) { | 
|  |                     if (flavor == null && attributes == null) { | 
|  |                         listOfServices.add(services[i]); | 
|  |                     } else if (((flavor != null && | 
|  |                                  services[i].isDocFlavorSupported(flavor)) || | 
|  |                                 flavor == null) && | 
|  |                                null == services[i].getUnsupportedAttributes( | 
|  |                                                       flavor, attributes)) { | 
|  |                         listOfServices.add(services[i]); | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |         return listOfServices; | 
|  |     } | 
|  |  | 
|  |     private static ArrayList getMultiDocServices(DocFlavor[] flavors, | 
|  |                                                  AttributeSet attributes) { | 
|  |  | 
|  |  | 
|  |         ArrayList listOfServices = new ArrayList(); | 
|  |         Iterator psIterator = getAllLookupServices().iterator(); | 
|  |         while (psIterator.hasNext()) { | 
|  |             try { | 
|  |                 PrintServiceLookup lus = (PrintServiceLookup)psIterator.next(); | 
|  |                 MultiDocPrintService[] services  = | 
|  |                     lus.getMultiDocPrintServices(flavors, attributes); | 
|  |                 if (services == null) { | 
|  |                     continue; | 
|  |                 } | 
|  |                 for (int i=0; i<services.length; i++) { | 
|  |                     listOfServices.add(services[i]); | 
|  |                 } | 
|  |             } catch (Exception e) { | 
|  |             } | 
|  |         } | 
|  |          | 
|  |         ArrayList registeredServices = null; | 
|  |         try { | 
|  |           SecurityManager security = System.getSecurityManager(); | 
|  |           if (security != null) { | 
|  |             security.checkPrintJobAccess(); | 
|  |           } | 
|  |           registeredServices = getRegisteredServices(); | 
|  |         } catch (Exception e) { | 
|  |         } | 
|  |         if (registeredServices != null) { | 
|  |             PrintService[] services = (PrintService[]) | 
|  |                 registeredServices.toArray( | 
|  |                            new PrintService[registeredServices.size()]); | 
|  |             for (int i=0; i<services.length; i++) { | 
|  |                 if (services[i] instanceof MultiDocPrintService && | 
|  |                     !listOfServices.contains(services[i])) { | 
|  |                     if (flavors == null || flavors.length == 0) { | 
|  |                         listOfServices.add(services[i]); | 
|  |                     } else { | 
|  |                         boolean supported = true; | 
|  |                         for (int f=0; f<flavors.length; f++) { | 
|  |                             if (services[i].isDocFlavorSupported(flavors[f])) { | 
|  |  | 
|  |                                 if (services[i].getUnsupportedAttributes( | 
|  |                                      flavors[f], attributes) != null) { | 
|  |                                         supported = false; | 
|  |                                         break; | 
|  |                                 } | 
|  |                             } else { | 
|  |                                 supported = false; | 
|  |                                 break; | 
|  |                             } | 
|  |                         } | 
|  |                         if (supported) { | 
|  |                             listOfServices.add(services[i]); | 
|  |                         } | 
|  |                     } | 
|  |                 } | 
|  |             } | 
|  |         } | 
|  |         return listOfServices; | 
|  |     } | 
|  |  | 
|  | } |