1 /* ContextContinuation.java -- handles corbaname: urls
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.giop;
40 import gnu.CORBA.NamingService.Ext;
41 import gnu.CORBA.NamingService.NameTransformer;
43 import java.util.Hashtable;
45 import javax.naming.Binding;
46 import javax.naming.Context;
47 import javax.naming.ContextNotEmptyException;
48 import javax.naming.InvalidNameException;
49 import javax.naming.Name;
50 import javax.naming.NameAlreadyBoundException;
51 import javax.naming.NameClassPair;
52 import javax.naming.NameNotFoundException;
53 import javax.naming.NameParser;
54 import javax.naming.NamingEnumeration;
55 import javax.naming.NamingException;
56 import javax.naming.OperationNotSupportedException;
57 import javax.naming.directory.InvalidAttributesException;
59 import org.omg.CORBA.ORB;
60 import org.omg.CORBA.portable.Delegate;
61 import org.omg.CORBA.portable.ObjectImpl;
62 import org.omg.CosNaming.BindingIteratorHolder;
63 import org.omg.CosNaming.BindingListHolder;
64 import org.omg.CosNaming.NameComponent;
65 import org.omg.CosNaming.NamingContext;
66 import org.omg.CosNaming.NamingContextExt;
67 import org.omg.CosNaming.NamingContextExtHelper;
68 import org.omg.CosNaming.NamingContextHelper;
69 import org.omg.CosNaming._NamingContextExtStub;
70 import org.omg.CosNaming._NamingContextStub;
71 import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
72 import org.omg.CosNaming.NamingContextPackage.CannotProceed;
73 import org.omg.CosNaming.NamingContextPackage.InvalidName;
74 import org.omg.CosNaming.NamingContextPackage.NotFound;
77 * The context to represent the corba naming service. Being the naming service,
78 * the returned context supports creating the subcontexts, forwarding this task
79 * to the existing naming service. When listing bindings, it uses the
80 * {@link Context#BATCHSIZE} property to determine, how many bindings should
81 * be returned at once (the process is transparend)
83 * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
85 public class ContextContinuation implements Context
88 * This number of bindings will be requested from the naming server at once,
89 * while the subsequent bindings will be requested via binding iterator one by
90 * one. Use {@link Context#BATCHSIZE} to override the value of this constant.
92 public int DEFAULT_BATCH_SIZE = 20;
95 * The actual CORBA naming service.
97 NamingContextExt service;
100 * The object request broker, used to access the naming service. This field
101 * is only initialised when the context is constructed from the URL.
108 Hashtable properties;
111 * The parent factory.
113 GiopNamingServiceFactory factory;
116 * The name transformer to obtain the name from its string representation. The
117 * to_name method of the naming service is avoided as it may be remote and
118 * hence expensive. The conversion rules are standard and cannot be service
121 static NameTransformer transformer = new NameTransformer();
124 * The batch size for list operations - how many to return at once.
126 public final int howMany;
129 * Creates a new naming context that uses naming service, represented by the
130 * given CORBA object.
133 * the naming service object. It must be possible to narrow it into
134 * the NamingContextExt.
136 * the environment table.
138 * the associated ORB. This reference is used during cleanup.
140 * parent factory. This reference is used during cleanup.
142 public ContextContinuation(org.omg.CORBA.Object nsObject,
143 Hashtable props, ORB anOrb,
144 GiopNamingServiceFactory aFactory)
149 Delegate delegate = ((ObjectImpl) nsObject)._get_delegate();
151 // If the IOR provides the IDL ID, we can check if our name
152 // service is old NamingContext or new NamingContextExt.
153 // Not all forms of the URL always provide the IDL id.
154 if (!nsObject._is_a(NamingContextExtHelper.id())
155 && nsObject._is_a(NamingContextHelper.id()))
157 // We are surely working with the old version.
158 _NamingContextStub stub = new _NamingContextStub();
159 stub._set_delegate(delegate);
160 // The Ext object will add the necessary extensions.
161 service = new Ext(stub);
165 // We expecte the service to be the NamingContextExt (this is true
166 // for both Sun's and our implementations). There is no easy way
167 // to check the version.
168 _NamingContextExtStub stub = new _NamingContextExtStub();
169 stub._set_delegate(delegate);
173 howMany = getBatchSize();
177 * Give the specified name for the specified object. The passed name must not
178 * be already bound to some other object. The components of the name are
179 * mapped into the components of the CORBA name.
182 * the name that will be given to the object (in the scope of this
185 * the object being named.
186 * @throws NameAlreadyBoundException
187 * if this name is already used to name some object.
188 * @throws InvalidAttributesException
189 * if the object does not supply all required attributes.
190 * @throws NamingException
191 * if the naming operation has failed due other reasons.
193 public void bind(Name name, Object obj) throws NamingException
197 org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
198 service.bind(toGiop(name), object);
200 catch (ClassCastException e)
202 throw new NamingException(org.omg.CORBA.Object.class + " required ");
204 catch (InvalidName e)
206 throw new InvalidNameException();
208 catch (AlreadyBound e)
210 throw new NameAlreadyBoundException();
214 throw new NamingException(e.toString());
219 * Give the specified name for the specified object. The passed name must not
220 * be already bound to some other object.
223 * the name that will be given to the object (in the scope of this
226 * the object being named.
227 * @throws NameAlreadyBoundException
228 * if this name is already used to name some object.
229 * @throws InvalidAttributesException
230 * if the object does not supply all required attributes.
231 * @throws NamingException
232 * if the naming operation has failed due other reasons.
234 public void bind(String name, Object obj) throws NamingException
238 org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
239 service.bind(transformer.toName(name), object);
241 catch (ClassCastException e)
243 throw new NamingException(org.omg.CORBA.Object.class + " required ");
245 catch (InvalidName e)
247 throw new InvalidNameException();
249 catch (AlreadyBound e)
251 throw new NameAlreadyBoundException();
255 throw new NamingException(e.toString());
260 * Releases all resources, associated with this context. The close() method
261 * can be called several times, but after it has been once invoked, it is not
262 * allowed to call any other method of this context. This method destroys
263 * the ORB, if we have one.
265 * @throws NamingException
267 public void close() throws NamingException
269 if (orb != null && factory !=null)
271 factory.checkIfReferenced(orb);
278 public Name composeName(Name name, Name prefix) throws NamingException
280 throw new OperationNotSupportedException();
286 public String composeName(String name1, String name2) throws NamingException
288 throw new OperationNotSupportedException();
292 * Creates the new naming subcontext and binds it to the current (this)
293 * context. The returned object will wrap around the newly created CORBA
297 * the name of the new context being created
298 * @return the newly created context, bound to the instance of the context on
299 * that the method has been called
300 * @throws NameAlreadyBoundException
301 * if this name is already bound
302 * @throws InvalidAttributesException
303 * if the creation of the new context requires the missing mandatory
305 * @throws NamingException
307 public Context createSubcontext(Name subContext) throws NamingException
311 org.omg.CORBA.Object subcontext = service.bind_new_context(
313 Hashtable clonedProps = new Hashtable();
314 clonedProps.putAll(properties);
316 // Nulls are passed both for orb and factory, as the child contexts
317 // need not to do any cleanup.
318 return new ContextContinuation(subcontext, clonedProps, null, null);
320 catch (AlreadyBound e)
322 throw new NameAlreadyBoundException();
324 catch (InvalidName e)
326 throw new InvalidNameException();
330 throw new NamingException(ex.toString());
335 * Creates the new naming subcontext and binds it to the current (this)
336 * context. The returned object will wrap around the newly created CORBA
340 * the name of the new context being created
341 * @return the newly created context, bound to the instance of the context on
342 * that the method has been called
343 * @throws NameAlreadyBoundException
344 * if this name is already bound
345 * @throws InvalidAttributesException
346 * if the creation of the new context requires the missing mandatory
348 * @throws NamingException
350 public Context createSubcontext(String subContext) throws NamingException
354 org.omg.CORBA.Object subcontext =
355 service.bind_new_context(transformer.toName(subContext));
356 Hashtable clonedProps = new Hashtable();
357 clonedProps.putAll(properties);
359 // Nulls are passed both for orb and factory, as the child contexts
360 // need not to do any cleanup.
361 return new ContextContinuation(subcontext, clonedProps, null,
364 catch (AlreadyBound e)
366 throw new NameAlreadyBoundException(subContext);
368 catch (InvalidName e)
370 throw new InvalidNameException(subContext);
374 throw new NamingException(ex.toString());
379 * Removes the naming subcontext from this naming context. Returns without
380 * action if such subcontext does not exist. The context being destroyed must
384 * the name of the subcontext beig removed.
385 * @throws ContextNotEmptyException
386 * if the named context is not empty.
387 * @throws NamingException
389 public void destroySubcontext(Name subContext) throws NamingException
395 * Removes the naming subcontext from this naming context. Returns without
396 * action if such subcontext does not exist. The context being destroyed must
400 * the name of the subcontext beig removed.
401 * @throws ContextNotEmptyException
402 * if the named context is not empty.
403 * @throws NamingException
405 public void destroySubcontext(String subContext) throws NamingException
411 * Returs the full name of this naming context. The returned string is not a
412 * JNDI composite name and should not be passed directly to the methods of the
413 * naming context. This implementation returns the IOR.
415 * @return the full name of this naming context, in its own namespace.
416 * @throws OperationNotSupportedException
417 * if the naming system, represented by this context, does not
418 * support the notation of the full name.
419 * @throws NamingException
421 public String getNameInNamespace() throws NamingException
424 return orb.object_to_string(service);
429 ObjectImpl impl = (ObjectImpl) service;
430 return impl._orb().object_to_string(impl);
432 catch (ClassCastException e)
434 throw new UnsupportedOperationException();
442 public NameParser getNameParser(Name name) throws NamingException
444 throw new UnsupportedOperationException();
450 public NameParser getNameParser(String name) throws NamingException
452 throw new UnsupportedOperationException();
456 * Creates and returns the enumeration over the name bindings that are present
457 * the given subcontext. The enumeration elements have the type of
458 * {@link NameClassPair}, providing also information about the class of the
459 * bound object. The behaviour in the case if the bindings are added or
460 * removed later is not defined. The contents of the subcontexts are not
464 * the name of the subcontext
465 * @return the enumeration over the names, known for the given subcontext.
466 * @throws NamingException
468 public NamingEnumeration list(Name name) throws NamingException
470 BindingIteratorHolder bi = new BindingIteratorHolder();
471 BindingListHolder bl = new BindingListHolder();
473 NamingContext subcontext;
475 if (name.size() == 0)
476 subcontext = service;
481 subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
485 throw new NamingException(e.toString());
490 subcontext.list(howMany, bl, bi);
492 return new ListEnumeration(bl, bi, howMany);
496 * Creates and returns the enumeration over the name bindings that are present
497 * the given subcontext. The enumeration elements have the type of
498 * {@link NameClassPair}, providing also information about the class of the
499 * bound object. The behaviour in the case if the bindings are added or
500 * removed later is not defined. The contents of the subcontexts are not
504 * the name of the subcontext
505 * @return the enumeration over the names, known for the given subcontext.
506 * @throws NamingException
508 public NamingEnumeration list(String name) throws NamingException
510 BindingIteratorHolder bi = new BindingIteratorHolder();
511 BindingListHolder bl = new BindingListHolder();
513 NamingContext subcontext;
515 if (name.length() == 0)
516 subcontext = service;
521 subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
525 throw new NamingException(e.toString());
530 subcontext.list(howMany, bl, bi);
532 return new ListEnumeration(bl, bi, howMany);
536 * Creates and returns the enumeration over the name - object bindings that
537 * are present the given subcontext. The enumeration elements have the type of
538 * {@link Binding}, providing also information about the class of the bound
539 * object. The behaviour in the case if the bindings are added or removed
540 * later is not defined. The contents of the subcontexts are not included.
543 * the name of the subcontext
544 * @return the enumeration over the names, known for the given subcontext.
545 * @throws NamingException
547 public NamingEnumeration listBindings(Name name) throws NamingException
549 BindingIteratorHolder bi = new BindingIteratorHolder();
550 BindingListHolder bl = new BindingListHolder();
552 NamingContext subcontext;
554 if (name.size() == 0)
555 subcontext = service;
560 subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name))));
564 throw new NamingException(e.toString());
568 subcontext.list(howMany, bl, bi);
570 return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
574 * Creates and returns the enumeration over the name - object bindings that
575 * are present the given subcontext. The enumeration elements have the type of
576 * {@link Binding}, providing also information about the class of the bound
577 * object. The behaviour in the case if the bindings are added or removed
578 * later is not defined. The contents of the subcontexts are not included.
581 * the name of the subcontext
582 * @return the enumeration over the names, known for the given subcontext.
583 * @throws NamingException
585 public NamingEnumeration listBindings(String name) throws NamingException
587 BindingIteratorHolder bi = new BindingIteratorHolder();
588 BindingListHolder bl = new BindingListHolder();
590 NamingContext subcontext;
592 if (name.length() == 0)
593 subcontext = service;
598 subcontext = (NamingContextHelper.narrow(service.resolve_str(name)));
602 throw new NamingException(e.toString());
607 subcontext.list(howMany, bl, bi);
609 return new ListBindingsEnumeration(bl, bi, howMany, subcontext);
613 * Gets the previously named object by name. If the passed name is empty, the
614 * method should return a cloned instance of this naming context.
617 * the name of the object being searched in this context
618 * @return the named object
619 * @throws NameNotFountException
620 * if the name is not found
622 public Object lookup(Name name) throws NamingException
626 return service.resolve(toGiop(name));
630 throw new NameNotFoundException();
632 catch (InvalidName e)
634 throw new InvalidNameException();
638 throw new NamingException(e.toString());
643 * Gets the previously named object by name. If the passed name is empty, the
644 * method should return a cloned instance of this naming context.
647 * the name of the object being searched in this context
648 * @return the named object
649 * @throws NamingException
650 * if the naming fails.
652 public Object lookup(String name) throws NamingException
656 return service.resolve_str(name);
660 throw new NameNotFoundException();
662 catch (InvalidName e)
664 throw new InvalidNameException();
668 throw new NamingException(e.toString());
675 public Object lookupLink(Name name) throws NamingException
677 throw new OperationNotSupportedException();
683 public Object lookupLink(String name) throws NamingException
685 throw new OperationNotSupportedException();
689 * Give the specified name for the specified object. Unlike bind, this method
690 * silently replaces the existing binding for this name, if one exists.
693 * the name that will be given to the object (in the scope of this
696 * the object being named.
697 * @throws InvalidAttributesException
698 * if the object does not supply all required attributes.
699 * @throws NamingException
700 * if the naming operation has failed due other reasons.
702 public void rebind(Name name, Object obj) throws NamingException
706 org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
707 service.rebind(toGiop(name), object);
709 catch (ClassCastException e)
711 throw new NamingException(org.omg.CORBA.Object.class + " required ");
713 catch (InvalidName e)
715 throw new InvalidNameException();
719 throw new NamingException(e.toString());
724 * Give the specified name for the specified object. Unlike bind, this method
725 * silently replaces the existing binding for this name, if one exists.
728 * the name that will be given to the object (in the scope of this
731 * the object being named.
732 * @throws InvalidAttributesException
733 * if the object does not supply all required attributes.
734 * @throws NamingException
735 * if the naming operation has failed due other reasons.
737 public void rebind(String name, Object obj) throws NamingException
741 org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj;
742 service.rebind(transformer.toName(name), object);
744 catch (ClassCastException e)
746 throw new NamingException(org.omg.CORBA.Object.class + " required ");
748 catch (InvalidName e)
750 throw new InvalidNameException();
754 throw new NamingException(e.toString());
759 * Renames the existing binding, removing the existing and giving the new name
760 * for the same object.
763 * the existing name of the known object
765 * the new name of the same object
766 * @throws NameNotFoundException
767 * if the oldName is unknown for this context
768 * @throws NamingException
769 * if the naming operation has failed due other reasons.
771 public void rename(Name oldName, Name newName) throws NamingException
773 Object object = lookup(oldName);
775 bind(newName, object);
779 * Renames the existing binding, removing the existing and giving the new name
780 * for the same object.
783 * the existing name of the known object
785 * the new name of the same object
786 * @throws NameNotFoundException
787 * if the oldName is unknown for this context
788 * @throws NamingException
789 * if the naming operation has failed due other reasons.
791 public void rename(String oldName, String newName) throws NamingException
793 Object object = lookup(oldName);
795 bind(newName, object);
799 * Removes the name - object mapping from the current context. This method
800 * returns without action if the name is not bound to an object in the
801 * terminal context, but throws {@link NameNotFoundException} if one of the
802 * intermadiate contexts does not exist.
805 * the name to be removed
806 * @throws NameNotFoundException
807 * if one of the intermediate naming contexts does not exist. Will
808 * not be thrown if just the terminal binding is missing.
809 * @throws NamingException
810 * if the naming operation has failed due other reasons.
812 public void unbind(Name name) throws NamingException
816 service.unbind(toGiop(name));
820 throw new NameNotFoundException();
822 catch (CannotProceed e)
824 throw new ContextNotEmptyException();
826 catch (InvalidName e)
828 throw new InvalidNameException();
833 * Removes the name - object mapping from the current context. This method
834 * returns without action if the name is not bound to an object in the
835 * terminal context, but throws {@link NameNotFoundException} if one of the
836 * intermadiate contexts does not exist.
839 * the name to be removed
840 * @throws NameNotFoundException
841 * if one of the intermediate naming contexts does not exist. Will
842 * not be thrown if just the terminal binding is missing.
843 * @throws NamingException
844 * if the naming operation has failed due other reasons.
846 public void unbind(String name) throws NamingException
850 service.unbind(transformer.toName(name));
854 throw new NameNotFoundException(name);
856 catch (CannotProceed e)
858 throw new ContextNotEmptyException(name);
860 catch (InvalidName e)
862 throw new InvalidNameException(name);
867 * Add new environment property to the environment of this context. Both name
868 * and value of the new property must not be null. If the property is already
869 * defined, is current value is replaced by the propVal.
872 * the name of the new property
874 * the value of the new property
875 * @return the previous value of this property or null if the property has not
876 * been previously defined
877 * @throws NamingException
879 public Object addToEnvironment(String key, Object value)
880 throws NamingException
882 if (key == null || value == null)
883 throw new NullPointerException();
884 return properties.put(key, value);
888 * Returns the environment, associated with this naming context. The returned
889 * table should never be modified by the caller. Use {@link #addToEnvironment}
890 * and {@link #removeFromEnvironment} to modify the environement, if needed.
892 * @return the table, representing the environment of this context
893 * @throws NamingException
895 public Hashtable getEnvironment() throws NamingException
901 * Removes the property with the given name from the environment. Returns
902 * without action if this property is not defined.
905 * the name of the property being removed.
906 * @return the value of the property that has been removed or null if the
907 * property was not defined.
908 * @throws NamingException
910 public Object removeFromEnvironment(String propName) throws NamingException
912 return properties.remove(propName);
916 * Convert the {@link Name} into array of the name components, required to the
917 * CORBA naming service. First the string representation is obtained, then
918 * it is converted using parsing rules of the CORBA name.
921 * then name to convert
922 * @return the converted array of components.
924 public NameComponent[] toGiop(Name name) throws InvalidName
926 return transformer.toName(name.toString());
930 * Get the batch size from the environment properties. The batch size is used
931 * for listing operations.
933 * @return the batch size, or some default value if not specified.
935 public int getBatchSize()
937 int batchSize = DEFAULT_BATCH_SIZE;
938 Object bs = properties.get(Context.BATCHSIZE);
943 int b = Integer.parseInt(bs.toString());
947 catch (NumberFormatException e)
949 // OK, use default value.