javax.print.StreamPrintServiceFactory.java Source code

Java tutorial

Introduction

Here is the source code for javax.print.StreamPrintServiceFactory.java

Source

/*
 * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.print;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;

import javax.print.attribute.PrintRequestAttributeSet;

import sun.awt.AppContext;

/**
 * A {@code StreamPrintServiceFactory} is the factory for
 * {@link StreamPrintService} instances, which can print to an output stream in
 * a particular document format described as a mime type. A typical output
 * document format may be Postscript(TM).
 * <p>
 * This class is implemented by a service and located by the implementation
 * using the {@link ServiceLoader} facility.
 * <p>
 * Applications locate instances of this class by calling the
 * {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method.
 * <p>
 * Applications can use a {@code StreamPrintService} obtained from a factory in
 * place of a {@code PrintService} which represents a physical printer device.
 */
public abstract class StreamPrintServiceFactory {

    /**
     * Contains a list of factories.
     */
    static class Services {

        /**
         * The list of factories which will be stored per appcontext.
         */
        private ArrayList<StreamPrintServiceFactory> listOfFactories = null;
    }

    /**
     * Returns the services from the current appcontext.
     *
     * @return the services
     */
    private static Services getServices() {
        Services services = (Services) AppContext.getAppContext().get(Services.class);
        if (services == null) {
            services = new Services();
            AppContext.getAppContext().put(Services.class, services);
        }
        return services;
    }

    /**
     * Returns the list of factories.
     *
     * @return the list of factories
     */
    private static ArrayList<StreamPrintServiceFactory> getListOfFactories() {
        return getServices().listOfFactories;
    }

    /**
     * Initialize the list of factories.
     *
     * @return the list of factories
     */
    private static ArrayList<StreamPrintServiceFactory> initListOfFactories() {
        ArrayList<StreamPrintServiceFactory> listOfFactories = new ArrayList<>();
        getServices().listOfFactories = listOfFactories;
        return listOfFactories;
    }

    /**
     * Locates factories for print services that can be used with a print job to
     * output a stream of data in the format specified by
     * {@code outputMimeType}.
     * <p>
     * The {@code outputMimeType} parameter describes the document type that you
     * want to create, whereas the {@code flavor} parameter describes the format
     * in which the input data will be provided by the application to the
     * {@code StreamPrintService}.
     * <p>
     * Although {@code null} is an acceptable value to use in the lookup of
     * stream printing services, it's typical to search for a particular desired
     * format, such as Postscript(TM).
     *
     * @param  flavor of the input document type - {@code null} means match all
     *         types
     * @param  outputMimeType representing the required output format, used to
     *         identify suitable stream printer factories. A value of
     *         {@code null} means match all formats.
     * @return matching factories for stream print service instance, empty if no
     *         suitable factories could be located
     */
    public static StreamPrintServiceFactory[] lookupStreamPrintServiceFactories(DocFlavor flavor,
            String outputMimeType) {

        ArrayList<StreamPrintServiceFactory> list = getFactories(flavor, outputMimeType);
        return list.toArray(new StreamPrintServiceFactory[list.size()]);
    }

    /**
     * Queries the factory for the document format that is emitted by printers
     * obtained from this factory.
     *
     * @return the output format described as a mime type
     */
    public abstract String getOutputFormat();

    /**
     * Queries the factory for the document flavors that can be accepted by
     * printers obtained from this factory.
     *
     * @return array of supported doc flavors
     */
    public abstract DocFlavor[] getSupportedDocFlavors();

    /**
     * Returns a {@code StreamPrintService} that can print to the specified
     * output stream. The output stream is created and managed by the
     * application. It is the application's responsibility to close the stream
     * and to ensure that this {@code Printer} is not reused. The application
     * should not close this stream until any print job created from the printer
     * is complete. Doing so earlier may generate a {@code PrinterException} and
     * an event indicating that the job failed.
     * <p>
     * Whereas a {@code PrintService} connected to a physical printer can be
     * reused, a {@code StreamPrintService} connected to a stream cannot. The
     * underlying {@code StreamPrintService} may be disposed by the print system
     * with the {@link StreamPrintService#dispose() dispose} method before
     * returning from the
     * {@link DocPrintJob#print(Doc, PrintRequestAttributeSet) print} method of
     * {@code DocPrintJob} so that the print system knows this printer is no
     * longer usable. This is equivalent to a physical printer going offline -
     * permanently. Applications may supply a {@code null} print stream to
     * create a queryable service. It is not valid to create a {@code PrintJob}
     * for such a stream. Implementations which allocate resources on
     * construction should examine the stream and may wish to only allocate
     * resources if the stream is {@code non-null}.
     *
     * @param  out destination stream for generated output
     * @return a {@code PrintService} which will generate the format specified
     *         by the {@code DocFlavor} supported by this factory
     */
    public abstract StreamPrintService getPrintService(OutputStream out);

    /**
     * Returns all factories for print services.
     *
     * @return all factories
     */
    private static ArrayList<StreamPrintServiceFactory> getAllFactories() {
        synchronized (StreamPrintServiceFactory.class) {

            ArrayList<StreamPrintServiceFactory> listOfFactories = getListOfFactories();
            if (listOfFactories != null) {
                return listOfFactories;
            } else {
                listOfFactories = initListOfFactories();
            }

            try {
                java.security.AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Object>() {
                    public Object run() {
                        Iterator<StreamPrintServiceFactory> iterator = ServiceLoader
                                .load(StreamPrintServiceFactory.class).iterator();
                        ArrayList<StreamPrintServiceFactory> lof = getListOfFactories();
                        while (iterator.hasNext()) {
                            try {
                                lof.add(iterator.next());
                            } catch (ServiceConfigurationError err) {
                                /* In the applet case, we continue */
                                if (System.getSecurityManager() != null) {
                                    err.printStackTrace();
                                } else {
                                    throw err;
                                }
                            }
                        }
                        return null;
                    }
                });
            } catch (java.security.PrivilegedActionException e) {
            }
            return listOfFactories;
        }
    }

    /**
     * Checks if the array of {@code flavors} contains the {@code flavor}
     * object.
     *
     * @param  flavor the flavor
     * @param  flavors the array of flavors
     * @return {@code true} if {@code flavors} contains the {@code flavor}
     *         object; {@code false} otherwise
     */
    private static boolean isMember(DocFlavor flavor, DocFlavor[] flavors) {
        for (int f = 0; f < flavors.length; f++) {
            if (flavor.equals(flavors[f])) {
                return true;
            }
        }
        return false;
    }

    /**
     * Utility method for {@link #lookupStreamPrintServiceFactories}.
     * <p>
     * Locates factories for print services that can be used with a print job to
     * output a stream of data in the format specified by
     * {@code outputMimeType}.
     *
     * @param  flavor of the input document type - {@code null} means match all
     *         types
     * @param  outType representing the required output format, used to identify
     *         suitable stream printer factories. A value of {@code null} means
     *         match all formats.
     * @return matching factories for stream print service instance, empty if no
     *         suitable factories could be located
     */
    private static ArrayList<StreamPrintServiceFactory> getFactories(DocFlavor flavor, String outType) {

        if (flavor == null && outType == null) {
            return getAllFactories();
        }

        ArrayList<StreamPrintServiceFactory> list = new ArrayList<>();
        Iterator<StreamPrintServiceFactory> iterator = getAllFactories().iterator();
        while (iterator.hasNext()) {
            StreamPrintServiceFactory factory = iterator.next();
            if ((outType == null || outType.equalsIgnoreCase(factory.getOutputFormat()))
                    && (flavor == null || isMember(flavor, factory.getSupportedDocFlavors()))) {
                list.add(factory);
            }
        }

        return list;
    }
}