Path: blob/master/src/java.desktop/share/classes/javax/print/StreamPrintServiceFactory.java
41153 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.print;2627import java.io.OutputStream;28import java.util.ArrayList;29import java.util.Iterator;30import java.util.ServiceConfigurationError;31import java.util.ServiceLoader;3233import javax.print.attribute.PrintRequestAttributeSet;3435import sun.awt.AppContext;3637/**38* A {@code StreamPrintServiceFactory} is the factory for39* {@link StreamPrintService} instances, which can print to an output stream in40* a particular document format described as a mime type. A typical output41* document format may be Postscript(TM).42* <p>43* This class is implemented by a service and located by the implementation44* using the {@link ServiceLoader} facility.45* <p>46* Applications locate instances of this class by calling the47* {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method.48* <p>49* Applications can use a {@code StreamPrintService} obtained from a factory in50* place of a {@code PrintService} which represents a physical printer device.51*/52public abstract class StreamPrintServiceFactory {5354/**55* Constructor for subclasses to call.56*/57protected StreamPrintServiceFactory() {}5859/**60* Contains a list of factories.61*/62static class Services {6364/**65* The list of factories which will be stored per appcontext.66*/67private ArrayList<StreamPrintServiceFactory> listOfFactories = null;68}6970/**71* Returns the services from the current appcontext.72*73* @return the services74*/75private static Services getServices() {76Services services =77(Services)AppContext.getAppContext().get(Services.class);78if (services == null) {79services = new Services();80AppContext.getAppContext().put(Services.class, services);81}82return services;83}8485/**86* Returns the list of factories.87*88* @return the list of factories89*/90private static ArrayList<StreamPrintServiceFactory> getListOfFactories() {91return getServices().listOfFactories;92}9394/**95* Initialize the list of factories.96*97* @return the list of factories98*/99private static ArrayList<StreamPrintServiceFactory> initListOfFactories() {100ArrayList<StreamPrintServiceFactory> listOfFactories = new ArrayList<>();101getServices().listOfFactories = listOfFactories;102return listOfFactories;103}104105/**106* Locates factories for print services that can be used with a print job to107* output a stream of data in the format specified by108* {@code outputMimeType}.109* <p>110* The {@code outputMimeType} parameter describes the document type that you111* want to create, whereas the {@code flavor} parameter describes the format112* in which the input data will be provided by the application to the113* {@code StreamPrintService}.114* <p>115* Although {@code null} is an acceptable value to use in the lookup of116* stream printing services, it's typical to search for a particular desired117* format, such as Postscript(TM).118*119* @param flavor of the input document type - {@code null} means match all120* types121* @param outputMimeType representing the required output format, used to122* identify suitable stream printer factories. A value of123* {@code null} means match all formats.124* @return matching factories for stream print service instance, empty if no125* suitable factories could be located126*/127public static StreamPrintServiceFactory[]128lookupStreamPrintServiceFactories(DocFlavor flavor,129String outputMimeType) {130131ArrayList<StreamPrintServiceFactory> list = getFactories(flavor, outputMimeType);132return list.toArray(new StreamPrintServiceFactory[list.size()]);133}134135/**136* Queries the factory for the document format that is emitted by printers137* obtained from this factory.138*139* @return the output format described as a mime type140*/141public abstract String getOutputFormat();142143/**144* Queries the factory for the document flavors that can be accepted by145* printers obtained from this factory.146*147* @return array of supported doc flavors148*/149public abstract DocFlavor[] getSupportedDocFlavors();150151/**152* Returns a {@code StreamPrintService} that can print to the specified153* output stream. The output stream is created and managed by the154* application. It is the application's responsibility to close the stream155* and to ensure that this {@code Printer} is not reused. The application156* should not close this stream until any print job created from the printer157* is complete. Doing so earlier may generate a {@code PrinterException} and158* an event indicating that the job failed.159* <p>160* Whereas a {@code PrintService} connected to a physical printer can be161* reused, a {@code StreamPrintService} connected to a stream cannot. The162* underlying {@code StreamPrintService} may be disposed by the print system163* with the {@link StreamPrintService#dispose() dispose} method before164* returning from the165* {@link DocPrintJob#print(Doc, PrintRequestAttributeSet) print} method of166* {@code DocPrintJob} so that the print system knows this printer is no167* longer usable. This is equivalent to a physical printer going offline -168* permanently. Applications may supply a {@code null} print stream to169* create a queryable service. It is not valid to create a {@code PrintJob}170* for such a stream. Implementations which allocate resources on171* construction should examine the stream and may wish to only allocate172* resources if the stream is {@code non-null}.173*174* @param out destination stream for generated output175* @return a {@code PrintService} which will generate the format specified176* by the {@code DocFlavor} supported by this factory177*/178public abstract StreamPrintService getPrintService(OutputStream out);179180/**181* Returns all factories for print services.182*183* @return all factories184*/185@SuppressWarnings("removal")186private static ArrayList<StreamPrintServiceFactory> getAllFactories() {187synchronized (StreamPrintServiceFactory.class) {188189ArrayList<StreamPrintServiceFactory> listOfFactories = getListOfFactories();190if (listOfFactories != null) {191return listOfFactories;192} else {193listOfFactories = initListOfFactories();194}195196try {197java.security.AccessController.doPrivileged(198new java.security.PrivilegedExceptionAction<Object>() {199public Object run() {200Iterator<StreamPrintServiceFactory> iterator =201ServiceLoader.load202(StreamPrintServiceFactory.class).iterator();203ArrayList<StreamPrintServiceFactory> lof = getListOfFactories();204while (iterator.hasNext()) {205try {206lof.add(iterator.next());207} catch (ServiceConfigurationError err) {208/* In the applet case, we continue */209if (System.getSecurityManager() != null) {210err.printStackTrace();211} else {212throw err;213}214}215}216return null;217}218});219} catch (java.security.PrivilegedActionException e) {220}221return listOfFactories;222}223}224225/**226* Checks if the array of {@code flavors} contains the {@code flavor}227* object.228*229* @param flavor the flavor230* @param flavors the array of flavors231* @return {@code true} if {@code flavors} contains the {@code flavor}232* object; {@code false} otherwise233*/234private static boolean isMember(DocFlavor flavor, DocFlavor[] flavors) {235for (int f=0; f<flavors.length; f++ ) {236if (flavor.equals(flavors[f])) {237return true;238}239}240return false;241}242243/**244* Utility method for {@link #lookupStreamPrintServiceFactories}.245* <p>246* Locates factories for print services that can be used with a print job to247* output a stream of data in the format specified by248* {@code outputMimeType}.249*250* @param flavor of the input document type - {@code null} means match all251* types252* @param outType representing the required output format, used to identify253* suitable stream printer factories. A value of {@code null} means254* match all formats.255* @return matching factories for stream print service instance, empty if no256* suitable factories could be located257*/258private static ArrayList<StreamPrintServiceFactory> getFactories(DocFlavor flavor, String outType) {259260if (flavor == null && outType == null) {261return getAllFactories();262}263264ArrayList<StreamPrintServiceFactory> list = new ArrayList<>();265for (StreamPrintServiceFactory factory : getAllFactories()) {266if ((outType == null ||267outType.equalsIgnoreCase(factory.getOutputFormat())) &&268(flavor == null ||269isMember(flavor, factory.getSupportedDocFlavors()))) {270list.add(factory);271}272}273274return list;275}276}277278279