1 /* ContextContinuation.java -- RMI naming context
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.javax.naming.jndi.url.rmi;
40 import java.rmi.AccessException;
41 import java.rmi.AlreadyBoundException;
42 import java.rmi.NotBoundException;
43 import java.rmi.Remote;
44 import java.rmi.RemoteException;
45 import java.rmi.registry.LocateRegistry;
46 import java.rmi.registry.Registry;
47 import java.util.Hashtable;
49 import java.util.Properties;
51 import javax.naming.CommunicationException;
52 import javax.naming.Context;
53 import javax.naming.InvalidNameException;
54 import javax.naming.Name;
55 import javax.naming.NameAlreadyBoundException;
56 import javax.naming.NameNotFoundException;
57 import javax.naming.NameParser;
58 import javax.naming.NamingEnumeration;
59 import javax.naming.NamingException;
60 import javax.naming.OperationNotSupportedException;
63 * The implementation of the RMI URL context. This context connects
65 * @author Audrius Meskauskas
67 public class ContextContinuation implements Context
70 * The default registry location.
72 public static final String DEFAULT_REGISTRY_LOCATION = "rmi://localhost:1099";
75 * The local or remote RMI registry, performing the actual work for this
83 Properties properties;
86 * The flag, indicating, that the lookup methods were called before.
87 * If the lookup methods were called before, the existing ORB cannot be
88 * destroyed, as references to the existing objects will become
94 * Add new environment property to the environment of this context. Both name
95 * and value of the new property must not be null. If the property is already
96 * defined, is current value is replaced by the propVal. This method replaces
97 * the registry. The new registry will be lazily instantiated on the first
101 * the name of the new property
103 * the value of the new property
104 * @return the previous value of this property or null if the property has not
105 * been previously defined
107 public Object addToEnvironment(String key, Object value)
110 if (key == null || value == null)
111 throw new NullPointerException();
112 return properties.put(key, value);
116 * Returns the environment, associated with this naming context. The returned
117 * table should never be modified by the caller (the registry would not be updated
118 * in such case). Use {@link #addToEnvironment} and
119 * {@link #removeFromEnvironment} to modify the environement, if needed.
121 * @return the table, representing the environment of this context
122 * @throws NamingException
124 public Hashtable getEnvironment() throws NamingException
130 * Removes the property with the given name from the environment. Returns
131 * without action if this property is not defined. Replaces the ORB,
132 * constructing the new ORB with the changes set of properties (you can
133 * replace the CORBA implementation provider, for instance). The new ORB will
134 * be lazily instantiated on the first call.
137 * the name of the property being removed.
138 * @return the value of the property that has been removed or null if the
139 * property was not defined.
140 * @throws NamingException
142 public Object removeFromEnvironment(String propName) throws NamingException
145 return properties.remove(propName);
149 * Remove the current registry reference.
151 public void removeRegistry()
157 * Get the cached or new registry reference.
159 * @return the registry reference, either cached or new.
161 public Registry getRegistry() throws NamingException
163 if (registry == null)
165 String address = properties.getProperty(Context.PROVIDER_URL,
166 DEFAULT_REGISTRY_LOCATION);
168 // The format like rmi://localhost:1099 is expected. Parse.
169 if (!address.startsWith("rmi://"))
170 throw new InvalidNameException(address);
172 String a = address.substring("rmi://".length());
174 // The colon, if present, indicates the start of the port number.
175 int colon = a.lastIndexOf(':');
182 port = Integer.parseInt(a.substring(colon+1));
183 a = a.substring(0, colon);
186 port = Registry.REGISTRY_PORT;
188 catch (NumberFormatException e1)
190 throw new InvalidNameException(address);
195 registry = LocateRegistry.getRegistry(a, port);
197 catch (RemoteException e)
199 throw new CommunicationException(e.toString());
206 * Create the rmi url context that works, talking with the given RMI registry.
209 * the properties for this context
210 * @param initialRegistry
211 * the initial value of the registry
213 public ContextContinuation(Map props, Registry initialRegistry)
215 properties = new Properties();
217 properties.putAll(props);
218 registry = initialRegistry;
222 * Bind the given name into this context. The .toString() is called to
223 * convert into the string representation, required by RMI registry.
225 * @throws NamingException if the object is not an instance of Remote
227 public void bind(Name name, Object obj) throws NamingException
229 bind(name.toString(), obj);
233 * Bind the given name into this context.
235 public void bind(String name, Object obj) throws NamingException
239 getRegistry().bind(name, (Remote) obj);
241 catch (AccessException e)
243 throw new NamingException("access:"+e.toString());
245 catch (RemoteException e)
247 throw new CommunicationException(e.toString());
249 catch (AlreadyBoundException e)
251 throw new NameAlreadyBoundException(name);
253 catch (ClassCastException c)
255 throw new NamingException("Only Remote can be bound:"
256 + obj.getClass().getName());
263 public Name composeName(Name name, Name prefix) throws NamingException
265 throw new OperationNotSupportedException();
271 public String composeName(String name, String prefix) throws NamingException
273 throw new OperationNotSupportedException();
277 * Subcontexts are not supporte by RMI registry. The only supported case is an
278 * empty name (returns the cloned instance of self).
280 public Context createSubcontext(Name name) throws NamingException
282 if (name.size() == 0)
283 return new rmiURLContext(properties);
285 throw new OperationNotSupportedException();
289 * Subcontexts are not supporte by RMI registry. The only supported case is an
290 * empty name (returns the cloned instance of self).
292 public Context createSubcontext(String name) throws NamingException
294 if (name.length() == 0)
295 return new rmiURLContext(properties);
297 throw new OperationNotSupportedException();
301 * Subcontexts are not supporte by RMI registry.
303 public void destroySubcontext(Name name) throws NamingException
305 throw new OperationNotSupportedException();
309 * Subcontexts are not supporte by RMI registry.
311 public void destroySubcontext(String name) throws NamingException
313 throw new OperationNotSupportedException();
317 * Returns the naming service URL, same that was passed vie
318 * {@link Context#PROVIDER_URL}.
320 public String getNameInNamespace() throws NamingException
322 return properties.getProperty(Context.PROVIDER_URL,
323 DEFAULT_REGISTRY_LOCATION);
327 * Not supported, this context never parses any names.
329 public NameParser getNameParser(Name name) throws NamingException
331 throw new OperationNotSupportedException();
335 * Not supported, this context never parses any names.
337 public NameParser getNameParser(String name) throws NamingException
339 throw new OperationNotSupportedException();
343 * List existing bindings of this context (the parameter must be empty name,
344 * indicating the root context). The class name of the returned name class
345 * pairs is "Remote", as this "quick preview" method should probably not call
346 * the naming service again. Use listBindings if more details are required.
348 public NamingEnumeration list(Name name) throws NamingException
351 throw new OperationNotSupportedException("Only empty name is accepted");
356 * List existing bindings of this context (the parameter must be empty string,
357 * indicating the root context). The class name of the returned name class
358 * pairs is "Remote", as this "quick preview" method should probably not call
359 * the naming service again. Use listBindings if more details are required.
361 public NamingEnumeration list(String name) throws NamingException
363 if (name.length() > 0)
364 throw new OperationNotSupportedException("Only empty name is accepted");
368 return new ListEnumeration(getRegistry().list());
372 throw new NamingException(e.toString());
377 * List existing bindings of this context (the parameter must be empty name,
378 * indicating the root context).
380 public NamingEnumeration listBindings(Name name) throws NamingException
383 throw new OperationNotSupportedException("Only empty name is accepted");
384 return listBindings("");
388 * List existing bindings of this context (the parameter must be empty name,
389 * indicating the root context).
391 public NamingEnumeration listBindings(String name) throws NamingException
393 if (name.length() > 0)
394 throw new OperationNotSupportedException("Only empty name is accepted");
398 Registry r = getRegistry();
399 return new ListBindingsEnumeration(r.list(), r);
403 throw new NamingException(e.toString());
410 public Object lookupLink(Name name) throws NamingException
412 throw new OperationNotSupportedException();
418 public Object lookupLink(String name) throws NamingException
420 throw new OperationNotSupportedException();
424 * Rebinds this object.
427 * the object name (.toString()) is used to convert into string
430 * object (must be an instance of Remote).
432 public void rebind(Name name, Object obj) throws NamingException
434 rebind(name.toString(), obj);
438 * Rebinds this object.
443 * object (must be an instance of Remote).
445 public void rebind(String name, Object obj) throws NamingException
449 getRegistry().rebind(name, (Remote) obj);
451 catch (AccessException e)
453 throw new NamingException("access:"+e.toString());
455 catch (RemoteException e)
457 throw new CommunicationException(e.toString());
459 catch (ClassCastException c)
461 throw new NamingException("Only Remote can be bound:"
462 + obj.getClass().getName());
467 * Renames the object. If the new name is already bound in the given context,
468 * the {@link AlreadyBoundException} is thrown and the oldName binding is
471 public void rename(Name oldName, Name newName) throws NamingException
473 rename(oldName.toString(), newName.toString());
477 * Renames the object. If the new name is already bound in the given context,
478 * the {@link AlreadyBoundException} is thrown and the oldName binding is
481 public synchronized void rename(String oldName, String newName)
482 throws NamingException
486 Registry r = getRegistry();
487 Remote object = r.lookup(oldName);
491 r.bind(newName, object);
493 catch (AlreadyBoundException e)
498 r.bind(oldName, object);
500 catch (AlreadyBoundException e1)
502 // We have just removed this name.
503 throw new InternalError();
505 throw new NameAlreadyBoundException(newName);
508 catch (AccessException e)
510 throw new NamingException(e.toString());
512 catch (RemoteException e)
514 throw new CommunicationException(e.toString());
516 catch (NotBoundException e)
518 throw new CommunicationException(e.toString());
525 public void unbind(Name name) throws NamingException
527 unbind(name.toString());
533 public void unbind(String name) throws NamingException
537 getRegistry().unbind(name);
539 catch (AccessException e)
541 throw new NamingException(e.toString());
543 catch (RemoteException e)
545 throw new CommunicationException(e.toString());
547 catch (NotBoundException e)
549 throw new CommunicationException(e.toString());
554 * Release the associated resources.
556 public void close() throws NamingException
562 * Resolve the object by name.
565 * the object name, .toString() is used to get the string
568 public Object lookup(Name name) throws NamingException
570 return lookup(name.toString());
574 * Resolve the object by name
576 * @param name the object name.
578 public Object lookup(String name) throws NamingException
582 return getRegistry().lookup(name);
584 catch (AccessException e)
586 throw new NamingException(e.toString());
588 catch (RemoteException e)
590 throw new CommunicationException(e.toString());
592 catch (NotBoundException e)
594 throw new NameNotFoundException(name);