1. /*
  2. * @(#)Naming.java 1.21 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.rmi;
  8. import java.rmi.registry.*;
  9. import java.net.MalformedURLException;
  10. import java.net.URI;
  11. import java.net.URISyntaxException;
  12. /**
  13. * The <code>Naming</code> class provides methods for storing and obtaining
  14. * references to remote objects in a remote object registry. Each method of
  15. * the <code>Naming</code> class takes as one of its arguments a name that
  16. * is a <code>java.lang.String</code> in URL format (without the
  17. * scheme component) of the form:
  18. *
  19. * <PRE>
  20. * //host:port/name
  21. * </PRE>
  22. *
  23. * <P>where <code>host</code> is the host (remote or local) where the registry
  24. * is located, <code>port</code> is the port number on which the registry
  25. * accepts calls, and where <code>name</code> is a simple string uninterpreted
  26. * by the registry. Both <code>host</code> and <code>port</code> are optional.
  27. * If <code>host</code> is omitted, the host defaults to the local host. If
  28. * <code>port</code> is omitted, then the port defaults to 1099, the
  29. * "well-known" port that RMI's registry, <code>rmiregistry</code>, uses.
  30. *
  31. * <P><em>Binding</em> a name for a remote object is associating or
  32. * registering a name for a remote object that can be used at a later time to
  33. * look up that remote object. A remote object can be associated with a name
  34. * using the <code>Naming</code> class's <code>bind</code> or
  35. * <code>rebind</code> methods.
  36. *
  37. * <P>Once a remote object is registered (bound) with the RMI registry on the
  38. * local host, callers on a remote (or local) host can lookup the remote
  39. * object by name, obtain its reference, and then invoke remote methods on the
  40. * object. A registry may be shared by all servers running on a host or an
  41. * individual server process may create and use its own registry if desired
  42. * (see <code>java.rmi.registry.LocateRegistry.createRegistry</code> method
  43. * for details).
  44. *
  45. * @version 1.13, 09/05/99
  46. * @author Ann Wollrath
  47. * @author Roger Riggs
  48. * @since JDK1.1
  49. * @see java.rmi.registry.Registry
  50. * @see java.rmi.registry.LocateRegistry
  51. * @see java.rmi.registry.LocateRegistry#createRegistry(int)
  52. */
  53. public final class Naming {
  54. /**
  55. * Disallow anyone from creating one of these
  56. */
  57. private Naming() {}
  58. /**
  59. * Returns a reference, a stub, for the remote object associated
  60. * with the specified <code>name</code>.
  61. *
  62. * @param name a name in URL format (without the scheme component)
  63. * @return a reference for a remote object
  64. * @exception NotBoundException if name is not currently bound
  65. * @exception RemoteException if registry could not be contacted
  66. * @exception AccessException if this operation is not permitted
  67. * @exception MalformedURLException if the name is not an appropriately
  68. * formatted URL
  69. * @since JDK1.1
  70. */
  71. public static Remote lookup(String name)
  72. throws NotBoundException,
  73. java.net.MalformedURLException,
  74. RemoteException
  75. {
  76. ParsedNamingURL parsed = parseURL(name);
  77. Registry registry = getRegistry(parsed);
  78. if (parsed.name == null)
  79. return registry;
  80. return registry.lookup(parsed.name);
  81. }
  82. /**
  83. * Binds the specified <code>name</code> to a remote object.
  84. *
  85. * @param name a name in URL format (without the scheme component)
  86. * @param obj a reference for the remote object (usually a stub)
  87. * @exception AlreadyBoundException if name is already bound
  88. * @exception MalformedURLException if the name is not an appropriately
  89. * formatted URL
  90. * @exception RemoteException if registry could not be contacted
  91. * @exception AccessException if this operation is not permitted (if
  92. * originating from a non-local host, for example)
  93. * @since JDK1.1
  94. */
  95. public static void bind(String name, Remote obj)
  96. throws AlreadyBoundException,
  97. java.net.MalformedURLException,
  98. RemoteException
  99. {
  100. ParsedNamingURL parsed = parseURL(name);
  101. Registry registry = getRegistry(parsed);
  102. if (obj == null)
  103. throw new NullPointerException("cannot bind to null");
  104. registry.bind(parsed.name, obj);
  105. }
  106. /**
  107. * Destroys the binding for the specified name that is associated
  108. * with a remote object.
  109. *
  110. * @param name a name in URL format (without the scheme component)
  111. * @exception NotBoundException if name is not currently bound
  112. * @exception MalformedURLException if the name is not an appropriately
  113. * formatted URL
  114. * @exception RemoteException if registry could not be contacted
  115. * @exception AccessException if this operation is not permitted (if
  116. * originating from a non-local host, for example)
  117. * @since JDK1.1
  118. */
  119. public static void unbind(String name)
  120. throws RemoteException,
  121. NotBoundException,
  122. java.net.MalformedURLException
  123. {
  124. ParsedNamingURL parsed = parseURL(name);
  125. Registry registry = getRegistry(parsed);
  126. registry.unbind(parsed.name);
  127. }
  128. /**
  129. * Rebinds the specified name to a new remote object. Any existing
  130. * binding for the name is replaced.
  131. *
  132. * @param name a name in URL format (without the scheme component)
  133. * @param obj new remote object to associate with the name
  134. * @exception MalformedURLException if the name is not an appropriately
  135. * formatted URL
  136. * @exception RemoteException if registry could not be contacted
  137. * @exception AccessException if this operation is not permitted (if
  138. * originating from a non-local host, for example)
  139. * @since JDK1.1
  140. */
  141. public static void rebind(String name, Remote obj)
  142. throws RemoteException, java.net.MalformedURLException
  143. {
  144. ParsedNamingURL parsed = parseURL(name);
  145. Registry registry = getRegistry(parsed);
  146. if (obj == null)
  147. throw new NullPointerException("cannot bind to null");
  148. registry.rebind(parsed.name, obj);
  149. }
  150. /**
  151. * Returns an array of the names bound in the registry. The names are
  152. * URL-formatted (without the scheme component) strings. The array contains
  153. * a snapshot of the names present in the registry at the time of the
  154. * call.
  155. *
  156. * @param name a registry name in URL format (without the scheme
  157. * component)
  158. * @return an array of names (in the appropriate format) bound
  159. * in the registry
  160. * @exception MalformedURLException if the name is not an appropriately
  161. * formatted URL
  162. * @exception RemoteException if registry could not be contacted.
  163. * @since JDK1.1
  164. */
  165. public static String[] list(String name)
  166. throws RemoteException, java.net.MalformedURLException
  167. {
  168. ParsedNamingURL parsed = parseURL(name);
  169. Registry registry = getRegistry(parsed);
  170. String prefix = "";
  171. if (parsed.port > 0 || !parsed.host.equals(""))
  172. prefix += "//" + parsed.host;
  173. if (parsed.port > 0)
  174. prefix += ":" + parsed.port;
  175. prefix += "/";
  176. String[] names = registry.list();
  177. for (int i = 0; i < names.length; i++) {
  178. names[i] = prefix + names[i];
  179. }
  180. return names;
  181. }
  182. /**
  183. * Returns a registry reference obtained from information in the URL.
  184. */
  185. private static Registry getRegistry(ParsedNamingURL parsed)
  186. throws RemoteException
  187. {
  188. return LocateRegistry.getRegistry(parsed.host, parsed.port);
  189. }
  190. /**
  191. * Dissect Naming URL strings to obtain referenced host, port and
  192. * object name.
  193. *
  194. * @return an object which contains each of the above
  195. * components.
  196. *
  197. * @exception MalformedURLException if given url string is malformed
  198. */
  199. private static ParsedNamingURL parseURL(String str)
  200. throws MalformedURLException
  201. {
  202. try {
  203. URI uri = new URI(str);
  204. if (uri.getFragment() != null) {
  205. throw new MalformedURLException(
  206. "invalid character, '#', in URL name: " + str);
  207. } else if (uri.getQuery() != null) {
  208. throw new MalformedURLException(
  209. "invalid character, '?', in URL name: " + str);
  210. } else if (uri.getUserInfo() != null) {
  211. throw new MalformedURLException(
  212. "invalid character, '@', in URL host: " + str);
  213. }
  214. String scheme = uri.getScheme();
  215. if (scheme != null && !scheme.equals("rmi")) {
  216. throw new MalformedURLException("invalid URL scheme: " + str);
  217. }
  218. String name = uri.getPath();
  219. if (name != null) {
  220. if (name.startsWith("/")) {
  221. name = name.substring(1);
  222. }
  223. if (name.length() == 0) {
  224. name = null;
  225. }
  226. }
  227. String host = uri.getHost();
  228. if (host == null) {
  229. host = "";
  230. if (uri.getPort() == -1) {
  231. /* handle URIs with explicit port but no host
  232. * (e.g., "//:1098/foo"); although they do not strictly
  233. * conform to RFC 2396, Naming's javadoc explicitly allows
  234. * them.
  235. */
  236. String authority = uri.getAuthority();
  237. if (authority != null && authority.startsWith(":")) {
  238. authority = "localhost" + authority;
  239. uri = new URI(null, authority, null, null, null);
  240. }
  241. }
  242. }
  243. int port = uri.getPort();
  244. if (port == -1) {
  245. port = Registry.REGISTRY_PORT;
  246. }
  247. return new ParsedNamingURL(host, port, name);
  248. } catch (URISyntaxException ex) {
  249. throw (MalformedURLException) new MalformedURLException(
  250. "invalid URL string: " + str).initCause(ex);
  251. }
  252. }
  253. /**
  254. * Simple class to enable multiple URL return values.
  255. */
  256. private static class ParsedNamingURL {
  257. String host;
  258. int port;
  259. String name;
  260. ParsedNamingURL(String host, int port, String name) {
  261. this.host = host;
  262. this.port = port;
  263. this.name = name;
  264. }
  265. }
  266. }