001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor A. Pyankov
019: * @version $Revision: 1.2 $
020: */package org.apache.harmony.x.print.ipp;
021:
022: import java.io.ByteArrayInputStream;
023: import java.io.ByteArrayOutputStream;
024: import java.io.DataInputStream;
025: import java.io.DataOutputStream;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.io.Reader;
029: import java.net.URL;
030: import java.util.Iterator;
031: import java.util.Vector;
032:
033: /**
034: * This class represents request encoding
035: * described in RFC 2910 (http://ietf.org/rfc/rfc2910.txt?number=2910)
036: */
037:
038: /*
039: *
040: * <pre>
041: *
042: *
043: * An operation request or response is encoded as follows:
044: *
045: * -----------------------------------------------
046: * | version-number | 2 bytes - required
047: * -----------------------------------------------
048: * | operation-id (request) |
049: * | or | 2 bytes - required
050: * | status-code (response) |
051: * -----------------------------------------------
052: * | request-id | 4 bytes - required
053: * -----------------------------------------------
054: * | attribute-group | n bytes - 0 or more
055: * -----------------------------------------------
056: * | end-of-attributes-tag | 1 byte - required
057: * -----------------------------------------------
058: * | data | q bytes - optional
059: * -----------------------------------------------
060: *
061: *
062: * </pre>
063: */
064: public class IppRequest {
065: static int requestcount;
066:
067: static protected void sortAttributes(Vector vaa) {
068: IppAttributeGroup g1, g2;
069: boolean the_end = false;
070:
071: while (!the_end) {
072: the_end = true;
073: for (int ii = vaa.size(), i = 0; i < (ii - 1); i++) {
074: g1 = (IppAttributeGroup) vaa.get(i);
075: g2 = (IppAttributeGroup) vaa.get(i + 1);
076: if (g1.agroupid > g2.agroupid) {
077: the_end = false;
078: vaa.set(i, g2);
079: vaa.set(i + 1, g1);
080: }
081: }
082: }
083: }
084:
085: protected byte[] ippversion = { 1, 1 };
086: protected short operationid;
087: protected int requestid;
088: protected IppAttributeGroupSet agroups;
089: protected Object document;
090:
091: public IppRequest() {
092: requestid = ++requestcount;
093: agroups = new IppAttributeGroupSet();
094: }
095:
096: public IppRequest(int version_major, int version_minor, short opid,
097: String charset, String natural_language) {
098: IppAttributeGroup agroup;
099:
100: requestid = ++requestcount;
101: agroups = new IppAttributeGroupSet();
102:
103: this .setVersion(version_major, version_minor);
104: this .setOperationId(opid);
105: agroup = this
106: .newGroup(IppAttributeGroup.TAG_OPERATION_ATTRIBUTES);
107: agroup.add(new IppAttribute(IppAttribute.TAG_CHARSET,
108: "attributes-charset", charset));
109: agroup.add(new IppAttribute(IppAttribute.TAG_NATURAL_LANGUAGE,
110: "attributes-natural-language", natural_language));
111: }
112:
113: public IppRequest(byte[] request) throws Exception {
114: ByteArrayInputStream ab = new ByteArrayInputStream(request);
115: DataInputStream ba = new DataInputStream(ab);
116:
117: boolean the_end = false;
118: byte tag;
119: IppAttributeGroup agroup = null;
120: IppAttribute attr;
121: short name_length;
122: String name = "";
123: short value_length;
124: Vector value = new Vector();
125:
126: agroups = new IppAttributeGroupSet();
127: ba.read(ippversion, 0, 2);
128: operationid = ba.readShort();
129: requestid = ba.readInt();
130:
131: while (!the_end) {
132: tag = ba.readByte();
133: if (isAttributeGroupTag(tag)) {
134: switch (tag) {
135: case IppAttributeGroup.TAG_END_OF_ATTRIBUTES:
136: the_end = true;
137: continue;
138: case IppAttributeGroup.TAG_OPERATION_ATTRIBUTES:
139: case IppAttributeGroup.TAG_JOB_ATTRIBUTES:
140: case IppAttributeGroup.TAG_PRINTER_ATTRIBUTES:
141: case IppAttributeGroup.TAG_UNSUPPORTED_ATTRIBUTES:
142: default:
143: agroup = newGroup(tag, -1);
144: break;
145: }
146: } else {
147: name_length = ba.readShort();
148: byte[] bname = new byte[name_length];
149: if (name_length != 0) {
150: ba.read(bname, 0, name_length);
151: name = new String(bname);
152: value = new Vector();
153: attr = new IppAttribute(tag, name, value);
154: agroup.add(attr);
155: }
156: value_length = ba.readShort();
157:
158: switch (tag) {
159: case IppAttribute.TAG_INTEGER:
160: value.add(new Integer(ba.readInt()));
161: break;
162: case IppAttribute.TAG_BOOLEAN:
163: value.add(new Integer(ba.readByte()));
164: break;
165: case IppAttribute.TAG_ENUM:
166: value.add(new Integer(ba.readInt()));
167: break;
168: case IppAttribute.TAG_OCTETSTRINGUNSPECIFIEDFORMAT:
169: case IppAttribute.TAG_DATETIME:
170: case IppAttribute.TAG_RESOLUTION:
171: case IppAttribute.TAG_RANGEOFINTEGER:
172: case IppAttribute.TAG_TEXTWITHLANGUAGE:
173: case IppAttribute.TAG_NAMEWITHLANGUAGE: {
174: byte[] b = new byte[value_length];
175: ba.read(b, 0, value_length);
176: value.add(b);
177: }
178: break;
179: case IppAttribute.TAG_TEXTWITHOUTLANGUAGE:
180: case IppAttribute.TAG_NAMEWITHOUTLANGUAGE:
181: case IppAttribute.TAG_KEYWORD:
182: case IppAttribute.TAG_URI:
183: case IppAttribute.TAG_URISCHEME:
184: case IppAttribute.TAG_CHARSET:
185: case IppAttribute.TAG_NATURAL_LANGUAGE:
186: case IppAttribute.TAG_MIMEMEDIATYPE:
187: case IppAttribute.TAG_UNSUPPORTED:
188: case IppAttribute.TAG_UNKNOWN:
189: case IppAttribute.TAG_NO_VALUE: {
190: byte[] b = new byte[value_length];
191: ba.read(b, 0, value_length);
192: value.add(b);
193: }
194: break;
195: default: {
196: byte[] b = new byte[value_length];
197: ba.read(b, 0, value_length);
198: value.add(b);
199: }
200: break;
201: }
202: }
203: }
204: }
205:
206: public static boolean isAttributeGroupTag(byte tag) {
207: return (tag < 0x10);
208: }
209:
210: public void setVersion(int major, int minor) {
211: ippversion[0] = (byte) major;
212: ippversion[1] = (byte) minor;
213: }
214:
215: public byte[] getVersion() {
216: return ippversion;
217: }
218:
219: public void setOperationId(short opid) {
220: operationid = opid;
221: }
222:
223: public short getOperationId() {
224: return operationid;
225: }
226:
227: public short getStatusCode() {
228: return getOperationId();
229: }
230:
231: public void setRequestId(int rid) {
232: requestid = rid;
233: }
234:
235: public int getRequestId() {
236: return requestid;
237: }
238:
239: public IppAttributeGroupSet getAgroups() {
240: return agroups;
241: }
242:
243: public IppAttributeGroup newGroup(int agid) {
244: Vector v = (Vector) agroups.get(new Integer(agid));
245: IppAttributeGroup g = new IppAttributeGroup(agid);
246:
247: if (v == null) {
248: v = new Vector();
249: agroups.put(new Integer(agid), v);
250: v.add(g);
251: } else {
252: v.set(0, g);
253: }
254:
255: return g;
256: }
257:
258: public IppAttributeGroup newGroup(int agid, int index) {
259: Vector v = (Vector) agroups.get(new Integer(agid));
260: IppAttributeGroup g = new IppAttributeGroup(agid);
261:
262: if (v == null) {
263: v = new Vector();
264: agroups.put(new Integer(agid), v);
265: v.add(g);
266: } else {
267: if (index < 0) {
268: v.add(g);
269: } else {
270: v.set(index, g);
271: }
272: }
273:
274: return g;
275: }
276:
277: public Vector newGroupVector(int agid, Vector v) {
278: agroups.put(new Integer(agid), v);
279:
280: return getGroupVector(agid);
281: }
282:
283: public IppAttributeGroup getGroup(int agid) {
284: Vector v = (Vector) agroups.get(new Integer(agid));
285: if (v != null) {
286: return (IppAttributeGroup) v.get(0);
287: }
288: return null;
289: }
290:
291: public IppAttributeGroup getGroup(int agid, int gid) {
292: Vector v = (Vector) agroups.get(new Integer(agid));
293: if (v != null) {
294: return (IppAttributeGroup) v.get(gid);
295: }
296: return null;
297: }
298:
299: public Vector getGroupVector(int agid) {
300: return (Vector) agroups.get(new Integer(agid));
301: }
302:
303: public void setDocument(Object data) throws IppException {
304: if (data instanceof InputStream || data instanceof byte[]
305: || data instanceof char[] || data instanceof String
306: || data instanceof Reader || data instanceof URL) {
307: this .document = data;
308: } else {
309: throw new IppException("Wrong type for IPP document");
310: }
311: }
312:
313: public Object getDocument() {
314: return document;
315: }
316:
317: public byte[] getBytes() throws Exception {
318: ByteArrayOutputStream ab = new ByteArrayOutputStream();
319: DataOutputStream ba;
320: Iterator ag = agroups.values().iterator();
321: IppAttributeGroup aa;
322: byte[] b;
323: Vector vaa = new Vector();
324:
325: for (; ag.hasNext();) {
326: vaa.addAll((Vector) ag.next());
327: }
328: sortAttributes(vaa);
329:
330: ba = new DataOutputStream(ab);
331:
332: ba.write(ippversion);
333: ba.writeShort(operationid);
334: ba.writeInt(requestid);
335: for (int ii = vaa.size(), i = 0; i < ii; i++) {
336: aa = (IppAttributeGroup) vaa.get(i);
337: b = aa.getBytes();
338: ba.write(b);
339: }
340: ba.write(IppAttributeGroup.TAG_END_OF_ATTRIBUTES);
341: ba.flush();
342: ba.close();
343:
344: return ab.toByteArray();
345: }
346:
347: public String toString() {
348: ByteArrayOutputStream ab = new ByteArrayOutputStream();
349: DataOutputStream ba;
350: Iterator ag = agroups.values().iterator();
351: IppAttributeGroup aa;
352: String s;
353: Vector vaa = new Vector();
354:
355: try {
356: for (; ag.hasNext();) {
357: vaa.addAll((Vector) ag.next());
358: }
359:
360: ba = new DataOutputStream(ab);
361:
362: ba.writeBytes("IPP version: " + ippversion[0] + "."
363: + ippversion[1] + "\n");
364: ba.writeBytes("Operation id/Status code: 0x"
365: + Integer.toHexString(operationid) + "\n");
366: ba.writeBytes("Request id: 0x"
367: + Integer.toHexString(requestid) + "\n");
368:
369: for (int ii = vaa.size(), i = 0; i < ii; i++) {
370: aa = (IppAttributeGroup) vaa.get(i);
371: s = aa.toString();
372: ba.writeBytes(s + "\n");
373: }
374: ba.flush();
375: ba.close();
376: } catch (IOException e) {
377: // IGNORE exception
378: e.printStackTrace();
379: }
380:
381: return ab.toString();
382: }
383:
384: }
|