001    /* PrintServiceLookup.java --
002       Copyright (C) 2004, 2006 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.print;
040    
041    import gnu.classpath.ServiceFactory;
042    import gnu.javax.print.CupsPrintServiceLookup;
043    
044    import java.util.ArrayList;
045    import java.util.Arrays;
046    import java.util.HashSet;
047    import java.util.Iterator;
048    
049    import javax.print.attribute.AttributeSet;
050    
051    
052    /**
053     * <code>PrintServiceLookup</code> implementations provide a way to lookup
054     * print services based on different constraints.
055     * <p>
056     * Implementations are located and loaded automatically through the SPI JAR
057     * file specification. Therefore implementation classes must provide a default
058     * constructor for instantiation. Furthermore, applications are able to
059     * register further instances directly at runtime.
060     * </p><p>
061     * If an SecurityManager is installed implementors should call
062     * <code>checkPrintJobAccess()</code> to disable access for untrusted code.
063     * This check is to be made in every lookup service implementation for
064     * flexibility. Print services registered by applications through
065     * <code>registerService(PrintService)</code> are suppressed in the
066     * lookup results if a security manager is installed and disallows access.
067     * </p>
068     *
069     * @author Michael Koch (konqueror@gmx.de)
070     * @author Wolfgang Baer (WBaer@gmx.de)
071     */
072    public abstract class PrintServiceLookup
073    {
074    
075      private static final CupsPrintServiceLookup systemProvider;
076      private static final HashSet printServices;
077      private static final HashSet printServiceLookups;
078    
079      static
080      {
081        systemProvider = new CupsPrintServiceLookup();
082    
083        printServices = new HashSet();
084        printServiceLookups = new HashSet();
085    
086        // check for service providers
087        Iterator it = ServiceFactory.lookupProviders(PrintServiceLookup.class);
088    
089        while (it.hasNext())
090          printServiceLookups.add(it.next());
091      }
092    
093      /**
094       * Constructs a <code>PrintServiceLookup</code> object.
095       */
096      public PrintServiceLookup()
097      {
098        // nothing to do here
099      }
100    
101      /**
102       * Explicitly registers the provided print service lookup implementation.
103       * <p>
104       * The registration will silently fail (returning <code>false</code>) if
105       * the lookup service is already registered or the registration somehow
106       * else fails.
107       * </p>
108       *
109       * @param sp the print service lookup implementation to register.
110       * @return <code>true</code> if registered, <code>false</code> otherwise.
111       */
112      public static boolean registerServiceProvider(PrintServiceLookup sp)
113      {
114        return printServiceLookups.add(sp);
115      }
116    
117      /**
118       * Explicitly registers the provided print service instance.
119       * <p>
120       * The registration will silently fail (returning <code>false</code>) if
121       * the print service instance is already registered or the registration
122       * somehow else fails.
123       * </p>
124       * @param service the single print service to register.
125       * @return <code>true</code> if registered, <code>false</code> otherwise.
126       */
127      public static boolean registerService(PrintService service)
128      {
129        if (service instanceof StreamPrintService)
130          return false;
131    
132        // security
133        try
134          {
135            SecurityManager sm = System.getSecurityManager();
136            if (sm != null)
137              sm.checkPrintJobAccess();
138    
139            return printServices.add(service);
140          }
141        catch (SecurityException se)
142          {
143            return false;
144          }
145      }
146    
147      /**
148       * Searches print services capable of printing in the given document flavor
149       * which supports the specified printing attributes.
150       *
151       * @param flavor the document flavor to support. If <code>null</code> this
152       * constraint is ignored during lookup.
153       * @param attributes the printing attributes to support. If
154       * <code>null</code> this constraint is ignored during lookup.
155       * @return The resulting available print services, or an array of length 0
156       * if none is found.
157       */
158      public static final PrintService[] lookupPrintServices(DocFlavor flavor,
159        AttributeSet attributes)
160      {
161        ArrayList result = new ArrayList();
162    
163        PrintService[] services =
164          systemProvider.getPrintServices(flavor, attributes);
165        result.addAll(Arrays.asList(services));
166    
167        for (Iterator it = printServiceLookups.iterator(); it.hasNext(); )
168          {
169            PrintServiceLookup lookup = (PrintServiceLookup) it.next();
170            services = lookup.getPrintServices(flavor, attributes);
171            result.addAll(Arrays.asList(services));
172          }
173    
174        for (Iterator it = printServices.iterator(); it.hasNext(); )
175          {
176            PrintService service = (PrintService) it.next();
177            if (systemProvider.checkPrintService(flavor, attributes, service))
178              result.add(service);
179          }
180    
181        return (PrintService[]) result.toArray(new PrintService[result.size()]);
182      }
183    
184      /**
185       * Searches print services capable of multi document printing in all of the
186       * given document flavors and supporting the specified printing attributes.
187       *
188       * @param flavors the document flavors to support. If <code>null</code> this
189       * constraint is ignored during lookup.
190       * @param attributes the printing attributes to support. If
191       * <code>null</code> this constraint is ignored during lookup.
192       * @return The resulting available multi document print services, or an
193       * array of length 0 if none is found.
194       */
195      public static final MultiDocPrintService[] lookupMultiDocPrintServices(
196        DocFlavor[] flavors, AttributeSet attributes)
197      {
198        ArrayList result = new ArrayList();
199    
200        MultiDocPrintService[] services =
201          systemProvider.getMultiDocPrintServices(flavors, attributes);
202        result.addAll(Arrays.asList(services));
203    
204        for (Iterator it = printServiceLookups.iterator(); it.hasNext(); )
205          {
206            PrintServiceLookup lookup = (PrintServiceLookup) it.next();
207            services = lookup.getMultiDocPrintServices(flavors, attributes);
208            result.addAll(Arrays.asList(services));
209          }
210    
211        for (Iterator it = printServices.iterator(); it.hasNext(); )
212          {
213            PrintService service = (PrintService) it.next();
214            if (systemProvider.checkMultiDocPrintService(flavors, attributes, service))
215              result.add(service);
216          }
217    
218        return (MultiDocPrintService[]) result.toArray(
219          new MultiDocPrintService[result.size()]);
220      }
221    
222    
223      /**
224       * Searches the default print service in the current environment.
225       * <p>
226       * If multiple lookup services are registered and each has a default
227       * print service the result is not specified. Usually the default
228       * print service of the native platform lookup service is returned.
229       * </p><p>
230       * The GNU classpath implementation will return the CUPS default
231       * printing service as the default print service, if available.
232       * </p><p>
233       * The default print service may be overriden by users through
234       * the property <code>javax.print.defaultPrinter</code>. A service
235       * specified must be found to be returned as the default.
236       * </p>
237       *
238       * @return The default print service, or <code>null</code> if none found.
239       */
240      public static final PrintService lookupDefaultPrintService()
241      {
242        // TODO Find out what the property controls and use it
243        // String defaultPrinter = System.getProperty("javax.print.defaultPrinter");
244    
245        // first test for platform specified default services
246        PrintService service = systemProvider.getDefaultPrintService();
247    
248        if (service != null)
249          return service;
250    
251        // none available by systemDefaultProvider
252        // search in other registered ones and take first
253        for (Iterator it = printServiceLookups.iterator(); it.hasNext(); )
254          {
255            service = ((PrintServiceLookup) it.next()).getDefaultPrintService();
256            if (service != null)
257              return service;
258          }
259    
260        return null;
261      }
262    
263      /**
264       * Not to be called directly by applications.
265       *
266       * @return The default lookup service of the implementing lookup service or
267       * <code>null</code> if there is no default one.
268       */
269      public abstract PrintService getDefaultPrintService();
270    
271      /**
272       * Not to be called directly by applications.
273       *
274       * @param flavors the document flavors which have to be supported.
275       * @param attributes the attributes which have to be supported.
276       *
277       * @return The multidoc print services of the implementing lookup service
278       * for the given parameters, or an array of length 0 if none is available.
279       */
280      public abstract MultiDocPrintService[]
281        getMultiDocPrintServices(DocFlavor[] flavors, AttributeSet attributes);
282    
283      /**
284       * Not to be called directly by applications.
285       *
286       * @return All known print services of the implementing lookup service
287       * regardless of supported features, or an array of length 0 if none is
288       * available.
289       */
290      public abstract PrintService[] getPrintServices();
291    
292      /**
293       * Not to be called directly by applications.
294       *
295       * @param flavor the document flavor which has to be supported.
296       * @param attributes the attributes which have to be supported.
297       *
298       * @return The print services of the implementing lookup service
299       * for the given parameters, or an array of length 0 if none is available.
300       */
301      public abstract PrintService[]
302        getPrintServices(DocFlavor flavor, AttributeSet attributes);
303    }