Path: blob/master/src/java.rmi/share/classes/java/rmi/Naming.java
41152 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.rmi;2526import java.rmi.registry.*;27import java.net.MalformedURLException;28import java.net.URI;29import java.net.URISyntaxException;3031/**32* The <code>Naming</code> class provides methods for storing and obtaining33* references to remote objects in a remote object registry. Each method of34* the <code>Naming</code> class takes as one of its arguments a name that35* is a <code>java.lang.String</code> in URL format (without the36* scheme component) of the form:37*38* <PRE>39* //host:port/name40* </PRE>41*42* <P>where <code>host</code> is the host (remote or local) where the registry43* is located, <code>port</code> is the port number on which the registry44* accepts calls, and where <code>name</code> is a simple string uninterpreted45* by the registry. Both <code>host</code> and <code>port</code> are optional.46* If <code>host</code> is omitted, the host defaults to the local host. If47* <code>port</code> is omitted, then the port defaults to 1099, the48* "well-known" port that RMI's registry, <code>rmiregistry</code>, uses.49*50* <P><em>Binding</em> a name for a remote object is associating or51* registering a name for a remote object that can be used at a later time to52* look up that remote object. A remote object can be associated with a name53* using the <code>Naming</code> class's <code>bind</code> or54* <code>rebind</code> methods.55*56* <P>Once a remote object is registered (bound) with the RMI registry on the57* local host, callers on a remote (or local) host can lookup the remote58* object by name, obtain its reference, and then invoke remote methods on the59* object. A registry may be shared by all servers running on a host or an60* individual server process may create and use its own registry if desired61* (see <code>java.rmi.registry.LocateRegistry.createRegistry</code> method62* for details).63*64* @author Ann Wollrath65* @author Roger Riggs66* @since 1.167* @see java.rmi.registry.Registry68* @see java.rmi.registry.LocateRegistry69* @see java.rmi.registry.LocateRegistry#createRegistry(int)70*/71public final class Naming {72/**73* Disallow anyone from creating one of these74*/75private Naming() {}7677/**78* Returns a reference, a stub, for the remote object associated79* with the specified <code>name</code>.80*81* @param name a name in URL format (without the scheme component)82* @return a reference for a remote object83* @throws NotBoundException if name is not currently bound84* @throws RemoteException if registry could not be contacted85* @throws AccessException if this operation is not permitted86* @throws MalformedURLException if the name is not an appropriately87* formatted URL88* @since 1.189*/90public static Remote lookup(String name)91throws NotBoundException,92java.net.MalformedURLException,93RemoteException94{95ParsedNamingURL parsed = parseURL(name);96Registry registry = getRegistry(parsed);9798if (parsed.name == null)99return registry;100return registry.lookup(parsed.name);101}102103/**104* Binds the specified <code>name</code> to a remote object.105*106* @param name a name in URL format (without the scheme component)107* @param obj a reference for the remote object (usually a stub)108* @throws AlreadyBoundException if name is already bound109* @throws MalformedURLException if the name is not an appropriately110* formatted URL111* @throws RemoteException if registry could not be contacted112* @throws AccessException if this operation is not permitted (if113* originating from a non-local host, for example)114* @since 1.1115*/116public static void bind(String name, Remote obj)117throws AlreadyBoundException,118java.net.MalformedURLException,119RemoteException120{121ParsedNamingURL parsed = parseURL(name);122Registry registry = getRegistry(parsed);123124if (obj == null)125throw new NullPointerException("cannot bind to null");126127registry.bind(parsed.name, obj);128}129130/**131* Destroys the binding for the specified name that is associated132* with a remote object.133*134* @param name a name in URL format (without the scheme component)135* @throws NotBoundException if name is not currently bound136* @throws MalformedURLException if the name is not an appropriately137* formatted URL138* @throws RemoteException if registry could not be contacted139* @throws AccessException if this operation is not permitted (if140* originating from a non-local host, for example)141* @since 1.1142*/143public static void unbind(String name)144throws RemoteException,145NotBoundException,146java.net.MalformedURLException147{148ParsedNamingURL parsed = parseURL(name);149Registry registry = getRegistry(parsed);150151registry.unbind(parsed.name);152}153154/**155* Rebinds the specified name to a new remote object. Any existing156* binding for the name is replaced.157*158* @param name a name in URL format (without the scheme component)159* @param obj new remote object to associate with the name160* @throws MalformedURLException if the name is not an appropriately161* formatted URL162* @throws RemoteException if registry could not be contacted163* @throws AccessException if this operation is not permitted (if164* originating from a non-local host, for example)165* @since 1.1166*/167public static void rebind(String name, Remote obj)168throws RemoteException, java.net.MalformedURLException169{170ParsedNamingURL parsed = parseURL(name);171Registry registry = getRegistry(parsed);172173if (obj == null)174throw new NullPointerException("cannot bind to null");175176registry.rebind(parsed.name, obj);177}178179/**180* Returns an array of the names bound in the registry. The names are181* URL-formatted (without the scheme component) strings. The array contains182* a snapshot of the names present in the registry at the time of the183* call.184*185* @param name a registry name in URL format (without the scheme186* component)187* @return an array of names (in the appropriate format) bound188* in the registry189* @throws MalformedURLException if the name is not an appropriately190* formatted URL191* @throws RemoteException if registry could not be contacted.192* @since 1.1193*/194public static String[] list(String name)195throws RemoteException, java.net.MalformedURLException196{197ParsedNamingURL parsed = parseURL(name);198Registry registry = getRegistry(parsed);199200String prefix = "";201if (parsed.port > 0 || !parsed.host.isEmpty())202prefix += "//" + parsed.host;203if (parsed.port > 0)204prefix += ":" + parsed.port;205prefix += "/";206207String[] names = registry.list();208for (int i = 0; i < names.length; i++) {209names[i] = prefix + names[i];210}211return names;212}213214/**215* Returns a registry reference obtained from information in the URL.216*/217private static Registry getRegistry(ParsedNamingURL parsed)218throws RemoteException219{220return LocateRegistry.getRegistry(parsed.host, parsed.port);221}222223/**224* Dissect Naming URL strings to obtain referenced host, port and225* object name.226*227* @return an object which contains each of the above228* components.229*230* @throws MalformedURLException if given url string is malformed231*/232private static ParsedNamingURL parseURL(String str)233throws MalformedURLException234{235try {236return intParseURL(str);237} catch (URISyntaxException ex) {238/* With RFC 3986 URI handling, 'rmi://:<port>' and239* '//:<port>' forms will result in a URI syntax exception240* Convert the authority to a localhost:<port> form241*/242MalformedURLException mue = new MalformedURLException(243"invalid URL String: " + str);244mue.initCause(ex);245int indexSchemeEnd = str.indexOf(':');246int indexAuthorityBegin = str.indexOf("//:");247if (indexAuthorityBegin < 0) {248throw mue;249}250if ((indexAuthorityBegin == 0) ||251((indexSchemeEnd > 0) &&252(indexAuthorityBegin == indexSchemeEnd + 1))) {253int indexHostBegin = indexAuthorityBegin + 2;254String newStr = str.substring(0, indexHostBegin) +255"localhost" +256str.substring(indexHostBegin);257try {258return intParseURL(newStr);259} catch (URISyntaxException inte) {260throw mue;261} catch (MalformedURLException inte) {262throw inte;263}264}265throw mue;266}267}268269private static ParsedNamingURL intParseURL(String str)270throws MalformedURLException, URISyntaxException271{272URI uri = new URI(str);273if (uri.isOpaque()) {274throw new MalformedURLException(275"not a hierarchical URL: " + str);276}277if (uri.getFragment() != null) {278throw new MalformedURLException(279"invalid character, '#', in URL name: " + str);280} else if (uri.getQuery() != null) {281throw new MalformedURLException(282"invalid character, '?', in URL name: " + str);283} else if (uri.getUserInfo() != null) {284throw new MalformedURLException(285"invalid character, '@', in URL host: " + str);286}287String scheme = uri.getScheme();288if (scheme != null && !scheme.equals("rmi")) {289throw new MalformedURLException("invalid URL scheme: " + str);290}291292String name = uri.getPath();293if (name != null) {294if (name.startsWith("/")) {295name = name.substring(1);296}297if (name.length() == 0) {298name = null;299}300}301302String host = uri.getHost();303if (host == null) {304host = "";305try {306/*307* With 2396 URI handling, forms such as 'rmi://host:bar'308* or 'rmi://:<port>' are parsed into a registry based309* authority. We only want to allow server based naming310* authorities.311*/312uri.parseServerAuthority();313} catch (URISyntaxException use) {314// Check if the authority is of form ':<port>'315String authority = uri.getAuthority();316if (authority != null && authority.startsWith(":")) {317// Convert the authority to 'localhost:<port>' form318authority = "localhost" + authority;319try {320uri = new URI(null, authority, null, null, null);321// Make sure it now parses to a valid server based322// naming authority323uri.parseServerAuthority();324} catch (URISyntaxException use2) {325throw new326MalformedURLException("invalid authority: " + str);327}328} else {329throw new330MalformedURLException("invalid authority: " + str);331}332}333}334int port = uri.getPort();335if (port == -1) {336port = Registry.REGISTRY_PORT;337}338return new ParsedNamingURL(host, port, name);339}340341/**342* Simple class to enable multiple URL return values.343*/344private static class ParsedNamingURL {345String host;346int port;347String name;348349ParsedNamingURL(String host, int port, String name) {350this.host = host;351this.port = port;352this.name = name;353}354}355}356357358