001: /*
002: * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.print;
027:
028: import java.net.URL;
029: import java.net.HttpURLConnection;
030: import java.io.OutputStream;
031: import java.io.InputStream;
032: import java.util.ArrayList;
033: import java.util.HashMap;
034: import sun.print.IPPPrintService;
035: import sun.print.CustomMediaSizeName;
036: import sun.print.CustomMediaTray;
037: import javax.print.attribute.standard.Media;
038: import javax.print.attribute.standard.MediaSizeName;
039: import javax.print.attribute.standard.MediaSize;
040: import javax.print.attribute.standard.MediaTray;
041: import javax.print.attribute.standard.MediaPrintableArea;
042: import javax.print.attribute.Size2DSyntax;
043: import javax.print.attribute.Attribute;
044: import javax.print.attribute.EnumSyntax;
045: import javax.print.attribute.standard.PrinterName;
046:
047: public class CUPSPrinter {
048:
049: private static final double PRINTER_DPI = 72.0;
050: private static boolean initialized;
051:
052: private static native String getCupsServer();
053:
054: private static native int getCupsPort();
055:
056: private static native boolean canConnect(String server, int port);
057:
058: private static native boolean initIDs();
059:
060: // These functions need to be synchronized as
061: // CUPS does not support multi-threading.
062: private static synchronized native String[] getMedia(String printer);
063:
064: private static synchronized native float[] getPageSizes(
065: String printer);
066:
067: //public static boolean useIPPMedia = false; will be used later
068:
069: private MediaPrintableArea[] cupsMediaPrintables;
070: private MediaSizeName[] cupsMediaSNames;
071: private CustomMediaSizeName[] cupsCustomMediaSNames;
072: private MediaTray[] cupsMediaTrays;
073:
074: public int nPageSizes = 0;
075: public int nTrays = 0;
076: private String[] media;
077: private float[] pageSizes;
078: private String printer;
079:
080: private static boolean libFound;
081: private static String cupsServer = null;
082: private static int cupsPort = 0;
083:
084: static {
085: // load awt library to access native code
086: java.security.AccessController
087: .doPrivileged(new sun.security.action.LoadLibraryAction(
088: "awt"));
089: libFound = initIDs();
090: if (libFound) {
091: cupsServer = getCupsServer();
092: cupsPort = getCupsPort();
093: }
094: }
095:
096: CUPSPrinter(String printerName) {
097: if (printerName == null) {
098: throw new IllegalArgumentException("null printer name");
099: }
100: printer = printerName;
101: cupsMediaSNames = null;
102: cupsMediaPrintables = null;
103: cupsMediaTrays = null;
104: initialized = false;
105:
106: if (!libFound) {
107: throw new RuntimeException("cups lib not found");
108: } else {
109: // get page + tray names
110: media = getMedia(printer);
111: if (media == null) {
112: // either PPD file is not found or printer is unknown
113: throw new RuntimeException("error getting PPD");
114: }
115:
116: // get sizes
117: pageSizes = getPageSizes(printer);
118: if (pageSizes != null) {
119: nPageSizes = pageSizes.length / 6;
120:
121: nTrays = media.length / 2 - nPageSizes;
122: assert (nTrays >= 0);
123: }
124: }
125: }
126:
127: /**
128: * Returns array of MediaSizeNames derived from PPD.
129: */
130: public MediaSizeName[] getMediaSizeNames() {
131: initMedia();
132: return cupsMediaSNames;
133: }
134:
135: /**
136: * Returns array of Custom MediaSizeNames derived from PPD.
137: */
138: public CustomMediaSizeName[] getCustomMediaSizeNames() {
139: initMedia();
140: return cupsCustomMediaSNames;
141: }
142:
143: /**
144: * Returns array of MediaPrintableArea derived from PPD.
145: */
146: public MediaPrintableArea[] getMediaPrintableArea() {
147: initMedia();
148: return cupsMediaPrintables;
149: }
150:
151: /**
152: * Returns array of MediaTrays derived from PPD.
153: */
154: public MediaTray[] getMediaTrays() {
155: initMedia();
156: return cupsMediaTrays;
157: }
158:
159: /**
160: * Initialize media by translating PPD info to PrintService attributes.
161: */
162: private void initMedia() {
163: if (initialized) {
164: return;
165: } else {
166: initialized = true;
167: }
168:
169: if (pageSizes == null) {
170: return;
171: }
172:
173: cupsMediaPrintables = new MediaPrintableArea[nPageSizes];
174: cupsMediaSNames = new MediaSizeName[nPageSizes];
175: cupsCustomMediaSNames = new CustomMediaSizeName[nPageSizes];
176:
177: CustomMediaSizeName msn;
178: MediaPrintableArea mpa;
179: float length, width, x, y, w, h;
180:
181: // initialize names and printables
182: for (int i = 0; i < nPageSizes; i++) {
183: // media width and length
184: width = (float) (pageSizes[i * 6] / PRINTER_DPI);
185: length = (float) (pageSizes[i * 6 + 1] / PRINTER_DPI);
186: // media printable area
187: x = (float) (pageSizes[i * 6 + 2] / PRINTER_DPI);
188: h = (float) (pageSizes[i * 6 + 3] / PRINTER_DPI);
189: w = (float) (pageSizes[i * 6 + 4] / PRINTER_DPI);
190: y = (float) (pageSizes[i * 6 + 5] / PRINTER_DPI);
191:
192: msn = new CustomMediaSizeName(media[i * 2],
193: media[i * 2 + 1], width, length);
194:
195: // add to list of standard MediaSizeNames
196: if ((cupsMediaSNames[i] = msn.getStandardMedia()) == null) {
197: // add custom if no matching standard media
198: cupsMediaSNames[i] = msn;
199:
200: // add this new custom msn to MediaSize array
201: if ((width > 0.0) && (length > 0.0)) {
202: new MediaSize(width, length, Size2DSyntax.INCH, msn);
203: }
204: }
205:
206: // add to list of custom MediaSizeName
207: // for internal use of IPPPrintService
208: cupsCustomMediaSNames[i] = msn;
209:
210: mpa = null;
211: try {
212: mpa = new MediaPrintableArea(x, y, w, h,
213: MediaPrintableArea.INCH);
214: } catch (IllegalArgumentException e) {
215: if (width > 0 && length > 0) {
216: mpa = new MediaPrintableArea(0, 0, width, length,
217: MediaPrintableArea.INCH);
218: }
219: }
220: cupsMediaPrintables[i] = mpa;
221: }
222:
223: // initialize trays
224: cupsMediaTrays = new MediaTray[nTrays];
225:
226: MediaTray mt;
227: for (int i = 0; i < nTrays; i++) {
228: mt = new CustomMediaTray(media[(nPageSizes + i) * 2],
229: media[(nPageSizes + i) * 2 + 1]);
230: cupsMediaTrays[i] = mt;
231: }
232:
233: }
234:
235: /**
236: * Get CUPS default printer using IPP.
237: */
238: public static String getDefaultPrinter() {
239: try {
240: URL url = new URL("http", getServer(), getPort(), "");
241: final HttpURLConnection urlConnection = IPPPrintService
242: .getIPPConnection(url);
243:
244: if (urlConnection != null) {
245: OutputStream os = (OutputStream) java.security.AccessController
246: .doPrivileged(new java.security.PrivilegedAction() {
247: public Object run() {
248: try {
249: return urlConnection
250: .getOutputStream();
251: } catch (Exception e) {
252: }
253: return null;
254: }
255: });
256:
257: if (os == null) {
258: return null;
259: }
260:
261: AttributeClass attCl[] = {
262: AttributeClass.ATTRIBUTES_CHARSET,
263: AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
264: new AttributeClass("requested-attributes",
265: AttributeClass.TAG_KEYWORD,
266: "printer-name") };
267:
268: if (IPPPrintService.writeIPPRequest(os,
269: IPPPrintService.OP_CUPS_GET_DEFAULT, attCl)) {
270:
271: HashMap defaultMap = null;
272: InputStream is = urlConnection.getInputStream();
273: HashMap[] responseMap = IPPPrintService
274: .readIPPResponse(is);
275: is.close();
276:
277: if (responseMap.length > 0) {
278: defaultMap = responseMap[0];
279: }
280:
281: if (defaultMap == null) {
282: os.close();
283: urlConnection.disconnect();
284: return null;
285: }
286:
287: AttributeClass attribClass = (AttributeClass) defaultMap
288: .get("printer-name");
289:
290: if (attribClass != null) {
291: String nameStr = attribClass.getStringValue();
292: os.close();
293: urlConnection.disconnect();
294: return nameStr;
295: }
296: }
297: os.close();
298: urlConnection.disconnect();
299: }
300: } catch (Exception e) {
301: }
302: return null;
303: }
304:
305: /**
306: * Get list of all CUPS printers using IPP.
307: */
308: public static String[] getAllPrinters() {
309: try {
310: URL url = new URL("http", getServer(), getPort(), "");
311:
312: final HttpURLConnection urlConnection = IPPPrintService
313: .getIPPConnection(url);
314:
315: if (urlConnection != null) {
316: OutputStream os = (OutputStream) java.security.AccessController
317: .doPrivileged(new java.security.PrivilegedAction() {
318: public Object run() {
319: try {
320: return urlConnection
321: .getOutputStream();
322: } catch (Exception e) {
323: }
324: return null;
325: }
326: });
327:
328: if (os == null) {
329: return null;
330: }
331:
332: AttributeClass attCl[] = {
333: AttributeClass.ATTRIBUTES_CHARSET,
334: AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
335: new AttributeClass("requested-attributes",
336: AttributeClass.TAG_KEYWORD,
337: "printer-name") };
338:
339: if (IPPPrintService.writeIPPRequest(os,
340: IPPPrintService.OP_CUPS_GET_PRINTERS, attCl)) {
341:
342: InputStream is = urlConnection.getInputStream();
343: HashMap[] responseMap = IPPPrintService
344: .readIPPResponse(is);
345:
346: is.close();
347: os.close();
348: urlConnection.disconnect();
349:
350: if (responseMap == null || responseMap.length == 0) {
351: return null;
352: }
353:
354: ArrayList printerNames = new ArrayList();
355: for (int i = 0; i < responseMap.length; i++) {
356: AttributeClass attribClass = (AttributeClass) responseMap[i]
357: .get("printer-name");
358:
359: if (attribClass != null) {
360: String nameStr = attribClass
361: .getStringValue();
362: printerNames.add(nameStr);
363: }
364: }
365: return (String[]) printerNames
366: .toArray(new String[] {});
367: } else {
368: os.close();
369: urlConnection.disconnect();
370: }
371: }
372:
373: } catch (Exception e) {
374: }
375: return null;
376:
377: }
378:
379: /**
380: * Returns CUPS server name.
381: */
382: public static String getServer() {
383: return cupsServer;
384: }
385:
386: /**
387: * Returns CUPS port number.
388: */
389: public static int getPort() {
390: return cupsPort;
391: }
392:
393: /**
394: * Detects if CUPS is running.
395: */
396: public static boolean isCupsRunning() {
397: IPPPrintService.debug_println("libFound " + libFound);
398: if (libFound) {
399: IPPPrintService.debug_println("CUPS server " + getServer()
400: + " port " + getPort());
401: return canConnect(getServer(), getPort());
402: } else {
403: return false;
404: }
405: }
406:
407: }
|