Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5083594

Different Behaviors parsing hostname with '_' between in 1.3.1 and 1.4.X/1.5

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 6
    • 5.0
    • core-libs
    • beta
    • x86
    • windows_2003

      In source code of Naming#parseURL() in 1.3.1, to parse URL String is hard coded.
      On the other hand, to parse URL process in 1.4.X/1.5 is done
      by getHost in java.net.URI..

      Please assume the URL includes a hostname which has '_'(underscore).
        ex.
          http://appsrv_k01:12200/

      To parse URL process in 1.3.1 doesn't check whether the String includes
      '_' or not, which is, that considers '_' no problem.
      Then hostname is extracted as specified in URL String
      (In the above example, "appsrv_k01" will be extracted.)


      === ./src/share/classes/java/rmi/Naming.java (1.3.1_12) ===

      213 private static ParsedNamingURL parseURL(String url)
      214 throws MalformedURLException
      215 {
      216 ParsedNamingURL parsed = new ParsedNamingURL();
      217 int startFile = -1;
      218
      219 // remove the approved protocol
      220 if (url.startsWith("rmi:")) {
      221 url = url.substring(4);
      222 }
      223
      224 // Anchors (i.e. '#') are meaningless in rmi URLs - disallow them
      225 if (url.indexOf('#') >= 0) {
      226 throw new MalformedURLException
      227 ("Invalid character, '#', in URL: " + url);
      228 }
      229
      230 // No protocol must remain
      231 int checkProtocol = url.indexOf(':');
      232 if (checkProtocol >= 0 && (checkProtocol < url.indexOf('/')))
      233 throw new java.net.MalformedURLException("invalid protocol: " +
      234 url.substring(0, checkProtocol));
      235
      236 if (url.startsWith("//")) {
      237 final int startHost = 2;
      238 int nextSlash = url.indexOf("/", startHost);
      239 if (nextSlash >= 0) {
      240 startFile = nextSlash + 1;
      241 } else {
      242 // no trailing slash implies no name
      243 nextSlash = url.length();
      244 startFile = nextSlash;
      245 }
      246
      247 int colon = url.indexOf(":", startHost);
      248 if ((colon > 1) && (colon < nextSlash)) {
      249 // explicit port supplied
      250 try {
      251 parsed.port =
      252 Integer.parseInt(url.substring(colon + 1,
      253 nextSlash));
      254 } catch (NumberFormatException e) {
      255 throw new MalformedURLException(
      256 "invalid port number: " + url);
      257 }
      258 }
      259
      260 // if have colon then endhost, else end with slash
      261 int endHost;
      262 if (colon >= startHost) {
      263 endHost = colon;
      264 } else {
      265 endHost = nextSlash;
      266 }
      267 parsed.host = url.substring(startHost, endHost);
      268
      269 } else if (url.startsWith("/")) {
      270 startFile = 1;
      271 } else {
      272 startFile = 0;
      273 }
      274 // set the bind name
      275 parsed.name = url.substring(startFile);
      276 if (parsed.name.equals("") || parsed.name.equals("/")) {
      277 parsed.name = null;
      278 }
      279
      280 return parsed;
      281 }
      ..............


      However, in 1.4.X/1.5, URI#getHost() returns null and URI#getPort() returns -1
      because "appsrv_k01" doesn't follow RF2396. The hostname includes '_'.
      In the above case, Naming#parseURL() seems to consider as hostname and port
      are abbreviated . The parseURL sets the hostname and port number to localhost IPaddress and 1089 respectively and keep processing.


      === ./j2se/src/share/classes/java/rmi/Naming.java (1.5b62) ====
      .............

         216 private static ParsedNamingURL parseURL(String str)
         217 throws MalformedURLException
         218 {
         219 try {
         220 URI uri = new URI(str);
         221 if (uri.getFragment() != null) {
         222 throw new MalformedURLException(
         223 "invalid character, '#', in URL name: " + str);
         224 } else if (uri.getQuery() != null) {
         225 throw new MalformedURLException(
         226 "invalid character, '?', in URL name: " + str);
         227 } else if (uri.getUserInfo() != null) {
         228 throw new MalformedURLException(
         229 "invalid character, '@', in URL host: " + str);
         230 }
         231 String scheme = uri.getScheme();
         232 if (scheme != null && !scheme.equals("rmi")) {
         233 throw new MalformedURLException("invalid URL scheme: " + str);
         234 }
         235
         236 String name = uri.getPath();
         237 if (name != null) {
         238 if (name.startsWith("/")) {
         239 name = name.substring(1);
         240 }
         241 if (name.length() == 0) {
         242 name = null;
         243 }
         244 }
         245
         246 String host = uri.getHost();
         247 if (host == null) {
         248 host = "";
         249 if (uri.getPort() == -1) {
         250 /* handle URIs with explicit port but no host
         251 * (e.g., "//:1098/foo"); although they do not strictly
         252 * conform to RFC 2396, Naming's javadoc explicitly allows
         253 * them.
         254 */
         255 String authority = uri.getAuthority();
         256 if (authority != null && authority.startsWith(":")) {
         257 authority = "localhost" + authority;
         258 uri = new URI(null, authority, null, null, null);
         259 }
         260 }
         261 }
         262 int port = uri.getPort();
         263 if (port == -1) {
         264 port = Registry.REGISTRY_PORT;
         265 }
         266 return new ParsedNamingURL(host, port, name);
         267
         268 } catch (URISyntaxException ex) {

      ...........

      PROBLEM :
        When a program uses the result of Naming#parseURL() as arguments
        for Naming#rebind,

       If the specifications is "argument for rebind should follow RFC 2396",
       MalformedURLException should be thrown by some method(parseURL or
       getHost ...?)
       At least, to consider "host name is abbreviated" doesn't seem reasonable.

       If the specifications is "argument for rebind may not follow RFC 2396",
       the hostname which includes '_' should be extracted. the current behavior
       in 1.4.X/1.5 to set hostname to local IP address doesn't seem reasonable.

      REQUEST :
        To clarify which behaviors is reasonable in rmi, in 1.3.1 and 1.4.X/1.5


      TEST PROGRAM:
        Please try the following program on the host which name includes '_'.

      ----- a.java -->
      import java.net.*;
      import java.rmi.*;
      import java.rmi.registry.*;
      import java.rmi.server.*;
      class a
      {
        public static void main(String[] arg)
        {
          try {
            int p = Integer.parseInt(arg[0]);
            String host = InetAddress.getLocalHost().getHostName();
            x xr = new x();
            LocateRegistry.createRegistry(p);
            try {
              Naming.rebind("rmi://" + host + ":"+p+"/xxx", xr);
              System.out.println("ok");
            } catch (Exception e) {
              System.out.println("ng");
              e.printStackTrace();
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
          System.exit(0);
        }
        interface z extends Remote {
          public void z() throws RemoteException;
        }
        static class x extends UnicastRemoteObject implements z
        {
          x() throws RemoteException {}
          public void z() {}
        }
      }
      <----

      HOW TO CONFIRM:
        - Launch the commnads in 1.5 as follows and you will see the similar
          message.

      K:\shares2\rmi-rfc2396-diff-131-141>javac a.java

      K:\shares2\rmi-rfc2396-diff-131-141>rmic a$x

      K:\shares2\rmi-rfc2396-diff-131-141>java a 12200

      java.rmi.ConnectException: Connection refused to host: xxx.yyy.zzz.uuu; nested exception is:
              java.net.ConnectException: Connection refused: connect
              at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:567)
              at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:185)
              at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:171)
              at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:313)
              at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
              at java.rmi.Naming.rebind(Naming.java:160)
              at a.main(a.java:15)
      Caused by: java.net.ConnectException: Connection refused: connect
              at java.net.PlainSocketImpl.socketConnect(Native Method)
              at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)
              at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:171)
              at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:158)
              at java.net.Socket.connect(Socket.java:452)
              at java.net.Socket.connect(Socket.java:402)
              at java.net.Socket.<init>(Socket.java:309)
              at java.net.Socket.<init>(Socket.java:124)
              at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:22)
              at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:128)
              at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:562)
              ... 6 more

      K:\shares2\rmi-rfc2396-diff-131-141>


      If you try in 1.3.1_0X, you will see only "o.k".


      =========================================================================================

            duke J. Duke
            tbaba Tadayuki Baba (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: