32 import java.io.IOException; |
32 import java.io.IOException; |
33 import java.io.InvalidObjectException; |
33 import java.io.InvalidObjectException; |
34 import java.io.ObjectInputStream; |
34 import java.io.ObjectInputStream; |
35 |
35 |
36 import java.io.Serializable; |
36 import java.io.Serializable; |
|
37 import java.net.Inet4Address; |
|
38 import java.net.Inet6Address; |
37 import java.net.InetAddress; |
39 import java.net.InetAddress; |
38 import java.net.MalformedURLException; |
40 import java.net.MalformedURLException; |
|
41 import java.net.NetworkInterface; |
|
42 import java.net.SocketException; |
39 import java.net.UnknownHostException; |
43 import java.net.UnknownHostException; |
40 import java.util.BitSet; |
44 import java.util.BitSet; |
|
45 import java.util.Enumeration; |
41 import java.util.Locale; |
46 import java.util.Locale; |
42 import java.util.StringTokenizer; |
47 import java.util.StringTokenizer; |
43 |
48 |
44 /** |
49 /** |
45 * <p>The address of a JMX API connector server. Instances of this class |
50 * <p>The address of a JMX API connector server. Instances of this class |
234 * JMXServiceURL(protocol, host, port, null)}.</p> |
239 * JMXServiceURL(protocol, host, port, null)}.</p> |
235 * |
240 * |
236 * @param protocol the protocol part of the URL. If null, defaults |
241 * @param protocol the protocol part of the URL. If null, defaults |
237 * to <code>jmxmp</code>. |
242 * to <code>jmxmp</code>. |
238 * |
243 * |
239 * @param host the host part of the URL. If null, defaults to the |
244 * @param host the host part of the URL. If host is null and if |
240 * local host name, as determined by |
245 * local host name can be resolved to an IP, then host defaults |
241 * <code>InetAddress.getLocalHost().getHostName()</code>. If it |
246 * to local host name as determined by |
242 * is a numeric IPv6 address, it can optionally be enclosed in |
247 * <code>InetAddress.getLocalHost().getHostName()</code>. If host is null |
|
248 * and if local host name cannot be resolved to an IP, then host |
|
249 * defaults to numeric IP address of one of the active network interfaces. |
|
250 * If host is a numeric IPv6 address, it can optionally be enclosed in |
243 * square brackets <code>[]</code>. |
251 * square brackets <code>[]</code>. |
244 * |
252 * |
245 * @param port the port part of the URL. |
253 * @param port the port part of the URL. |
246 * |
254 * |
247 * @exception MalformedURLException if one of the parts is |
255 * @exception MalformedURLException if one of the parts is |
258 * <p>Constructs a <code>JMXServiceURL</code> with the given parts. |
266 * <p>Constructs a <code>JMXServiceURL</code> with the given parts. |
259 * |
267 * |
260 * @param protocol the protocol part of the URL. If null, defaults |
268 * @param protocol the protocol part of the URL. If null, defaults |
261 * to <code>jmxmp</code>. |
269 * to <code>jmxmp</code>. |
262 * |
270 * |
263 * @param host the host part of the URL. If null, defaults to the |
271 * @param host the host part of the URL. If host is null and if |
264 * local host name, as determined by |
272 * local host name can be resolved to an IP, then host defaults |
265 * <code>InetAddress.getLocalHost().getHostName()</code>. If it |
273 * to local host name as determined by |
266 * is a numeric IPv6 address, it can optionally be enclosed in |
274 * <code>InetAddress.getLocalHost().getHostName()</code>. If host is null |
|
275 * and if local host name cannot be resolved to an IP, then host |
|
276 * defaults to numeric IP address of one of the active network interfaces. |
|
277 * If host is a numeric IPv6 address, it can optionally be enclosed in |
267 * square brackets <code>[]</code>. |
278 * square brackets <code>[]</code>. |
268 * |
279 * |
269 * @param port the port part of the URL. |
280 * @param port the port part of the URL. |
270 * |
281 * |
271 * @param urlPath the URL path part of the URL. If null, defaults to |
282 * @param urlPath the URL path part of the URL. If null, defaults to |
284 |
295 |
285 if (host == null) { |
296 if (host == null) { |
286 InetAddress local; |
297 InetAddress local; |
287 try { |
298 try { |
288 local = InetAddress.getLocalHost(); |
299 local = InetAddress.getLocalHost(); |
289 } catch (UnknownHostException e) { |
300 host = local.getHostName(); |
290 throw new MalformedURLException("Local host name unknown: " + |
301 |
291 e); |
302 /* We might have a hostname that violates DNS naming |
292 } |
303 rules, for example that contains an `_'. While we |
293 |
304 could be strict and throw an exception, this is rather |
294 host = local.getHostName(); |
305 user-hostile. Instead we use its numerical IP address. |
295 |
306 We can only reasonably do this for the host==null case. |
296 /* We might have a hostname that violates DNS naming |
307 If we're given an explicit host name that is illegal we |
297 rules, for example that contains an `_'. While we |
308 have to reject it. (Bug 5057532.) */ |
298 could be strict and throw an exception, this is rather |
309 try { |
299 user-hostile. Instead we use its numerical IP address. |
310 validateHost(host, port); |
300 We can only reasonably do this for the host==null case. |
311 } catch (MalformedURLException e) { |
301 If we're given an explicit host name that is illegal we |
312 if (logger.fineOn()) { |
302 have to reject it. (Bug 5057532.) */ |
|
303 try { |
|
304 validateHost(host, port); |
|
305 } catch (MalformedURLException e) { |
|
306 if (logger.fineOn()) { |
|
307 logger.fine("JMXServiceURL", |
313 logger.fine("JMXServiceURL", |
308 "Replacing illegal local host name " + |
314 "Replacing illegal local host name " + |
309 host + " with numeric IP address " + |
315 host + " with numeric IP address " + |
310 "(see RFC 1034)", e); |
316 "(see RFC 1034)", e); |
311 } |
317 } |
312 host = local.getHostAddress(); |
318 host = local.getHostAddress(); |
313 /* Use the numeric address, which could be either IPv4 |
319 } |
314 or IPv6. validateHost will accept either. */ |
320 } catch (UnknownHostException e) { |
|
321 try { |
|
322 /* |
|
323 If hostname cannot be resolved, we will try and use numeric |
|
324 IPv4/IPv6 address. If host=null while starting agent, |
|
325 we know that it will be started on all interfaces - 0.0.0.0. |
|
326 Hence we will use IP address of first active non-loopback |
|
327 interface |
|
328 */ |
|
329 host = getActiveNetworkInterfaceIP(); |
|
330 if (host == null) { |
|
331 throw new MalformedURLException("Unable" |
|
332 + " to resolve hostname or " |
|
333 + "get valid IP address"); |
|
334 } |
|
335 } catch (SocketException ex) { |
|
336 throw new MalformedURLException("Unable" |
|
337 + " to resolve hostname or get valid IP address"); |
|
338 } |
315 } |
339 } |
316 } |
340 } |
317 |
341 |
318 if (host.startsWith("[")) { |
342 if (host.startsWith("[")) { |
319 if (!host.endsWith("]")) { |
343 if (!host.endsWith("]")) { |
336 if (urlPath == null) |
360 if (urlPath == null) |
337 urlPath = ""; |
361 urlPath = ""; |
338 this.urlPath = urlPath; |
362 this.urlPath = urlPath; |
339 |
363 |
340 validate(); |
364 validate(); |
|
365 } |
|
366 |
|
367 private String getActiveNetworkInterfaceIP() throws SocketException { |
|
368 Enumeration<NetworkInterface> |
|
369 networkInterface = NetworkInterface.getNetworkInterfaces(); |
|
370 String ipv6AddrStr = null; |
|
371 while (networkInterface.hasMoreElements()) { |
|
372 NetworkInterface nic = networkInterface.nextElement(); |
|
373 if (nic.isUp() && !nic.isLoopback()) { |
|
374 Enumeration<InetAddress> inet = nic.getInetAddresses(); |
|
375 while (inet.hasMoreElements()) { |
|
376 InetAddress addr = inet.nextElement(); |
|
377 if (addr instanceof Inet4Address |
|
378 && !addr.isLinkLocalAddress()) { |
|
379 return addr.getHostAddress(); |
|
380 }else if (addr instanceof Inet6Address |
|
381 && !addr.isLinkLocalAddress()) { |
|
382 /* |
|
383 We save last seen IPv6 address which we will return |
|
384 if we do not find any interface with IPv4 address. |
|
385 */ |
|
386 ipv6AddrStr = addr.getHostAddress(); |
|
387 } |
|
388 } |
|
389 } |
|
390 } |
|
391 return ipv6AddrStr; |
341 } |
392 } |
342 |
393 |
343 private static final String INVALID_INSTANCE_MSG = |
394 private static final String INVALID_INSTANCE_MSG = |
344 "Trying to deserialize an invalid instance of JMXServiceURL"; |
395 "Trying to deserialize an invalid instance of JMXServiceURL"; |
345 private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { |
396 private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { |
538 * parameter, the result is the substring specifying the host in |
589 * parameter, the result is the substring specifying the host in |
539 * that URL. If the Service URL was constructed with a |
590 * that URL. If the Service URL was constructed with a |
540 * constructor that takes a separate host parameter, the result is |
591 * constructor that takes a separate host parameter, the result is |
541 * the string that was specified. If that string was null, the |
592 * the string that was specified. If that string was null, the |
542 * result is |
593 * result is |
543 * <code>InetAddress.getLocalHost().getHostName()</code>.</p> |
594 * <code>InetAddress.getLocalHost().getHostName()</code> if local host name |
|
595 * can be resolved to an IP. Else numeric IP address of an active |
|
596 * network interface will be used.</p> |
544 * |
597 * |
545 * <p>In either case, if the host was specified using the |
598 * <p>In either case, if the host was specified using the |
546 * <code>[...]</code> syntax for numeric IPv6 addresses, the |
599 * <code>[...]</code> syntax for numeric IPv6 addresses, the |
547 * square brackets are not included in the return value here.</p> |
600 * square brackets are not included in the return value here.</p> |
548 * |
601 * |