0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: /**
0018: * @author Igor A. Pyankov
0019: * @version $Revision: 1.5 $
0020: */package org.apache.harmony.x.print.cups;
0021:
0022: import java.io.BufferedInputStream;
0023: import java.io.BufferedOutputStream;
0024: import java.io.ByteArrayInputStream;
0025: import java.io.DataOutputStream;
0026: import java.io.File;
0027: import java.io.FileOutputStream;
0028: import java.io.FilePermission;
0029: import java.io.InputStream;
0030: import java.lang.reflect.Array;
0031: import java.net.URI;
0032: import java.net.URISyntaxException;
0033: import java.net.URL;
0034: import java.security.AccessController;
0035: import java.security.PrivilegedAction;
0036: import java.util.ArrayList;
0037: import java.util.Locale;
0038:
0039: import javax.print.Doc;
0040: import javax.print.DocFlavor;
0041: import javax.print.PrintException;
0042: import javax.print.attribute.Attribute;
0043: import javax.print.attribute.AttributeSet;
0044: import javax.print.attribute.AttributeSetUtilities;
0045: import javax.print.attribute.DocAttributeSet;
0046: import javax.print.attribute.HashAttributeSet;
0047: import javax.print.attribute.HashPrintServiceAttributeSet;
0048: import javax.print.attribute.PrintRequestAttributeSet;
0049: import javax.print.attribute.PrintServiceAttribute;
0050: import javax.print.attribute.PrintServiceAttributeSet;
0051: import javax.print.attribute.standard.Destination;
0052: import javax.print.attribute.standard.DocumentName;
0053: import javax.print.attribute.standard.JobName;
0054: import javax.print.attribute.standard.Media;
0055: import javax.print.attribute.standard.RequestingUserName;
0056:
0057: import org.apache.harmony.x.print.PrintClient;
0058: import org.apache.harmony.x.print.ipp.IppAttribute;
0059: import org.apache.harmony.x.print.ipp.IppAttributeGroup;
0060: import org.apache.harmony.x.print.ipp.IppAttributeGroupSet;
0061: import org.apache.harmony.x.print.ipp.IppDocument;
0062: import org.apache.harmony.x.print.ipp.IppPrinter;
0063: import org.apache.harmony.x.print.ipp.IppResponse;
0064: import org.apache.harmony.x.print.ipp.util.Ipp2Java;
0065:
0066: /*
0067: * CUPSClient is a print client based on CUPS protocol.
0068: * (see Common UNIX Printing System, http://www.cups.org/)
0069: *
0070: * The CUPS itself extends IPP protocol
0071: * (see Internet Printing Protocol, http://www.pwg.org/ipp/index.html)
0072: *
0073: * So, this class supports as CUPS as IPP print servers
0074: *
0075: * The class uses special IPP package org.apache.harmony.x.print.ipp for
0076: * ipp/cups specific operations.
0077: *
0078: * CUPSClient implements PrintClient interface, therefore
0079: * see PrintClient.java for more information.
0080: *
0081: *
0082: */
0083: class CUPSClient implements PrintClient {
0084: // for debug
0085: private static int verbose = 0;
0086:
0087: private IppPrinter printer;
0088: private URI printeruri;
0089: private PrintServiceAttributeSet attributeset;
0090: private DocFlavor[] supportedFlavors = null;
0091:
0092: CUPSClient(String name) throws PrintException {
0093: try {
0094: this .printeruri = new URI(name);
0095: this .printer = new IppPrinter(printeruri);
0096: this .attributeset = new HashPrintServiceAttributeSet();
0097: } catch (Exception e) {
0098: throw new PrintException(e);
0099: }
0100: }
0101:
0102: /*
0103: * SPECIAL - supportedFlavors is global for performance
0104: * but it can be set local for dynamic
0105: *
0106: * @org.apache.harmony.x.print.PrintClient#getSupportedDocFlavors()
0107: */
0108: public DocFlavor[] getSupportedDocFlavors() {
0109: if (supportedFlavors == null) {
0110: ArrayList df = new ArrayList();
0111:
0112: try {
0113: String[] mimetypes = new String[ALLDOCFLAVORS.length];
0114: String[] validmimes;
0115:
0116: for (int i = 0, ii = ALLDOCFLAVORS.length; i < ii; i++) {
0117: mimetypes[i] = ALLDOCFLAVORS[i].getMimeType();
0118: }
0119: validmimes = printer
0120: .requestGetSupportedMimeTypes(mimetypes);
0121: for (int i = 0, ii = ALLDOCFLAVORS.length; i < ii; i++) {
0122: if (validmimes[i] != null) {
0123: if (validmimes[i].equals("application/ps")) {
0124: /*
0125: * SPECIAL processing application/ps
0126: */
0127: df.add(ipp2java(ALLDOCFLAVORS[i]));
0128: } else {
0129: df.add(ALLDOCFLAVORS[i]);
0130: }
0131: }
0132: }
0133: } catch (Exception e) {
0134: // IGNORE exception
0135: e.printStackTrace();
0136: }
0137:
0138: supportedFlavors = (df.size() == 0 ? new DocFlavor[] { DocFlavor.INPUT_STREAM.AUTOSENSE }
0139: : (DocFlavor[]) df.toArray(new DocFlavor[0]));
0140: }
0141: return supportedFlavors;
0142: }
0143:
0144: /*
0145: * @see org.apache.harmony.x.print.PrintClient#getAttributes()
0146: */
0147: public PrintServiceAttributeSet getAttributes() {
0148: synchronized (this ) {
0149: try {
0150: IppResponse response;
0151: IppAttributeGroup agroup;
0152: IppAttribute attr;
0153: Object[] attrx = new Object[0];
0154:
0155: response = printer
0156: .requestPrinterDescriptionAttributes();
0157: agroup = response
0158: .getGroup(IppAttributeGroup.TAG_GET_PRINTER_ATTRIBUTES);
0159: if (agroup != null) {
0160: attributeset.clear();
0161: for (int i = 0, ii = agroup.size(); i < ii; i++) {
0162: attr = (IppAttribute) agroup.get(i);
0163: attrx = Ipp2Java.getJavaByIpp(attr);
0164: for (int j = 0, jj = attrx.length; j < jj; j++) {
0165: if (attrx[j] instanceof PrintServiceAttribute) {
0166: attributeset.add((Attribute) attrx[j]);
0167: }
0168: }
0169: }
0170: }
0171: } catch (Exception e) {
0172: // IGNORE exception
0173: e.printStackTrace();
0174: }
0175: }
0176:
0177: return AttributeSetUtilities.unmodifiableView(attributeset);
0178: }
0179:
0180: /*
0181: * @see org.apache.harmony.x.PrintClient#getSupportedAttributeCategories()
0182: */
0183: public Class[] getSupportedAttributeCategories() {
0184: ArrayList clazz = new ArrayList();
0185:
0186: try {
0187: IppResponse response = printer.requestPrinterAttributes();
0188: IppAttributeGroup agroup = response
0189: .getGroup(IppAttributeGroup.TAG_GET_PRINTER_ATTRIBUTES);
0190: String aname;
0191: Class claz;
0192: IppAttribute attr;
0193:
0194: if (agroup != null) {
0195: for (int i = 0, ii = agroup.size(); i < ii; i++) {
0196: attr = (IppAttribute) agroup.get(i);
0197: aname = new String(attr.getName());
0198: if (aname.indexOf("-supported") > 0) {
0199: claz = Ipp2Java
0200: .getClassByIppAttributeName(aname
0201: .substring(0, aname
0202: .indexOf("-supported")));
0203: if (claz != null) {
0204: clazz.add(claz);
0205: }
0206: }
0207: }
0208: }
0209: // SPECIAL attributes processing
0210: getSupportedAttributeCategoriesEx(clazz);
0211: } catch (Exception e) {
0212: // IGNORE exception
0213: // e.printStackTrace();
0214: }
0215: return (clazz.size() == 0 ? new Class[0] : (Class[]) clazz
0216: .toArray(new Class[0]));
0217: }
0218:
0219: private void getSupportedAttributeCategoriesEx(ArrayList clazz) {
0220: if (!clazz.contains(Destination.class)) {
0221: clazz.add(Destination.class);
0222: }
0223: if (!clazz.contains(RequestingUserName.class)) {
0224: clazz.add(RequestingUserName.class);
0225: }
0226: if (!clazz.contains(JobName.class)) {
0227: clazz.add(JobName.class);
0228: }
0229: if (!clazz.contains(DocumentName.class)) {
0230: clazz.add(DocumentName.class);
0231: }
0232: }
0233:
0234: /*
0235: * @see org.apache.harmony.x.print.PrintClient#getDefaultAttributeValue(java.lang.Class)
0236: */
0237: public Object getDefaultAttributeValue(Class category) {
0238: if (category == null) {
0239: throw new NullPointerException("Argument is null");
0240: }
0241: if (!(Attribute.class.isAssignableFrom(category))) {
0242: throw new IllegalArgumentException(
0243: "Argument must implement interface Attribute");
0244: }
0245:
0246: Object defval[] = null;
0247:
0248: // SPECIAL attributes processing
0249: defval = getDefaultAttributeValueEx(category);
0250: if (defval != null) {
0251: if (defval.length == 0) {
0252: return null;
0253: }
0254: return defval[0];
0255: }
0256:
0257: if (Media.class.isAssignableFrom(category)) {
0258: category = Media.class;
0259: }
0260: try {
0261: IppResponse response = printer.requestPrinterAttributes();
0262: IppAttributeGroup agroup = response
0263: .getGroup(IppAttributeGroup.TAG_GET_PRINTER_ATTRIBUTES);
0264: IppAttribute attr;
0265: String aname;
0266: int andex;
0267:
0268: if (agroup != null) {
0269: aname = Ipp2Java.getIppAttributeNameByClass(category);
0270: if (aname != null) {
0271: if (aname.endsWith("-supported")) {
0272: aname = aname.substring(0, aname
0273: .indexOf("-supported"));
0274: }
0275: if (aname.endsWith("-default")) {
0276: aname = aname.substring(0, aname
0277: .indexOf("-default"));
0278: }
0279: andex = agroup.findAttribute(aname + "-default");
0280: if (andex >= 0) {
0281: attr = (IppAttribute) agroup.get(andex);
0282: defval = Ipp2Java.getJavaByIpp(attr);
0283: }
0284: }
0285: }
0286: } catch (Exception e) {
0287: // IGNORE exception
0288: e.printStackTrace();
0289: }
0290:
0291: return (defval != null && defval.length > 0 ? defval[0] : null);
0292: }
0293:
0294: /*
0295: * If attribute was processed - return Object[1]
0296: * Else - return null
0297: */
0298: private Object[] getDefaultAttributeValueEx(Class category) {
0299: if (Destination.class.isAssignableFrom(category)) {
0300: return new Object[0];
0301: } else if (RequestingUserName.class.isAssignableFrom(category)) {
0302: return new Object[] { new RequestingUserName(
0303: (String) AccessController
0304: .doPrivileged(new PrivilegedAction() {
0305: public Object run() {
0306: return System
0307: .getProperty("user.name");
0308: }
0309: }), Locale.US) };
0310: } else if (JobName.class.isAssignableFrom(category)) {
0311: return new Object[] { new JobName("Java print job",
0312: Locale.US) };
0313: } else if (DocumentName.class.isAssignableFrom(category)) {
0314: return new Object[] { new DocumentName(
0315: "Java print document", Locale.US) };
0316: }
0317: return null;
0318: }
0319:
0320: /*
0321: * @see org.apache.harmony.x.print.PrintClient#isAttributeValueSupported(javax.print.attribute.Attribute,
0322: * javax.print.DocFlavor, javax.print.attribute.AttributeSet)
0323: */
0324: public boolean isAttributeValueSupported(Attribute attribute,
0325: DocFlavor flavor, AttributeSet attributes) {
0326:
0327: // verify parameters
0328: if (attribute == null) {
0329: throw new NullPointerException("Argument is null");
0330: }
0331: if (flavor != null && !isDocFlavorSupported(flavor)) {
0332: throw new IllegalArgumentException("DocFlavor '" + flavor
0333: + "' is not supported by the print service");
0334: }
0335:
0336: // SPECIAL attributes processing
0337: boolean[] supportedEx = isAttributeValueSupportedEx(attribute,
0338: flavor);
0339: if (supportedEx != null) {
0340: return supportedEx[0];
0341: }
0342:
0343: boolean supported = false;
0344: try {
0345: IppDocument document;
0346: IppResponse response;
0347: IppAttributeGroup agroup;
0348: IppAttributeGroupSet agroupset;
0349: Attribute[] attrs;
0350: String mime = null;
0351: String aname;
0352:
0353: aname = Ipp2Java.getIppAttributeNameByClass(attribute
0354: .getClass(), -1);
0355: if (aname == null) {
0356: return false;
0357: }
0358: if (flavor == null) {
0359: mime = "application/octet-stream";
0360: } else {
0361: mime = java2ipp(flavor).getMimeType();
0362: }
0363: if (attributes == null || attributes.isEmpty()) {
0364: document = new IppDocument("Qwerty", mime, "");
0365: agroupset = new IppAttributeGroupSet();
0366: agroupset.setAttribute(aname, Ipp2Java
0367: .getIppByJava(attribute));
0368: response = printer.requestValidateJob(aname, document,
0369: agroupset);
0370: agroup = response
0371: .getGroup(IppAttributeGroup.TAG_UNSUPPORTED_ATTRIBUTES);
0372:
0373: if (agroup == null) {
0374: supported = true;
0375: } else if (agroup != null
0376: && agroup.findAttribute(aname) < 0) {
0377: supported = true;
0378: }
0379: } else {
0380: document = new IppDocument("Qwerty", mime, "");
0381: agroupset = new IppAttributeGroupSet();
0382: agroupset.setAttribute(aname, Ipp2Java
0383: .getIppByJava(attribute));
0384: attrs = attributes.toArray();
0385: for (int i = 0, ii = attrs.length; i < ii; i++) {
0386: agroupset.setAttribute(Ipp2Java
0387: .getIppAttributeNameByClass(attrs[i]
0388: .getClass(), -1), Ipp2Java
0389: .getIppByJava(attrs[i]));
0390: }
0391:
0392: response = printer.requestValidateJob(aname, document,
0393: agroupset);
0394: agroup = response
0395: .getGroup(IppAttributeGroup.TAG_UNSUPPORTED_ATTRIBUTES);
0396:
0397: if (agroup == null) {
0398: supported = true;
0399: } else if (agroup != null
0400: && agroup.findAttribute(aname) < 0) {
0401: supported = true;
0402: }
0403: }
0404: } catch (Exception e) {
0405: e.printStackTrace();
0406: return false;
0407: }
0408:
0409: return supported;
0410: }
0411:
0412: /*
0413: * If attribute was processed - return boolean[1]
0414: * Else return null
0415: */
0416: private boolean[] isAttributeValueSupportedEx(Attribute avalue,
0417: DocFlavor flavor) {
0418: if (Destination.class.isAssignableFrom(avalue.getCategory())) {
0419: String ms = (flavor != null ? flavor.getMediaSubtype() : "");
0420: Class cls = (flavor != null ? flavor.getClass() : null);
0421:
0422: if (ms.equalsIgnoreCase("gif")
0423: || ms.equalsIgnoreCase("jpeg")
0424: || ms.equalsIgnoreCase("png")
0425: || ms.equalsIgnoreCase("postscript")
0426: || flavor == null
0427: || cls == DocFlavor.SERVICE_FORMATTED.class) {
0428: if (!canPrintToFile()) {
0429: return new boolean[] { false };
0430: }
0431:
0432: URI uri = ((Destination) avalue).getURI();
0433: try {
0434: File file = new File(uri);
0435:
0436: if (file.isFile()) {
0437: if (file.canWrite()) {
0438: return new boolean[] { true };
0439: }
0440: return new boolean[] { false };
0441: }
0442:
0443: String path = file.getParent();
0444: File parent = new File(path);
0445: if (parent.isDirectory()) {
0446: if (parent.canWrite()) {
0447: return new boolean[] { true };
0448: }
0449: return new boolean[] { false };
0450: }
0451: } catch (Exception e) {
0452: return new boolean[] { false };
0453: }
0454: }
0455: }
0456: return null;
0457: }
0458:
0459: /*
0460: * @see org.apache.harmony.x.print.PrintClient#getSupportedAttributeValues(java.lang.Class,
0461: * javax.print.DocFlavor, javax.print.attribute.AttributeSet)
0462: */
0463: public Object getSupportedAttributeValues(Class category,
0464: DocFlavor flavor, AttributeSet attributes) {
0465: if (category == null) {
0466: throw new NullPointerException("Argument is null");
0467: }
0468: if (!(Attribute.class.isAssignableFrom(category))) {
0469: throw new IllegalArgumentException(
0470: "Argument must implement interface Attribute");
0471: }
0472: if (flavor != null && !isDocFlavorSupported(flavor)) {
0473: throw new IllegalArgumentException("DocFlavor '" + flavor
0474: + "' is not supported by the print service");
0475: }
0476:
0477: Object vals = null;
0478:
0479: // SPECIAL attributes processing
0480: vals = getSupportedAttributeValuesEx(category, flavor);
0481: if (vals != null) {
0482: if (((Object[]) vals).length == 0) {
0483: return null;
0484: }
0485: return ((Object[]) vals)[0];
0486: }
0487:
0488: // General attributes
0489: try {
0490: String aname = Ipp2Java.getIppAttributeNameByClass(
0491: category, 0)
0492: + "-supported";
0493: doVerbose(2,
0494: "CUPSClient.java: getSupportedAttributeValues(): ipp attribute: "
0495: + aname);
0496: IppResponse response = printer.requestPrinterAttributes(
0497: aname, (flavor == null ? null : java2ipp(flavor)
0498: .getMimeType()));
0499: doVerbose(2,
0500: "CUPSClient.java: getSupportedAttributeValues(): response: "
0501: + response.toString());
0502: IppAttributeGroup agroup = response
0503: .getGroup(IppAttributeGroup.TAG_GET_PRINTER_ATTRIBUTES);
0504: doVerbose(1,
0505: "CUPSClient.java: getSupportedAttributeValues(): agroup: "
0506: + agroup.toString());
0507: if (agroup != null) {
0508: int aind = agroup.findAttribute(aname);
0509: if (aind >= 0) {
0510: IppAttribute attr = (IppAttribute) agroup.get(aind);
0511: vals = Ipp2Java.getJavaByIpp(attr);
0512: }
0513: }
0514: doVerbose(1,
0515: "CUPSClient.java: getSupportedAttributeValues(): 1");
0516: // Make right type/value for return
0517: if (vals != null && vals.getClass().isArray()) {
0518: Object[] ara = (Object[]) vals;
0519: if (ara.length == 1 && ara[0].getClass() != category) {
0520: vals = ara[0];
0521: }
0522: }
0523: doVerbose(1,
0524: "CUPSClient.java: getSupportedAttributeValues(): 2");
0525: if (vals != null && vals.getClass().isArray()) {
0526: int asize = ((Object[]) vals).length;
0527: if (asize > 0) {
0528: Class c = ((Object[]) vals)[0].getClass();
0529: /* SPECIAL case for Media* attributes
0530: *
0531: * Special case for Media* attributes.
0532: * vals[] contains all type of Media classes
0533: * So, c must be Media type, not a[0] type
0534: */
0535: if (Media.class.isAssignableFrom(c)) {
0536: c = Media.class;
0537: }
0538: doVerbose(1,
0539: "CUPSClient.java: getSupportedAttributeValues(): 3");
0540: Object[] a = (Object[]) Array.newInstance(c, asize);
0541: System.arraycopy(vals, 0, a, 0, a.length);
0542:
0543: vals = a;
0544: } else {
0545: vals = null;
0546: }
0547: }
0548: doVerbose(1,
0549: "CUPSClient.java: getSupportedAttributeValues(): 4");
0550: if (vals != null && vals.getClass().isArray()) {
0551: for (int i = 0, ii = ((Attribute[]) vals).length; i < ii; i++) {
0552: if (!isAttributeValueSupported(
0553: ((Attribute[]) vals)[i], flavor, attributes)) {
0554: ((Attribute[]) vals)[i] = null;
0555: }
0556: }
0557: doVerbose(1,
0558: "CUPSClient.java: getSupportedAttributeValues(): 5");
0559: int newvalslength = 0;
0560: for (int i = 0, ii = ((Attribute[]) vals).length; i < ii; i++) {
0561: if (((Attribute[]) vals)[i] != null) {
0562: newvalslength++;
0563: }
0564: }
0565: doVerbose(1,
0566: "CUPSClient.java: getSupportedAttributeValues(): 6");
0567: if (newvalslength != ((Attribute[]) vals).length) {
0568: Object[] newvals = new Object[newvalslength];
0569: for (int j = 0, i = 0, ii = ((Attribute[]) vals).length; i < ii; i++) {
0570: if (((Attribute[]) vals)[i] != null) {
0571: newvals[j++] = ((Attribute[]) vals)[i];
0572: }
0573: }
0574:
0575: vals = newvals;
0576: }
0577: } else if (vals != null) {
0578: if (!isAttributeValueSupported((Attribute) vals,
0579: flavor, attributes)) {
0580: vals = null;
0581: }
0582: }
0583: doVerbose(1,
0584: "CUPSClient.java: getSupportedAttributeValues(): 7");
0585: return vals;
0586: } catch (Exception e) {
0587: // IGNORE exception
0588: e.printStackTrace();
0589: }
0590: doVerbose(1,
0591: "CUPSClient.java: getSupportedAttributeValues(): 8");
0592: return null;
0593: } /*
0594: * If category processed - return non-null value
0595: */
0596:
0597: private Object[] getSupportedAttributeValuesEx(Class category,
0598: DocFlavor flavor) {
0599: if (Destination.class.isAssignableFrom(category)) {
0600: String ms = flavor.getMediaSubtype();
0601:
0602: if (ms.equalsIgnoreCase("gif")
0603: || ms.equalsIgnoreCase("jpeg")
0604: || ms.equalsIgnoreCase("png")
0605: || ms.equalsIgnoreCase("postscript")
0606: || flavor.getClass() == DocFlavor.SERVICE_FORMATTED.class) {
0607: try {
0608: return new Object[] { new Destination(new URI(
0609: "file:///foo/bar")) };
0610: } catch (URISyntaxException e) {
0611: // return empty array - values are not supported
0612: return new Object[0];
0613: }
0614: }
0615: } else if (RequestingUserName.class.isAssignableFrom(category)) {
0616: return new Object[] { new RequestingUserName("I.A.Muser",
0617: Locale.US) };
0618: } else if (JobName.class.isAssignableFrom(category)) {
0619: return new Object[] { new JobName("Foo print job",
0620: Locale.US) };
0621: } else if (DocumentName.class.isAssignableFrom(category)) {
0622: return new Object[] { new DocumentName("Foo document",
0623: Locale.US) };
0624: }
0625: return null;
0626: }
0627:
0628: /*
0629: * @see org.apache.harmony.x.print.PrintClient#print(javax.print.Doc,
0630: * javax.print.attribute.PrintRequestAttributeSet)
0631: */
0632: public void print(Doc doc, PrintRequestAttributeSet attributes)
0633: throws PrintException {
0634: synchronized (this ) {
0635: doVerbose(1, "Print " + doc.toString());
0636: try {
0637: DocFlavor df = doc.getDocFlavor();
0638: if (!(df instanceof DocFlavor.INPUT_STREAM
0639: || df instanceof DocFlavor.BYTE_ARRAY
0640: || df instanceof DocFlavor.CHAR_ARRAY
0641: || df instanceof DocFlavor.STRING
0642: || df instanceof DocFlavor.READER || df instanceof DocFlavor.URL)) {
0643: throw new PrintException("Doc flavor "
0644: + df.getRepresentationClassName()
0645: + " is not supported yet");
0646: }
0647:
0648: HashAttributeSet as = new HashAttributeSet();
0649: DocAttributeSet das;
0650: das = doc.getAttributes();
0651:
0652: // construct attributes
0653: if (das != null) {
0654: as.addAll(das);
0655: }
0656: if (attributes != null) {
0657: as.addAll(attributes);
0658: }
0659: as.addAll(attributeset);
0660:
0661: // print
0662: if (as.containsKey(Destination.class)) {
0663: print2destination(doc, (Destination) as
0664: .get(Destination.class));
0665: } else {
0666: printsimple(doc, as);
0667: }
0668: } catch (PrintException e) {
0669: throw e;
0670: } catch (Exception e) {
0671: throw new PrintException(e);
0672: }
0673: }
0674: }
0675:
0676: /*
0677: * printing to Destination
0678: */
0679: private void print2destination(Doc doc, Destination destination)
0680: throws PrintException {
0681:
0682: try {
0683: DataOutputStream bw = new DataOutputStream(
0684: new BufferedOutputStream(new FileOutputStream(
0685: new File(destination.getURI()))));
0686:
0687: if (doc != null) {
0688: if (doc.getDocFlavor() instanceof DocFlavor.INPUT_STREAM) {
0689: InputStream stream = (InputStream) doc
0690: .getPrintData();
0691: byte[] buf = new byte[1024 * 8];
0692: int count = 0;
0693:
0694: while ((count = stream.read(buf, 0, buf.length)) != -1) {
0695: bw.write(buf, 0, count);
0696: }
0697: stream.close();
0698: } else if (doc.getDocFlavor() instanceof DocFlavor.URL) {
0699: BufferedInputStream stream = new BufferedInputStream(
0700: ((URL) doc.getPrintData()).openStream());
0701: byte[] buf = new byte[1024 * 8];
0702: int count = 0;
0703: while ((count = stream.read(buf, 0, buf.length)) != -1) {
0704: if (count > 0) {
0705: bw.write(buf, 0, count);
0706: }
0707: }
0708: stream.close();
0709: } else if (doc.getDocFlavor() instanceof DocFlavor.BYTE_ARRAY) {
0710: InputStream stream = new ByteArrayInputStream(
0711: (byte[]) doc.getPrintData());
0712: byte[] buf = new byte[1024 * 8];
0713: int count = 0;
0714:
0715: while ((count = stream.read(buf, 0, buf.length)) != -1) {
0716: bw.write(buf, 0, count);
0717: }
0718: stream.close();
0719: } else if (doc.getDocFlavor() instanceof DocFlavor.SERVICE_FORMATTED) {
0720: // TODO - print DocFlavor.SERVICE_FORMATTED
0721: }
0722: }
0723:
0724: bw.flush();
0725: bw.close();
0726: } catch (Exception e) {
0727: throw new PrintException(e);
0728: }
0729: }
0730:
0731: /*
0732: * request IppPrinter printer to print document
0733: */
0734: private void printsimple(Doc doc, HashAttributeSet as)
0735: throws PrintException {
0736: IppDocument document;
0737: IppResponse response;
0738: IppAttributeGroupSet agroupset;
0739: Attribute[] attrs;
0740: DocFlavor df = doc.getDocFlavor();
0741: String docname = doc.toString();
0742:
0743: try {
0744: document = new IppDocument(docname, java2ipp(df)
0745: .getMimeType(), doc.getPrintData());
0746:
0747: agroupset = new IppAttributeGroupSet();
0748: attrs = as.toArray();
0749: for (int i = 0, ii = attrs.length; i < ii; i++) {
0750: agroupset.setAttribute(Ipp2Java
0751: .getIppAttributeNameByClass(
0752: attrs[i].getClass(), -1), Ipp2Java
0753: .getIppByJava(attrs[i]));
0754: }
0755: document.setAgroups(agroupset);
0756:
0757: doVerbose(1, "Validating print job...");
0758: response = printer.requestValidateJob(docname, document,
0759: agroupset);
0760: doVerbose(1, response.toString());
0761: checkResponseIsZero(response, "IPP Validate Job: \n");
0762: doVerbose(1, "Validate OK");
0763:
0764: doVerbose(1, "Printing " + docname + "...");
0765: response = printer.requestPrintJob(docname, document,
0766: agroupset);
0767: doVerbose(1, response.toString());
0768: checkResponseIsZero(response, "IPP Print Job: \n");
0769: doVerbose(1, "Printing OK");
0770: } catch (PrintException e) {
0771: throw e;
0772: } catch (Exception e) {
0773: if (getVerbose() > 1) {
0774: e.printStackTrace();
0775: }
0776: throw new PrintException(e);
0777: }
0778: }
0779:
0780: /*
0781: * just check that IppResponse is OK
0782: */
0783: private void checkResponseIsZero(IppResponse response, String prefix)
0784: throws PrintException {
0785: if (response.getStatusCode() != 0) {
0786: String status = Integer.toHexString(response
0787: .getStatusCode());
0788: String id = Integer.toHexString(response.getRequestId());
0789:
0790: throw new PrintException(prefix
0791: + "\n================ IPP response id: 0x" + id
0792: + " ====================="
0793: + "\nresponse status code: 0x" + status + "\n"
0794: + response.toString()
0795: + "\n================ end IPP response 0x" + id
0796: + " =====================");
0797: }
0798: }
0799:
0800: /*
0801: * convert DocFlavor to DocFlavor ;-)
0802: *
0803: * some printers support application/ps instead of application/postscript
0804: * So:
0805: * if mimetype==application/postscript
0806: * && printer does not support mimetype application/postscript
0807: * && printer supports mimetype application/ps
0808: * then
0809: * we change mimetype of docflavor to application/ps
0810: */
0811: private DocFlavor java2ipp(DocFlavor pDocFlavor) {
0812: DocFlavor ippDocFlavor = pDocFlavor;
0813: String mime = pDocFlavor.getMimeType();
0814:
0815: /*
0816: * SPECIAL processing application/ps
0817: */
0818: if (mime.equals("application/postscript")) {
0819: try {
0820: IppDocument document = new IppDocument("Qwerty",
0821: "application/postscript", "");
0822: IppResponse response = printer.requestValidateJob(
0823: "Qwerty", document, null);
0824: if (response.getStatusCode() != 0) {
0825: document = new IppDocument("Qwerty",
0826: "application/ps", "");
0827: response = printer.requestValidateJob("Qwerty",
0828: document, null);
0829: if (response.getStatusCode() == 0) {
0830: if (pDocFlavor instanceof DocFlavor.INPUT_STREAM) {
0831: ippDocFlavor = new DocFlavor.INPUT_STREAM(
0832: "application/ps");
0833: } else if (ippDocFlavor instanceof DocFlavor.BYTE_ARRAY) {
0834: ippDocFlavor = new DocFlavor.BYTE_ARRAY(
0835: "application/ps");
0836: } else if (ippDocFlavor instanceof DocFlavor.URL) {
0837: ippDocFlavor = new DocFlavor.URL(
0838: "application/ps");
0839: }
0840: }
0841: }
0842: } catch (Exception e) {
0843: e.printStackTrace();
0844: }
0845: }
0846:
0847: return ippDocFlavor;
0848: }
0849:
0850: /*
0851: * opposite to java2ipp() method
0852: */
0853: private DocFlavor ipp2java(DocFlavor ippDocFlavor) {
0854: DocFlavor pDocFlavor = ippDocFlavor;
0855: String mime = ippDocFlavor.getMimeType();
0856:
0857: /*
0858: * SPECIAL processing application/ps
0859: */
0860: if (mime.equals("application/ps")) {
0861: if (ippDocFlavor instanceof DocFlavor.INPUT_STREAM) {
0862: pDocFlavor = DocFlavor.INPUT_STREAM.POSTSCRIPT;
0863: } else if (ippDocFlavor instanceof DocFlavor.BYTE_ARRAY) {
0864: pDocFlavor = DocFlavor.BYTE_ARRAY.POSTSCRIPT;
0865: } else if (ippDocFlavor instanceof DocFlavor.URL) {
0866: pDocFlavor = DocFlavor.URL.POSTSCRIPT;
0867: }
0868: }
0869:
0870: return pDocFlavor;
0871: }
0872:
0873: /*
0874: * the method's name is saying all
0875: */
0876: private boolean isDocFlavorSupported(DocFlavor flavor) {
0877: if (flavor == null) {
0878: throw new NullPointerException("DocFlavor flavor is null");
0879: }
0880:
0881: DocFlavor clientFlavors[] = getSupportedDocFlavors();
0882: for (int i = 0; i < clientFlavors.length; i++) {
0883: if (clientFlavors[i].equals(flavor)) {
0884: return true;
0885: }
0886: }
0887: return false;
0888: }
0889:
0890: /*
0891: * check permission to read/write to any file
0892: */
0893: private boolean canPrintToFile() {
0894: SecurityManager sm = System.getSecurityManager();
0895: if (sm != null) {
0896: try {
0897: sm.checkPermission(new FilePermission("<<ALL FILES>>",
0898: "read,write"));
0899: return true;
0900: } catch (SecurityException e) {
0901: return false;
0902: }
0903: }
0904: return true;
0905: }
0906:
0907: /*
0908: * just list of all doc flavors from specification
0909: * it is used in getSupportedDocFlavors() method
0910: */
0911: private static DocFlavor[] ALLDOCFLAVORS = {
0912: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST,
0913: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8,
0914: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16,
0915: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE,
0916: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE,
0917: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII,
0918: DocFlavor.BYTE_ARRAY.TEXT_HTML_HOST,
0919: DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_8,
0920: DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16,
0921: DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16BE,
0922: DocFlavor.BYTE_ARRAY.TEXT_HTML_UTF_16LE,
0923: DocFlavor.BYTE_ARRAY.TEXT_HTML_US_ASCII,
0924: DocFlavor.BYTE_ARRAY.PDF, DocFlavor.BYTE_ARRAY.POSTSCRIPT,
0925: DocFlavor.BYTE_ARRAY.PCL, DocFlavor.BYTE_ARRAY.GIF,
0926: DocFlavor.BYTE_ARRAY.JPEG, DocFlavor.BYTE_ARRAY.PNG,
0927: DocFlavor.BYTE_ARRAY.AUTOSENSE,
0928:
0929: DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,
0930: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8,
0931: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16,
0932: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE,
0933: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE,
0934: DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII,
0935: DocFlavor.INPUT_STREAM.TEXT_HTML_HOST,
0936: DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_8,
0937: DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16,
0938: DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16BE,
0939: DocFlavor.INPUT_STREAM.TEXT_HTML_UTF_16LE,
0940: DocFlavor.INPUT_STREAM.TEXT_HTML_US_ASCII,
0941: DocFlavor.INPUT_STREAM.PDF,
0942: DocFlavor.INPUT_STREAM.POSTSCRIPT,
0943: DocFlavor.INPUT_STREAM.PCL, DocFlavor.INPUT_STREAM.GIF,
0944: DocFlavor.INPUT_STREAM.JPEG, DocFlavor.INPUT_STREAM.PNG,
0945: DocFlavor.INPUT_STREAM.AUTOSENSE,
0946:
0947: DocFlavor.URL.TEXT_PLAIN_HOST,
0948: DocFlavor.URL.TEXT_PLAIN_UTF_8,
0949: DocFlavor.URL.TEXT_PLAIN_UTF_16,
0950: DocFlavor.URL.TEXT_PLAIN_UTF_16BE,
0951: DocFlavor.URL.TEXT_PLAIN_UTF_16LE,
0952: DocFlavor.URL.TEXT_PLAIN_US_ASCII,
0953: DocFlavor.URL.TEXT_HTML_HOST,
0954: DocFlavor.URL.TEXT_HTML_UTF_8,
0955: DocFlavor.URL.TEXT_HTML_UTF_16,
0956: DocFlavor.URL.TEXT_HTML_UTF_16BE,
0957: DocFlavor.URL.TEXT_HTML_UTF_16LE,
0958: DocFlavor.URL.TEXT_HTML_US_ASCII, DocFlavor.URL.PDF,
0959: DocFlavor.URL.POSTSCRIPT, DocFlavor.URL.PCL,
0960: DocFlavor.URL.GIF, DocFlavor.URL.JPEG, DocFlavor.URL.PNG,
0961: DocFlavor.URL.AUTOSENSE,
0962:
0963: DocFlavor.CHAR_ARRAY.TEXT_PLAIN,
0964: DocFlavor.CHAR_ARRAY.TEXT_HTML,
0965:
0966: DocFlavor.STRING.TEXT_PLAIN, DocFlavor.STRING.TEXT_HTML,
0967:
0968: DocFlavor.READER.TEXT_PLAIN, DocFlavor.READER.TEXT_HTML,
0969:
0970: DocFlavor.SERVICE_FORMATTED.RENDERABLE_IMAGE,
0971: DocFlavor.SERVICE_FORMATTED.PRINTABLE,
0972: DocFlavor.SERVICE_FORMATTED.PAGEABLE,
0973:
0974: /*
0975: * Some printers accept "application/ps" instead of "application/postscript"
0976: * So, we have special processing for those DocFlavor
0977: * See comments with phrase:
0978: * SPECIAL processing application/ps
0979: */
0980: new DocFlavor.INPUT_STREAM("application/ps"),
0981: new DocFlavor.URL("application/ps"),
0982: new DocFlavor.BYTE_ARRAY("application/ps") };
0983:
0984: public static int getVerbose() {
0985: return verbose;
0986: }
0987:
0988: public static void setVerbose(int newverbose) {
0989: verbose = newverbose;
0990: IppPrinter.setVerbose(verbose);
0991: }
0992:
0993: public static void doVerbose(String v) {
0994: System.out.println(v);
0995: }
0996:
0997: public static void doVerbose(int level, String v) {
0998: if (verbose >= level) {
0999: System.out.println(v);
1000: }
1001: }
1002:
1003: }
|