001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.kvem.jsr082.obex;
027:
028: import javax.obex.HeaderSet;
029: import java.io.IOException;
030: import java.util.Hashtable;
031: import java.util.Enumeration;
032: import java.util.Calendar;
033: import java.util.Vector;
034:
035: public class HeaderSetImpl implements HeaderSet {
036:
037: /** Debug information, should be false for RR. */
038: private static final boolean DEBUG = false;
039:
040: public static final int OWNER_SERVER = 1;
041: public static final int OWNER_CLIENT = 2;
042: public static final int OWNER_SERVER_USER = 3;
043: public static final int OWNER_CLIENT_USER = 4;
044:
045: static final int TYPE_UNICODE = 0;
046: static final int TYPE_BYTEARRAY = 1;
047: static final int TYPE_BYTE = 2;
048: static final int TYPE_LONG = 3;
049: static final int TYPE_SPECIAL_TIME_4 = 4;
050: static final int TYPE_SPECIAL_TIME_ISO = 5;
051: static final int TYPE_SPECIAL_TYPE = 6;
052: static final int TYPE_UNSUPPORTED = 7;
053: static final int TYPE_AUTH_CHALLENGE = 8;
054: static final int TYPE_AUTH_RESPONSE = 9;
055:
056: /* package protected */int owner;
057: /* package protected */int packetType;
058:
059: private Hashtable headers;
060: Vector challenges = new Vector();
061:
062: public HeaderSetImpl(int owner) {
063: this .owner = owner;
064: headers = new Hashtable(5);
065: }
066:
067: /**
068: * Adds headers from h to this HeaderSet.
069: */
070: void merge(HeaderSetImpl h) {
071: int[] idList = h.getHeaderList();
072:
073: if (idList == null) {
074: return;
075: }
076:
077: for (int i = 0; i < idList.length; i++) {
078: int id = idList[i];
079: Object val = h.getHeader(id);
080: int type = internalType(id);
081: switch (type) {
082: case TYPE_UNICODE:
083: case TYPE_BYTE:
084: case TYPE_LONG:
085: case TYPE_SPECIAL_TYPE:
086: setHeader(id, val);
087: break;
088:
089: case TYPE_BYTEARRAY:
090: byte[] array = (byte[]) val;
091: byte[] copy = new byte[array.length];
092: System.arraycopy(array, 0, copy, 0, array.length);
093: setHeader(id, (Object) copy);
094: break;
095:
096: case TYPE_SPECIAL_TIME_4:
097: case TYPE_SPECIAL_TIME_ISO:
098: Calendar cal = (Calendar) val;
099: Calendar calCopy = Calendar.getInstance();
100: calCopy.setTime(cal.getTime());
101: setHeader(id, (Object) calCopy);
102: break;
103:
104: default:
105: // no default
106: if (DEBUG) {
107: System.out.println("Debug: unknown header id");
108: }
109: }
110: }
111: }
112:
113: /**
114: * Makes private copy of the headers.
115: */
116: HeaderSetImpl(HeaderSetImpl h) {
117: this .packetType = h.packetType;
118: this .owner = h.owner;
119: headers = new Hashtable(5);
120: merge(h);
121: }
122:
123: boolean isSendable() {
124: return owner >= OWNER_SERVER_USER;
125: }
126:
127: // interface functions:
128: public void createAuthenticationChallenge(java.lang.String realm,
129: boolean userID, boolean access) {
130:
131: ObexAuth auth = ObexAuth.createChallenge(realm, userID, access);
132: challenges.addElement(auth);
133: }
134:
135: public Object getHeader(int headerID) {
136: Object value = headers.get(new Integer(headerID));
137:
138: if (value != null) {
139: return value;
140: }
141:
142: // check validness of headerID
143: int type = internalType(headerID);
144:
145: if (type >= TYPE_UNSUPPORTED) {
146: throw new IllegalArgumentException("bad header id");
147: }
148: return null;
149: }
150:
151: public int[] getHeaderList() {
152: synchronized (headers) {
153: if (headers.isEmpty()) {
154: return null;
155: }
156: Enumeration keys = headers.keys();
157: int[] ids = new int[headers.size()];
158: int i = 0;
159:
160: while (keys.hasMoreElements()) {
161: Object obj = keys.nextElement();
162: ids[i++] = ((Integer) obj).intValue();
163: }
164: return ids;
165: }
166: }
167:
168: public int getResponseCode() throws IOException {
169: if (owner != OWNER_CLIENT) {
170: throw new IOException("invalid use");
171: }
172: if (packetType == ObexPacketStream.OPCODE_CONTINUE) {
173: throw new IOException("operation not finished");
174: }
175: return packetType;
176: }
177:
178: public void setHeader(int headerID, Object headerValue) {
179: int type = internalType(headerID);
180: String errormsg = "incompatible header object";
181:
182: if (type >= TYPE_UNSUPPORTED) {
183: throw new IllegalArgumentException("bad header id");
184: }
185:
186: if (headerValue == null) {
187: synchronized (headers) {
188: headers.remove(new Integer(headerID));
189: }
190: return;
191: }
192:
193: boolean fail = false;
194: switch (type) {
195: case TYPE_UNICODE:
196: if (!(headerValue instanceof String))
197: fail = true;
198: break;
199:
200: case TYPE_BYTEARRAY:
201: if (!(headerValue instanceof byte[]))
202: fail = true;
203: break;
204:
205: case TYPE_BYTE:
206: if (!(headerValue instanceof Byte))
207: fail = true;
208: break;
209:
210: case TYPE_LONG:
211: if (!(headerValue instanceof Long)) {
212: fail = true;
213: break;
214: }
215: long value = ((Long) headerValue).longValue();
216:
217: if (value < 0L || value > 0xFFFFFFFFL) {
218: errormsg = "long value out of range 0 .. 0xFFFFFFFF";
219: fail = true;
220: }
221: break;
222:
223: case TYPE_SPECIAL_TIME_4:
224: if (!(headerValue instanceof Calendar))
225: fail = true;
226: break;
227:
228: case TYPE_SPECIAL_TIME_ISO:
229: if (!(headerValue instanceof Calendar))
230: fail = true;
231: break;
232:
233: case TYPE_SPECIAL_TYPE:
234: if (!(headerValue instanceof String))
235: fail = true;
236: break;
237: // no default
238: }
239:
240: if (fail) {
241: throw new IllegalArgumentException(errormsg);
242: }
243: synchronized (headers) {
244: headers.put(new Integer(headerID), headerValue);
245: }
246: }
247:
248: static final int internalType(int headerID) {
249: if ((headerID & ~0xFF) != 0) {
250: return TYPE_UNSUPPORTED;
251: }
252: if ((headerID & 0x30) == 0x30) {
253: // user defined
254: return headerID >> 6;
255: }
256:
257: switch (headerID) {
258: case HeaderSet.TIME_ISO_8601:
259: return TYPE_SPECIAL_TIME_ISO;
260:
261: case HeaderSet.TIME_4_BYTE:
262: return TYPE_SPECIAL_TIME_4;
263:
264: case HeaderSet.TYPE:
265: return TYPE_SPECIAL_TYPE;
266:
267: case HeaderSet.COUNT:
268: case HeaderSet.LENGTH:
269: return TYPE_LONG;
270:
271: case HeaderSet.NAME:
272: case HeaderSet.DESCRIPTION:
273: return TYPE_UNICODE;
274:
275: case HeaderSet.TARGET:
276: case HeaderSet.HTTP:
277: case HeaderSet.WHO:
278: case HeaderSet.OBJECT_CLASS:
279: case HeaderSet.APPLICATION_PARAMETER:
280: return TYPE_BYTEARRAY;
281:
282: case ObexPacketStream.HEADER_AUTH_CHALLENGE:
283: return TYPE_AUTH_CHALLENGE;
284:
285: case ObexPacketStream.HEADER_AUTH_RESPONSE:
286: return TYPE_AUTH_RESPONSE;
287:
288: default:
289: return TYPE_UNSUPPORTED;
290: }
291: }
292: }
|