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