1. /*
  2. * @(#)StreamPrintServiceFactory.java 1.8 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.print;
  8. import java.io.OutputStream;
  9. import java.util.ArrayList;
  10. import java.util.Iterator;
  11. import javax.print.DocFlavor;
  12. import sun.awt.AppContext;
  13. import sun.misc.Service;
  14. /**
  15. * A <code>StreamPrintServiceFactory</code> is the factory for
  16. * {@link StreamPrintService} instances,
  17. * which can print to an output stream in a particular
  18. * document format described as a mime type.
  19. * A typical output document format may be Postscript(TM).
  20. * <p>
  21. * This class is implemented by a service and located by the
  22. * implementation using the
  23. * <a href="http:/java.sun.com/products/jdk/1.3/docs/guide/jar/jar.html#Service Provider">
  24. * SPI JAR File specification</a>.
  25. * <p>
  26. * Applications locate instances of this class by calling the
  27. * {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method.
  28. * <p>
  29. * Applications can use a <code>StreamPrintService</code> obtained from a
  30. * factory in place of a <code>PrintService</code> which represents a
  31. * physical printer device.
  32. */
  33. public abstract class StreamPrintServiceFactory {
  34. static class Services {
  35. private ArrayList listOfFactories = null;
  36. }
  37. private static Services getServices() {
  38. Services services =
  39. (Services)AppContext.getAppContext().get(Services.class);
  40. if (services == null) {
  41. services = new Services();
  42. AppContext.getAppContext().put(Services.class, services);
  43. }
  44. return services;
  45. }
  46. private static ArrayList getListOfFactories() {
  47. return getServices().listOfFactories;
  48. }
  49. private static ArrayList initListOfFactories() {
  50. ArrayList listOfFactories = new ArrayList();
  51. getServices().listOfFactories = listOfFactories;
  52. return listOfFactories;
  53. }
  54. /**
  55. * Locates factories for print services that can be used with
  56. * a print job to output a stream of data in the
  57. * format specified by <code>flavor</code>.
  58. * For example, the doc flavor is the document type that you want to
  59. * create, not the flavor of the
  60. * document before printing.
  61. * <p>
  62. * Although null is an acceptable value to use in the lookup of stream
  63. * printing services, it's typical to search for a particular
  64. * desired format, such as Postscript(TM).
  65. * <p>
  66. * @param flavor of the input document type - null means match all
  67. * types.
  68. * @param outputMimeType representing the required output format, used to
  69. * identify suitable stream printer factories. A value of null means
  70. * match all formats.
  71. * @return - matching factories for stream print service instance,
  72. * empty if no suitable factories could be located.
  73. */
  74. public static StreamPrintServiceFactory[]
  75. lookupStreamPrintServiceFactories(DocFlavor flavor,
  76. String outputMimeType) {
  77. ArrayList list = getFactories(flavor, outputMimeType);
  78. return (StreamPrintServiceFactory[])
  79. (list.toArray(new StreamPrintServiceFactory[list.size()]));
  80. }
  81. /** Queries the factory for the document format that is emitted
  82. * by printers obtained from this factory.
  83. *
  84. * @return the output format described as a mime type.
  85. */
  86. public abstract String getOutputFormat();
  87. /**
  88. * Queries the factory for the document flavors that can be accepted
  89. * by printers obtained from this factory.
  90. * @return array of supported doc flavors.
  91. */
  92. public abstract DocFlavor[] getSupportedDocFlavors();
  93. /**
  94. * Returns a <code>StreamPrintService</code> that can print to
  95. * the specified output stream.
  96. * The output stream is created and managed by the application.
  97. * It is the application's responsibility to close the stream and
  98. * to ensure that this Printer is not reused.
  99. * The application should not close this stream until any print job
  100. * created from the printer is complete. Doing so earlier may generate
  101. * a <code>PrinterException</code> and an event indicating that the
  102. * job failed.
  103. * <p>
  104. * Whereas a <code>PrintService</code> connected to a physical printer
  105. * can be reused,
  106. * a <code>StreamPrintService</code> connected to a stream cannot.
  107. * The underlying <code>StreamPrintService</code> may be disposed by
  108. * the print system with
  109. * the {@link StreamPrintService#dispose() dispose} method
  110. * before returning from the
  111. * {@link DocPrintJob#print(Doc, javax.print.attribute.PrintRequestAttributeSet) print}
  112. * method of <code>DocPrintJob</code> so that the print system knows
  113. * this printer is no longer usable.
  114. * This is equivalent to a physical printer going offline - permanently.
  115. * Applications may supply a null print stream to create a queryable
  116. * service. It is not valid to create a PrintJob for such a stream.
  117. * Implementations which allocate resources on construction should examine
  118. * the stream and may wish to only allocate resources if the stream is
  119. * non-null.
  120. * <p>
  121. * @param out destination stream for generated output.
  122. * @return a PrintService which will generate the format specified by the
  123. * DocFlavor supported by this Factory.
  124. */
  125. public abstract StreamPrintService getPrintService(OutputStream out);
  126. private static ArrayList getAllFactories() {
  127. synchronized (StreamPrintServiceFactory.class) {
  128. ArrayList listOfFactories = getListOfFactories();
  129. if (listOfFactories != null) {
  130. return listOfFactories;
  131. } else {
  132. listOfFactories = initListOfFactories();
  133. }
  134. try {
  135. java.security.AccessController.doPrivileged(
  136. new java.security.PrivilegedExceptionAction() {
  137. public Object run() {
  138. Iterator iterator =
  139. Service.providers(
  140. StreamPrintServiceFactory.class);
  141. ArrayList lof = getListOfFactories();
  142. while (iterator.hasNext()) {
  143. try {
  144. StreamPrintServiceFactory factory =
  145. (StreamPrintServiceFactory)
  146. iterator.next();
  147. lof.add(factory);
  148. } catch (Exception e) {
  149. }
  150. }
  151. return null;
  152. }
  153. });
  154. } catch (java.security.PrivilegedActionException e) {
  155. }
  156. return listOfFactories;
  157. }
  158. }
  159. private static boolean isMember(DocFlavor flavor, DocFlavor[] flavors) {
  160. for (int f=0; f<flavors.length; f++ ) {
  161. if (flavor.equals(flavors[f])) {
  162. return true;
  163. }
  164. }
  165. return false;
  166. }
  167. private static ArrayList getFactories(DocFlavor flavor, String outType) {
  168. if (flavor == null && outType == null) {
  169. return getAllFactories();
  170. }
  171. ArrayList list = new ArrayList();
  172. Iterator iterator = getAllFactories().iterator();
  173. while (iterator.hasNext()) {
  174. StreamPrintServiceFactory factory =
  175. (StreamPrintServiceFactory)iterator.next();
  176. if ((outType == null ||
  177. outType.equalsIgnoreCase(factory.getOutputFormat())) &&
  178. (flavor == null ||
  179. isMember(flavor, factory.getSupportedDocFlavors()))) {
  180. list.add(factory);
  181. }
  182. }
  183. return list;
  184. }
  185. }