001 /* NetworkInterface.java --
002 Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath 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 for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package java.net;
040
041 import java.util.Collection;
042 import java.util.Collections;
043 import java.util.Enumeration;
044 import java.util.HashMap;
045 import java.util.Iterator;
046 import java.util.Map;
047 import java.util.Vector;
048
049 /**
050 * This class models a network interface on the host computer. A network
051 * interface contains a name (typically associated with a specific
052 * hardware adapter) and a list of addresses that are bound to it.
053 * For example, an ethernet interface may be named "eth0" and have the
054 * address 192.168.1.101 assigned to it.
055 *
056 * @author Michael Koch (konqueror@gmx.de)
057 * @since 1.4
058 */
059 public final class NetworkInterface
060 {
061 private String name;
062 private Vector<InetAddress> inetAddresses;
063
064 NetworkInterface(String name, InetAddress address)
065 {
066 this.name = name;
067 this.inetAddresses = new Vector(1, 1);
068 this.inetAddresses.add(address);
069 }
070
071 NetworkInterface(String name, InetAddress[] addresses)
072 {
073 this.name = name;
074 this.inetAddresses = new Vector(addresses.length, 1);
075
076 for (int i = 0; i < addresses.length; i++)
077 this.inetAddresses.add(addresses[i]);
078 }
079
080 /**
081 * Returns the name of the network interface
082 *
083 * @return The name of the interface.
084 */
085 public String getName()
086 {
087 return name;
088 }
089
090 /**
091 * Returns all available addresses of the network interface
092 *
093 * If a @see SecurityManager is available all addresses are checked
094 * with @see SecurityManager::checkConnect() if they are available.
095 * Only <code>InetAddresses</code> are returned where the security manager
096 * doesn't throw an exception.
097 *
098 * @return An enumeration of all addresses.
099 */
100 public Enumeration<InetAddress> getInetAddresses()
101 {
102 SecurityManager s = System.getSecurityManager();
103
104 if (s == null)
105 return inetAddresses.elements();
106
107 Vector<InetAddress> tmpInetAddresses = new Vector<InetAddress>(1, 1);
108
109 for (Enumeration<InetAddress> addresses = inetAddresses.elements();
110 addresses.hasMoreElements();)
111 {
112 InetAddress addr = addresses.nextElement();
113 try
114 {
115 s.checkConnect(addr.getHostAddress(), 58000);
116 tmpInetAddresses.add(addr);
117 }
118 catch (SecurityException e)
119 {
120 // Ignore.
121 }
122 }
123
124 return tmpInetAddresses.elements();
125 }
126
127 /**
128 * Returns the display name of the interface
129 *
130 * @return The display name of the interface
131 */
132 public String getDisplayName()
133 {
134 return name;
135 }
136
137 /**
138 * Returns an network interface by name
139 *
140 * @param name The name of the interface to return
141 *
142 * @return a <code>NetworkInterface</code> object representing the interface,
143 * or null if there is no interface with that name.
144 *
145 * @exception SocketException If an error occurs
146 * @exception NullPointerException If the specified name is null
147 */
148 public static NetworkInterface getByName(String name)
149 throws SocketException
150 {
151 for (Enumeration e = getNetworkInterfaces(); e.hasMoreElements();)
152 {
153 NetworkInterface tmp = (NetworkInterface) e.nextElement();
154
155 if (name.equals(tmp.getName()))
156 return tmp;
157 }
158
159 // No interface with the given name found.
160 return null;
161 }
162
163 /**
164 * Return a network interface by its address
165 *
166 * @param addr The address of the interface to return
167 *
168 * @return the interface, or <code>null</code> if none found
169 *
170 * @exception SocketException If an error occurs
171 * @exception NullPointerException If the specified addess is null
172 */
173 public static NetworkInterface getByInetAddress(InetAddress addr)
174 throws SocketException
175 {
176 for (Enumeration interfaces = getNetworkInterfaces();
177 interfaces.hasMoreElements();)
178 {
179 NetworkInterface tmp = (NetworkInterface) interfaces.nextElement();
180
181 for (Enumeration addresses = tmp.inetAddresses.elements();
182 addresses.hasMoreElements();)
183 {
184 if (addr.equals((InetAddress) addresses.nextElement()))
185 return tmp;
186 }
187 }
188
189 throw new SocketException("no network interface is bound to such an IP address");
190 }
191
192 static private Collection condense(Collection interfaces)
193 {
194 final Map condensed = new HashMap();
195
196 final Iterator interfs = interfaces.iterator();
197 while (interfs.hasNext()) {
198
199 final NetworkInterface face = (NetworkInterface) interfs.next();
200 final String name = face.getName();
201
202 if (condensed.containsKey(name))
203 {
204 final NetworkInterface conface = (NetworkInterface) condensed.get(name);
205 if (!conface.inetAddresses.containsAll(face.inetAddresses))
206 {
207 final Iterator faceAddresses = face.inetAddresses.iterator();
208 while (faceAddresses.hasNext())
209 {
210 final InetAddress faceAddress = (InetAddress) faceAddresses.next();
211 if (!conface.inetAddresses.contains(faceAddress))
212 {
213 conface.inetAddresses.add(faceAddress);
214 }
215 }
216 }
217 }
218 else
219 {
220 condensed.put(name, face);
221 }
222 }
223
224 return condensed.values();
225 }
226
227 /**
228 * Return an <code>Enumeration</code> of all available network interfaces
229 *
230 * @return all interfaces
231 *
232 * @exception SocketException If an error occurs
233 */
234 public static Enumeration<NetworkInterface> getNetworkInterfaces()
235 throws SocketException
236 {
237 Vector<NetworkInterface> networkInterfaces =
238 VMNetworkInterface.getInterfaces();
239
240 if (networkInterfaces.isEmpty())
241 return null;
242
243 Collection condensed = condense(networkInterfaces);
244
245 return Collections.enumeration(condensed);
246 }
247
248 /**
249 * Checks if the current instance is equal to obj
250 *
251 * @param obj The object to compare with
252 *
253 * @return <code>true</code> if equal, <code>false</code> otherwise
254 */
255 public boolean equals(Object obj)
256 {
257 if (! (obj instanceof NetworkInterface))
258 return false;
259
260 NetworkInterface tmp = (NetworkInterface) obj;
261
262 return (name.equals(tmp.name) && inetAddresses.equals(tmp.inetAddresses));
263 }
264
265 /**
266 * Returns the hashcode of the current instance
267 *
268 * @return the hashcode
269 */
270 public int hashCode()
271 {
272 // FIXME: hash correctly
273 return name.hashCode() + inetAddresses.hashCode();
274 }
275
276 /**
277 * Returns a string representation of the interface
278 *
279 * @return the string
280 */
281 public String toString()
282 {
283 // FIXME: check if this is correct
284 String result;
285 String separator = System.getProperty("line.separator");
286
287 result =
288 "name: " + getDisplayName() + " (" + getName() + ") addresses:"
289 + separator;
290
291 for (Enumeration e = inetAddresses.elements(); e.hasMoreElements();)
292 {
293 InetAddress address = (InetAddress) e.nextElement();
294 result += address.toString() + ";" + separator;
295 }
296
297 return result;
298 }
299 }