mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8278972: Improve URL supports
Reviewed-by: skoivu, rhalade, alanb
This commit is contained in:
parent
395bb5b7f9
commit
9e051d5396
5 changed files with 656 additions and 81 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,10 @@ package com.sun.jndi.ldap;
|
||||||
import javax.naming.*;
|
import javax.naming.*;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import com.sun.jndi.toolkit.url.Uri;
|
import com.sun.jndi.toolkit.url.Uri;
|
||||||
import com.sun.jndi.toolkit.url.UrlUtil;
|
import com.sun.jndi.toolkit.url.UrlUtil;
|
||||||
|
@ -64,6 +68,25 @@ import com.sun.jndi.toolkit.url.UrlUtil;
|
||||||
|
|
||||||
public final class LdapURL extends Uri {
|
public final class LdapURL extends Uri {
|
||||||
|
|
||||||
|
private static final String PARSE_MODE_PROP = "com.sun.jndi.ldapURLParsing";
|
||||||
|
private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT;
|
||||||
|
|
||||||
|
public static final ParseMode PARSE_MODE;
|
||||||
|
static {
|
||||||
|
PrivilegedAction<String> action = () ->
|
||||||
|
System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString());
|
||||||
|
ParseMode parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
String mode = AccessController.doPrivileged(action);
|
||||||
|
parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
} finally {
|
||||||
|
PARSE_MODE = parseMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean useSsl = false;
|
private boolean useSsl = false;
|
||||||
private String DN = null;
|
private String DN = null;
|
||||||
private String attributes = null;
|
private String attributes = null;
|
||||||
|
@ -83,7 +106,7 @@ public final class LdapURL extends Uri {
|
||||||
useSsl = scheme.equalsIgnoreCase("ldaps");
|
useSsl = scheme.equalsIgnoreCase("ldaps");
|
||||||
|
|
||||||
if (! (scheme.equalsIgnoreCase("ldap") || useSsl)) {
|
if (! (scheme.equalsIgnoreCase("ldap") || useSsl)) {
|
||||||
throw new MalformedURLException("Not an LDAP URL: " + url);
|
throw newInvalidURISchemeException(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
parsePathAndQuery(); // DN, attributes, scope, filter, extensions
|
parsePathAndQuery(); // DN, attributes, scope, filter, extensions
|
||||||
|
@ -99,6 +122,21 @@ public final class LdapURL extends Uri {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MalformedURLException newInvalidURISchemeException(String uri) {
|
||||||
|
return new MalformedURLException("Not an LDAP URL: " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isSchemeOnly(String uri) {
|
||||||
|
return isLdapSchemeOnly(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ParseMode parseMode() {
|
||||||
|
return PARSE_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the URL is an LDAPS URL.
|
* Returns true if the URL is an LDAPS URL.
|
||||||
*/
|
*/
|
||||||
|
@ -151,13 +189,33 @@ public final class LdapURL extends Uri {
|
||||||
StringTokenizer st = new StringTokenizer(urlList, " ");
|
StringTokenizer st = new StringTokenizer(urlList, " ");
|
||||||
|
|
||||||
while (st.hasMoreTokens()) {
|
while (st.hasMoreTokens()) {
|
||||||
urls[i++] = st.nextToken();
|
// we don't accept scheme-only URLs here
|
||||||
|
urls[i++] = validateURI(st.nextToken());
|
||||||
}
|
}
|
||||||
String[] trimmed = new String[i];
|
String[] trimmed = new String[i];
|
||||||
System.arraycopy(urls, 0, trimmed, 0, i);
|
System.arraycopy(urls, 0, trimmed, 0, i);
|
||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isLdapSchemeOnly(String uri) {
|
||||||
|
return "ldap:".equals(uri) || "ldaps:".equals(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String validateURI(String uri) {
|
||||||
|
// no validation in legacy mode parsing
|
||||||
|
if (PARSE_MODE == ParseMode.LEGACY) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case of scheme-only URIs
|
||||||
|
if (isLdapSchemeOnly(uri)) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use java.net.URI to validate the uri syntax
|
||||||
|
return URI.create(uri).toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether an LDAP URL has query components.
|
* Determines whether an LDAP URL has query components.
|
||||||
*/
|
*/
|
||||||
|
@ -181,7 +239,8 @@ public final class LdapURL extends Uri {
|
||||||
String p = (port != -1) ? (":" + port) : "";
|
String p = (port != -1) ? (":" + port) : "";
|
||||||
String d = (dn != null) ? ("/" + UrlUtil.encode(dn, "UTF8")) : "";
|
String d = (dn != null) ? ("/" + UrlUtil.encode(dn, "UTF8")) : "";
|
||||||
|
|
||||||
return useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d;
|
String uri = useSsl ? "ldaps://" + h + p + d : "ldap://" + h + p + d;
|
||||||
|
return validateURI(uri);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
// UTF8 should always be supported
|
// UTF8 should always be supported
|
||||||
throw new IllegalStateException("UTF-8 encoding unavailable");
|
throw new IllegalStateException("UTF-8 encoding unavailable");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -32,6 +32,8 @@ import javax.naming.spi.NamingManager;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
|
||||||
|
import com.sun.jndi.toolkit.url.Uri.ParseMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This abstract class is a generic URL context that accepts as the
|
* This abstract class is a generic URL context that accepts as the
|
||||||
* name argument either a string URL or a Name whose first component
|
* name argument either a string URL or a Name whose first component
|
||||||
|
@ -48,6 +50,7 @@ import java.net.MalformedURLException;
|
||||||
* @author Rosanna Lee
|
* @author Rosanna Lee
|
||||||
*/
|
*/
|
||||||
public abstract class GenericURLContext implements Context {
|
public abstract class GenericURLContext implements Context {
|
||||||
|
|
||||||
protected Hashtable<String, Object> myEnv = null;
|
protected Hashtable<String, Object> myEnv = null;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
|
@SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
|
||||||
|
@ -161,8 +164,18 @@ public abstract class GenericURLContext implements Context {
|
||||||
if (url.startsWith("//", start)) {
|
if (url.startsWith("//", start)) {
|
||||||
start += 2; // skip double slash
|
start += 2; // skip double slash
|
||||||
|
|
||||||
// find last slash
|
// find where the authority component ends
|
||||||
int posn = url.indexOf('/', start);
|
// and the rest of the URL starts
|
||||||
|
int slash = url.indexOf('/', start);
|
||||||
|
int qmark = url.indexOf('?', start);
|
||||||
|
int fmark = url.indexOf('#', start);
|
||||||
|
if (fmark > -1 && qmark > fmark) qmark = -1;
|
||||||
|
if (fmark > -1 && slash > fmark) slash = -1;
|
||||||
|
if (qmark > -1 && slash > qmark) slash = -1;
|
||||||
|
int posn = slash > -1 ? slash
|
||||||
|
: (qmark > -1 ? qmark
|
||||||
|
: (fmark > -1 ? fmark
|
||||||
|
: url.length()));
|
||||||
if (posn >= 0) {
|
if (posn >= 0) {
|
||||||
start = posn;
|
start = posn;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,6 +27,8 @@ package com.sun.jndi.toolkit.url;
|
||||||
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,15 +38,17 @@ import java.net.MalformedURLException;
|
||||||
*
|
*
|
||||||
* <p> The java.net.URL class cannot be used to parse URIs since it
|
* <p> The java.net.URL class cannot be used to parse URIs since it
|
||||||
* requires the installation of URL stream handlers that may not be
|
* requires the installation of URL stream handlers that may not be
|
||||||
* available. The hack of getting around this by temporarily
|
* available.
|
||||||
* replacing the scheme part of a URI is not appropriate here: JNDI
|
|
||||||
* service providers must work on older Java platforms, and we want
|
|
||||||
* new features and bug fixes that are not available in old versions
|
|
||||||
* of the URL class.
|
|
||||||
*
|
*
|
||||||
* <p> It may be appropriate to drop this code in favor of the
|
* <p> The {@linkplain ParseMode#STRICT strict} parsing mode uses
|
||||||
* java.net.URI class. The changes would need to be written so as to
|
* the java.net.URI class to syntactically validate URI strings.
|
||||||
* still run on pre-1.4 platforms not containing that class.
|
* The {@linkplain ParseMode#COMPAT compat} mode validate the
|
||||||
|
* URI authority and rejects URI fragments, but doesn't perform any
|
||||||
|
* additional validation on path and query, other than that
|
||||||
|
* which may be implemented in the concrete the Uri subclasses.
|
||||||
|
* The {@linkplain ParseMode#LEGACY legacy} mode should not be
|
||||||
|
* used unless the application is capable of validating all URI
|
||||||
|
* strings before any constructors of this class is invoked.
|
||||||
*
|
*
|
||||||
* <p> The format of an absolute URI (see the RFCs mentioned above) is:
|
* <p> The format of an absolute URI (see the RFCs mentioned above) is:
|
||||||
* <blockquote><pre>{@code
|
* <blockquote><pre>{@code
|
||||||
|
@ -105,6 +109,28 @@ import java.net.MalformedURLException;
|
||||||
|
|
||||||
public class Uri {
|
public class Uri {
|
||||||
|
|
||||||
|
// three parsing modes
|
||||||
|
public enum ParseMode {
|
||||||
|
/**
|
||||||
|
* Strict validation mode.
|
||||||
|
* Validate the URI syntactically using {@link java.net.URI}.
|
||||||
|
* Rejects URI fragments unless explicitly supported by the
|
||||||
|
* subclass.
|
||||||
|
*/
|
||||||
|
STRICT,
|
||||||
|
/**
|
||||||
|
* Compatibility mode. The URI authority is syntactically validated.
|
||||||
|
* Rejects URI fragments unless explicitly supported by the
|
||||||
|
* subclass.
|
||||||
|
* This is the default.
|
||||||
|
*/
|
||||||
|
COMPAT,
|
||||||
|
/**
|
||||||
|
* Legacy mode. In this mode, no validation is performed.
|
||||||
|
*/
|
||||||
|
LEGACY
|
||||||
|
}
|
||||||
|
|
||||||
protected String uri;
|
protected String uri;
|
||||||
protected String scheme;
|
protected String scheme;
|
||||||
protected String host = null;
|
protected String host = null;
|
||||||
|
@ -112,6 +138,7 @@ public class Uri {
|
||||||
protected boolean hasAuthority;
|
protected boolean hasAuthority;
|
||||||
protected String path;
|
protected String path;
|
||||||
protected String query = null;
|
protected String query = null;
|
||||||
|
protected String fragment;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,6 +155,15 @@ public class Uri {
|
||||||
protected Uri() {
|
protected Uri() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parse mode for parsing this URI.
|
||||||
|
* The default is {@link ParseMode#COMPAT}.
|
||||||
|
* @return the parse mode for parsing this URI.
|
||||||
|
*/
|
||||||
|
protected ParseMode parseMode() {
|
||||||
|
return ParseMode.COMPAT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a Uri object given a URI string.
|
* Initializes a Uri object given a URI string.
|
||||||
* This method must be called exactly once, and before any other Uri
|
* This method must be called exactly once, and before any other Uri
|
||||||
|
@ -135,7 +171,7 @@ public class Uri {
|
||||||
*/
|
*/
|
||||||
protected void init(String uri) throws MalformedURLException {
|
protected void init(String uri) throws MalformedURLException {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
parse(uri);
|
parse(uri, parseMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,10 +224,229 @@ public class Uri {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parse(String uri, ParseMode mode) throws MalformedURLException {
|
||||||
|
switch (mode) {
|
||||||
|
case STRICT -> parseStrict(uri);
|
||||||
|
case COMPAT -> parseCompat(uri);
|
||||||
|
case LEGACY -> parseLegacy(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parses a URI string and sets this object's fields accordingly.
|
* Parses a URI string and sets this object's fields accordingly.
|
||||||
|
* Use java.net.URI to validate the uri string syntax
|
||||||
*/
|
*/
|
||||||
private void parse(String uri) throws MalformedURLException {
|
private void parseStrict(String uri) throws MalformedURLException {
|
||||||
|
try {
|
||||||
|
if (!isSchemeOnly(uri)) {
|
||||||
|
URI u = new URI(uri);
|
||||||
|
scheme = u.getScheme();
|
||||||
|
if (scheme == null) throw new MalformedURLException("Invalid URI: " + uri);
|
||||||
|
var auth = u.getRawAuthority();
|
||||||
|
hasAuthority = auth != null;
|
||||||
|
if (hasAuthority) {
|
||||||
|
var host = u.getHost();
|
||||||
|
var port = u.getPort();
|
||||||
|
if (host != null) this.host = host;
|
||||||
|
if (port != -1) this.port = port;
|
||||||
|
String hostport = (host == null ? "" : host)
|
||||||
|
+ (port == -1 ? "" : (":" + port));
|
||||||
|
if (!hostport.equals(auth)) {
|
||||||
|
// throw if we have user info or regname
|
||||||
|
throw new MalformedURLException("unsupported authority: " + auth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path = u.getRawPath();
|
||||||
|
if (u.getRawQuery() != null) {
|
||||||
|
query = "?" + u.getRawQuery();
|
||||||
|
}
|
||||||
|
if (u.getRawFragment() != null) {
|
||||||
|
if (!acceptsFragment()) {
|
||||||
|
throw new MalformedURLException("URI fragments not supported: " + uri);
|
||||||
|
}
|
||||||
|
fragment = "#" + u.getRawFragment();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// scheme-only URIs are not supported by java.net.URI
|
||||||
|
// validate the URI by appending "/" to the uri string.
|
||||||
|
var s = uri.substring(0, uri.indexOf(':'));
|
||||||
|
URI u = new URI(uri + "/");
|
||||||
|
if (!s.equals(u.getScheme())
|
||||||
|
|| !checkSchemeOnly(uri, u.getScheme())) {
|
||||||
|
throw newInvalidURISchemeException(uri);
|
||||||
|
}
|
||||||
|
scheme = s;
|
||||||
|
path = "";
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
var mue = new MalformedURLException(e.getMessage());
|
||||||
|
mue.initCause(e);
|
||||||
|
throw mue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses a URI string and sets this object's fields accordingly.
|
||||||
|
* Compatibility mode. Use java.net.URI to validate the syntax of
|
||||||
|
* the uri string authority.
|
||||||
|
*/
|
||||||
|
private void parseCompat(String uri) throws MalformedURLException {
|
||||||
|
int i; // index into URI
|
||||||
|
|
||||||
|
i = uri.indexOf(':'); // parse scheme
|
||||||
|
int slash = uri.indexOf('/');
|
||||||
|
int qmark = uri.indexOf('?');
|
||||||
|
int fmark = uri.indexOf('#');
|
||||||
|
if (i < 0 || slash > 0 && i > slash || qmark > 0 && i > qmark || fmark > 0 && i > fmark) {
|
||||||
|
throw new MalformedURLException("Invalid URI: " + uri);
|
||||||
|
}
|
||||||
|
if (fmark > -1) {
|
||||||
|
if (!acceptsFragment()) {
|
||||||
|
throw new MalformedURLException("URI fragments not supported: " + uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == uri.length() - 1) {
|
||||||
|
if (!isSchemeOnly(uri)) {
|
||||||
|
throw newInvalidURISchemeException(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scheme = uri.substring(0, i);
|
||||||
|
i++; // skip past ":"
|
||||||
|
|
||||||
|
hasAuthority = uri.startsWith("//", i);
|
||||||
|
if (fmark > -1 && qmark > fmark) qmark = -1;
|
||||||
|
int endp = qmark > -1 ? qmark : fmark > -1 ? fmark : uri.length();
|
||||||
|
if (hasAuthority) { // parse "//host:port"
|
||||||
|
i += 2; // skip past "//"
|
||||||
|
int starta = i;
|
||||||
|
// authority ends at the first appearance of /, ?, or #
|
||||||
|
int enda = uri.indexOf('/', i);
|
||||||
|
if (enda == -1 || qmark > -1 && qmark < enda) enda = qmark;
|
||||||
|
if (enda == -1 || fmark > -1 && fmark < enda) enda = fmark;
|
||||||
|
if (enda < 0) {
|
||||||
|
enda = uri.length();
|
||||||
|
}
|
||||||
|
if (uri.startsWith(":", i)) {
|
||||||
|
// LdapURL supports empty host.
|
||||||
|
i++;
|
||||||
|
host = "";
|
||||||
|
if (enda > i) {
|
||||||
|
port = Integer.parseInt(uri.substring(i, enda));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use URI to parse authority
|
||||||
|
try {
|
||||||
|
// URI requires at least one char after authority:
|
||||||
|
// we use "/" and expect that the resulting URI path
|
||||||
|
// will be exactly "/".
|
||||||
|
URI u = new URI(uri.substring(0, enda) + "/");
|
||||||
|
String auth = uri.substring(starta, enda);
|
||||||
|
host = u.getHost();
|
||||||
|
port = u.getPort();
|
||||||
|
String p = u.getRawPath();
|
||||||
|
String q = u.getRawQuery();
|
||||||
|
String f = u.getRawFragment();
|
||||||
|
String ui = u.getRawUserInfo();
|
||||||
|
if (ui != null) {
|
||||||
|
throw new MalformedURLException("user info not supported in authority: " + ui);
|
||||||
|
}
|
||||||
|
if (!"/".equals(p)) {
|
||||||
|
throw new MalformedURLException("invalid authority: " + auth);
|
||||||
|
}
|
||||||
|
if (q != null) {
|
||||||
|
throw new MalformedURLException("invalid trailing characters in authority: ?" + q);
|
||||||
|
}
|
||||||
|
if (f != null) {
|
||||||
|
throw new MalformedURLException("invalid trailing characters in authority: #" + f);
|
||||||
|
}
|
||||||
|
String hostport = (host == null ? "" : host)
|
||||||
|
+ (port == -1?"":(":" + port));
|
||||||
|
if (!auth.equals(hostport)) {
|
||||||
|
// throw if we have user info or regname
|
||||||
|
throw new MalformedURLException("unsupported authority: " + auth);
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
var mue = new MalformedURLException(e.getMessage());
|
||||||
|
mue.initCause(e);
|
||||||
|
throw mue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = enda;
|
||||||
|
}
|
||||||
|
path = uri.substring(i, endp);
|
||||||
|
// look for query
|
||||||
|
if (qmark > -1) {
|
||||||
|
if (fmark > -1) {
|
||||||
|
query = uri.substring(qmark, fmark);
|
||||||
|
} else {
|
||||||
|
query = uri.substring(qmark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fmark > -1) {
|
||||||
|
fragment = uri.substring(fmark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subclass of {@code Uri} that supports scheme only
|
||||||
|
* URIs can override this method and return true in the
|
||||||
|
* case where the URI string is a scheme-only URI that
|
||||||
|
* the subclass supports.
|
||||||
|
* @implSpec
|
||||||
|
* The default implementation of this method returns false,
|
||||||
|
* always.
|
||||||
|
* @param uri An URI string
|
||||||
|
* @return if this is a scheme-only URI supported by the subclass
|
||||||
|
*/
|
||||||
|
protected boolean isSchemeOnly(String uri) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given uri string should be considered
|
||||||
|
* as a scheme-only URI. For some protocols - e.g. DNS, we
|
||||||
|
* might accept "dns://" as a valid URL denoting default DNS.
|
||||||
|
* For others - we might only accept "scheme:".
|
||||||
|
* @implSpec
|
||||||
|
* The default implementation of this method returns true if
|
||||||
|
* the URI is of the form {@code "<scheme>:"} with nothing
|
||||||
|
* after the scheme delimiter.
|
||||||
|
* @param uri the URI
|
||||||
|
* @param scheme the scheme
|
||||||
|
* @return true if the URI should be considered as a scheme-only
|
||||||
|
* URI supported by this URI scheme.
|
||||||
|
*/
|
||||||
|
protected boolean checkSchemeOnly(String uri, String scheme) {
|
||||||
|
return uri.equals(scheme + ":");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@code MalformedURLException} to be thrown when the
|
||||||
|
* URI scheme is not supported.
|
||||||
|
*
|
||||||
|
* @param uri the URI string
|
||||||
|
* @return a {@link MalformedURLException}
|
||||||
|
*/
|
||||||
|
protected MalformedURLException newInvalidURISchemeException(String uri) {
|
||||||
|
return new MalformedURLException("Invalid URI scheme: " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether fragments are supported.
|
||||||
|
* @implSpec
|
||||||
|
* The default implementation of this method retturns false, always.
|
||||||
|
* @return true if fragments are supported.
|
||||||
|
*/
|
||||||
|
protected boolean acceptsFragment() {
|
||||||
|
return parseMode() == ParseMode.LEGACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses a URI string and sets this object's fields accordingly.
|
||||||
|
* Legacy parsing mode.
|
||||||
|
*/
|
||||||
|
private void parseLegacy(String uri) throws MalformedURLException {
|
||||||
int i; // index into URI
|
int i; // index into URI
|
||||||
|
|
||||||
i = uri.indexOf(':'); // parse scheme
|
i = uri.indexOf(':'); // parse scheme
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,7 +27,11 @@ package com.sun.jndi.dns;
|
||||||
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.Hashtable;
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import com.sun.jndi.toolkit.url.Uri;
|
import com.sun.jndi.toolkit.url.Uri;
|
||||||
|
@ -56,6 +60,24 @@ import com.sun.jndi.toolkit.url.UrlUtil;
|
||||||
|
|
||||||
public class DnsUrl extends Uri {
|
public class DnsUrl extends Uri {
|
||||||
|
|
||||||
|
private static final String PARSE_MODE_PROP = "com.sun.jndi.dnsURLParsing";
|
||||||
|
private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT;
|
||||||
|
|
||||||
|
public static final ParseMode PARSE_MODE;
|
||||||
|
static {
|
||||||
|
PrivilegedAction<String> action = () ->
|
||||||
|
System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString());
|
||||||
|
ParseMode parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
String mode = AccessController.doPrivileged(action);
|
||||||
|
parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
} finally {
|
||||||
|
PARSE_MODE = parseMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
private String domain; // domain name of the context
|
private String domain; // domain name of the context
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,19 +93,58 @@ public class DnsUrl extends Uri {
|
||||||
StringTokenizer st = new StringTokenizer(urlList, " ");
|
StringTokenizer st = new StringTokenizer(urlList, " ");
|
||||||
|
|
||||||
while (st.hasMoreTokens()) {
|
while (st.hasMoreTokens()) {
|
||||||
urls[i++] = new DnsUrl(st.nextToken());
|
try {
|
||||||
|
urls[i++] = new DnsUrl(validateURI(st.nextToken()));
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
MalformedURLException mue = new MalformedURLException(e.getMessage());
|
||||||
|
mue.initCause(e);
|
||||||
|
throw mue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DnsUrl[] trimmed = new DnsUrl[i];
|
DnsUrl[] trimmed = new DnsUrl[i];
|
||||||
System.arraycopy(urls, 0, trimmed, 0, i);
|
System.arraycopy(urls, 0, trimmed, 0, i);
|
||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ParseMode parseMode() {
|
||||||
|
return PARSE_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final boolean isSchemeOnly(String uri) {
|
||||||
|
return isDnsSchemeOnly(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean checkSchemeOnly(String uri, String scheme) {
|
||||||
|
return uri.equals(scheme + ":") || uri.equals(scheme + "://");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final MalformedURLException newInvalidURISchemeException(String uri) {
|
||||||
|
return new MalformedURLException(
|
||||||
|
uri + " is not a valid DNS pseudo-URL");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDnsSchemeOnly(String uri) {
|
||||||
|
return "dns:".equals(uri) || "dns://".equals(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String validateURI(String uri) throws URISyntaxException {
|
||||||
|
// no validation in legacy parsing mode
|
||||||
|
if (PARSE_MODE == ParseMode.LEGACY) return uri;
|
||||||
|
// special case of scheme-only URIs
|
||||||
|
if (isDnsSchemeOnly(uri)) return uri;
|
||||||
|
// use java.net.URI to validate the uri syntax
|
||||||
|
return new URI(uri).toString();
|
||||||
|
}
|
||||||
|
|
||||||
public DnsUrl(String url) throws MalformedURLException {
|
public DnsUrl(String url) throws MalformedURLException {
|
||||||
super(url);
|
super(url);
|
||||||
|
|
||||||
if (!scheme.equals("dns")) {
|
if (!scheme.equals("dns")) {
|
||||||
throw new MalformedURLException(
|
throw newInvalidURISchemeException(url);
|
||||||
url + " is not a valid DNS pseudo-URL");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
domain = path.startsWith("/")
|
domain = path.startsWith("/")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,12 +25,17 @@
|
||||||
|
|
||||||
package com.sun.jndi.url.rmi;
|
package com.sun.jndi.url.rmi;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.naming.*;
|
import javax.naming.*;
|
||||||
import javax.naming.spi.ResolveResult;
|
import javax.naming.spi.ResolveResult;
|
||||||
import com.sun.jndi.toolkit.url.GenericURLContext;
|
import com.sun.jndi.toolkit.url.GenericURLContext;
|
||||||
import com.sun.jndi.rmi.registry.RegistryContext;
|
import com.sun.jndi.rmi.registry.RegistryContext;
|
||||||
|
import com.sun.jndi.toolkit.url.Uri.ParseMode;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,10 +52,244 @@ import com.sun.jndi.rmi.registry.RegistryContext;
|
||||||
*/
|
*/
|
||||||
public class rmiURLContext extends GenericURLContext {
|
public class rmiURLContext extends GenericURLContext {
|
||||||
|
|
||||||
|
private static final String PARSE_MODE_PROP = "com.sun.jndi.rmiURLParsing";
|
||||||
|
private static final ParseMode DEFAULT_PARSE_MODE = ParseMode.COMPAT;
|
||||||
|
|
||||||
|
public static final ParseMode PARSE_MODE;
|
||||||
|
static {
|
||||||
|
PrivilegedAction<String> action = () ->
|
||||||
|
System.getProperty(PARSE_MODE_PROP, DEFAULT_PARSE_MODE.toString());
|
||||||
|
ParseMode parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
try {
|
||||||
|
@SuppressWarnings("removal")
|
||||||
|
String mode = AccessController.doPrivileged(action);
|
||||||
|
parseMode = ParseMode.valueOf(mode.toUpperCase(Locale.ROOT));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
parseMode = DEFAULT_PARSE_MODE;
|
||||||
|
} finally {
|
||||||
|
PARSE_MODE = parseMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public rmiURLContext(Hashtable<?,?> env) {
|
public rmiURLContext(Hashtable<?,?> env) {
|
||||||
super(env);
|
super(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Parser {
|
||||||
|
final String url;
|
||||||
|
final ParseMode mode;
|
||||||
|
String host = null;
|
||||||
|
int port = -1;
|
||||||
|
String objName = null;
|
||||||
|
public Parser(String url) {
|
||||||
|
this(url, PARSE_MODE);
|
||||||
|
}
|
||||||
|
public Parser(String url, ParseMode mode) {
|
||||||
|
this.url = url;
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String url() {return url;}
|
||||||
|
public String host() {return host;}
|
||||||
|
public int port() {return port;}
|
||||||
|
public String objName() {return objName;}
|
||||||
|
public ParseMode mode() {return mode;}
|
||||||
|
|
||||||
|
public void parse() throws NamingException {
|
||||||
|
if (!url.startsWith("rmi:")) {
|
||||||
|
throw (new IllegalArgumentException(
|
||||||
|
"rmiURLContext: name is not an RMI URL: " + url));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case STRICT -> parseStrict();
|
||||||
|
case COMPAT -> parseCompat();
|
||||||
|
case LEGACY -> parseLegacy();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseStrict() throws NamingException {
|
||||||
|
assert url.startsWith("rmi:");
|
||||||
|
|
||||||
|
if (url.equals("rmi:") || url.equals("rmi://")) return;
|
||||||
|
|
||||||
|
// index into url, following the "rmi:"
|
||||||
|
int i = 4;
|
||||||
|
|
||||||
|
if (url.startsWith("//", i)) {
|
||||||
|
i += 2;
|
||||||
|
try {
|
||||||
|
URI uri = URI.create(url);
|
||||||
|
host = uri.getHost();
|
||||||
|
port = uri.getPort();
|
||||||
|
String auth = uri.getRawAuthority();
|
||||||
|
String hostport = (host == null ? "" : host)
|
||||||
|
+ (port == -1 ? "" : ":" + port);
|
||||||
|
if (!hostport.equals(auth)) {
|
||||||
|
boolean failed = true;
|
||||||
|
if (hostport.equals("") && auth.startsWith(":")) {
|
||||||
|
// supports missing host
|
||||||
|
try {
|
||||||
|
port = Integer.parseInt(auth.substring(1));
|
||||||
|
failed = false;
|
||||||
|
} catch (NumberFormatException x) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failed) {
|
||||||
|
throw newNamingException(new IllegalArgumentException("invalid authority: "
|
||||||
|
+ auth));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i += auth.length();
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
throw newNamingException(iae);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("".equals(host)) {
|
||||||
|
host = null;
|
||||||
|
}
|
||||||
|
if (url.startsWith("/", i)) { // skip "/" before object name
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i < url.length()) {
|
||||||
|
objName = url.substring(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseCompat() throws NamingException {
|
||||||
|
assert url.startsWith("rmi:");
|
||||||
|
|
||||||
|
int i = 4; // index into url, following the "rmi:"
|
||||||
|
boolean hasAuthority = url.startsWith("//", i);
|
||||||
|
if (hasAuthority) i += 2; // skip past "//"
|
||||||
|
int slash = url.indexOf('/', i);
|
||||||
|
int qmark = url.indexOf('?', i);
|
||||||
|
int fmark = url.indexOf('#', i);
|
||||||
|
if (fmark > -1 && qmark > fmark) qmark = -1;
|
||||||
|
if (fmark > -1 && slash > fmark) slash = -1;
|
||||||
|
if (qmark > -1 && slash > qmark) slash = -1;
|
||||||
|
|
||||||
|
// The end of the authority component is either the
|
||||||
|
// slash (slash will be -1 if it doesn't come before
|
||||||
|
// query or fragment), or the question mark (qmark will
|
||||||
|
// be -1 if it doesn't come before the fragment), or
|
||||||
|
// the fragment separator, or the end of the URI
|
||||||
|
// string if there is no path, no query, and no fragment.
|
||||||
|
int enda = slash > -1 ? slash
|
||||||
|
: (qmark > -1 ? qmark
|
||||||
|
: (fmark > -1 ? fmark
|
||||||
|
: url.length()));
|
||||||
|
if (fmark > -1) {
|
||||||
|
if (!acceptsFragment()) {
|
||||||
|
throw newNamingException(new IllegalArgumentException("URI fragments not supported: " + url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAuthority && enda > i) { // parse "//host:port"
|
||||||
|
if (url.startsWith(":", i)) {
|
||||||
|
// LdapURL supports empty host.
|
||||||
|
i++;
|
||||||
|
host = "";
|
||||||
|
if (enda > i) {
|
||||||
|
port = Integer.parseInt(url.substring(i, enda));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
URI uri = URI.create(url.substring(0, enda));
|
||||||
|
host = uri.getHost();
|
||||||
|
port = uri.getPort();
|
||||||
|
String hostport = (host == null ? "" : host)
|
||||||
|
+ (port == -1 ? "" : ":" + port);
|
||||||
|
if (!hostport.equals(uri.getRawAuthority())) {
|
||||||
|
throw newNamingException(new IllegalArgumentException("invalid authority: "
|
||||||
|
+ uri.getRawAuthority()));
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
throw newNamingException(iae);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = enda;
|
||||||
|
}
|
||||||
|
if ("".equals(host)) {
|
||||||
|
host = null;
|
||||||
|
}
|
||||||
|
if (url.startsWith("/", i)) { // skip "/" before object name
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i < url.length()) {
|
||||||
|
objName = url.substring(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The legacy parsing used to only throw IllegalArgumentException
|
||||||
|
// and continues to do so
|
||||||
|
private void parseLegacy() {
|
||||||
|
assert url.startsWith("rmi:");
|
||||||
|
|
||||||
|
// Parse the URL.
|
||||||
|
int i = 4; // index into url, following the "rmi:"
|
||||||
|
|
||||||
|
if (url.startsWith("//", i)) { // parse "//host:port"
|
||||||
|
i += 2; // skip past "//"
|
||||||
|
int slash = url.indexOf('/', i);
|
||||||
|
if (slash < 0) {
|
||||||
|
slash = url.length();
|
||||||
|
}
|
||||||
|
if (url.startsWith("[", i)) { // at IPv6 literal
|
||||||
|
int brac = url.indexOf(']', i + 1);
|
||||||
|
if (brac < 0 || brac > slash) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"rmiURLContext: name is an Invalid URL: " + url);
|
||||||
|
}
|
||||||
|
host = url.substring(i, brac + 1); // include brackets
|
||||||
|
i = brac + 1; // skip past "[...]"
|
||||||
|
} else { // at host name or IPv4
|
||||||
|
int colon = url.indexOf(':', i);
|
||||||
|
int hostEnd = (colon < 0 || colon > slash)
|
||||||
|
? slash
|
||||||
|
: colon;
|
||||||
|
if (i < hostEnd) {
|
||||||
|
host = url.substring(i, hostEnd);
|
||||||
|
}
|
||||||
|
i = hostEnd; // skip past host
|
||||||
|
}
|
||||||
|
if ((i + 1 < slash)) {
|
||||||
|
if ( url.startsWith(":", i)) { // parse port
|
||||||
|
i++; // skip past ":"
|
||||||
|
port = Integer.parseInt(url.substring(i, slash));
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"rmiURLContext: name is an Invalid URL: " + url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = slash;
|
||||||
|
}
|
||||||
|
if ("".equals(host)) {
|
||||||
|
host = null;
|
||||||
|
}
|
||||||
|
if (url.startsWith("/", i)) { // skip "/" before object name
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i < url.length()) {
|
||||||
|
objName = url.substring(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NamingException newNamingException(Throwable cause) {
|
||||||
|
NamingException ne = new NamingException(cause.getMessage());
|
||||||
|
ne.initCause(cause);
|
||||||
|
return ne;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean acceptsFragment() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the registry portion of "url" to the corresponding
|
* Resolves the registry portion of "url" to the corresponding
|
||||||
* RMI registry, and returns the atomic object name as the
|
* RMI registry, and returns the atomic object name as the
|
||||||
|
@ -59,63 +298,11 @@ public class rmiURLContext extends GenericURLContext {
|
||||||
protected ResolveResult getRootURLContext(String url, Hashtable<?,?> env)
|
protected ResolveResult getRootURLContext(String url, Hashtable<?,?> env)
|
||||||
throws NamingException
|
throws NamingException
|
||||||
{
|
{
|
||||||
if (!url.startsWith("rmi:")) {
|
Parser parser = new Parser(url);
|
||||||
throw (new IllegalArgumentException(
|
parser.parse();
|
||||||
"rmiURLContext: name is not an RMI URL: " + url));
|
String host = parser.host;
|
||||||
}
|
int port = parser.port;
|
||||||
|
String objName = parser.objName;
|
||||||
// Parse the URL.
|
|
||||||
|
|
||||||
String host = null;
|
|
||||||
int port = -1;
|
|
||||||
String objName = null;
|
|
||||||
|
|
||||||
int i = 4; // index into url, following the "rmi:"
|
|
||||||
|
|
||||||
if (url.startsWith("//", i)) { // parse "//host:port"
|
|
||||||
i += 2; // skip past "//"
|
|
||||||
int slash = url.indexOf('/', i);
|
|
||||||
if (slash < 0) {
|
|
||||||
slash = url.length();
|
|
||||||
}
|
|
||||||
if (url.startsWith("[", i)) { // at IPv6 literal
|
|
||||||
int brac = url.indexOf(']', i + 1);
|
|
||||||
if (brac < 0 || brac > slash) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"rmiURLContext: name is an Invalid URL: " + url);
|
|
||||||
}
|
|
||||||
host = url.substring(i, brac + 1); // include brackets
|
|
||||||
i = brac + 1; // skip past "[...]"
|
|
||||||
} else { // at host name or IPv4
|
|
||||||
int colon = url.indexOf(':', i);
|
|
||||||
int hostEnd = (colon < 0 || colon > slash)
|
|
||||||
? slash
|
|
||||||
: colon;
|
|
||||||
if (i < hostEnd) {
|
|
||||||
host = url.substring(i, hostEnd);
|
|
||||||
}
|
|
||||||
i = hostEnd; // skip past host
|
|
||||||
}
|
|
||||||
if ((i + 1 < slash)) {
|
|
||||||
if ( url.startsWith(":", i)) { // parse port
|
|
||||||
i++; // skip past ":"
|
|
||||||
port = Integer.parseInt(url.substring(i, slash));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"rmiURLContext: name is an Invalid URL: " + url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = slash;
|
|
||||||
}
|
|
||||||
if ("".equals(host)) {
|
|
||||||
host = null;
|
|
||||||
}
|
|
||||||
if (url.startsWith("/", i)) { // skip "/" before object name
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i < url.length()) {
|
|
||||||
objName = url.substring(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represent object name as empty or single-component composite name.
|
// Represent object name as empty or single-component composite name.
|
||||||
CompositeName remaining = new CompositeName();
|
CompositeName remaining = new CompositeName();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue