1: package ;
2:
3: import ;
4: import ;
5: import ;
6: import ;
7: import ;
8: import ;
9: import ;
10: import ;
11: import ;
12:
13:
21: public class ExtensionList implements Builder, Iterable<Extension>
22: {
23: private final ByteBuffer buffer;
24: private int modCount;
25:
26: public ExtensionList (ByteBuffer buffer)
27: {
28: this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
29: modCount = 0;
30: }
31:
32: public ExtensionList(List<Extension> extensions)
33: {
34: int length = 2;
35: for (Extension extension : extensions)
36: length += extension.length();
37: buffer = ByteBuffer.allocate(length);
38: buffer.putShort((short) (length - 2));
39: for (Extension extension : extensions)
40: buffer.put(extension.buffer());
41: buffer.rewind();
42: }
43:
44: public ByteBuffer buffer()
45: {
46: return (ByteBuffer) buffer.duplicate().limit(length());
47: }
48:
49: public Extension get (final int index)
50: {
51: int length = length ();
52: int i;
53: int n = 0;
54: for (i = 2; i < length && n < index; )
55: {
56: int l = buffer.getShort (i+2) & 0xFFFF;
57: i += l + 4;
58: n++;
59: }
60: if (n < index)
61: throw new IndexOutOfBoundsException ("no elemenet at " + index);
62: int el = buffer.getShort (i+2) & 0xFFFF;
63: ByteBuffer b = (ByteBuffer) buffer.duplicate().position(i).limit(i+el+4);
64: return new Extension(b.slice());
65: }
66:
67:
72: public int size ()
73: {
74: int length = length ();
75: if (length == 0)
76: return 0;
77: int n = 0;
78: for (int i = 2; i < length; )
79: {
80: int len = buffer.getShort (i+2) & 0xFFFF;
81: i += len + 4;
82: n++;
83: }
84: return n;
85: }
86:
87:
92: public int length ()
93: {
94: return (buffer.getShort (0) & 0xFFFF) + 2;
95: }
96:
97:
117: public void set (final int index, Extension e)
118: {
119: int length = length();
120: int n = 0;
121: int i;
122: for (i = 2; i < length && n < index; )
123: {
124: int len = buffer.getShort(i+2) & 0xFFFF;
125: i += len + 4;
126: n++;
127: }
128: if (n < index)
129: throw new IllegalArgumentException("nothing set at index " + (index-1)
130: + " or insufficient space");
131: if (i + e.length() + 2 > length)
132: throw new IllegalArgumentException("adding this element will exceed the "
133: + "list length");
134: buffer.putShort(i, (short) e.type().getValue());
135: buffer.putShort(i+2, (short) e.length());
136: ((ByteBuffer) buffer.duplicate().position(i+4)).put (e.valueBuffer());
137: modCount++;
138: }
139:
140:
150: public void set (final int index, Extension.Type t, final int eLength)
151: {
152: int length = length ();
153: int n = 0;
154: int i;
155: for (i = 2; i < length && n < index; )
156: {
157: int len = buffer.getShort (i+2) & 0xFFFF;
158: i += len + 4;
159: n++;
160: }
161: if (n < index)
162: throw new IllegalArgumentException ("nothing set at index " + (index-1)
163: + " or insufficient space");
164: if (i + eLength + 2 > length)
165: throw new IllegalArgumentException ("adding this element will exceed the "
166: + "list length");
167: buffer.putShort(i, (short) t.getValue());
168: buffer.putShort(i+2, (short) eLength);
169: modCount++;
170: }
171:
172:
177: public void setLength (final int newLength)
178: {
179: if (newLength < 0 || newLength > 65535)
180: throw new IllegalArgumentException ("invalid length");
181: buffer.putShort (0, (short) newLength);
182: modCount++;
183: }
184:
185: public Iterator<Extension> iterator()
186: {
187: return new ExtensionsIterator();
188: }
189:
190: public String toString()
191: {
192: return toString (null);
193: }
194:
195: public String toString(final String prefix)
196: {
197: StringWriter str = new StringWriter();
198: PrintWriter out = new PrintWriter(str);
199: if (prefix != null) out.print(prefix);
200: out.println("ExtensionList {");
201: if (prefix != null) out.print(prefix);
202: out.print(" length = ");
203: out.print(length());
204: out.println(";");
205: String subprefix = " ";
206: if (prefix != null)
207: subprefix = prefix + subprefix;
208: for (Extension e : this)
209: out.println(e.toString(subprefix));
210: if (prefix != null) out.print(prefix);
211: out.print("};");
212: return str.toString();
213: }
214:
215:
220: public final class ExtensionsIterator implements ListIterator<Extension>
221: {
222: private final int modCount;
223: private int index;
224: private final int size;
225:
226: public ExtensionsIterator ()
227: {
228: this.modCount = ExtensionList.this.modCount;
229: index = 0;
230: size = size ();
231: }
232:
233: public boolean hasNext()
234: {
235: return index < size;
236: }
237:
238: public boolean hasPrevious()
239: {
240: return index > 0;
241: }
242:
243: public Extension next() throws NoSuchElementException
244: {
245: if (modCount != ExtensionList.this.modCount)
246: throw new ConcurrentModificationException ();
247: if (!hasNext ())
248: throw new NoSuchElementException ();
249: return get (index++);
250: }
251:
252: public Extension previous() throws NoSuchElementException
253: {
254: if (modCount != ExtensionList.this.modCount)
255: throw new ConcurrentModificationException ();
256: if (!hasPrevious ())
257: throw new NoSuchElementException ();
258: return get (--index);
259: }
260:
261: public int nextIndex()
262: {
263: if (hasNext ())
264: return index + 1;
265: return index;
266: }
267:
268: public int previousIndex()
269: {
270: if (hasPrevious ())
271: return index - 1;
272: return -1;
273: }
274:
275: public void add(Extension e)
276: {
277: throw new UnsupportedOperationException ("cannot add items to this iterator");
278: }
279:
280: public void remove()
281: {
282: throw new UnsupportedOperationException ("cannot remove items from this iterator");
283: }
284:
285: public void set(Extension e)
286: {
287: ExtensionList.this.set (index, e);
288: }
289: }
290: }