1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70: import ;
71: import ;
72: import ;
73:
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85: import ;
86:
87: import ;
88: import ;
89: import ;
90: import ;
91: import ;
92: import ;
93: import ;
94: import ;
95: import ;
96: import ;
97: import ;
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109: import ;
110: import ;
111: import ;
112: import ;
113: import ;
114: import ;
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120: import ;
121: import ;
122: import ;
123: import ;
124: import ;
125: import ;
126: import ;
127: import ;
128:
129:
130:
136: public class IppPrintService implements PrintService
137: {
138:
146: private Map printerAttr;
147:
148:
149: private HashSet printServiceAttributeListener;
150:
151:
152: private transient String user;
153:
154:
155: private transient String passwd;
156:
157:
158: private String name;
159:
160:
161: private List flavors;
162:
163:
164: private PrinterURI printerUri;
165:
166:
167: private ArrayList printerUris;
168:
169:
173: static final Logger logger = SystemLogger.SYSTEM;
174:
175:
178: public static final RequestingUserName REQUESTING_USER_NAME;
179:
180:
183: public static final JobName JOB_NAME;
184:
185: static
186: {
187: JOB_NAME = new JobName("Java Printing", null);
188: REQUESTING_USER_NAME = new RequestingUserName(
189: SystemProperties.getProperty("user.name", ""), null);
190: }
191:
192:
193:
194:
203: public IppPrintService(URI uri, String username, String password)
204: throws IppException
205: {
206: printerUri = new PrinterURI(uri);
207: user = username;
208: passwd = password;
209:
210: printServiceAttributeListener = new HashSet();
211:
212: printerAttr = getPrinterAttributes();
213: processResponse();
214: }
215:
216:
222: private Map getPrinterAttributes() throws IppException
223: {
224: IppResponse response = null;
225:
226: try
227: {
228: IppRequest request = new IppRequest(printerUri.getURI(), user, passwd);
229:
230: int operation = OperationsSupported.GET_PRINTER_ATTRIBUTES.getValue();
231: request.setOperationID((short) operation);
232: request.setOperationAttributeDefaults();
233: request.addOperationAttribute(printerUri);
234:
235: response = request.send();
236: }
237: catch (IOException e)
238: {
239: throw new IppException("IOException in IPP request/response.", e);
240: }
241:
242: return (Map) response.getPrinterAttributes().get(0);
243: }
244:
245:
252: private Set getPrinterAttributeSet(Class attributeClass)
253: {
254: return (Set) printerAttr.get(attributeClass);
255: }
256:
257:
267: private Attribute getPrinterDefaultAttribute(Class attributeClass)
268: {
269: Set set = (Set) printerAttr.get(attributeClass);
270: return ((DefaultValueAttribute) set.toArray()[0]).getAssociatedAttribute();
271: }
272:
273:
276: private void processResponse()
277: {
278:
279: PrinterName[] tmp = (PrinterName[]) getPrinterAttributeSet(
280: PrinterName.class).toArray(new PrinterName[1]);
281: name = tmp[0].getValue();
282:
283:
284:
285:
286:
287:
288: flavors = new ArrayList();
289: Set flavorAttributes = getPrinterAttributeSet(DocumentFormatSupported.class);
290: if (flavorAttributes != null)
291: {
292: for (Iterator it = flavorAttributes.iterator(); it.hasNext();)
293: {
294: String mimeType = ((DocumentFormatSupported) it.next()).getValue();
295:
296: if (mimeType.equals("text/plain"))
297: {
298: flavors.add(DocFlavor.CHAR_ARRAY.TEXT_PLAIN);
299: flavors.add(DocFlavor.READER.TEXT_PLAIN);
300: flavors.add(DocFlavor.STRING.TEXT_PLAIN);
301:
302:
303: mimeType = mimeType + "; charset=utf-8";
304: }
305: else if (mimeType.equals("text/html"))
306: {
307: flavors.add(DocFlavor.CHAR_ARRAY.TEXT_HTML);
308: flavors.add(DocFlavor.READER.TEXT_HTML);
309: flavors.add(DocFlavor.STRING.TEXT_HTML);
310:
311:
312: mimeType = mimeType + "; charset=utf-8";
313: }
314:
315:
316:
317:
318: boolean changed = false;
319: try
320: {
321: Class[] clazzes = new Class[] { DocFlavor.BYTE_ARRAY.class,
322: DocFlavor.INPUT_STREAM.class,
323: DocFlavor.URL.class };
324:
325: for (int j = 0; j < clazzes.length; j++)
326: {
327: Field[] fields = clazzes[j].getDeclaredFields();
328: for (int i = 0; i < fields.length; i++)
329: {
330: if (fields[i].getType().equals(clazzes[j]))
331: {
332: DocFlavor flavor = (DocFlavor) fields[i].get(null);
333: if (flavor.getMimeType().equals(mimeType))
334: changed = flavors.add(flavor);
335: }
336: }
337: }
338: if (!changed)
339: {
340:
341: flavors.add(new DocFlavor(mimeType, "[B"));
342: flavors.add(new DocFlavor(mimeType, "java.io.InputStream"));
343: flavors.add(new DocFlavor(mimeType, "java.net.URL"));
344: }
345: }
346: catch (SecurityException e)
347: {
348:
349: }
350: catch (IllegalArgumentException e)
351: {
352:
353: }
354: catch (IllegalAccessException e)
355: {
356:
357: }
358: }
359: }
360:
361:
362: Set uris = getPrinterAttributeSet(PrinterUriSupported.class);
363: printerUris = new ArrayList(uris.size());
364: Iterator it = uris.iterator();
365: while (it.hasNext())
366: {
367: PrinterUriSupported uri = (PrinterUriSupported) it.next();
368: printerUris.add( new PrinterURI(uri.getURI()));
369: }
370: }
371:
372:
377: public DocPrintJob createPrintJob()
378: {
379: return new DocPrintJobImpl(this, user, passwd);
380: }
381:
382:
383:
386: public PrintServiceAttribute getAttribute(Class category)
387: {
388: if (category == null)
389: throw new NullPointerException("category may not be null");
390:
391: if (! PrintServiceAttribute.class.isAssignableFrom(category))
392: throw new IllegalArgumentException(
393: "category must be of type PrintServiceAttribute");
394:
395: Set set = getPrinterAttributeSet(category);
396: if (set != null && set.size() > 0)
397: return (PrintServiceAttribute) set.toArray()[0];
398:
399: return null;
400: }
401:
402:
405: public PrintServiceAttributeSet getAttributes()
406: {
407: PrintServiceAttributeSet set = new HashPrintServiceAttributeSet();
408:
409: Iterator it = printerAttr.values().iterator();
410: while (it.hasNext())
411: {
412: Iterator it2 = ((Set) it.next()).iterator();
413: while (it2.hasNext())
414: {
415: Attribute attr = (Attribute) it2.next();
416: if (attr instanceof PrintServiceAttribute)
417: set.add(attr);
418: }
419: }
420:
421: return AttributeSetUtilities.unmodifiableView(set);
422: }
423:
424:
427: public Object getDefaultAttributeValue(Class category)
428: {
429:
430: if (category.equals(Fidelity.class))
431: return Fidelity.FIDELITY_FALSE;
432: if (category.equals(JobName.class))
433: return JOB_NAME;
434: if (category.equals(RequestingUserName.class))
435: return REQUESTING_USER_NAME;
436:
437:
438: if (category.equals(JobPriority.class)
439: && printerAttr.containsKey(JobPriorityDefault.class))
440: return getPrinterDefaultAttribute(JobPriorityDefault.class);
441: if (category.equals(JobHoldUntil.class)
442: && printerAttr.containsKey(JobHoldUntilDefault.class))
443: return getPrinterDefaultAttribute(JobHoldUntilDefault.class);
444: if (category.equals(JobSheets.class)
445: && printerAttr.containsKey(JobSheetsDefault.class))
446: return getPrinterDefaultAttribute(JobSheetsDefault .class);
447: if (category.equals(MultipleDocumentHandling.class)
448: && printerAttr.containsKey(MultipleDocumentHandlingDefault.class))
449: return getPrinterDefaultAttribute(MultipleDocumentHandlingDefault.class);
450: if (category.equals(Copies.class)
451: && printerAttr.containsKey(CopiesDefault.class))
452: return getPrinterDefaultAttribute(CopiesDefault.class);
453: if (category.equals(Finishings.class)
454: && printerAttr.containsKey(FinishingsDefault.class))
455: return getPrinterDefaultAttribute(FinishingsDefault.class);
456: if (category.equals(Sides.class)
457: && printerAttr.containsKey(SidesDefault.class))
458: return getPrinterDefaultAttribute(SidesDefault.class);
459: if (category.equals(NumberUp.class)
460: && printerAttr.containsKey(NumberUpDefault.class))
461: return getPrinterDefaultAttribute(NumberUpDefault.class);
462: if (category.equals(OrientationRequested.class)
463: && printerAttr.containsKey(OrientationRequestedDefault.class))
464: return getPrinterDefaultAttribute(OrientationRequestedDefault.class);
465: if (category.equals(Media.class)
466: && printerAttr.containsKey(MediaDefault.class))
467: return getPrinterDefaultAttribute(MediaDefault.class);
468: if (category.equals(PrinterResolution.class)
469: && printerAttr.containsKey(PrinterResolutionDefault.class))
470: return getPrinterDefaultAttribute(PrinterResolutionDefault.class);
471: if (category.equals(PrintQuality.class)
472: && printerAttr.containsKey(PrintQualityDefault.class))
473: return getPrinterDefaultAttribute(PrintQualityDefault.class);
474: if (category.equals(Compression.class)
475: && printerAttr.containsKey(CompressionSupported.class))
476: return Compression.NONE;
477: if (category.equals(PageRanges.class))
478: return new PageRanges(1, Integer.MAX_VALUE);
479:
480: return null;
481: }
482:
483:
487: public String getName()
488: {
489: return name;
490: }
491:
492:
496: public ServiceUIFactory getServiceUIFactory()
497: {
498:
499:
500:
501:
502:
503: return null;
504: }
505:
506:
509: public Class[] getSupportedAttributeCategories()
510: {
511: Set categories = new HashSet();
512:
513:
514: if (printerAttr.containsKey(JobPrioritySupported.class))
515: categories.add(JobPriority.class);
516: if (printerAttr.containsKey(JobHoldUntilSupported.class))
517: categories.add(JobHoldUntil.class);
518: if (printerAttr.containsKey(JobSheetsSupported.class))
519: categories.add(JobSheets.class);
520: if (printerAttr.containsKey(MultipleDocumentHandlingSupported.class))
521: categories.add(MultipleDocumentHandling.class);
522: if (printerAttr.containsKey(CopiesSupported.class))
523: categories.add(Copies.class);
524: if (printerAttr.containsKey(FinishingsSupported.class))
525: {
526:
527: Set set = getPrinterAttributeSet(FinishingsSupported.class);
528: if (! (set.size() == 1 && set.contains(FinishingsSupported.NONE)))
529: categories.add(Finishings.class);
530: }
531: if (printerAttr.containsKey(PageRangesSupported.class))
532: categories.add(PageRanges.class);
533: if (printerAttr.containsKey(SidesSupported.class))
534: categories.add(Sides.class);
535: if (printerAttr.containsKey(NumberUpSupported.class))
536: categories.add(NumberUp.class);
537: if (printerAttr.containsKey(OrientationRequestedSupported.class))
538: categories.add(OrientationRequested.class);
539: if (printerAttr.containsKey(MediaSupported.class))
540: categories.add(Media.class);
541: if (printerAttr.containsKey(PrinterResolutionSupported.class))
542: categories.add(PrinterResolution.class);
543: if (printerAttr.containsKey(PrintQualitySupported.class))
544: categories.add(PrintQuality.class);
545:
546:
547:
548:
549:
550: if (printerAttr.containsKey(CompressionSupported.class))
551: categories.add(Compression.class);
552: if (printerAttr.containsKey(JobImpressionsSupported.class))
553: categories.add(JobImpressions.class);
554: if (printerAttr.containsKey(JobKOctetsSupported.class))
555: categories.add(JobKOctets.class);
556: if (printerAttr.containsKey(JobMediaSheetsSupported.class))
557: categories.add(JobMediaSheets.class);
558:
559:
560: categories.add(Fidelity.class);
561: categories.add(JobName.class);
562: categories.add(RequestingUserName.class);
563:
564: return (Class[]) categories.toArray(new Class[categories.size()]);
565: }
566:
567:
576: public Object getSupportedAttributeValues(Class category, DocFlavor flavor,
577: AttributeSet attributes)
578: {
579:
580:
581:
582: if (category == null)
583: throw new NullPointerException("category may not be null");
584:
585: if (!Attribute.class.isAssignableFrom(category))
586: throw new IllegalArgumentException("category must be of type Attribute");
587:
588: if (flavor != null && !isDocFlavorSupported(flavor))
589: throw new IllegalArgumentException("flavor is not supported");
590:
591: if (!isAttributeCategorySupported(category))
592: return null;
593:
594:
595: if (category.equals(Fidelity.class))
596: return new Fidelity[] { Fidelity.FIDELITY_FALSE, Fidelity.FIDELITY_TRUE };
597: if (category.equals(JobName.class))
598: return JOB_NAME;
599: if (category.equals(RequestingUserName.class))
600: return REQUESTING_USER_NAME;
601:
602:
603: String categoryName = IppUtilities.getSupportedAttrName(category);
604:
605: IppResponse response = null;
606: try
607: {
608: IppRequest request = new IppRequest(printerUri.getURI(), user, passwd);
609: request.setOperationID(
610: (short) OperationsSupported.GET_PRINTER_ATTRIBUTES.getValue());
611: request.setOperationAttributeDefaults();
612: request.addOperationAttribute(new RequestedAttributes(categoryName));
613: request.addOperationAttribute(printerUri);
614:
615: if (flavor != null)
616: {
617: DocumentFormat f = DocumentFormat.createDocumentFormat(flavor);
618: request.addOperationAttribute(f);
619: }
620:
621: response = request.send();
622:
623: int status = response.getStatusCode();
624: if (! (status == IppStatusCode.SUCCESSFUL_OK
625: || status == IppStatusCode.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUED_ATTRIBUTES
626: || status == IppStatusCode.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES) )
627: {
628: logger.log(Component.IPP, "Statuscode not OK - got:" + status);
629: }
630: }
631: catch (IOException e)
632: {
633:
634: logger.log(Component.IPP, "IOException", e);
635: }
636: catch (IppException e)
637: {
638:
639: logger.log(Component.IPP, "IPPException", e);
640: }
641:
642: return handleSupportedAttributeValuesResponse(response, category);
643: }
644:
645:
658: protected Object handleSupportedAttributeValuesResponse(IppResponse response,
659: Class category)
660: {
661: List printerAtts = response.getPrinterAttributes();
662:
663:
664: Map printerAttribute = (Map) printerAtts.get(0);
665: Class suppCategory = IppUtilities.getSupportedCategory(category);
666: Set attr = (Set) printerAttribute.get(suppCategory);
667:
668:
669:
670:
671:
672:
673:
674: if (suppCategory.equals(JobPrioritySupported.class))
675: return (JobPrioritySupported) attr.toArray(new JobPrioritySupported[1])[0];
676: if (suppCategory.equals(JobHoldUntilSupported.class))
677: return new JobHoldUntil(new Date());
678: if (suppCategory.equals(JobSheetsSupported.class))
679: return JobSheetsSupported.getAssociatedAttributeArray(attr);
680: if (suppCategory.equals(MultipleDocumentHandlingSupported.class))
681: return MultipleDocumentHandlingSupported.getAssociatedAttributeArray(attr);
682: if (suppCategory.equals(CopiesSupported.class))
683: return (CopiesSupported) attr.toArray(new CopiesSupported[1])[0];
684: if (suppCategory.equals(FinishingsSupported.class))
685: return FinishingsSupported.getAssociatedAttributeArray(attr);
686: if (suppCategory.equals(PageRangesSupported.class))
687: return new PageRanges[] { new PageRanges(1, Integer.MAX_VALUE) };
688: if (suppCategory.equals(OrientationRequestedSupported.class))
689: return OrientationRequestedSupported.getAssociatedAttributeArray(attr);
690: if (suppCategory.equals(MediaSupported.class))
691: return MediaSupported.getAssociatedAttributeArray(attr);
692: if (suppCategory.equals(PrinterResolutionSupported.class))
693: return PrinterResolutionSupported.getAssociatedAttributeArray(attr);
694: if (suppCategory.equals(PrintQualitySupported.class))
695: return PrintQualitySupported.getAssociatedAttributeArray(attr);
696: if (suppCategory.equals(CompressionSupported.class))
697: return CompressionSupported.getAssociatedAttributeArray(attr);
698:
699: if (suppCategory.equals(NumberUpSupported.class))
700: {
701: NumberUpSupported[] tmp = (NumberUpSupported[])
702: attr.toArray(new NumberUpSupported[attr.size()]);
703:
704: if (attr.size() == 1)
705: return tmp[0];
706:
707: int[][] members = new int[attr.size()][2];
708: for (int j = 0; j < attr.size(); j++)
709: {
710: int value = tmp[j].getMembers()[0][0];
711: members[j] = new int[] { value, value };
712: }
713:
714: NumberUpSupported supported = new NumberUpSupported(members);
715: return supported;
716: }
717:
718: return null;
719: }
720:
721:
724: public DocFlavor[] getSupportedDocFlavors()
725: {
726: return (DocFlavor[]) flavors.toArray(new DocFlavor[flavors.size()]);
727: }
728:
729:
736: public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
737: AttributeSet attributes)
738: {
739: if (flavor != null && !isDocFlavorSupported(flavor))
740: throw new IllegalArgumentException("flavor is not supported");
741:
742: IppResponse response = null;
743: try
744: {
745: IppRequest request = new IppRequest(printerUri.getURI(), user, passwd);
746: short operationId = (short) OperationsSupported.VALIDATE_JOB.getValue();
747: request.setOperationID(operationId);
748: request.setOperationAttributeDefaults();
749: request.addOperationAttribute(printerUri);
750: request.addOperationAttribute(Fidelity.FIDELITY_TRUE);
751:
752: if (attributes != null && attributes.size() > 0)
753: {
754: request.addAndFilterJobOperationAttributes(attributes);
755: request.addAndFilterJobTemplateAttributes(attributes);
756: }
757:
758: if (flavor != null)
759: {
760: DocumentFormat f = DocumentFormat.createDocumentFormat(flavor);
761: request.addOperationAttribute(f);
762: }
763:
764: response = request.send();
765:
766: int status = response.getStatusCode();
767: if (! (status == IppStatusCode.SUCCESSFUL_OK
768: || status == IppStatusCode.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUED_ATTRIBUTES
769: || status == IppStatusCode.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES) )
770: {
771: logger.log(Component.IPP, "Statuscode not OK - got:" + status);
772: }
773: }
774: catch (IOException e)
775: {
776:
777: logger.log(Component.IPP, "IOException", e);
778: }
779: catch (IppException e)
780: {
781:
782: logger.log(Component.IPP, "IPPException", e);
783: }
784:
785:
786: List unsupportedMaps = response.getUnsupportedAttributes();
787: if (unsupportedMaps.size() == 0)
788: return null;
789:
790: Map unsupportedAttr = (Map) unsupportedMaps.get(0);
791: if (unsupportedAttr.size() == 0)
792: return null;
793:
794:
795:
796: HashAttributeSet set = new HashAttributeSet();
797: Iterator it = unsupportedAttr.values().iterator();
798: while (it.hasNext())
799: {
800: Set unsupported = (Set) it.next();
801: Iterator it2 = unsupported.iterator();
802: while (it2.hasNext())
803: set.add((Attribute) it2.next());
804: }
805:
806: return set;
807: }
808:
809:
812: public boolean isAttributeCategorySupported(Class category)
813: {
814: if (category == null)
815: throw new NullPointerException("category may not be null");
816:
817: if (! Attribute.class.isAssignableFrom(category))
818: throw new IllegalArgumentException("category must be of type Attribute");
819:
820: return Arrays.asList(getSupportedAttributeCategories()).contains(category);
821: }
822:
823:
826: public boolean isAttributeValueSupported(Attribute attrval, DocFlavor flavor,
827: AttributeSet attributes)
828: {
829:
830: Object values = getSupportedAttributeValues(attrval.getCategory(),
831: flavor, attributes);
832:
833: if (values == null)
834: return false;
835:
836:
837: if (values.getClass().isArray())
838: return Arrays.asList((Object[]) values).contains(attrval);
839:
840:
841: if (values.getClass().equals(attrval.getCategory()))
842: return true;
843:
844:
845:
846: if (values.getClass().equals(CopiesSupported.class))
847: return ((CopiesSupported) values).contains((IntegerSyntax) attrval);
848:
849: if (values.getClass().equals(NumberUpSupported.class))
850: return ((NumberUpSupported) values).contains((IntegerSyntax) attrval);
851:
852: if (values.getClass().equals(JobPrioritySupported.class))
853: {
854: JobPriority priority = (JobPriority) attrval;
855: JobPrioritySupported maxSupported = (JobPrioritySupported) values;
856: if (priority.getValue() < maxSupported.getValue())
857: return true;
858: }
859:
860:
861:
862:
863:
864: return false;
865: }
866:
867:
868:
871: public boolean isDocFlavorSupported(DocFlavor flavor)
872: {
873: if (flavor == null)
874: throw new NullPointerException("DocFlavor may not be null.");
875:
876: return flavors.contains(flavor);
877: }
878:
879:
880:
883: public void addPrintServiceAttributeListener(
884: PrintServiceAttributeListener listener)
885: {
886: printServiceAttributeListener.add(listener);
887: }
888:
889:
892: public void removePrintServiceAttributeListener(
893: PrintServiceAttributeListener listener)
894: {
895: printServiceAttributeListener.remove(listener);
896: }
897:
898:
902: public String toString()
903: {
904: return "IppPrinter: " + getName();
905: }
906:
907:
912: public PrinterURI getPrinterURI()
913: {
914: return printerUri;
915: }
916: }