001    /* Naming.java --
002       Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006  
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011     
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.rmi;
041    
042    import java.net.MalformedURLException;
043    import java.net.URI;
044    import java.net.URISyntaxException;
045    import java.net.URL;
046    import java.rmi.registry.LocateRegistry;
047    import java.rmi.registry.Registry;
048    
049    /**
050     * <p>
051     * The <code>Naming</code> class handles interactions with RMI registries.
052     * Each method takes a URL in <code>String</code> form, which points to
053     * the RMI registry.  The scheme of the URL is irrelevant.  The relevant
054     * part is:
055     * </p>
056     * <p>
057     * <code>//host:port/name</code>
058     * </p>
059     * <p>
060     * which tells the method how to locate and access the registry.  The host
061     * and port are both optional, and default to `localhost' and the standard
062     * RMI registry port (1099) respectively.  The name is simply a string
063     * used to refer to a particular service hosted by the registry.  The
064     * registry does not attempt to interpret this further.
065     * </p>
066     * <p>
067     * RMI services are registered using one of these names, and the same name
068     * is later used by the client to lookup the service and access its methods. 
069     * Registries can be shared by multiple services, or a service can create
070     * its own registry using <code>createRegistry()</code>.
071     * </p>
072     *
073     * @author Original author unknown.
074     * @author Ingo Proetel (proetel@aicas.com)
075     * @author Guilhem Lavaux (guilhem@kaffe.org)
076     * @author Jeroen Frijters (jeroen@frijters.net)
077     * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
078     * @since 1.1
079     */
080    public final class Naming
081    {
082      /**
083       * This class isn't intended to be instantiated.
084       */
085      private Naming()
086      {
087      }
088    
089      /**
090       * Looks for the remote object that is associated with the named service. 
091       * Name and location is given in form of a URL without a scheme:
092       * 
093       * <pre>
094       * //host:port/service-name
095       * </pre>
096       * 
097       * The port is optional.
098       * 
099       * @param name the service name and location
100       * @return Remote-object that implements the named service
101       * @throws NotBoundException if no object implements the service
102       * @throws MalformedURLException
103       * @throws RemoteException
104       */
105      public static Remote lookup(String name) throws NotBoundException,
106        MalformedURLException, RemoteException
107      {
108        URL u = parseURL(name);
109        String serviceName = getName(u);
110        return (getRegistry(u).lookup(serviceName));
111      }
112    
113      /**
114       * Try to bind the given object to the given service name.
115       * 
116       * @param name
117       * @param obj
118       * @throws AlreadyBoundException
119       * @throws MalformedURLException
120       * @throws RemoteException
121       */
122      public static void bind(String name, Remote obj)
123        throws AlreadyBoundException, MalformedURLException, RemoteException
124      {
125        URL u = parseURL(name);
126        String serviceName = getName(u);
127        getRegistry(u).bind(serviceName, obj);
128      }
129    
130      /**
131       * Remove a binding for a given service name.
132       * 
133       * @param name
134       * @throws RemoteException
135       * @throws NotBoundException
136       * @throws MalformedURLException
137       */
138      public static void unbind(String name) throws RemoteException,
139        NotBoundException, MalformedURLException
140      {
141        URL u = parseURL(name);
142        String serviceName = getName(u);
143        getRegistry(u).unbind(serviceName);
144      }
145    
146      /**
147       * Forces the binding between the given Remote-object and the given service
148       * name, even if there was already an object bound to this name.
149       * 
150       * @param name
151       * @param obj
152       * @throws RemoteException
153       * @throws MalformedURLException
154       */
155      public static void rebind(String name, Remote obj) throws RemoteException,
156        MalformedURLException
157      {
158        URL u = parseURL(name);
159        String serviceName = getName(u);
160        getRegistry(u).rebind(serviceName, obj);
161      }
162    
163      /**
164       * Lists all services at the named registry.
165       * 
166       * @param name url that specifies the registry
167       * @return list of services at the name registry
168       * @throws RemoteException
169       * @throws MalformedURLException
170       */
171      public static String[] list(String name) throws RemoteException,
172        MalformedURLException
173      {
174        return (getRegistry(parseURL(name)).list());
175      }
176    
177      private static Registry getRegistry(URL u) throws RemoteException
178      {
179        if (u.getPort() == - 1)
180          {
181            return (LocateRegistry.getRegistry(u.getHost()));
182          }
183        else
184          {
185            return (LocateRegistry.getRegistry(u.getHost(), u.getPort()));
186          }
187      }
188    
189      /**
190       * Parses the supplied URL and converts it to use the HTTP protocol. From an
191       * RMI perspective, the scheme is irrelevant and we want to be able to create
192       * a URL for which a handler is available.
193       * 
194       * @param name the URL in String form.
195       * @throws MalformedURLException if the URL is invalid.
196       */
197      private static URL parseURL(String name) throws MalformedURLException
198      {
199        try
200          {
201            URI uri = new URI(name);
202            String host = uri.getHost();
203            int port = uri.getPort();
204            String query = uri.getQuery();
205            String path = uri.getPath();
206            return new URL("http", (host == null ? "localhost" : host),
207                (port == - 1 ? 1099 : port), uri.getPath()
208                                             + (query == null ? "" : query));
209          }
210        catch (URISyntaxException e)
211          {
212            throw new MalformedURLException("The URL syntax was invalid: "
213                                            + e.getMessage());
214          }
215      }
216    
217      /**
218       * Checks that the URL contains a name, and removes any leading slashes.
219       * 
220       * @param url the URL to check.
221       * @throws MalformedURLException if no name is specified.
222       */
223      private static String getName(URL url) throws MalformedURLException
224      {
225        String filename = url.getFile();
226        if (filename.length() == 0)
227          throw new MalformedURLException("No path specified: " + url);
228        // If the filename begins with a slash we must cut it for
229        // name resolution.
230        if (filename.charAt(0) == '/')
231          return filename.substring(1);
232        return filename;
233      }
234    }