/*
 * Copyright 2000-2002 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */


package javax.print;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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;
    }

    /**
     * Locates print services capable of printing the specified
     * {@link DocFlavor}.
     *
     * @param flavor the flavor to print. If null, this constraint is not
     *        used.
     * @param attributes attributes that the print service must support.
     * If null this constraint is not used.
     *
     * @return array of matching <code>PrintService</code> objects
     * representing print services that support the specified flavor
     * attributes.  If no services match, the array is zero-length.
     */
    public static final PrintService[]
        lookupPrintServices(DocFlavor flavor,
                            AttributeSet attributes) {
        ArrayList list = getServices(flavor, attributes);
        return (PrintService[])(list.toArray(new PrintService[list.size()]));
    }


    /**
     * Locates MultiDoc print Services capable of printing MultiDocs
     * containing all the specified doc flavors.
     * <P> This method is useful to help locate a service that can print
     * a <code>MultiDoc</code> in which the elements may be different
     * flavors. An application could perform this itself by multiple lookups
     * on each <code>DocFlavor</code> in turn and collating the results,
     * but the lookup service may be able to do this more efficiently.
     *
     * @param flavors the flavors to print. If null or empty this
     *        constraint is not used.
     * Otherwise return only multidoc print services that can print all
     * specified doc flavors.
     * @param attributes attributes that the print service must
     * support.  If null this constraint is not used.
     *
     * @return array of matching {@link MultiDocPrintService} objects.
     * If no services match, the array is zero-length.
     *
     */
    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;
    }


    /**
     * Allows an application to explicitly register a class that
     * implements lookup services. The registration will not persist
     * across VM invocations.
     * This is useful if an application needs to make a new service
     * available that is not part of the installation.
     * If the lookup service is already registered, or cannot be registered,
     * the method returns false.
     * <p>
     *
     * @param sp an implementation of a lookup service.
     * @return <code>true</code> if the new lookup service is newly
     *         registered; <code>false</code> otherwise.
     */
    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;
        }
    }


   /**
    * Locates services that can be positively confirmed to support
    * the combination of attributes and DocFlavors specified.
    * This method is not called directly by applications.
    * <p>
    * Implemented by a service provider, used by the static methods
    * of this class.
    * <p>
    * The results should be the same as obtaining all the PrintServices
    * and querying each one individually on its support for the
    * specified attributes and flavors, but the process can be more
    * efficient by taking advantage of the capabilities of lookup services
    * for the print services.
    *
    * @param flavor of document required.  If null it is ignored.
    * @param attributes required to be supported. If null this
    * constraint is not used.
    * @return array of matching PrintServices. If no services match, the
    * array is zero-length.
    */
    public abstract PrintService[] getPrintServices(DocFlavor flavor,
                                                    AttributeSet attributes);

    /**
     * Not called directly by applications.
     * Implemented by a service provider, used by the static methods
     * of this class.
     * @return array of all PrintServices known to this lookup service
     * class. If none are found, the array is zero-length.
     */
    public abstract PrintService[] getPrintServices() ;


   /**
    * Not called directly by applications.
    * <p>
    * Implemented by a service provider, used by the static methods
    * of this class.
    * <p>
    * Locates MultiDoc print services which can be positively confirmed
    * to support the combination of attributes and DocFlavors specified.
    * <p>
    *
    * @param flavors of documents required. If null or empty it is ignored.
    * @param attributes required to be supported. If null this
     * constraint is not used.
    * @return array of matching PrintServices. If no services match, the
    * array is zero-length.
    */
    public abstract MultiDocPrintService[]
        getMultiDocPrintServices(DocFlavor[] flavors,
                                 AttributeSet attributes);

    /**
     * Not called directly by applications.
     * Implemented by a service provider, and called by the print lookup
     * service
     * @return the default PrintService for this lookup service.
     * If there is no default, returns null.
     */
    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) {
                                    /* In the applet case, we continue */
                                    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) {
            }
        }
        /* add any directly registered services */
        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) {
            }
        }
        /* add any directly registered services */
        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;
    }

}
