1 /* IppUtilities.java --
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.javax.print.ipp;
41 import gnu.javax.print.ipp.attribute.DetailedStatusMessage;
42 import gnu.javax.print.ipp.attribute.DocumentAccessError;
43 import gnu.javax.print.ipp.attribute.StatusMessage;
44 import gnu.javax.print.ipp.attribute.defaults.CopiesDefault;
45 import gnu.javax.print.ipp.attribute.defaults.FinishingsDefault;
46 import gnu.javax.print.ipp.attribute.defaults.JobHoldUntilDefault;
47 import gnu.javax.print.ipp.attribute.defaults.JobPriorityDefault;
48 import gnu.javax.print.ipp.attribute.defaults.JobSheetsDefault;
49 import gnu.javax.print.ipp.attribute.defaults.MediaDefault;
50 import gnu.javax.print.ipp.attribute.defaults.MultipleDocumentHandlingDefault;
51 import gnu.javax.print.ipp.attribute.defaults.NumberUpDefault;
52 import gnu.javax.print.ipp.attribute.defaults.OrientationRequestedDefault;
53 import gnu.javax.print.ipp.attribute.defaults.PrintQualityDefault;
54 import gnu.javax.print.ipp.attribute.defaults.SidesDefault;
55 import gnu.javax.print.ipp.attribute.job.JobDetailedStatusMessages;
56 import gnu.javax.print.ipp.attribute.job.JobDocumentAccessErrors;
57 import gnu.javax.print.ipp.attribute.job.JobId;
58 import gnu.javax.print.ipp.attribute.job.JobStateMessage;
59 import gnu.javax.print.ipp.attribute.printer.MultipleOperationTimeOut;
60 import gnu.javax.print.ipp.attribute.printer.PrinterStateMessage;
61 import gnu.javax.print.ipp.attribute.printer.PrinterUpTime;
62 import gnu.javax.print.ipp.attribute.supported.CompressionSupported;
63 import gnu.javax.print.ipp.attribute.supported.FinishingsSupported;
64 import gnu.javax.print.ipp.attribute.supported.IppVersionsSupported;
65 import gnu.javax.print.ipp.attribute.supported.JobHoldUntilSupported;
66 import gnu.javax.print.ipp.attribute.supported.JobSheetsSupported;
67 import gnu.javax.print.ipp.attribute.supported.MediaSupported;
68 import gnu.javax.print.ipp.attribute.supported.MultipleDocumentHandlingSupported;
69 import gnu.javax.print.ipp.attribute.supported.MultipleDocumentJobsSupported;
70 import gnu.javax.print.ipp.attribute.supported.OperationsSupported;
71 import gnu.javax.print.ipp.attribute.supported.OrientationRequestedSupported;
72 import gnu.javax.print.ipp.attribute.supported.PageRangesSupported;
73 import gnu.javax.print.ipp.attribute.supported.PrintQualitySupported;
74 import gnu.javax.print.ipp.attribute.supported.PrinterResolutionSupported;
75 import gnu.javax.print.ipp.attribute.supported.SidesSupported;
76 import gnu.javax.print.ipp.attribute.supported.UriAuthenticationSupported;
77 import gnu.javax.print.ipp.attribute.supported.UriSecuritySupported;
79 import java.lang.reflect.Constructor;
80 import java.lang.reflect.Field;
81 import java.lang.reflect.InvocationTargetException;
82 import java.util.HashMap;
83 import java.util.Locale;
85 import javax.print.attribute.Attribute;
86 import javax.print.attribute.EnumSyntax;
87 import javax.print.attribute.SupportedValuesAttribute;
88 import javax.print.attribute.standard.Chromaticity;
89 import javax.print.attribute.standard.ColorSupported;
90 import javax.print.attribute.standard.Compression;
91 import javax.print.attribute.standard.Copies;
92 import javax.print.attribute.standard.CopiesSupported;
93 import javax.print.attribute.standard.Fidelity;
94 import javax.print.attribute.standard.Finishings;
95 import javax.print.attribute.standard.JobHoldUntil;
96 import javax.print.attribute.standard.JobImpressionsCompleted;
97 import javax.print.attribute.standard.JobKOctetsProcessed;
98 import javax.print.attribute.standard.JobMediaSheetsCompleted;
99 import javax.print.attribute.standard.JobMessageFromOperator;
100 import javax.print.attribute.standard.JobName;
101 import javax.print.attribute.standard.JobOriginatingUserName;
102 import javax.print.attribute.standard.JobPriority;
103 import javax.print.attribute.standard.JobPrioritySupported;
104 import javax.print.attribute.standard.JobSheets;
105 import javax.print.attribute.standard.JobState;
106 import javax.print.attribute.standard.JobStateReason;
107 import javax.print.attribute.standard.Media;
108 import javax.print.attribute.standard.MediaSizeName;
109 import javax.print.attribute.standard.MultipleDocumentHandling;
110 import javax.print.attribute.standard.NumberOfInterveningJobs;
111 import javax.print.attribute.standard.NumberUp;
112 import javax.print.attribute.standard.NumberUpSupported;
113 import javax.print.attribute.standard.OrientationRequested;
114 import javax.print.attribute.standard.OutputDeviceAssigned;
115 import javax.print.attribute.standard.PDLOverrideSupported;
116 import javax.print.attribute.standard.PageRanges;
117 import javax.print.attribute.standard.PagesPerMinute;
118 import javax.print.attribute.standard.PagesPerMinuteColor;
119 import javax.print.attribute.standard.PresentationDirection;
120 import javax.print.attribute.standard.PrintQuality;
121 import javax.print.attribute.standard.PrinterInfo;
122 import javax.print.attribute.standard.PrinterIsAcceptingJobs;
123 import javax.print.attribute.standard.PrinterLocation;
124 import javax.print.attribute.standard.PrinterMakeAndModel;
125 import javax.print.attribute.standard.PrinterMessageFromOperator;
126 import javax.print.attribute.standard.PrinterName;
127 import javax.print.attribute.standard.PrinterResolution;
128 import javax.print.attribute.standard.PrinterState;
129 import javax.print.attribute.standard.PrinterStateReason;
130 import javax.print.attribute.standard.QueuedJobCount;
131 import javax.print.attribute.standard.ReferenceUriSchemesSupported;
132 import javax.print.attribute.standard.Severity;
133 import javax.print.attribute.standard.SheetCollate;
134 import javax.print.attribute.standard.Sides;
137 * Collection of static utilities methods used in
138 * IPP response parsing and all over the place.
140 * Also provides mapping from the attribute name values to
141 * the actual class object. Used to construct objects via reflection.
144 * @author Wolfgang Baer (WBaer@gmx.de)
146 public final class IppUtilities
148 // These are reused in the reflection code to not instantiate an array everytime
149 private static Object[] INTEGER_ATT_VALUE = new Object[1];
150 private static Class[] INTEGER_CLASS_ARRAY = new Class[] {int.class};
151 private static Object[] TEXT_ATT_VALUE = new Object[2];
152 private static Class[] TEXT_CLASS_ARRAY = new Class[] {String.class, Locale.class};
154 // The map -> Attribute name to Attribute class
155 private static HashMap classesByName = new HashMap();
156 // The map -> StandardAttribute class to SupportedAttribute category name
157 private static HashMap instanceByClass = new HashMap();
160 * All the currently needed attributes
165 classesByName.put(JobState.ABORTED.getName(), JobState.class);
166 classesByName.put(Sides.DUPLEX.getName(), Sides.class);
167 classesByName.put(SheetCollate.COLLATED.getName(), SheetCollate.class);
168 classesByName.put(Severity.ERROR.getName(), Severity.class);
169 classesByName.put(JobSheets.NONE.getName(), JobSheets.class);
170 classesByName.put(Finishings.BIND.getName(), Finishings.class);
171 classesByName.put(Fidelity.FIDELITY_FALSE.getName(), Fidelity.class);
172 classesByName.put(Compression.GZIP.getName(), Compression.class);
173 classesByName.put(Chromaticity.COLOR.getName(), Chromaticity.class);
174 classesByName.put(PrintQuality.DRAFT.getName(), PrintQuality.class);
175 classesByName.put(PrinterState.IDLE.getName(), PrinterState.class);
176 classesByName.put(SidesDefault.ONE_SIDED.getName(), SidesDefault.class);
177 classesByName.put(ReferenceUriSchemesSupported.FILE.getName(),
178 ReferenceUriSchemesSupported.class);
179 classesByName.put(PrinterStateReason.DOOR_OPEN.getName(),
180 PrinterStateReason.class);
181 classesByName.put(PresentationDirection.TOLEFT_TOTOP.getName(),
182 PresentationDirection.class);
183 classesByName.put(PDLOverrideSupported.ATTEMPTED.getName(),
184 PDLOverrideSupported.class);
185 classesByName.put(OrientationRequested.PORTRAIT.getName(),
186 OrientationRequested.class);
187 classesByName.put(MultipleDocumentHandling.SINGLE_DOCUMENT.getName(),
188 MultipleDocumentHandling.class);
189 classesByName.put(JobStateReason.JOB_QUEUED.getName(),
190 JobStateReason.class);
191 classesByName.put(UriAuthenticationSupported.NONE.getName(),
192 UriAuthenticationSupported.class);
193 classesByName.put(OperationsSupported.GET_JOBS.getName(),
194 OperationsSupported.class);
195 classesByName.put(UriSecuritySupported.NONE.getName(),
196 UriSecuritySupported.class);
197 classesByName.put(FinishingsSupported.NONE.getName(),
198 FinishingsSupported.class);
199 classesByName.put(FinishingsDefault.NONE.getName(),
200 FinishingsDefault.class);
201 classesByName.put(IppVersionsSupported.V_1_0.getName(),
202 IppVersionsSupported.class);
203 classesByName.put(MultipleDocumentHandlingSupported.SINGLE_DOCUMENT.getName(),
204 MultipleDocumentHandlingSupported.class);
205 classesByName.put(MultipleDocumentHandlingDefault.SINGLE_DOCUMENT.getName(),
206 MultipleDocumentHandlingDefault.class);
207 classesByName.put(CompressionSupported.NONE.getName(),
208 CompressionSupported.class);
209 classesByName.put(OrientationRequestedSupported.PORTRAIT.getName(),
210 OrientationRequestedSupported.class);
211 classesByName.put(OrientationRequestedDefault.PORTRAIT.getName(),
212 OrientationRequestedDefault.class);
213 classesByName.put(SidesSupported.ONE_SIDED.getName(),
214 SidesSupported.class);
215 classesByName.put(PrintQualityDefault.DRAFT.getName(),
216 PrintQualityDefault.class);
217 classesByName.put(PrintQualitySupported.DRAFT.getName(),
218 PrintQualitySupported.class);
219 classesByName.put(ReferenceUriSchemesSupported.FTP.getName(),
220 ReferenceUriSchemesSupported.class);
223 classesByName.put(ColorSupported.SUPPORTED.getName(), ColorSupported.class);
224 classesByName.put(PrinterIsAcceptingJobs.ACCEPTING_JOBS.getName(),
225 PrinterIsAcceptingJobs.class);
226 classesByName.put(MultipleDocumentJobsSupported.SUPPORTED.getName(),
227 MultipleDocumentJobsSupported.class);
228 classesByName.put(PageRangesSupported.SUPPORTED.getName(),
229 PageRangesSupported.class);
231 // TextSyntax derived attributes
232 classesByName.put("media-default", MediaDefault.class);
233 classesByName.put("media-supported", MediaSupported.class);
234 classesByName.put("media", MediaSizeName.class);
235 classesByName.put("printer-location", PrinterLocation.class);
236 classesByName.put("printer-info", PrinterInfo.class);
237 classesByName.put("printer-make-and-model", PrinterMakeAndModel.class);
238 classesByName.put("printer-state-message", PrinterStateMessage.class);
239 classesByName.put("job-state-message", JobStateMessage.class);
240 classesByName.put("job-sheets-default", JobSheetsDefault.class);
241 classesByName.put("job-sheets-supported", JobSheetsSupported.class);
242 classesByName.put("job-name", JobName.class);
243 classesByName.put("printer-name", PrinterName.class);
244 classesByName.put("status-message", StatusMessage.class);
245 classesByName.put("detailed-status-message", DetailedStatusMessage.class);
246 classesByName.put("document-access-error", DocumentAccessError.class);
247 classesByName.put("output-device-assigned", OutputDeviceAssigned.class);
248 classesByName.put("job-hold-until-default", JobHoldUntilDefault.class);
249 classesByName.put("job-originating-user-name",
250 JobOriginatingUserName.class);
251 classesByName.put("job-hold-until-supported",
252 JobHoldUntilSupported.class);
253 classesByName.put("job-message-from-operator",
254 JobMessageFromOperator.class);
255 classesByName.put("printer-message-from-operator",
256 PrinterMessageFromOperator.class);
257 classesByName.put("job-detailed-status-messages",
258 JobDetailedStatusMessages.class);
259 classesByName.put("job-document-access-errors",
260 JobDocumentAccessErrors.class);
262 // IntegerSyntax derived Attributes
263 classesByName.put("copies-default", CopiesDefault.class);
264 classesByName.put("job-id", JobId.class);
265 classesByName.put("job-priority-supported", JobPrioritySupported.class);
266 classesByName.put("job-priority-default", JobPriorityDefault.class);
267 classesByName.put("number-up-supported", NumberUpSupported.class);
268 classesByName.put("number-up-default", NumberUpDefault.class);
269 classesByName.put("queued-job-count", QueuedJobCount.class);
270 classesByName.put("printer-up-time", PrinterUpTime.class);
271 classesByName.put("pages-per-minute", PagesPerMinute.class);
272 classesByName.put("pages-per-minute-color", PagesPerMinuteColor.class);
273 classesByName.put("job-k-octets-processed", JobKOctetsProcessed.class);
274 classesByName.put("number-of-intervening-jobs",
275 NumberOfInterveningJobs.class);
276 classesByName.put("job-impressions-completed",
277 JobImpressionsCompleted.class);
278 classesByName.put("job-media-sheets-completed",
279 JobMediaSheetsCompleted.class);
280 classesByName.put("multiple-operation-time-out",
281 MultipleOperationTimeOut.class);
284 // 4.2 job template attributes
285 instanceByClass.put(JobPriority.class, new JobPrioritySupported(1));
286 instanceByClass.put(JobHoldUntil.class, new JobHoldUntilSupported("", null));
287 instanceByClass.put(JobSheets.class, new JobSheetsSupported("", null));
288 instanceByClass.put(MultipleDocumentHandling.class, MultipleDocumentHandlingSupported.SINGLE_DOCUMENT);
289 instanceByClass.put(Copies.class, new CopiesSupported(1));
290 instanceByClass.put(Finishings.class, FinishingsSupported.BIND);
291 instanceByClass.put(PageRanges.class, PageRangesSupported.SUPPORTED);
292 instanceByClass.put(Sides.class, SidesSupported.DUPLEX);
293 instanceByClass.put(NumberUp.class, new NumberUpSupported(1));
294 instanceByClass.put(OrientationRequested.class, OrientationRequestedSupported.LANDSCAPE);
295 instanceByClass.put(Media.class, new MediaSupported("", null));
296 instanceByClass.put(PrinterResolution.class, new PrinterResolutionSupported(1,1,1));
297 instanceByClass.put(PrintQuality.class, PrintQualitySupported.DRAFT);
299 // 4.4 printer attributes
300 instanceByClass.put(Compression.class, CompressionSupported.COMPRESS);
303 private IppUtilities()
305 // not to be instantiated
309 * Returns the implementing class object for given
310 * attribute name objects.
312 * @param name the attribute name
313 * @return The <code>Class</code> object.
315 public static Class getClass(String name)
317 return (Class) classesByName.get(name);
321 * Returns the name of the supported attribute
322 * based on the given standard attribute category.
324 * @param clazz the standard attribute category
325 * @return The name of the supported attribute category.
327 public static String getSupportedAttrName(Class clazz)
329 return ((SupportedValuesAttribute) instanceByClass.get(clazz)).getName();
333 * Returns the category of the supported attribute
334 * based on the given standard attribute category.
336 * @param clazz the standard attribute category
337 * @return The supported attribute category.
339 public static Class getSupportedCategory(Class clazz)
341 return ((SupportedValuesAttribute) instanceByClass.get(clazz)).getCategory();
345 * Helper method to convert to an int.
346 * @param b the byte array
347 * @return The converted int.
349 public static int convertToInt(byte[] b)
351 return (((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16)
352 | ((b[2] & 0xff) << 8) | (b[3] & 0xff));
356 * Helper method to convert to an int.
357 * @param b1 the 1th byte
358 * @param b2 the 2th byte
359 * @param b3 the 3th byte
360 * @param b4 the 4th byte
361 * @return The converted int.
363 public static int convertToInt(byte b1, byte b2, byte b3, byte b4)
365 return (((b1 & 0xff) << 24) | ((b2 & 0xff) << 16)
366 | ((b3 & 0xff) << 8) | (b4 & 0xff));
370 * Helper method to convert to a short.
371 * @param b1 the 1th byte
372 * @param b2 the 2th byte
373 * @return The converted short.
375 public static short convertToShort(byte b1, byte b2)
377 return (short) ((b1 << 8) | (b2 & 0xff));
381 * Instantiates an <code>EnumSyntax</code> based attribute with the given IPP
382 * name and the given value (Enums maybe int or String based).
384 * @param name the attribute name of the subclass.
385 * @param value the integer value of the specific enum.
386 * @return The Attribute (a subclass of EnumSyntax)
388 public static Attribute getEnumAttribute(String name, Object value)
390 Class attrClass = getClass(name);
392 // There might be unknown enums we have no mapped class for
393 if (attrClass == null)
398 Field[] fields = attrClass.getDeclaredFields();
399 for (int i = 0; i < fields.length; i++)
401 Field field = fields[i];
402 if (field.getType().equals(attrClass))
404 EnumSyntax attr = (EnumSyntax) field.get(null);
405 if (value instanceof Integer
406 && attr.getValue() == ((Integer) value).intValue())
407 return (Attribute) attr;
408 else if (value instanceof String
409 && attr.toString().equals(value))
410 return (Attribute) attr;
414 catch (SecurityException e)
418 catch (IllegalArgumentException e)
422 catch (IllegalAccessException e)
424 // should not happen, all fields are public
433 * Instantiates an <code>IntegerSyntax</code> based attribute with the
434 * given IPP name for the given int value.
436 * @param name the attribute name of the subclass.
437 * @param value the integer value
438 * @return The Attribute (a subclass of IntegerSyntax)
440 public static Attribute getIntegerAttribute(String name, int value)
442 Class attrClass = getClass(name);
444 // There might be unknown attributes we have no mapped class for
445 if (attrClass == null)
450 INTEGER_ATT_VALUE[0] = new Integer(value);
451 Constructor c = attrClass.getDeclaredConstructor(INTEGER_CLASS_ARRAY);
452 return (Attribute) c.newInstance(INTEGER_ATT_VALUE);
454 catch (SecurityException e)
458 catch (NoSuchMethodException e)
462 catch (IllegalAccessException e)
464 // should not happen, all fields are public
466 catch (InstantiationException e)
468 // should not happen, all fields are public
470 catch (InvocationTargetException e)
472 // should not happen, all fields are public
479 * Instantiates an <code>TextSyntax</code> based attribute with the given
480 * IPP name for the given text value (will be decoded).
482 * @param name the attribute name of the subclass.
483 * @param tag the tag defined in {@link IppValueTag}
484 * @param value the byte[] value to be decoded based on the tag value.
485 * @return The Attribute (a subclass of TextSyntax)
487 public static Attribute getTextAttribute(String name, byte tag, byte[] value)
489 // without language tag is rather easy - default locale
490 if (tag == IppValueTag.NAME_WITHOUT_LANGUAGE
491 || tag == IppValueTag.TEXT_WITHOUT_LANGUAGE)
493 TEXT_ATT_VALUE[0] = new String(value);
494 TEXT_ATT_VALUE[1] = Locale.getDefault();
498 short langLength = convertToShort(value[0], value[1]);
499 byte[] tmp = new byte[langLength];
500 byte[] tmp2 = new byte[value.length - 4 - langLength];
501 System.arraycopy(value, 2, tmp, 0, langLength);
503 // parse into language/region
504 String language = new String(tmp);
505 String text = new String(tmp2);
506 Locale locale = null;
508 if (language.length() > 2)
509 locale = new Locale(language.substring(0, 2), language.substring(3));
511 locale = new Locale(language);
513 TEXT_ATT_VALUE[0] = text;
514 TEXT_ATT_VALUE[1] = locale;
517 Class attrClass = getClass(name);
519 // There might be unknown attributes we have no mapped class for
520 if (attrClass == null)
525 Constructor c = attrClass.getDeclaredConstructor(TEXT_CLASS_ARRAY);
526 return (Attribute) c.newInstance(TEXT_ATT_VALUE);
528 catch (SecurityException e)
532 catch (NoSuchMethodException e)
536 catch (IllegalAccessException e)
538 // should not happen, all fields are public
540 catch (InstantiationException e)
542 // should not happen, all fields are public
544 catch (InvocationTargetException e)
546 // should not happen, all fields are public