OSDN Git Service

libjava/ChangeLog:
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / net / Inet6Address.java
1 /* Inet6Address.java --
2    Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3
4 This file is 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, or (at your option)
9 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; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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 java.net;
40
41 import gnu.java.lang.CPStringBuilder;
42
43 import java.util.Arrays;
44 import java.io.ObjectInputStream;
45 import java.io.ObjectOutputStream;
46 import java.io.IOException;
47
48 /*
49  * Written using on-line Java Platform 1.4 API Specification and
50  * RFC 1884 (http://www.ietf.org/rfc/rfc1884.txt)
51  * 
52  * @author Michael Koch
53  * @status Updated to 1.5. Serialization compatibility is tested.
54  */
55 public final class Inet6Address extends InetAddress
56 {
57   static final long serialVersionUID = 6880410070516793377L;
58
59   /**
60    * Needed for serialization
61    */
62   byte[] ipaddress;
63
64   /**
65    * The scope ID, if any. 
66    * @since 1.5
67    * @serial 
68    */
69   private int scope_id;
70
71   /**
72    * The scope ID, if any. 
73    * @since 1.5
74    * @serial 
75    */
76   private boolean scope_id_set;
77
78   /**
79    * Whether ifname is set or not.
80    * @since 1.5
81    * @serial 
82    */
83   private boolean scope_ifname_set;
84
85   /**
86    * Name of the network interface, used only by the serialization methods
87    * @since 1.5
88    * @serial 
89    */
90   private String ifname;
91
92   /**
93    * Scope network interface, or <code>null</code>.
94    */
95   private transient NetworkInterface nif; 
96
97   /**
98    * The address family of these addresses (used for serialization).
99    */
100   private static final int AF_INET6 = 10;
101
102   /**
103    * Create an Inet6Address object
104    *
105    * @param addr The IP address
106    * @param host The hostname
107    */
108   Inet6Address(byte[] addr, String host)
109   {
110     super(addr, host, AF_INET6);
111     // Super constructor clones the addr.  Get a reference to the clone.
112     this.ipaddress = this.addr;
113     ifname = null;
114     scope_ifname_set = scope_id_set = false;
115     scope_id = 0;
116     nif = null;
117   }
118
119   /**
120    * Utility routine to check if the InetAddress is an IP multicast address
121    *
122    * @since 1.1
123    */
124   public boolean isMulticastAddress()
125   {
126     return ipaddress[0] == (byte) 0xFF;
127   }
128
129   /**
130    * Utility routine to check if the InetAddress in a wildcard address
131    *
132    * @since 1.4
133    */
134   public boolean isAnyLocalAddress()
135   {
136     byte[] anylocal = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
137
138     return Arrays.equals(ipaddress, anylocal);
139   }
140
141   /**
142    * Utility routine to check if the InetAddress is a loopback address
143    *
144    * @since 1.4
145    */
146   public boolean isLoopbackAddress()
147   {
148     byte[] loopback = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
149
150     return Arrays.equals(ipaddress, loopback);
151   }
152
153   /**
154    * Utility routine to check if the InetAddress is an link local address
155    *
156    * @since 1.4
157    */
158   public boolean isLinkLocalAddress()
159   {
160     return ipaddress[0] == 0xFA;
161   }
162
163   /**
164    * Utility routine to check if the InetAddress is a site local address
165    *
166    * @since 1.4
167    */
168   public boolean isSiteLocalAddress()
169   {
170     return ipaddress[0] == 0xFB;
171   }
172
173   /**
174    * Utility routine to check if the multicast address has global scope
175    *
176    * @since 1.4
177    */
178   public boolean isMCGlobal()
179   {
180     if (! isMulticastAddress())
181       return false;
182
183     return (ipaddress[1] & 0x0F) == 0xE;
184   }
185
186   /**
187    * Utility routine to check if the multicast address has node scope
188    *
189    * @since 1.4
190    */
191   public boolean isMCNodeLocal()
192   {
193     if (! isMulticastAddress())
194       return false;
195
196     return (ipaddress[1] & 0x0F) == 0x1;
197   }
198
199   /**
200    * Utility routine to check if the multicast address has link scope
201    *
202    * @since 1.4
203    */
204   public boolean isMCLinkLocal()
205   {
206     if (! isMulticastAddress())
207       return false;
208
209     return (ipaddress[1] & 0x0F) == 0x2;
210   }
211
212   /**
213    * Utility routine to check if the multicast address has site scope
214    *
215    * @since 1.4
216    */
217   public boolean isMCSiteLocal()
218   {
219     if (! isMulticastAddress())
220       return false;
221
222     return (ipaddress[1] & 0x0F) == 0x5;
223   }
224
225   /**
226    * Utility routine to check if the multicast address has organization scope
227    *
228    * @since 1.4
229    */
230   public boolean isMCOrgLocal()
231   {
232     if (! isMulticastAddress())
233       return false;
234
235     return (ipaddress[1] & 0x0F) == 0x8;
236   }
237
238   /**
239    * Returns the raw IP address of this InetAddress object. The result is in
240    * network byte order: the highest order byte of the address is i
241    * n getAddress()[0]
242    */
243   public byte[] getAddress()
244   {
245     return (byte[]) ipaddress.clone();
246   }
247
248   /**
249    * Creates a scoped Inet6Address where the scope has an integer id.
250    *
251    * @throws UnkownHostException if the address is an invalid number of bytes.
252    * @since 1.5
253    */  
254   public static Inet6Address getByAddress(String host, byte[] addr, 
255                                           int scopeId)
256     throws UnknownHostException
257   {
258     if( addr.length != 16 )
259       throw new UnknownHostException("Illegal address length: " + addr.length
260                                      + " bytes.");
261     Inet6Address ip = new Inet6Address( addr, host );
262     ip.scope_id = scopeId;
263     ip.scope_id_set = true;
264     return ip;
265   }
266
267   /**
268    * Creates a scoped Inet6Address where the scope is a given
269    * NetworkInterface.
270    *
271    * @throws UnkownHostException if the address is an invalid number of bytes.
272    * @since 1.5
273    */  
274   public static Inet6Address getByAddress(String host, byte[] addr, 
275                                           NetworkInterface nif)
276     throws UnknownHostException
277   {
278     if( addr.length != 16 )
279       throw new UnknownHostException("Illegal address length: " + addr.length
280                                      + " bytes.");
281     Inet6Address ip = new Inet6Address( addr, host );
282     ip.nif = nif;
283
284     return ip;
285   }
286
287   /**
288    * Returns the <code>NetworkInterface</code> of the address scope
289    * if it is a scoped address and the scope is given in the form of a
290    * NetworkInterface. 
291    * (I.e. the address was created using  the 
292    * getByAddress(String, byte[], NetworkInterface) method)
293    * Otherwise this method returns <code>null</code>.
294    * @since 1.5
295    */
296   public NetworkInterface getScopedInterface()
297   {
298     return nif;
299   }
300
301   /**
302    * Returns the scope ID of the address scope if it is a scoped adress using
303    * an integer to identify the scope.
304    *
305    * Otherwise this method returns 0.
306    * @since 1.5
307    */
308   public int getScopeId()
309   {
310     // check scope_id_set because some JDK-serialized objects seem to have
311     // scope_id set to a nonzero value even when scope_id_set == false
312     if( scope_id_set )
313       return scope_id; 
314     return 0;
315   }
316
317   /**
318    * Returns the IP address string in textual presentation
319    */
320   public String getHostAddress()
321   {
322     CPStringBuilder sbuf = new CPStringBuilder(40);
323
324     for (int i = 0; i < 16; i += 2)
325       {
326         int x = ((ipaddress[i] & 0xFF) << 8) | (ipaddress[i + 1] & 0xFF);
327
328         if (i > 0)
329           sbuf.append(':');
330
331         sbuf.append(Integer.toHexString(x));
332       }
333     if( nif != null )
334       sbuf.append( "%" + nif.getName() );
335     else if( scope_id_set )
336       sbuf.append( "%" + scope_id );
337
338     return sbuf.toString();
339   }
340
341   /**
342    * Returns a hashcode for this IP address
343    * (The hashcode is independent of scope)
344    */
345   public int hashCode()
346   {
347     return super.hashCode();
348   }
349
350   /**
351    * Compares this object against the specified object
352    */
353   public boolean equals(Object obj)
354   {
355     if (! (obj instanceof Inet6Address))
356       return false;
357
358     Inet6Address ip = (Inet6Address)obj;
359     if (ipaddress.length != ip.ipaddress.length)
360       return false;
361
362     for (int i = 0; i < ip.ipaddress.length; i++)
363       if (ipaddress[i] != ip.ipaddress[i])
364         return false;
365
366     if( ip.nif != null && nif != null )
367       return nif.equals( ip.nif );
368     if( ip.nif != nif )
369       return false;
370     if( ip.scope_id_set != scope_id_set )
371       return false;
372     if( scope_id_set )
373       return (scope_id == ip.scope_id);
374     return true;
375   }
376
377   /**
378    * Utility routine to check if the InetAddress is an
379    * IPv4 compatible IPv6 address
380    *
381    * @since 1.4
382    */
383   public boolean isIPv4CompatibleAddress()
384   {
385     if (ipaddress[0] != 0x00 || ipaddress[1] != 0x00 || ipaddress[2] != 0x00
386         || ipaddress[3] != 0x00 || ipaddress[4] != 0x00
387         || ipaddress[5] != 0x00 || ipaddress[6] != 0x00
388         || ipaddress[7] != 0x00 || ipaddress[8] != 0x00
389         || ipaddress[9] != 0x00 || ipaddress[10] != 0x00
390         || ipaddress[11] != 0x00)
391       return false;
392
393     return true;
394   }
395
396   /**
397    * Required for 1.5-compatible serialization.
398    * @since 1.5
399    */
400   private void readObject(ObjectInputStream s)
401     throws IOException, ClassNotFoundException
402   {  
403     s.defaultReadObject();
404     try
405       {
406         if( scope_ifname_set )
407           nif = NetworkInterface.getByName( ifname );
408       }
409     catch( SocketException se )
410       {
411         // FIXME: Ignore this? or throw an IOException?
412       }
413   }
414
415   /**
416    * Required for 1.5-compatible serialization.
417    * @since 1.5
418    */
419   private void writeObject(ObjectOutputStream s)
420     throws IOException
421   {
422     if( nif != null )
423       {
424         ifname = nif.getName();
425         scope_ifname_set = true;
426       }
427     s.defaultWriteObject();
428   }
429 }