1 package com
.google
.code
.jspi
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.lang
.reflect
.Constructor
;
7 import java
.lang
.reflect
.Field
;
8 import java
.lang
.reflect
.InvocationTargetException
;
10 import java
.net
.URISyntaxException
;
11 import java
.text
.DateFormat
;
12 import java
.text
.DecimalFormat
;
13 import java
.text
.ParseException
;
14 import java
.text
.SimpleDateFormat
;
15 import java
.util
.Date
;
16 import java
.util
.HashMap
;
17 import java
.util
.HashSet
;
18 import java
.util
.Locale
;
21 import java
.util
.logging
.Level
;
22 import java
.util
.logging
.Logger
;
24 import javax
.print
.attribute
.Attribute
;
25 import javax
.print
.attribute
.EnumSyntax
;
27 import de
.lohndirekt
.print
.attribute
.AttributeWriter
;
28 import de
.lohndirekt
.print
.attribute
.IppAttributeName
;
29 import de
.lohndirekt
.print
.attribute
.IppDelimiterTag
;
30 import de
.lohndirekt
.print
.attribute
.IppValueTag
;
31 import de
.lohndirekt
.print
.attribute
.ipp
.Charset
;
32 import de
.lohndirekt
.print
.exception
.EndOfAttributesException
;
38 public final class AttributeParser
{
40 private final static EndOfAttributesException END_OF_ATTRIBUTES_EXCEPTION
= new EndOfAttributesException();
42 private final static Logger log
= Logger
.getLogger(AttributeParser
.class.getName());
51 private static Attribute
getAttribute(String name
, Object
[] values
) {
52 Attribute attribute
= null;
53 IppAttributeName attrName
= IppAttributeName
.get(name
);
54 Class attrClass
= attrName
.getAttributeClass();
55 Class superClass
= attrClass
.getSuperclass();
56 if (superClass
!= null) {
57 if (superClass
.equals(EnumSyntax
.class)) {
59 Field
[] fields
= attrClass
.getDeclaredFields();
60 for (int i
= 0; i
< fields
.length
; i
++) {
61 Field field
= fields
[i
];
62 if (field
.getType().equals(attrClass
)) {
63 EnumSyntax attr
= (EnumSyntax
) field
.get(null);
64 if (values
[0] instanceof String
) {
65 if (attr
.toString().equals(values
[0])) {
66 attribute
= (Attribute
) attr
;
70 if (attr
.getValue() == ((Integer
) values
[0]).intValue()) {
71 attribute
= (Attribute
) attr
;
77 } catch (SecurityException e
) {
78 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
79 } catch (IllegalArgumentException e
) {
80 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
81 } catch (IllegalAccessException e
) {
82 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
86 Class
[] parameters
= toClassArray(values
);
88 Constructor constructor
= attrClass
.getDeclaredConstructor(parameters
);
89 attribute
= (Attribute
) constructor
.newInstance(values
);
90 } catch (SecurityException e
) {
91 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
92 } catch (NoSuchMethodException e
) {
93 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
94 } catch (IllegalArgumentException e
) {
95 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
96 } catch (InstantiationException e
) {
97 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
98 } catch (IllegalAccessException e
) {
99 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
100 } catch (InvocationTargetException e
) {
101 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
112 * @param lastAttribute
115 private static Attribute
parseAttribute(InputStream in
, Attribute lastAttribute
)
116 throws IOException
, EndOfAttributesException
{
119 while ((valueTag
= in
.read()) < IppValueTag
.UNSUPPORTED_VALUE
.getValue()) {
120 if (valueTag
== IppDelimiterTag
.END_ATTRIBUTES
.getValue()) {
121 throw END_OF_ATTRIBUTES_EXCEPTION
;
125 int nameLength
= parseInt2(in
);
126 // parse the Attribute-Name
128 if (nameLength
== 0) {
129 name
= lastAttribute
.getName();
131 name
= parseString(in
, nameLength
);
135 Object
[] values
= parseValues(valueTag
, in
);
137 return getAttribute(name
, values
);
140 private static String
parseString(InputStream in
, int nameLength
) throws IOException
{
141 return parseString(in
, nameLength
, Charset
.US_ASCII
.getValue());
144 private static String
parseNameAndTextString(InputStream in
, int nameLength
) throws IOException
{
145 return parseString(in
, nameLength
, AttributeWriter
.DEFAULT_CHARSET
.getValue());
152 private static String
parseString(InputStream in
, int nameLength
, String charsetName
) throws IOException
{
153 byte[] bytes
= new byte[nameLength
];
155 return new String(bytes
, charsetName
);
167 private static Date
parseDate(InputStream in
) throws IOException
{
168 DecimalFormat twoDigits
= new DecimalFormat("00");
169 DecimalFormat threeDigits
= new DecimalFormat("000");
170 DecimalFormat fourDigits
= new DecimalFormat("0000");
171 //year is encoded in network-byte order
172 int year
= parseInt2(in
);
173 int month
= in
.read();
175 int hour
= in
.read();
176 int minute
= in
.read();
177 int second
= in
.read();
178 int deci
= in
.read();
179 int mili
= deci
* 100;
180 char direction
= (char) in
.read();
181 int hoursFromUtc
= in
.read();
182 int minutesFromUtc
= in
.read();
184 String yearString
= fourDigits
.format(year
);
185 String monthString
= twoDigits
.format(month
);
186 String dayString
= twoDigits
.format(day
);
187 String hourString
= twoDigits
.format(hour
);
188 String minuteString
= twoDigits
.format(minute
);
189 String secondString
= twoDigits
.format(second
);
190 String miliString
= threeDigits
.format(mili
);
191 String timeZone
= direction
+ twoDigits
.format(hoursFromUtc
) + twoDigits
.format(minutesFromUtc
);
207 DateFormat dateFormat
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSSZ");
210 date
= dateFormat
.parse(dateString
);
211 } catch (ParseException e
) {
212 log
.log(Level
.SEVERE
, e
.getMessage(), e
);
217 private static int parseInt4(InputStream in
) throws IOException
{
219 //Same parsing as in java.io.DataInput readInt()
224 int value
= (((a
& 0xff) << 24) | ((b
& 0xff) << 16) | ((c
& 0xff) << 8) | (d
& 0xff));
233 private static int parseInt4(byte[] bytes
, int offset
) {
235 //Same parsing as in java.io.DataInput readInt()
236 byte a
= bytes
[offset
++];
237 byte b
= bytes
[offset
++];
238 byte c
= bytes
[offset
++];
239 byte d
= bytes
[offset
++];
240 int value
= (((a
& 0xff) << 24) | ((b
& 0xff) << 16) | ((c
& 0xff) << 8) | (d
& 0xff));
244 private static int parseInt2(InputStream in
) throws IOException
{
246 //Same parsing as in java.io.DataInput readInt()
249 int value
= ((a
& 0xff) << 8) | ((b
& 0xff));
255 * @return map of attributes (key -> category, value -> Set with attributes)
259 public static Map
parseRequest(InputStream response
) throws IOException
{
260 Map attributes
= new HashMap();
261 long start
= System
.currentTimeMillis();
262 Attribute lastAttribute
= null;
263 boolean finished
= false;
267 Attribute attribute
= null;
269 attribute
= parseAttribute(response
, lastAttribute
);
270 if (attribute
!= null) {
271 lastAttribute
= attribute
;
272 attributes
= put(attributes
, attribute
);
273 if (log
.isLoggable(Level
.FINEST
)) {
274 log
.finest("parsed attribute(" + attribute
.getName() + "): " + attribute
.toString());
277 if (log
.isLoggable(Level
.FINEST
)) {
279 log
.finest("Attribute was null");
282 } catch (EndOfAttributesException e
) {
285 if (log
.isLoggable(Level
.INFO
)) {
286 log
.info("--- Attribute parsing finished ---");
290 long end
= System
.currentTimeMillis();
291 if (log
.isLoggable(Level
.INFO
)) {
292 log
.info("Parsing took " + (end
- start
) + "ms.");
304 private static URI
parseUri(InputStream in
, int valueLength
) throws IOException
{
305 String uriString
= parseString(in
, valueLength
);
308 uri
= new URI(uriString
);
309 } catch (URISyntaxException e
) {
310 throw new RuntimeException(e
);
323 private static Object
[] parseValues(int valueTag
, InputStream in
) throws IOException
{
324 int valueLength
= parseInt2(in
);
325 Object
[] values
= null;
326 if (valueTag
== IppValueTag
.INTEGER
.getValue() || valueTag
== IppValueTag
.ENUM
.getValue()) {
327 Integer number
= new Integer(parseInt4(in
));
328 values
= new Object
[] { number
};
330 valueTag
== IppValueTag
.STRING
.getValue()
331 || valueTag
== IppValueTag
.TEXT
.getValue()
332 || valueTag
== IppValueTag
.NAME
.getValue()){
333 String word
= parseNameAndTextString(in
, valueLength
);
334 values
= new Object
[] { word
, Locale
.getDefault()};
336 valueTag
== IppValueTag
.CHARSET
.getValue()
337 || valueTag
== IppValueTag
.LANGUAGE
.getValue()
338 || valueTag
== IppValueTag
.MIMETYPE
.getValue()) {
339 String word
= parseString(in
, valueLength
);
340 values
= new Object
[] { word
, Locale
.getDefault()};
341 } else if (valueTag
== IppValueTag
.URI
.getValue()) {
342 URI uri
= parseUri(in
, valueLength
);
343 values
= new Object
[] { uri
};
344 } else if (valueTag
== IppValueTag
.KEYWORD
.getValue()) {
345 String word
= parseString(in
, valueLength
);
346 values
= new Object
[] { word
, Locale
.getDefault()};
347 } else if (valueTag
== IppValueTag
.BOOLEAN
.getValue()) {
348 Integer bool
= new Integer(in
.read());
349 values
= new Object
[] { bool
};
350 } else if (valueTag
== IppValueTag
.RANGE
.getValue()) {
351 Integer lowerBound
= new Integer(parseInt4(in
));
352 Integer upperBound
= new Integer(parseInt4(in
));
353 values
= new Object
[] { lowerBound
, upperBound
};
354 } else if (valueTag
== IppValueTag
.DATE
.getValue()) {
356 Date date
= parseDate(in
);
357 values
= new Object
[] { date
};
358 } else if (valueTag
== IppValueTag
.NOVALUE
.getValue()) {
359 values
= new Object
[] {
362 throw new IllegalArgumentException("\"" + Integer
.toHexString(valueTag
) + "\" is not a valid value-tag");
372 private static Map
put(Map attributes
, Attribute attribute
) {
373 Set values
= (Set
) attributes
.get(attribute
.getCategory());
374 if (values
== null) {
375 values
= new HashSet();
376 attributes
.put(attribute
.getCategory(), values
);
378 values
.add(attribute
);
386 private static Class
[] toClassArray(Object
[] values
) {
387 Class
[] classes
= new Class
[values
.length
];
388 for (int i
= 0; i
< values
.length
; i
++) {
389 Class clazz
= values
[i
].getClass();
390 if (clazz
.equals(Integer
.class)) {