jdk/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java
changeset 37318 fee950a46e67
parent 35268 d5aa211825e1
equal deleted inserted replaced
37317:6c2ff92720da 37318:fee950a46e67
    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      *