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