1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54:
55:
82: public class ServerNameList extends Value implements Iterable<ServerNameList.ServerName>
83: {
84: private ByteBuffer buffer;
85:
86: public ServerNameList (final ByteBuffer buffer)
87: {
88: this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
89: }
90:
91: public ServerNameList(List<ServerName> names)
92: {
93: int length = 2;
94: for (ServerName name : names)
95: length += name.length();
96: buffer = ByteBuffer.allocate(length);
97: buffer.putShort((short) (length - 2));
98: for (ServerName name : names)
99: buffer.put(name.buffer());
100: buffer.rewind();
101: }
102:
103: public int length()
104: {
105: return (buffer.getShort(0) & 0xFFFF) + 2;
106: }
107:
108: public ByteBuffer buffer()
109: {
110: return (ByteBuffer) buffer.duplicate().limit(length());
111: }
112:
113: public int size()
114: {
115: int n = 0;
116: final int len = length();
117: for (int i = 2; i < len; )
118: {
119: int l = buffer.getShort(i+1);
120: i += l + 3;
121: n++;
122: }
123: return n;
124: }
125:
126: public ServerName get (int index)
127: {
128: final int len = length();
129: if (len == 0)
130: throw new IndexOutOfBoundsException("0; " + index);
131: int n = 0;
132: int i;
133: int l = buffer.getShort(3);
134: for (i = 2; i < len && n < index; )
135: {
136: l = buffer.getShort(i+1);
137: i += l + 3;
138: n++;
139: }
140: if (n < index)
141: throw new IndexOutOfBoundsException(n + "; " + index);
142: ByteBuffer buf = ((ByteBuffer) buffer.duplicate().position(i).limit(i+l+3)).slice();
143: return new ServerName (buf);
144: }
145:
146: public void setLength(final int newLength)
147: {
148: if (newLength < 0 || newLength > 65535)
149: throw new IllegalArgumentException("length must be between 0 and 65535");
150: buffer.putShort(0, (short) newLength);
151: }
152:
153: public String toString()
154: {
155: return toString(null);
156: }
157:
158: public String toString(String prefix)
159: {
160: StringWriter str = new StringWriter();
161: PrintWriter out = new PrintWriter(str);
162: if (prefix != null) out.print(prefix);
163: out.println ("ServerNameList {");
164: String subprefix = " ";
165: if (prefix != null)
166: subprefix = prefix + subprefix;
167: for (ServerName name : this)
168: {
169: out.println (name.toString(subprefix));
170: }
171: if (prefix != null) out.print(prefix);
172: out.print ("};");
173: return str.toString();
174: }
175:
176: public java.util.Iterator<ServerName> iterator()
177: {
178: return new Iterator();
179: }
180:
181: public class Iterator implements java.util.Iterator<ServerName>
182: {
183: private int index;
184:
185: public Iterator()
186: {
187: index = 0;
188: }
189:
190: public boolean hasNext()
191: {
192: return index < size();
193: }
194:
195: public ServerName next() throws NoSuchElementException
196: {
197: try
198: {
199: return get (index++);
200: }
201: catch (IndexOutOfBoundsException ioobe)
202: {
203: throw new NoSuchElementException();
204: }
205: }
206:
207: public void remove()
208: {
209: throw new UnsupportedOperationException();
210: }
211: }
212:
213: public static class ServerName implements Constructed
214: {
215: private ByteBuffer buffer;
216:
217: public ServerName(final ByteBuffer buffer)
218: {
219: this.buffer = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
220: }
221:
222: public ServerName(NameType type, String name)
223: {
224: CharsetEncoder utf8 = Charset.forName("UTF-8").newEncoder();
225: ByteBuffer nameBuf = null;
226: try
227: {
228: nameBuf = utf8.encode(CharBuffer.wrap(name));
229: }
230: catch (CharacterCodingException cce)
231: {
232:
233: throw new IllegalArgumentException(cce);
234: }
235: int length = 3 + nameBuf.remaining();
236: buffer = ByteBuffer.allocate(length);
237: buffer.put((byte) type.getValue());
238: buffer.putShort((short) (length - 3));
239: buffer.put(nameBuf);
240: buffer.rewind();
241: }
242:
243: public int length()
244: {
245: return (buffer.getShort(1) & 0xFFFF) + 3;
246: }
247:
248: public ByteBuffer buffer()
249: {
250: return (ByteBuffer) buffer.duplicate().limit(length());
251: }
252:
253: public NameType type()
254: {
255: int v = (buffer.get(0) & 0xFF);
256: if (v == 0)
257: {
258: return NameType.HOST_NAME;
259: }
260: throw new IllegalArgumentException ("illegal name type: " + v);
261: }
262:
263: public String name()
264: {
265: int len = length();
266: Charset cs = Charset.forName ("UTF-8");
267: return cs.decode(((ByteBuffer) buffer.duplicate().position(3).limit(len))).toString();
268: }
269:
270: public String toString()
271: {
272: return toString (null);
273: }
274:
275: public String toString(String prefix)
276: {
277: StringWriter str = new StringWriter();
278: PrintWriter out = new PrintWriter(str);
279: if (prefix != null) out.print (prefix);
280: out.println ("struct {");
281: if (prefix != null) out.print (prefix);
282: out.print (" name_type = ");
283: out.print (type());
284: out.println (";");
285: if (prefix != null) out.print (prefix);
286: out.print (" server_name = ");
287: out.print (name());
288: out.println (";");
289: if (prefix != null) out.print (prefix);
290: out.print ("} ServerName;");
291: return str.toString();
292: }
293: }
294:
295: public static enum NameType
296: {
297: HOST_NAME (0);
298:
299: private final int value;
300:
301: private NameType (int value)
302: {
303: this.value = value;
304: }
305:
306: public int getValue()
307: {
308: return value;
309: }
310: }
311: }