src/share/classes/javax/print/PrintServiceLookup.java

Print this page




  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


 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 }


  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<PrintServiceLookup> listOfLookupServices = null;
  73         private ArrayList<PrintService> 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<PrintServiceLookup> getListOfLookupServices() {
  87         return getServicesForContext().listOfLookupServices;
  88     }
  89 
  90     private static ArrayList<PrintServiceLookup> initListOfLookupServices() {
  91         ArrayList<PrintServiceLookup> listOfLookupServices = new ArrayList<>();
  92         getServicesForContext().listOfLookupServices = listOfLookupServices;
  93         return listOfLookupServices;
  94     }
  95 
  96 
  97     private static ArrayList<PrintService> getRegisteredServices() {
  98         return getServicesForContext().registeredServices;
  99     }
 100 
 101     private static ArrayList<PrintService> initRegisteredServices() {
 102         ArrayList<PrintService> 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<PrintService> list = getServices(flavor, attributes);
 124         return 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<MultiDocPrintService> list = getMultiDocServices(flavors, attributes);
 152         return list.toArray(new MultiDocPrintService[list.size()]);

 153     }
 154 
 155 
 156     /**
 157      * Locates the default print service for this environment.
 158      * This may return null.
 159      * If multiple lookup services each specify a default, the
 160      * chosen service is not precisely defined, but a
 161      * platform native service, rather than an installed service,
 162      * is usually returned as the default.  If there is no clearly
 163      * identifiable
 164      * platform native default print service, the default is the first
 165      * to be located in an implementation-dependent manner.
 166      * <p>
 167      * This may include making use of any preferences API that is available
 168      * as part of the Java or native platform.
 169      * This algorithm may be overridden by a user setting the property
 170      * javax.print.defaultPrinter.
 171      * A service specified must be discovered to be valid and currently
 172      * available to be returned as the default.
 173      *
 174      * @return the default PrintService.
 175      */
 176 
 177     public static final PrintService lookupDefaultPrintService() {
 178 
 179         Iterator<PrintServiceLookup> psIterator = getAllLookupServices().iterator();
 180         while (psIterator.hasNext()) {
 181             try {
 182                 PrintServiceLookup lus = psIterator.next();
 183                 PrintService service = lus.getDefaultPrintService();
 184                 if (service != null) {
 185                     return service;
 186                 }
 187             } catch (Exception e) {
 188             }
 189         }
 190         return null;
 191     }
 192 
 193 
 194     /**
 195      * Allows an application to explicitly register a class that
 196      * implements lookup services. The registration will not persist
 197      * across VM invocations.
 198      * This is useful if an application needs to make a new service
 199      * available that is not part of the installation.
 200      * If the lookup service is already registered, or cannot be registered,
 201      * the method returns false.
 202      * <p>
 203      *
 204      * @param sp an implementation of a lookup service.
 205      * @return <code>true</code> if the new lookup service is newly
 206      *         registered; <code>false</code> otherwise.
 207      */
 208     public static boolean registerServiceProvider(PrintServiceLookup sp) {
 209         synchronized (PrintServiceLookup.class) {
 210             Iterator<?> psIterator = getAllLookupServices().iterator();
 211             while (psIterator.hasNext()) {
 212                 try {
 213                     Object lus = psIterator.next();
 214                     if (lus.getClass() == sp.getClass()) {
 215                         return false;
 216                     }
 217                 } catch (Exception e) {
 218                 }
 219             }
 220             getListOfLookupServices().add(sp);
 221             return true;
 222         }
 223 
 224     }
 225 
 226 
 227     /**
 228      * Allows an application to directly register an instance of a
 229      * class which implements a print service.
 230      * The lookup operations for this service will be
 231      * performed by the PrintServiceLookup class using the attribute
 232      * values and classes reported by the service.
 233      * This may be less efficient than a lookup
 234      * service tuned for that service.
 235      * Therefore registering a <code>PrintServiceLookup</code> instance
 236      * instead is recommended.
 237      * The method returns true if this service is not previously
 238      * registered and is now successfully registered.
 239      * This method should not be called with StreamPrintService instances.
 240      * They will always fail to register and the method will return false.
 241      * @param service an implementation of a print service.
 242      * @return <code>true</code> if the service is newly
 243      *         registered; <code>false</code> otherwise.
 244      */
 245 
 246     public static boolean registerService(PrintService service) {
 247         synchronized (PrintServiceLookup.class) {
 248             if (service instanceof StreamPrintService) {
 249                 return false;
 250             }
 251             ArrayList<PrintService> registeredServices = getRegisteredServices();
 252             if (registeredServices == null) {
 253                 registeredServices = initRegisteredServices();
 254             }
 255             else {
 256               if (registeredServices.contains(service)) {
 257                 return false;
 258               }
 259             }
 260             registeredServices.add(service);
 261             return true;
 262         }
 263     }
 264 
 265 
 266    /**
 267     * Locates services that can be positively confirmed to support
 268     * the combination of attributes and DocFlavors specified.
 269     * This method is not called directly by applications.
 270     * <p>
 271     * Implemented by a service provider, used by the static methods


 308     *
 309     * @param flavors of documents required. If null or empty it is ignored.
 310     * @param attributes required to be supported. If null this
 311      * constraint is not used.
 312     * @return array of matching PrintServices. If no services match, the
 313     * array is zero-length.
 314     */
 315     public abstract MultiDocPrintService[]
 316         getMultiDocPrintServices(DocFlavor[] flavors,
 317                                  AttributeSet attributes);
 318 
 319     /**
 320      * Not called directly by applications.
 321      * Implemented by a service provider, and called by the print lookup
 322      * service
 323      * @return the default PrintService for this lookup service.
 324      * If there is no default, returns null.
 325      */
 326     public abstract PrintService getDefaultPrintService();
 327 
 328     private static ArrayList<PrintServiceLookup> getAllLookupServices() {
 329         synchronized (PrintServiceLookup.class) {
 330             ArrayList<PrintServiceLookup> listOfLookupServices = getListOfLookupServices();
 331             if (listOfLookupServices != null) {
 332                 return listOfLookupServices;
 333             } else {
 334                 listOfLookupServices = initListOfLookupServices();
 335             }
 336             try {
 337                 java.security.AccessController.doPrivileged(
 338                      new java.security.PrivilegedExceptionAction<Object>() {
 339                         public Object run() {
 340                             Iterator<PrintServiceLookup> iterator =
 341                                 ServiceLoader.load(PrintServiceLookup.class).
 342                                 iterator();
 343                             ArrayList<PrintServiceLookup> los = getListOfLookupServices();
 344                             while (iterator.hasNext()) {
 345                                 try {
 346                                     los.add(iterator.next());
 347                                 }  catch (ServiceConfigurationError err) {
 348                                     /* In the applet case, we continue */
 349                                     if (System.getSecurityManager() != null) {
 350                                         err.printStackTrace();
 351                                     } else {
 352                                         throw err;
 353                                     }
 354                                 }
 355                             }
 356                             return null;
 357                         }
 358                 });
 359             } catch (java.security.PrivilegedActionException e) {
 360             }
 361 
 362             return listOfLookupServices;
 363         }
 364     }
 365 
 366     private static ArrayList<PrintService> getServices(DocFlavor flavor,
 367                                                        AttributeSet attributes) {
 368 
 369         ArrayList<PrintService> listOfServices = new ArrayList<>();
 370         Iterator<PrintServiceLookup> psIterator = getAllLookupServices().iterator();
 371         while (psIterator.hasNext()) {
 372             try {
 373                 PrintServiceLookup lus = psIterator.next();
 374                 PrintService[] services=null;
 375                 if (flavor == null && attributes == null) {
 376                     try {
 377                     services = lus.getPrintServices();
 378                     } catch (Throwable tr) {
 379                     }
 380                 } else {
 381                     services = lus.getPrintServices(flavor, attributes);
 382                 }
 383                 if (services == null) {
 384                     continue;
 385                 }
 386                 for (int i=0; i<services.length; i++) {
 387                     listOfServices.add(services[i]);
 388                 }
 389             } catch (Exception e) {
 390             }
 391         }
 392         /* add any directly registered services */
 393         ArrayList<PrintService> registeredServices = null;
 394         try {
 395           SecurityManager security = System.getSecurityManager();
 396           if (security != null) {
 397             security.checkPrintJobAccess();
 398           }
 399           registeredServices = getRegisteredServices();
 400         } catch (SecurityException se) {
 401         }
 402         if (registeredServices != null) {
 403             PrintService[] services = registeredServices.toArray(

 404                            new PrintService[registeredServices.size()]);
 405             for (int i=0; i<services.length; i++) {
 406                 if (!listOfServices.contains(services[i])) {
 407                     if (flavor == null && attributes == null) {
 408                         listOfServices.add(services[i]);
 409                     } else if (((flavor != null &&
 410                                  services[i].isDocFlavorSupported(flavor)) ||
 411                                 flavor == null) &&
 412                                null == services[i].getUnsupportedAttributes(
 413                                                       flavor, attributes)) {
 414                         listOfServices.add(services[i]);
 415                     }
 416                 }
 417             }
 418         }
 419         return listOfServices;
 420     }
 421 
 422     private static ArrayList<MultiDocPrintService> getMultiDocServices(DocFlavor[] flavors,
 423                                                                        AttributeSet attributes) {
 424 
 425 
 426         ArrayList<MultiDocPrintService> listOfServices = new ArrayList<>();
 427         Iterator<PrintServiceLookup> psIterator = getAllLookupServices().iterator();
 428         while (psIterator.hasNext()) {
 429             try {
 430                 PrintServiceLookup lus = psIterator.next();
 431                 MultiDocPrintService[] services  =
 432                     lus.getMultiDocPrintServices(flavors, attributes);
 433                 if (services == null) {
 434                     continue;
 435                 }
 436                 for (int i=0; i<services.length; i++) {
 437                     listOfServices.add(services[i]);
 438                 }
 439             } catch (Exception e) {
 440             }
 441         }
 442         /* add any directly registered services */
 443         ArrayList<PrintService> registeredServices = null;
 444         try {
 445           SecurityManager security = System.getSecurityManager();
 446           if (security != null) {
 447             security.checkPrintJobAccess();
 448           }
 449           registeredServices = getRegisteredServices();
 450         } catch (Exception e) {
 451         }
 452         if (registeredServices != null) {
 453             PrintService[] services =
 454                 registeredServices.toArray(new PrintService[registeredServices.size()]);

 455             for (int i=0; i<services.length; i++) {
 456                 if (services[i] instanceof MultiDocPrintService &&
 457                     !listOfServices.contains(services[i])) {
 458                     if (flavors == null || flavors.length == 0) {
 459                         listOfServices.add((MultiDocPrintService)services[i]);
 460                     } else {
 461                         boolean supported = true;
 462                         for (int f=0; f<flavors.length; f++) {
 463                             if (services[i].isDocFlavorSupported(flavors[f])) {
 464 
 465                                 if (services[i].getUnsupportedAttributes(
 466                                      flavors[f], attributes) != null) {
 467                                         supported = false;
 468                                         break;
 469                                 }
 470                             } else {
 471                                 supported = false;
 472                                 break;
 473                             }
 474                         }
 475                         if (supported) {
 476                             listOfServices.add((MultiDocPrintService)services[i]);
 477                         }
 478                     }
 479                 }
 480             }
 481         }
 482         return listOfServices;
 483     }
 484 
 485 }