OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / javax / net / ssl / provider / ServerNameList.java
1 /* ServerNameList.java --
2    Copyright (C) 2006  Free Software Foundation, Inc.
3
4 This file is a part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or (at
9 your option) any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 USA
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version.  */
37
38
39 package gnu.javax.net.ssl.provider;
40
41 import gnu.javax.net.ssl.provider.Extension.Value;
42
43 import java.io.PrintWriter;
44 import java.io.StringWriter;
45
46 import java.nio.ByteBuffer;
47 import java.nio.ByteOrder;
48 import java.nio.CharBuffer;
49 import java.nio.charset.CharacterCodingException;
50 import java.nio.charset.Charset;
51 import java.nio.charset.CharsetEncoder;
52 import java.util.List;
53 import java.util.NoSuchElementException;
54
55 /**
56  * The ServerName extension.
57  * 
58  * <pre>
59  struct {
60    NameType name_type;
61    select (name_type) {
62      case host_name: HostName;
63    } name;
64 } ServerName;
65
66 enum {
67   host_name(0), (255)
68 } NameType;
69
70 opaque HostName<1..2^16-1>;
71
72 struct {
73   ServerName server_name_list<1..2^16-1>
74 } ServerNameList;</pre>
75  *
76  * <p><b>Implementation note: this class does not currently contain a
77  * <code>set</code> method. If you are modifying this list, then use the
78  * {@link #get(int)} method, and modify the returned {@link ServerName}.
79  *
80  * @author csm
81  */
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           // We don't expect this to happen; it's UTF-8.
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 }