9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.print; 27 28 import java.io.OutputStream; 29 30 import java.util.ArrayList; 31 import java.util.Iterator; 32 33 import javax.print.DocFlavor; 34 35 import sun.awt.AppContext; 36 import java.util.ServiceLoader; 37 import java.util.ServiceConfigurationError; 38 39 /** 40 * A {@code StreamPrintServiceFactory} is the factory for 41 * {@link StreamPrintService} instances, 42 * which can print to an output stream in a particular 43 * document format described as a mime type. 44 * A typical output document format may be Postscript(TM). 45 * <p> 46 * This class is implemented by a service and located by the 47 * implementation using the {@link java.util.ServiceLoader} facility. 48 * <p> 49 * Applications locate instances of this class by calling the 50 * {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method. 51 * <p> 52 * Applications can use a {@code StreamPrintService} obtained from a 53 * factory in place of a {@code PrintService} which represents a 54 * physical printer device. 55 */ 56 57 public abstract class StreamPrintServiceFactory { 58 59 static class Services { 60 private ArrayList<StreamPrintServiceFactory> listOfFactories = null; 61 } 62 63 private static Services getServices() { 64 Services services = 65 (Services)AppContext.getAppContext().get(Services.class); 66 if (services == null) { 67 services = new Services(); 68 AppContext.getAppContext().put(Services.class, services); 69 } 70 return services; 71 } 72 73 private static ArrayList<StreamPrintServiceFactory> getListOfFactories() { 74 return getServices().listOfFactories; 75 } 76 77 private static ArrayList<StreamPrintServiceFactory> initListOfFactories() { 78 ArrayList<StreamPrintServiceFactory> listOfFactories = new ArrayList<>(); 79 getServices().listOfFactories = listOfFactories; 80 return listOfFactories; 81 } 82 83 /** 84 * Locates factories for print services that can be used with 85 * a print job to output a stream of data in the 86 * format specified by {@code outputMimeType}. 87 * <p> 88 * The {@code outputMimeType} parameter describes the document type that 89 * you want to create, whereas the {@code flavor} parameter describes the 90 * format in which the input data will be provided by the application 91 * to the {@code StreamPrintService}. 92 * <p> 93 * Although null is an acceptable value to use in the lookup of stream 94 * printing services, it's typical to search for a particular 95 * desired format, such as Postscript(TM). 96 * 97 * @param flavor of the input document type - null means match all 98 * types. 99 * @param outputMimeType representing the required output format, used to 100 * identify suitable stream printer factories. A value of null means 101 * match all formats. 102 * @return matching factories for stream print service instance, 103 * empty if no suitable factories could be located. 104 */ 105 public static StreamPrintServiceFactory[] 106 lookupStreamPrintServiceFactories(DocFlavor flavor, 107 String outputMimeType) { 108 109 ArrayList<StreamPrintServiceFactory> list = getFactories(flavor, outputMimeType); 110 return list.toArray(new StreamPrintServiceFactory[list.size()]); 111 } 112 113 /** Queries the factory for the document format that is emitted 114 * by printers obtained from this factory. 115 * 116 * @return the output format described as a mime type. 117 */ 118 public abstract String getOutputFormat(); 119 120 /** 121 * Queries the factory for the document flavors that can be accepted 122 * by printers obtained from this factory. 123 * @return array of supported doc flavors. 124 */ 125 public abstract DocFlavor[] getSupportedDocFlavors(); 126 127 /** 128 * Returns a {@code StreamPrintService} that can print to 129 * the specified output stream. 130 * The output stream is created and managed by the application. 131 * It is the application's responsibility to close the stream and 132 * to ensure that this Printer is not reused. 133 * The application should not close this stream until any print job 134 * created from the printer is complete. Doing so earlier may generate 135 * a {@code PrinterException} and an event indicating that the 136 * job failed. 137 * <p> 138 * Whereas a {@code PrintService} connected to a physical printer 139 * can be reused, 140 * a {@code StreamPrintService} connected to a stream cannot. 141 * The underlying {@code StreamPrintService} may be disposed by 142 * the print system with 143 * the {@link StreamPrintService#dispose() dispose} method 144 * before returning from the 145 * {@link DocPrintJob#print(Doc, javax.print.attribute.PrintRequestAttributeSet) print} 146 * method of {@code DocPrintJob} so that the print system knows 147 * this printer is no longer usable. 148 * This is equivalent to a physical printer going offline - permanently. 149 * Applications may supply a null print stream to create a queryable 150 * service. It is not valid to create a PrintJob for such a stream. 151 * Implementations which allocate resources on construction should examine 152 * the stream and may wish to only allocate resources if the stream is 153 * non-null. 154 * 155 * @param out destination stream for generated output. 156 * @return a PrintService which will generate the format specified by the 157 * DocFlavor supported by this Factory. 158 */ 159 public abstract StreamPrintService getPrintService(OutputStream out); 160 161 162 private static ArrayList<StreamPrintServiceFactory> getAllFactories() { 163 synchronized (StreamPrintServiceFactory.class) { 164 165 ArrayList<StreamPrintServiceFactory> listOfFactories = getListOfFactories(); 166 if (listOfFactories != null) { 167 return listOfFactories; 168 } else { 169 listOfFactories = initListOfFactories(); 170 } 171 172 try { 173 java.security.AccessController.doPrivileged( 174 new java.security.PrivilegedExceptionAction<Object>() { 175 public Object run() { 176 Iterator<StreamPrintServiceFactory> iterator = 177 ServiceLoader.load 178 (StreamPrintServiceFactory.class).iterator(); 179 ArrayList<StreamPrintServiceFactory> lof = getListOfFactories(); 180 while (iterator.hasNext()) { 181 try { 182 lof.add(iterator.next()); 183 } catch (ServiceConfigurationError err) { 184 /* In the applet case, we continue */ 185 if (System.getSecurityManager() != null) { 186 err.printStackTrace(); 187 } else { 188 throw err; 189 } 190 } 191 } 192 return null; 193 } 194 }); 195 } catch (java.security.PrivilegedActionException e) { 196 } 197 return listOfFactories; 198 } 199 } 200 201 private static boolean isMember(DocFlavor flavor, DocFlavor[] flavors) { 202 for (int f=0; f<flavors.length; f++ ) { 203 if (flavor.equals(flavors[f])) { 204 return true; 205 } 206 } 207 return false; 208 } 209 210 private static ArrayList<StreamPrintServiceFactory> getFactories(DocFlavor flavor, String outType) { 211 212 if (flavor == null && outType == null) { 213 return getAllFactories(); 214 } 215 216 ArrayList<StreamPrintServiceFactory> list = new ArrayList<>(); 217 Iterator<StreamPrintServiceFactory> iterator = getAllFactories().iterator(); 218 while (iterator.hasNext()) { 219 StreamPrintServiceFactory factory = iterator.next(); 220 if ((outType == null || 221 outType.equalsIgnoreCase(factory.getOutputFormat())) && 222 (flavor == null || 223 isMember(flavor, factory.getSupportedDocFlavors()))) { 224 list.add(factory); 225 } 226 } 227 228 return list; 229 } 230 231 } | 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.print; 27 28 import java.io.OutputStream; 29 import java.util.ArrayList; 30 import java.util.Iterator; 31 import java.util.ServiceConfigurationError; 32 import java.util.ServiceLoader; 33 34 import javax.print.attribute.PrintRequestAttributeSet; 35 36 import sun.awt.AppContext; 37 38 /** 39 * A {@code StreamPrintServiceFactory} is the factory for 40 * {@link StreamPrintService} instances, which can print to an output stream in 41 * a particular document format described as a mime type. A typical output 42 * document format may be Postscript(TM). 43 * <p> 44 * This class is implemented by a service and located by the implementation 45 * using the {@link ServiceLoader} facility. 46 * <p> 47 * Applications locate instances of this class by calling the 48 * {@link #lookupStreamPrintServiceFactories(DocFlavor, String)} method. 49 * <p> 50 * Applications can use a {@code StreamPrintService} obtained from a factory in 51 * place of a {@code PrintService} which represents a physical printer device. 52 */ 53 public abstract class StreamPrintServiceFactory { 54 55 /** 56 * Contains a list of factories. 57 */ 58 static class Services { 59 60 /** 61 * The list of factories which will be stored per appcontext. 62 */ 63 private ArrayList<StreamPrintServiceFactory> listOfFactories = null; 64 } 65 66 /** 67 * Returns the services from the current appcontext. 68 * 69 * @return the services 70 */ 71 private static Services getServices() { 72 Services services = 73 (Services)AppContext.getAppContext().get(Services.class); 74 if (services == null) { 75 services = new Services(); 76 AppContext.getAppContext().put(Services.class, services); 77 } 78 return services; 79 } 80 81 /** 82 * Returns the list of factories. 83 * 84 * @return the list of factories 85 */ 86 private static ArrayList<StreamPrintServiceFactory> getListOfFactories() { 87 return getServices().listOfFactories; 88 } 89 90 /** 91 * Initialize the list of factories. 92 * 93 * @return the list of factories 94 */ 95 private static ArrayList<StreamPrintServiceFactory> initListOfFactories() { 96 ArrayList<StreamPrintServiceFactory> listOfFactories = new ArrayList<>(); 97 getServices().listOfFactories = listOfFactories; 98 return listOfFactories; 99 } 100 101 /** 102 * Locates factories for print services that can be used with a print job to 103 * output a stream of data in the format specified by 104 * {@code outputMimeType}. 105 * <p> 106 * The {@code outputMimeType} parameter describes the document type that you 107 * want to create, whereas the {@code flavor} parameter describes the format 108 * in which the input data will be provided by the application to the 109 * {@code StreamPrintService}. 110 * <p> 111 * Although {@code null} is an acceptable value to use in the lookup of 112 * stream printing services, it's typical to search for a particular desired 113 * format, such as Postscript(TM). 114 * 115 * @param flavor of the input document type - {@code null} means match all 116 * types 117 * @param outputMimeType representing the required output format, used to 118 * identify suitable stream printer factories. A value of 119 * {@code null} means match all formats. 120 * @return matching factories for stream print service instance, empty if no 121 * suitable factories could be located 122 */ 123 public static StreamPrintServiceFactory[] 124 lookupStreamPrintServiceFactories(DocFlavor flavor, 125 String outputMimeType) { 126 127 ArrayList<StreamPrintServiceFactory> list = getFactories(flavor, outputMimeType); 128 return list.toArray(new StreamPrintServiceFactory[list.size()]); 129 } 130 131 /** 132 * Queries the factory for the document format that is emitted by printers 133 * obtained from this factory. 134 * 135 * @return the output format described as a mime type 136 */ 137 public abstract String getOutputFormat(); 138 139 /** 140 * Queries the factory for the document flavors that can be accepted by 141 * printers obtained from this factory. 142 * 143 * @return array of supported doc flavors 144 */ 145 public abstract DocFlavor[] getSupportedDocFlavors(); 146 147 /** 148 * Returns a {@code StreamPrintService} that can print to the specified 149 * output stream. The output stream is created and managed by the 150 * application. It is the application's responsibility to close the stream 151 * and to ensure that this {@code Printer} is not reused. The application 152 * should not close this stream until any print job created from the printer 153 * is complete. Doing so earlier may generate a {@code PrinterException} and 154 * an event indicating that the job failed. 155 * <p> 156 * Whereas a {@code PrintService} connected to a physical printer can be 157 * reused, a {@code StreamPrintService} connected to a stream cannot. The 158 * underlying {@code StreamPrintService} may be disposed by the print system 159 * with the {@link StreamPrintService#dispose() dispose} method before 160 * returning from the 161 * {@link DocPrintJob#print(Doc, PrintRequestAttributeSet) print} method of 162 * {@code DocPrintJob} so that the print system knows this printer is no 163 * longer usable. This is equivalent to a physical printer going offline - 164 * permanently. Applications may supply a {@code null} print stream to 165 * create a queryable service. It is not valid to create a {@code PrintJob} 166 * for such a stream. Implementations which allocate resources on 167 * construction should examine the stream and may wish to only allocate 168 * resources if the stream is {@code non-null}. 169 * 170 * @param out destination stream for generated output 171 * @return a {@code PrintService} which will generate the format specified 172 * by the {@code DocFlavor} supported by this factory 173 */ 174 public abstract StreamPrintService getPrintService(OutputStream out); 175 176 /** 177 * Returns all factories for print services. 178 * 179 * @return all factories 180 */ 181 private static ArrayList<StreamPrintServiceFactory> getAllFactories() { 182 synchronized (StreamPrintServiceFactory.class) { 183 184 ArrayList<StreamPrintServiceFactory> listOfFactories = getListOfFactories(); 185 if (listOfFactories != null) { 186 return listOfFactories; 187 } else { 188 listOfFactories = initListOfFactories(); 189 } 190 191 try { 192 java.security.AccessController.doPrivileged( 193 new java.security.PrivilegedExceptionAction<Object>() { 194 public Object run() { 195 Iterator<StreamPrintServiceFactory> iterator = 196 ServiceLoader.load 197 (StreamPrintServiceFactory.class).iterator(); 198 ArrayList<StreamPrintServiceFactory> lof = getListOfFactories(); 199 while (iterator.hasNext()) { 200 try { 201 lof.add(iterator.next()); 202 } catch (ServiceConfigurationError err) { 203 /* In the applet case, we continue */ 204 if (System.getSecurityManager() != null) { 205 err.printStackTrace(); 206 } else { 207 throw err; 208 } 209 } 210 } 211 return null; 212 } 213 }); 214 } catch (java.security.PrivilegedActionException e) { 215 } 216 return listOfFactories; 217 } 218 } 219 220 /** 221 * Checks if the array of {@code flavors} contains the {@code flavor} 222 * object. 223 * 224 * @param flavor the flavor 225 * @param flavors the array of flavors 226 * @return {@code true} if {@code flavors} contains the {@code flavor} 227 * object; {@code false} otherwise 228 */ 229 private static boolean isMember(DocFlavor flavor, DocFlavor[] flavors) { 230 for (int f=0; f<flavors.length; f++ ) { 231 if (flavor.equals(flavors[f])) { 232 return true; 233 } 234 } 235 return false; 236 } 237 238 /** 239 * Utility method for {@link #lookupStreamPrintServiceFactories}. 240 * <p> 241 * Locates factories for print services that can be used with a print job to 242 * output a stream of data in the format specified by 243 * {@code outputMimeType}. 244 * 245 * @param flavor of the input document type - {@code null} means match all 246 * types 247 * @param outType representing the required output format, used to identify 248 * suitable stream printer factories. A value of {@code null} means 249 * match all formats. 250 * @return matching factories for stream print service instance, empty if no 251 * suitable factories could be located 252 */ 253 private static ArrayList<StreamPrintServiceFactory> getFactories(DocFlavor flavor, String outType) { 254 255 if (flavor == null && outType == null) { 256 return getAllFactories(); 257 } 258 259 ArrayList<StreamPrintServiceFactory> list = new ArrayList<>(); 260 Iterator<StreamPrintServiceFactory> iterator = getAllFactories().iterator(); 261 while (iterator.hasNext()) { 262 StreamPrintServiceFactory factory = iterator.next(); 263 if ((outType == null || 264 outType.equalsIgnoreCase(factory.getOutputFormat())) && 265 (flavor == null || 266 isMember(flavor, factory.getSupportedDocFlavors()))) { 267 list.add(factory); 268 } 269 } 270 271 return list; 272 } 273 } |