Home » openjdk-7 » javax » print » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   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   
   27   package javax.print;
   28   
   29   import java.util.ArrayList;
   30   import java.util.Iterator;
   31   import javax.print.attribute.AttributeSet;
   32   
   33   import sun.awt.AppContext;
   34   import java.util.ServiceLoader;
   35   import java.util.ServiceConfigurationError;
   36   
   37   /** Implementations of this class provide lookup services for
   38     * print services (typically equivalent to printers) of a particular type.
   39     * <p>
   40     * Multiple implementations may be installed concurrently.
   41     * All implementations must be able to describe the located printers
   42     * as instances of a PrintService.
   43     * Typically implementations of this service class are located
   44     * automatically in JAR files (see the SPI JAR file specification).
   45     * These classes must be instantiable using a default constructor.
   46     * Alternatively applications may explicitly register instances
   47     * at runtime.
   48     * <p>
   49     * Applications use only the static methods of this abstract class.
   50     * The instance methods are implemented by a service provider in a subclass
   51     * and the unification of the results from all installed lookup classes
   52     * are reported by the static methods of this class when called by
   53     * the application.
   54     * <p>
   55     * A PrintServiceLookup implementor is recommended to check for the
   56     * SecurityManager.checkPrintJobAccess() to deny access to untrusted code.
   57     * Following this recommended policy means that untrusted code may not
   58     * be able to locate any print services. Downloaded applets are the most
   59     * common example of untrusted code.
   60     * <p>
   61     * This check is made on a per lookup service basis to allow flexibility in
   62     * the policy to reflect the needs of different lookup services.
   63     * <p>
   64     * Services which are registered by registerService(PrintService)
   65     * will not be included in lookup results if a security manager is
   66     * installed and its checkPrintJobAccess() method denies access.
   67     */
   68   
   69   public abstract class PrintServiceLookup {
   70   
   71       static class Services {
   72           private ArrayList listOfLookupServices = null;
   73           private ArrayList registeredServices = null;
   74       }
   75   
   76       private static Services getServicesForContext() {
   77           Services services =
   78               (Services)AppContext.getAppContext().get(Services.class);
   79           if (services == null) {
   80               services = new Services();
   81               AppContext.getAppContext().put(Services.class, services);
   82           }
   83           return services;
   84       }
   85   
   86       private static ArrayList getListOfLookupServices() {
   87           return getServicesForContext().listOfLookupServices;
   88       }
   89   
   90       private static ArrayList initListOfLookupServices() {
   91           ArrayList listOfLookupServices = new ArrayList();
   92           getServicesForContext().listOfLookupServices = listOfLookupServices;
   93           return listOfLookupServices;
   94       }
   95   
   96   
   97       private static ArrayList getRegisteredServices() {
   98           return getServicesForContext().registeredServices;
   99       }
  100   
  101       private static ArrayList initRegisteredServices() {
  102           ArrayList registeredServices = new ArrayList();
  103           getServicesForContext().registeredServices = registeredServices;
  104           return registeredServices;
  105       }
  106   
  107       /**
  108        * Locates print services capable of printing the specified
  109        * {@link DocFlavor}.
  110        *
  111        * @param flavor the flavor to print. If null, this constraint is not
  112        *        used.
  113        * @param attributes attributes that the print service must support.
  114        * If null this constraint is not used.
  115        *
  116        * @return array of matching <code>PrintService</code> objects
  117        * representing print services that support the specified flavor
  118        * attributes.  If no services match, the array is zero-length.
  119        */
  120       public static final PrintService[]
  121           lookupPrintServices(DocFlavor flavor,
  122                               AttributeSet attributes) {
  123           ArrayList list = getServices(flavor, attributes);
  124           return (PrintService[])(list.toArray(new PrintService[list.size()]));
  125       }
  126   
  127   
  128       /**
  129        * Locates MultiDoc print Services capable of printing MultiDocs
  130        * containing all the specified doc flavors.
  131        * <P> This method is useful to help locate a service that can print
  132        * a <code>MultiDoc</code> in which the elements may be different
  133        * flavors. An application could perform this itself by multiple lookups
  134        * on each <code>DocFlavor</code> in turn and collating the results,
  135        * but the lookup service may be able to do this more efficiently.
  136        *
  137        * @param flavors the flavors to print. If null or empty this
  138        *        constraint is not used.
  139        * Otherwise return only multidoc print services that can print all
  140        * specified doc flavors.
  141        * @param attributes attributes that the print service must
  142        * support.  If null this constraint is not used.
  143        *
  144        * @return array of matching {@link MultiDocPrintService} objects.
  145        * If no services match, the array is zero-length.
  146        *
  147        */
  148       public static final MultiDocPrintService[]
  149           lookupMultiDocPrintServices(DocFlavor[] flavors,
  150                                       AttributeSet attributes) {
  151           ArrayList list = getMultiDocServices(flavors, attributes);
  152           return (MultiDocPrintService[])
  153               list.toArray(new MultiDocPrintService[list.size()]);
  154       }
  155   
  156   
  157       /**
  158        * Locates the default print service for this environment.
  159        * This may return null.
  160        * If multiple lookup services each specify a default, the
  161        * chosen service is not precisely defined, but a
  162        * platform native service, rather than an installed service,
  163        * is usually returned as the default.  If there is no clearly
  164        * identifiable
  165        * platform native default print service, the default is the first
  166        * to be located in an implementation-dependent manner.
  167        * <p>
  168        * This may include making use of any preferences API that is available
  169        * as part of the Java or native platform.
  170        * This algorithm may be overridden by a user setting the property
  171        * javax.print.defaultPrinter.
  172        * A service specified must be discovered to be valid and currently
  173        * available to be returned as the default.
  174        *
  175        * @return the default PrintService.
  176        */
  177   
  178       public static final PrintService lookupDefaultPrintService() {
  179   
  180           Iterator psIterator = getAllLookupServices().iterator();
  181           while (psIterator.hasNext()) {
  182               try {
  183                   PrintServiceLookup lus = (PrintServiceLookup)psIterator.next();
  184                   PrintService service = lus.getDefaultPrintService();
  185                   if (service != null) {
  186                       return service;
  187                   }
  188               } catch (Exception e) {
  189               }
  190           }
  191           return null;
  192       }
  193   
  194   
  195       /**
  196        * Allows an application to explicitly register a class that
  197        * implements lookup services. The registration will not persist
  198        * across VM invocations.
  199        * This is useful if an application needs to make a new service
  200        * available that is not part of the installation.
  201        * If the lookup service is already registered, or cannot be registered,
  202        * the method returns false.
  203        * <p>
  204        *
  205        * @param sp an implementation of a lookup service.
  206        * @return <code>true</code> if the new lookup service is newly
  207        *         registered; <code>false</code> otherwise.
  208        */
  209       public static boolean registerServiceProvider(PrintServiceLookup sp) {
  210           synchronized (PrintServiceLookup.class) {
  211               Iterator psIterator = getAllLookupServices().iterator();
  212               while (psIterator.hasNext()) {
  213                   try {
  214                       Object lus = psIterator.next();
  215                       if (lus.getClass() == sp.getClass()) {
  216                           return false;
  217                       }
  218                   } catch (Exception e) {
  219                   }
  220               }
  221               getListOfLookupServices().add(sp);
  222               return true;
  223           }
  224   
  225       }
  226   
  227   
  228       /**
  229        * Allows an application to directly register an instance of a
  230        * class which implements a print service.
  231        * The lookup operations for this service will be
  232        * performed by the PrintServiceLookup class using the attribute
  233        * values and classes reported by the service.
  234        * This may be less efficient than a lookup
  235        * service tuned for that service.
  236        * Therefore registering a <code>PrintServiceLookup</code> instance
  237        * instead is recommended.
  238        * The method returns true if this service is not previously
  239        * registered and is now successfully registered.
  240        * This method should not be called with StreamPrintService instances.
  241        * They will always fail to register and the method will return false.
  242        * @param service an implementation of a print service.
  243        * @return <code>true</code> if the service is newly
  244        *         registered; <code>false</code> otherwise.
  245        */
  246   
  247       public static boolean registerService(PrintService service) {
  248           synchronized (PrintServiceLookup.class) {
  249               if (service instanceof StreamPrintService) {
  250                   return false;
  251               }
  252               ArrayList registeredServices = getRegisteredServices();
  253               if (registeredServices == null) {
  254                   registeredServices = initRegisteredServices();
  255               }
  256               else {
  257                 if (registeredServices.contains(service)) {
  258                   return false;
  259                 }
  260               }
  261               registeredServices.add(service);
  262               return true;
  263           }
  264       }
  265   
  266   
  267      /**
  268       * Locates services that can be positively confirmed to support
  269       * the combination of attributes and DocFlavors specified.
  270       * This method is not called directly by applications.
  271       * <p>
  272       * Implemented by a service provider, used by the static methods
  273       * of this class.
  274       * <p>
  275       * The results should be the same as obtaining all the PrintServices
  276       * and querying each one individually on its support for the
  277       * specified attributes and flavors, but the process can be more
  278       * efficient by taking advantage of the capabilities of lookup services
  279       * for the print services.
  280       *
  281       * @param flavor of document required.  If null it is ignored.
  282       * @param attributes required to be supported. If null this
  283       * constraint is not used.
  284       * @return array of matching PrintServices. If no services match, the
  285       * array is zero-length.
  286       */
  287       public abstract PrintService[] getPrintServices(DocFlavor flavor,
  288                                                       AttributeSet attributes);
  289   
  290       /**
  291        * Not called directly by applications.
  292        * Implemented by a service provider, used by the static methods
  293        * of this class.
  294        * @return array of all PrintServices known to this lookup service
  295        * class. If none are found, the array is zero-length.
  296        */
  297       public abstract PrintService[] getPrintServices() ;
  298   
  299   
  300      /**
  301       * Not called directly by applications.
  302       * <p>
  303       * Implemented by a service provider, used by the static methods
  304       * of this class.
  305       * <p>
  306       * Locates MultiDoc print services which can be positively confirmed
  307       * to support the combination of attributes and DocFlavors specified.
  308       * <p>
  309       *
  310       * @param flavors of documents required. If null or empty it is ignored.
  311       * @param attributes required to be supported. If null this
  312        * constraint is not used.
  313       * @return array of matching PrintServices. If no services match, the
  314       * array is zero-length.
  315       */
  316       public abstract MultiDocPrintService[]
  317           getMultiDocPrintServices(DocFlavor[] flavors,
  318                                    AttributeSet attributes);
  319   
  320       /**
  321        * Not called directly by applications.
  322        * Implemented by a service provider, and called by the print lookup
  323        * service
  324        * @return the default PrintService for this lookup service.
  325        * If there is no default, returns null.
  326        */
  327       public abstract PrintService getDefaultPrintService();
  328   
  329       private static ArrayList getAllLookupServices() {
  330           synchronized (PrintServiceLookup.class) {
  331               ArrayList listOfLookupServices = getListOfLookupServices();
  332               if (listOfLookupServices != null) {
  333                   return listOfLookupServices;
  334               } else {
  335                   listOfLookupServices = initListOfLookupServices();
  336               }
  337               try {
  338                   java.security.AccessController.doPrivileged(
  339                        new java.security.PrivilegedExceptionAction() {
  340                           public Object run() {
  341                               Iterator<PrintServiceLookup> iterator =
  342                                   ServiceLoader.load(PrintServiceLookup.class).
  343                                   iterator();
  344                               ArrayList los = getListOfLookupServices();
  345                               while (iterator.hasNext()) {
  346                                   try {
  347                                       los.add(iterator.next());
  348                                   }  catch (ServiceConfigurationError err) {
  349                                       /* In the applet case, we continue */
  350                                       if (System.getSecurityManager() != null) {
  351                                           err.printStackTrace();
  352                                       } else {
  353                                           throw err;
  354                                       }
  355                                   }
  356                               }
  357                               return null;
  358                           }
  359                   });
  360               } catch (java.security.PrivilegedActionException e) {
  361               }
  362   
  363               return listOfLookupServices;
  364           }
  365       }
  366   
  367       private static ArrayList getServices(DocFlavor flavor,
  368                                            AttributeSet attributes) {
  369   
  370           ArrayList listOfServices = new ArrayList();
  371           Iterator psIterator = getAllLookupServices().iterator();
  372           while (psIterator.hasNext()) {
  373               try {
  374                   PrintServiceLookup lus = (PrintServiceLookup)psIterator.next();
  375                   PrintService[] services=null;
  376                   if (flavor == null && attributes == null) {
  377                       try {
  378                       services = lus.getPrintServices();
  379                       } catch (Throwable tr) {
  380                       }
  381                   } else {
  382                       services = lus.getPrintServices(flavor, attributes);
  383                   }
  384                   if (services == null) {
  385                       continue;
  386                   }
  387                   for (int i=0; i<services.length; i++) {
  388                       listOfServices.add(services[i]);
  389                   }
  390               } catch (Exception e) {
  391               }
  392           }
  393           /* add any directly registered services */
  394           ArrayList registeredServices = null;
  395           try {
  396             SecurityManager security = System.getSecurityManager();
  397             if (security != null) {
  398               security.checkPrintJobAccess();
  399             }
  400             registeredServices = getRegisteredServices();
  401           } catch (SecurityException se) {
  402           }
  403           if (registeredServices != null) {
  404               PrintService[] services = (PrintService[])
  405                   registeredServices.toArray(
  406                              new PrintService[registeredServices.size()]);
  407               for (int i=0; i<services.length; i++) {
  408                   if (!listOfServices.contains(services[i])) {
  409                       if (flavor == null && attributes == null) {
  410                           listOfServices.add(services[i]);
  411                       } else if (((flavor != null &&
  412                                    services[i].isDocFlavorSupported(flavor)) ||
  413                                   flavor == null) &&
  414                                  null == services[i].getUnsupportedAttributes(
  415                                                         flavor, attributes)) {
  416                           listOfServices.add(services[i]);
  417                       }
  418                   }
  419               }
  420           }
  421           return listOfServices;
  422       }
  423   
  424       private static ArrayList getMultiDocServices(DocFlavor[] flavors,
  425                                                    AttributeSet attributes) {
  426   
  427   
  428           ArrayList listOfServices = new ArrayList();
  429           Iterator psIterator = getAllLookupServices().iterator();
  430           while (psIterator.hasNext()) {
  431               try {
  432                   PrintServiceLookup lus = (PrintServiceLookup)psIterator.next();
  433                   MultiDocPrintService[] services  =
  434                       lus.getMultiDocPrintServices(flavors, attributes);
  435                   if (services == null) {
  436                       continue;
  437                   }
  438                   for (int i=0; i<services.length; i++) {
  439                       listOfServices.add(services[i]);
  440                   }
  441               } catch (Exception e) {
  442               }
  443           }
  444           /* add any directly registered services */
  445           ArrayList registeredServices = null;
  446           try {
  447             SecurityManager security = System.getSecurityManager();
  448             if (security != null) {
  449               security.checkPrintJobAccess();
  450             }
  451             registeredServices = getRegisteredServices();
  452           } catch (Exception e) {
  453           }
  454           if (registeredServices != null) {
  455               PrintService[] services = (PrintService[])
  456                   registeredServices.toArray(
  457                              new PrintService[registeredServices.size()]);
  458               for (int i=0; i<services.length; i++) {
  459                   if (services[i] instanceof MultiDocPrintService &&
  460                       !listOfServices.contains(services[i])) {
  461                       if (flavors == null || flavors.length == 0) {
  462                           listOfServices.add(services[i]);
  463                       } else {
  464                           boolean supported = true;
  465                           for (int f=0; f<flavors.length; f++) {
  466                               if (services[i].isDocFlavorSupported(flavors[f])) {
  467   
  468                                   if (services[i].getUnsupportedAttributes(
  469                                        flavors[f], attributes) != null) {
  470                                           supported = false;
  471                                           break;
  472                                   }
  473                               } else {
  474                                   supported = false;
  475                                   break;
  476                               }
  477                           }
  478                           if (supported) {
  479                               listOfServices.add(services[i]);
  480                           }
  481                       }
  482                   }
  483               }
  484           }
  485           return listOfServices;
  486       }
  487   
  488   }

Home » openjdk-7 » javax » print » [javadoc | source]