diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/naming/giop')
7 files changed, 2839 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/naming/giop/ContextContinuation.java b/libjava/classpath/gnu/javax/naming/giop/ContextContinuation.java new file mode 100644 index 000000000..e952393cc --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/ContextContinuation.java @@ -0,0 +1,956 @@ +/* ContextContinuation.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.naming.giop; + +import gnu.CORBA.NamingService.Ext; +import gnu.CORBA.NamingService.NameTransformer; + +import java.util.Hashtable; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.ContextNotEmptyException; +import javax.naming.InvalidNameException; +import javax.naming.Name; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NameClassPair; +import javax.naming.NameNotFoundException; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.OperationNotSupportedException; +import javax.naming.directory.InvalidAttributesException; + +import org.omg.CORBA.ORB; +import org.omg.CORBA.portable.Delegate; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.CosNaming.BindingIteratorHolder; +import org.omg.CosNaming.BindingListHolder; +import org.omg.CosNaming.NameComponent; +import org.omg.CosNaming.NamingContext; +import org.omg.CosNaming.NamingContextExt; +import org.omg.CosNaming.NamingContextExtHelper; +import org.omg.CosNaming.NamingContextHelper; +import org.omg.CosNaming._NamingContextExtStub; +import org.omg.CosNaming._NamingContextStub; +import org.omg.CosNaming.NamingContextPackage.AlreadyBound; +import org.omg.CosNaming.NamingContextPackage.CannotProceed; +import org.omg.CosNaming.NamingContextPackage.InvalidName; +import org.omg.CosNaming.NamingContextPackage.NotFound; + +/** + * The context to represent the corba naming service. Being the naming service, + * the returned context supports creating the subcontexts, forwarding this task + * to the existing naming service. When listing bindings, it uses the + * {@link Context#BATCHSIZE} property to determine, how many bindings should + * be returned at once (the process is transparend) + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ +public class ContextContinuation implements Context +{ + /** + * This number of bindings will be requested from the naming server at once, + * while the subsequent bindings will be requested via binding iterator one by + * one. Use {@link Context#BATCHSIZE} to override the value of this constant. + */ + public int DEFAULT_BATCH_SIZE = 20; + + /** + * The actual CORBA naming service. + */ + NamingContextExt service; + + /** + * The object request broker, used to access the naming service. This field + * is only initialised when the context is constructed from the URL. + */ + ORB orb; + + /** + * The properties. + */ + Hashtable properties; + + /** + * The parent factory. + */ + GiopNamingServiceFactory factory; + + /** + * The name transformer to obtain the name from its string representation. The + * to_name method of the naming service is avoided as it may be remote and + * hence expensive. The conversion rules are standard and cannot be service + * specific. + */ + static NameTransformer transformer = new NameTransformer(); + + /** + * The batch size for list operations - how many to return at once. + */ + public final int howMany; + + /** + * Creates a new naming context that uses naming service, represented by the + * given CORBA object. + * + * @param nsObject + * the naming service object. It must be possible to narrow it into + * the NamingContextExt. + * @param props + * the environment table. + * @param anOrb + * the associated ORB. This reference is used during cleanup. + * @param aFactory + * parent factory. This reference is used during cleanup. + */ + public ContextContinuation(org.omg.CORBA.Object nsObject, + Hashtable props, ORB anOrb, + GiopNamingServiceFactory aFactory) + { + factory = aFactory; + orb = anOrb; + + Delegate delegate = ((ObjectImpl) nsObject)._get_delegate(); + + // If the IOR provides the IDL ID, we can check if our name + // service is old NamingContext or new NamingContextExt. + // Not all forms of the URL always provide the IDL id. + if (!nsObject._is_a(NamingContextExtHelper.id()) + && nsObject._is_a(NamingContextHelper.id())) + { + // We are surely working with the old version. + _NamingContextStub stub = new _NamingContextStub(); + stub._set_delegate(delegate); + // The Ext object will add the necessary extensions. + service = new Ext(stub); + } + else + { + // We expecte the service to be the NamingContextExt (this is true + // for both Sun's and our implementations). There is no easy way + // to check the version. + _NamingContextExtStub stub = new _NamingContextExtStub(); + stub._set_delegate(delegate); + service = stub; + } + properties = props; + howMany = getBatchSize(); + } + + /** + * Give the specified name for the specified object. The passed name must not + * be already bound to some other object. The components of the name are + * mapped into the components of the CORBA name. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws NameAlreadyBoundException + * if this name is already used to name some object. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void bind(Name name, Object obj) throws NamingException + { + try + { + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + service.bind(toGiop(name), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Give the specified name for the specified object. The passed name must not + * be already bound to some other object. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws NameAlreadyBoundException + * if this name is already used to name some object. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void bind(String name, Object obj) throws NamingException + { + try + { + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + service.bind(transformer.toName(name), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Releases all resources, associated with this context. The close() method + * can be called several times, but after it has been once invoked, it is not + * allowed to call any other method of this context. This method destroys + * the ORB, if we have one. + * + * @throws NamingException + */ + public void close() throws NamingException + { + if (orb != null && factory !=null) + { + factory.checkIfReferenced(orb); + } + } + + /** + * Not supported. + */ + public Name composeName(Name name, Name prefix) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Not supported + */ + public String composeName(String name1, String name2) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Creates the new naming subcontext and binds it to the current (this) + * context. The returned object will wrap around the newly created CORBA + * subcontext + * + * @param subContext + * the name of the new context being created + * @return the newly created context, bound to the instance of the context on + * that the method has been called + * @throws NameAlreadyBoundException + * if this name is already bound + * @throws InvalidAttributesException + * if the creation of the new context requires the missing mandatory + * attributes + * @throws NamingException + */ + public Context createSubcontext(Name subContext) throws NamingException + { + try + { + org.omg.CORBA.Object subcontext = service.bind_new_context( + toGiop(subContext)); + Hashtable clonedProps = new Hashtable(); + clonedProps.putAll(properties); + + // Nulls are passed both for orb and factory, as the child contexts + // need not to do any cleanup. + return new ContextContinuation(subcontext, clonedProps, null, null); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception ex) + { + throw new NamingException(ex.toString()); + } + } + + /** + * Creates the new naming subcontext and binds it to the current (this) + * context. The returned object will wrap around the newly created CORBA + * subcontext + * + * @param subContext + * the name of the new context being created + * @return the newly created context, bound to the instance of the context on + * that the method has been called + * @throws NameAlreadyBoundException + * if this name is already bound + * @throws InvalidAttributesException + * if the creation of the new context requires the missing mandatory + * attributes + * @throws NamingException + */ + public Context createSubcontext(String subContext) throws NamingException + { + try + { + org.omg.CORBA.Object subcontext = + service.bind_new_context(transformer.toName(subContext)); + Hashtable clonedProps = new Hashtable(); + clonedProps.putAll(properties); + + // Nulls are passed both for orb and factory, as the child contexts + // need not to do any cleanup. + return new ContextContinuation(subcontext, clonedProps, null, + null); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(subContext); + } + catch (InvalidName e) + { + throw new InvalidNameException(subContext); + } + catch (Exception ex) + { + throw new NamingException(ex.toString()); + } + } + + /** + * Removes the naming subcontext from this naming context. Returns without + * action if such subcontext does not exist. The context being destroyed must + * be empty. + * + * @param subContext + * the name of the subcontext beig removed. + * @throws ContextNotEmptyException + * if the named context is not empty. + * @throws NamingException + */ + public void destroySubcontext(Name subContext) throws NamingException + { + unbind(subContext); + } + + /** + * Removes the naming subcontext from this naming context. Returns without + * action if such subcontext does not exist. The context being destroyed must + * be empty. + * + * @param subContext + * the name of the subcontext beig removed. + * @throws ContextNotEmptyException + * if the named context is not empty. + * @throws NamingException + */ + public void destroySubcontext(String subContext) throws NamingException + { + unbind(subContext); + } + + /** + * Returs the full name of this naming context. The returned string is not a + * JNDI composite name and should not be passed directly to the methods of the + * naming context. This implementation returns the IOR. + * + * @return the full name of this naming context, in its own namespace. + * @throws OperationNotSupportedException + * if the naming system, represented by this context, does not + * support the notation of the full name. + * @throws NamingException + */ + public String getNameInNamespace() throws NamingException + { + if (orb != null) + return orb.object_to_string(service); + else + { + try + { + ObjectImpl impl = (ObjectImpl) service; + return impl._orb().object_to_string(impl); + } + catch (ClassCastException e) + { + throw new UnsupportedOperationException(); + } + } + } + + /** + * Not supported. + */ + public NameParser getNameParser(Name name) throws NamingException + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + */ + public NameParser getNameParser(String name) throws NamingException + { + throw new UnsupportedOperationException(); + } + + /** + * Creates and returns the enumeration over the name bindings that are present + * the given subcontext. The enumeration elements have the type of + * {@link NameClassPair}, providing also information about the class of the + * bound object. The behaviour in the case if the bindings are added or + * removed later is not defined. The contents of the subcontexts are not + * included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration list(Name name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + if (name.size() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name)))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + + } + + subcontext.list(howMany, bl, bi); + + return new ListEnumeration(bl, bi, howMany); + } + + /** + * Creates and returns the enumeration over the name bindings that are present + * the given subcontext. The enumeration elements have the type of + * {@link NameClassPair}, providing also information about the class of the + * bound object. The behaviour in the case if the bindings are added or + * removed later is not defined. The contents of the subcontexts are not + * included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration list(String name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + if (name.length() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve_str(name))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + + } + + subcontext.list(howMany, bl, bi); + + return new ListEnumeration(bl, bi, howMany); + } + + /** + * Creates and returns the enumeration over the name - object bindings that + * are present the given subcontext. The enumeration elements have the type of + * {@link Binding}, providing also information about the class of the bound + * object. The behaviour in the case if the bindings are added or removed + * later is not defined. The contents of the subcontexts are not included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration listBindings(Name name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + if (name.size() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve(toGiop(name)))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + subcontext.list(howMany, bl, bi); + + return new ListBindingsEnumeration(bl, bi, howMany, subcontext); + } + + /** + * Creates and returns the enumeration over the name - object bindings that + * are present the given subcontext. The enumeration elements have the type of + * {@link Binding}, providing also information about the class of the bound + * object. The behaviour in the case if the bindings are added or removed + * later is not defined. The contents of the subcontexts are not included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration listBindings(String name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + if (name.length() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve_str(name))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + + } + + subcontext.list(howMany, bl, bi); + + return new ListBindingsEnumeration(bl, bi, howMany, subcontext); + } + + /** + * Gets the previously named object by name. If the passed name is empty, the + * method should return a cloned instance of this naming context. + * + * @param name + * the name of the object being searched in this context + * @return the named object + * @throws NameNotFountException + * if the name is not found + */ + public Object lookup(Name name) throws NamingException + { + try + { + return service.resolve(toGiop(name)); + } + catch (NotFound e) + { + throw new NameNotFoundException(); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Gets the previously named object by name. If the passed name is empty, the + * method should return a cloned instance of this naming context. + * + * @param name + * the name of the object being searched in this context + * @return the named object + * @throws NamingException + * if the naming fails. + */ + public Object lookup(String name) throws NamingException + { + try + { + return service.resolve_str(name); + } + catch (NotFound e) + { + throw new NameNotFoundException(); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Not supported. + */ + public Object lookupLink(Name name) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Not supported. + */ + public Object lookupLink(String name) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Give the specified name for the specified object. Unlike bind, this method + * silently replaces the existing binding for this name, if one exists. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rebind(Name name, Object obj) throws NamingException + { + try + { + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + service.rebind(toGiop(name), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Give the specified name for the specified object. Unlike bind, this method + * silently replaces the existing binding for this name, if one exists. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rebind(String name, Object obj) throws NamingException + { + try + { + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + service.rebind(transformer.toName(name), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Renames the existing binding, removing the existing and giving the new name + * for the same object. + * + * @param oldName + * the existing name of the known object + * @param newName + * the new name of the same object + * @throws NameNotFoundException + * if the oldName is unknown for this context + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rename(Name oldName, Name newName) throws NamingException + { + Object object = lookup(oldName); + unbind(oldName); + bind(newName, object); + } + + /** + * Renames the existing binding, removing the existing and giving the new name + * for the same object. + * + * @param oldName + * the existing name of the known object + * @param newName + * the new name of the same object + * @throws NameNotFoundException + * if the oldName is unknown for this context + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rename(String oldName, String newName) throws NamingException + { + Object object = lookup(oldName); + unbind(oldName); + bind(newName, object); + } + + /** + * Removes the name - object mapping from the current context. This method + * returns without action if the name is not bound to an object in the + * terminal context, but throws {@link NameNotFoundException} if one of the + * intermadiate contexts does not exist. + * + * @param name + * the name to be removed + * @throws NameNotFoundException + * if one of the intermediate naming contexts does not exist. Will + * not be thrown if just the terminal binding is missing. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void unbind(Name name) throws NamingException + { + try + { + service.unbind(toGiop(name)); + } + catch (NotFound e) + { + throw new NameNotFoundException(); + } + catch (CannotProceed e) + { + throw new ContextNotEmptyException(); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + } + + /** + * Removes the name - object mapping from the current context. This method + * returns without action if the name is not bound to an object in the + * terminal context, but throws {@link NameNotFoundException} if one of the + * intermadiate contexts does not exist. + * + * @param name + * the name to be removed + * @throws NameNotFoundException + * if one of the intermediate naming contexts does not exist. Will + * not be thrown if just the terminal binding is missing. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void unbind(String name) throws NamingException + { + try + { + service.unbind(transformer.toName(name)); + } + catch (NotFound e) + { + throw new NameNotFoundException(name); + } + catch (CannotProceed e) + { + throw new ContextNotEmptyException(name); + } + catch (InvalidName e) + { + throw new InvalidNameException(name); + } + } + + /** + * Add new environment property to the environment of this context. Both name + * and value of the new property must not be null. If the property is already + * defined, is current value is replaced by the propVal. + * + * @param key + * the name of the new property + * @param value + * the value of the new property + * @return the previous value of this property or null if the property has not + * been previously defined + * @throws NamingException + */ + public Object addToEnvironment(String key, Object value) + throws NamingException + { + if (key == null || value == null) + throw new NullPointerException(); + return properties.put(key, value); + } + + /** + * Returns the environment, associated with this naming context. The returned + * table should never be modified by the caller. Use {@link #addToEnvironment} + * and {@link #removeFromEnvironment} to modify the environement, if needed. + * + * @return the table, representing the environment of this context + * @throws NamingException + */ + public Hashtable getEnvironment() throws NamingException + { + return properties; + } + + /** + * Removes the property with the given name from the environment. Returns + * without action if this property is not defined. + * + * @param propName + * the name of the property being removed. + * @return the value of the property that has been removed or null if the + * property was not defined. + * @throws NamingException + */ + public Object removeFromEnvironment(String propName) throws NamingException + { + return properties.remove(propName); + } + + /** + * Convert the {@link Name} into array of the name components, required to the + * CORBA naming service. First the string representation is obtained, then + * it is converted using parsing rules of the CORBA name. + * + * @param name + * then name to convert + * @return the converted array of components. + */ + public NameComponent[] toGiop(Name name) throws InvalidName + { + return transformer.toName(name.toString()); + } + + /** + * Get the batch size from the environment properties. The batch size is used + * for listing operations. + * + * @return the batch size, or some default value if not specified. + */ + public int getBatchSize() + { + int batchSize = DEFAULT_BATCH_SIZE; + Object bs = properties.get(Context.BATCHSIZE); + if (bs != null) + { + try + { + int b = Integer.parseInt(bs.toString()); + if (b >= 0) + batchSize = b; + } + catch (NumberFormatException e) + { + // OK, use default value. + } + } + return batchSize; + } + + +} diff --git a/libjava/classpath/gnu/javax/naming/giop/CorbalocParser.java b/libjava/classpath/gnu/javax/naming/giop/CorbalocParser.java new file mode 100644 index 000000000..4b7883969 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/CorbalocParser.java @@ -0,0 +1,441 @@ +/* CorbalocParser.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.javax.naming.giop; + +import gnu.CORBA.IOR; +import gnu.CORBA.Minor; +import gnu.CORBA.Unexpected; +import gnu.CORBA.Version; +import gnu.CORBA.NamingService.NameTransformer; + +import gnu.java.lang.CPStringBuilder; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.StringTokenizer; + +import javax.naming.InvalidNameException; + +import org.omg.CORBA.BAD_PARAM; +import org.omg.CORBA.DATA_CONVERSION; +import org.omg.CORBA.ORB; +import org.omg.CORBA.Object; +import org.omg.CORBA.ORBPackage.InvalidName; + +/** + * Parses the alternative IOR representations into our IOR structure. + * + * TODO This parser currently supports only one address per target string. A + * string with the multiple addresses will be accepted, but only the last + * address will be taken into consideration. The fault tolerance is not yet + * implemented. + * + * The key string is filtered using {@link java.net.URLDecoder} that replaces + * the agreed escape sequences by the corresponding non alphanumeric characters. + * + * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) + */ +public class CorbalocParser + extends NameTransformer +{ + /** + * The corbaloc prefix. + */ + public static final String pxCORBALOC = "corbaloc"; + + /** + * The corbaname prefix. + */ + public static final String pxCORBANAME = "corbaname"; + + /** + * The IOR prefix. + */ + public static final String pxIOR = "ior"; + + /** + * The file:// prefix. + */ + public static final String pxFILE = "file://"; + + /** + * The ftp:// prefix. + */ + public static final String pxFTP = "ftp://"; + + /** + * The http:// prefix. + */ + public static final String pxHTTP = "http://"; + + /** + * Marks iiop protocol. + */ + public static final String IIOP = "iiop"; + + /** + * Marks rir protocol. + */ + public static final String RIR = "rir"; + + /** + * The default port value, as specified in OMG documentation. + */ + public static final int DEFAULT_PORT = 2809; + + /** + * The default name. + */ + public static final String DEFAULT_NAME = "NameService"; + + /** + * The string to name converter, initialized on demand. + */ + static NameTransformer converter; + + /** + * The current position. + */ + int p; + + /** + * The address being parsed, splitted into tokens. + */ + String[] t; + + /** + * Parse CORBALOC. + * + * The expected format is: <br> + * 1. corbaloc:[iiop][version.subversion@]:host[:port]/key <br> + * 2. corbaloc:rir:[/key] <br> + * 3. corbaname:[iiop][version.subversion@]:host[:port]/key <br> + * 4. corbaname:rir:[/key] <br> + * 5. file://[file name]<br> + * 6. http://[url]<br> + * 7. ftp://[url]<br> + * + * Protocol defaults to IOP, the object key defaults to the NameService. + * + * @param corbaloc the string to parse. + * @param orb the ORB, needed to create IORs and resolve rir references. + * + * @return the arrey of strings, first member being the IOR of the + * naming service, second member the name in the naming service. + */ + public synchronized String[] corbaloc(String corbaloc, + ORB orb) + throws InvalidNameException + { + return corbaloc(corbaloc, orb, 0); + } + + /** + * Parse controlling against the infinite recursion loop. + */ + private String[] corbaloc(String corbaloc, + ORB orb, int recursion) throws InvalidNameException + { + // The used CORBA specification does not state how many times we should to + //redirect, but the infinite loop may be used to knock out the system. + // by malicious attempt. + if (recursion > 10) + throw new DATA_CONVERSION("More than 10 redirections"); + + if (corbaloc.startsWith(pxFILE)) + return corbaloc(readFile(corbaloc.substring(pxFILE.length())), orb, recursion+1); + else if (corbaloc.startsWith(pxHTTP)) + return corbaloc(readUrl(corbaloc), orb, recursion+1); + else if (corbaloc.startsWith(pxFTP)) + return corbaloc(readUrl(corbaloc), orb, recursion+1); + + // The version numbers with default values. + int major = 1; + int minor = 0; + + // The host address. + String host; + + // The port. + int port = DEFAULT_PORT; + + // The object key as string. + String key; + + StringTokenizer st = new StringTokenizer(corbaloc, ":@/.,#", true); + + t = new String[st.countTokens()]; + + for (int i = 0; i < t.length; i++) + { + t[i] = st.nextToken(); + } + + p = 0; + + if (!t[p].startsWith(pxCORBANAME)) + throw new InvalidNameException(corbaloc+" must start with "+pxCORBANAME); + + p++; + + if (!t[p++].equals(":")) + throw new BAD_PARAM("Syntax (':' expected after name prefix)"); + + // Check for rir: + if (t[p].equals(RIR)) + { + p++; + if (!t[p++].equals(":")) + throw new BAD_PARAM("':' expected after 'rir'"); + + key = readKey("/"); + + Object object; + try + { + object = orb.resolve_initial_references(key); + return resolve(orb.object_to_string(object)); + } + catch (InvalidName e) + { + throw new BAD_PARAM("Unknown initial reference '" + key + "'"); + } + } + else + // Check for iiop. + if (t[p].equals(IIOP) || t[p].equals(":")) + { + IOR ior = new IOR(); + + Addresses: do + { // Read addresses. + if (t[p].equals(":")) + { + p++; + } + else + { + p++; + if (!t[p++].equals(":")) + throw new BAD_PARAM("':' expected after 'iiop'"); + // Check if version is present. + if (t[p + 1].equals(".")) + if (t[p + 3].equals("@")) + { + // Version info present. + try + { + major = Integer.parseInt(t[p++]); + } + catch (NumberFormatException e) + { + throw new BAD_PARAM("Major version number '" + + t[p - 1] + "'"); + } + p++; // '.' at this point. + try + { + minor = Integer.parseInt(t[p++]); + } + catch (NumberFormatException e) + { + throw new BAD_PARAM("Major version number '" + + t[p - 1] + "'"); + } + p++; // '@' at this point. + } + } + + ior.Internet.version = new Version(major, minor); + + // Then host data goes till '/' or ':'. + CPStringBuilder bhost = new CPStringBuilder(corbaloc.length()); + while (!t[p].equals(":") && !t[p].equals("/") && !t[p].equals(",")) + bhost.append(t[p++]); + + host = bhost.toString(); + + ior.Internet.host = host; + + if (t[p].equals(":")) + { + // Port specified. + p++; + try + { + port = Integer.parseInt(t[p++]); + } + catch (NumberFormatException e) + { + throw new BAD_PARAM("Invalid port '" + t[p - 1] + "'"); + } + } + + ior.Internet.port = port; + + // Id is not listed. + ior.Id = ""; + + if (t[p].equals(",")) + p++; + else + break Addresses; + } + while (true); + + key = readKey("/"); + ior.key = key.getBytes(); + + return resolve(ior.toStringifiedReference()); + } + + else + throw new InvalidNameException("Unsupported protocol '" + t[p] + + "' (iiop expected)"); + } + + /** + * Read IOR from the file in the local file system. + */ + String readFile(String file) + { + File f = new File(file); + if (!f.exists()) + { + DATA_CONVERSION err = new DATA_CONVERSION(f.getAbsolutePath() + + " does not exist."); + err.minor = Minor.Missing_IOR; + } + try + { + char[] c = new char[(int) f.length()]; + FileReader fr = new FileReader(f); + fr.read(c); + fr.close(); + return new String(c).trim(); + } + catch (IOException ex) + { + DATA_CONVERSION d = new DATA_CONVERSION(); + d.initCause(ex); + d.minor = Minor.Missing_IOR; + throw (d); + } + } + + /** + * Read IOR from the remote URL. + */ + String readUrl(String url) + { + URL u; + try + { + u = new URL(url); + } + catch (MalformedURLException mex) + { + throw new BAD_PARAM("Malformed URL: '" + url + "'"); + } + + try + { + InputStreamReader r = new InputStreamReader(u.openStream()); + + CPStringBuilder b = new CPStringBuilder(); + int c; + + while ((c = r.read()) > 0) + b.append((char) c); + + return b.toString().trim(); + } + catch (Exception exc) + { + DATA_CONVERSION d = new DATA_CONVERSION("Reading " + url + " failed."); + d.minor = Minor.Missing_IOR; + throw d; + } + } + + private String[] resolve(String nsIor) + { + String [] n = new String[2]; + n[0] = nsIor; + n[1] = readKey("#"); + return n; + } + + private String readKey(String delimiter) + throws BAD_PARAM + { + if (p < t.length) + if (!t[p].equals(delimiter)) + { + if (t[p].equals("#")) + return DEFAULT_NAME; + else + throw new BAD_PARAM("'" + delimiter + "String' expected '" + t[p] + + "' found"); + } + + CPStringBuilder bKey = new CPStringBuilder(); + p++; + + while (p < t.length && !t[p].equals("#")) + bKey.append(t[p++]); + + if (bKey.length() == 0) + return DEFAULT_NAME; + + try + { + return URLDecoder.decode(bKey.toString(), "UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new Unexpected("URLDecoder does not support UTF-8", e); + } + } +} diff --git a/libjava/classpath/gnu/javax/naming/giop/GiopNamingEnumeration.java b/libjava/classpath/gnu/javax/naming/giop/GiopNamingEnumeration.java new file mode 100644 index 000000000..c2de75b38 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/GiopNamingEnumeration.java @@ -0,0 +1,187 @@ +/* GiopNamingEnumeration.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.naming.giop; + +import java.util.NoSuchElementException; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; + +import org.omg.CosNaming.Binding; +import org.omg.CosNaming.BindingIterator; +import org.omg.CosNaming.BindingIteratorHolder; +import org.omg.CosNaming.BindingListHolder; + +/** + * Iterates over name class pairs, obtaining values first from the binding list + * and then from the binding iterator. + * + * @author Audrius Meskauskas + */ +public abstract class GiopNamingEnumeration implements NamingEnumeration +{ + /** + * The array of bindings, returned at once. + */ + Binding[] list; + + /** + * The binding iterator to obtain the subsequent bindings. May be null, + * if all values are stored in the <code>list</code>. + */ + BindingIterator iterator; + + /** + * The batch size. + */ + int batch; + + /** + * The position of the element in the binding list, that must be returned + * during the subsequent call of the next(). If this field is grater or equal + * to the lenght of the list, the subsequent values must be requested from the + * iterator. + */ + int p; + + GiopNamingEnumeration(BindingListHolder bh, BindingIteratorHolder bih, int batchSize) + { + list = bh.value; + iterator = bih.value; + batch = batchSize; + } + + /** + * Convert from the CORBA binding into that this enumeration should return. + * + * @param binding + * the binding to convert + * @return the value, that must be returned by the {@link #next()}. + */ + public abstract Object convert(Binding binding); + + public void close() throws NamingException + { + if (iterator != null) + { + iterator.destroy(); + iterator = null; + } + } + + /** + * Checks if there are more elements to return. + * + * @throws NamingException + * never + */ + public boolean hasMore() throws NamingException + { + return hasMoreElements(); + } + + /** + * Returns the next element. + * + * @throws NamingException + * never + */ + public Object next() throws NamingException + { + return nextElement(); + } + + /** + * Checks if there are more elements to return. + */ + public boolean hasMoreElements() + { + if (p < 0) + return false; + else if (p < list.length) + return true; + else + return getMore(); + } + + /** + * Returns the next element. + */ + public Object nextElement() + { + if (p < 0) + throw new NoSuchElementException(); + else if (p < list.length) + return convert(list[p++]); + else if (getMore()) + // getMore updates p + return convert(list[p++]); + else + throw new NoSuchElementException(); + } + + /** + * Tries to obtain more elements, return true on success. Updates the fields + * accordingly. + */ + boolean getMore() + { + if (iterator != null) + { + BindingListHolder holder = new BindingListHolder(); + boolean rt = iterator.next_n(batch, holder); + if (rt) + { + // The new pack of the bindings arrived. + p = 0; + list = holder.value; + return true; + } + else + { + iterator.destroy(); + iterator = null; + p = -1; + return false; + } + } + else + return false; + } +} diff --git a/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceFactory.java b/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceFactory.java new file mode 100644 index 000000000..e8aac3b65 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceFactory.java @@ -0,0 +1,179 @@ +/* GiopNamingServiceFactory.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.naming.giop; + +import gnu.CORBA.OrbFunctional; + +import gnu.java.lang.CPStringBuilder; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; + +import javax.naming.Context; +import javax.naming.Name; + +import org.omg.CORBA.ORB; + +/** + * The context factory to represent the corbaname: style urls. Such URL states + * that the CORBA naming service exists on the given host. This service can + * return the required object, finding it by the given name. The names are + * parsed using the specification of the corbaname urls. Being the naming + * service, the returned context supports creating the subcontexts, forwarding + * this task to the existing naming service. + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ +public class GiopNamingServiceFactory +{ + /** + * The default naming service provider. It is assumed, that the naming service + * is running on the port 900 of the local host, using the GIOP version 1.2 + */ + public static final String DEFAULT_PROVIDER = + "corbaloc:iiop:1.2@127.0.0.1:900/NameService"; + + /** + * The table of all instantiated ORB's that are found by they ORB + * properties signatures. If all ORB related properties are the same, + * the ORB's are shared. + */ + public static Hashtable orbs = new Hashtable(); + + + /** + * Create a new instance of the corbaname URL context. + */ + public Object getObjectInstance(Object refObj, Name name, Context nameCtx, + Hashtable environment) + { + String provider = (String) environment.get(Context.PROVIDER_URL); + if (provider == null) + provider = DEFAULT_PROVIDER; + + String orbSignature = getOrbSignature(environment); + + ORB orb; + synchronized (orbs) + { + orb = (ORB) orbs.get(orbSignature); + if (orb == null) + { + Properties props = new Properties(); + props.putAll(environment); + orb = ORB.init(new String[0], props); + orbs.put(orbSignature, orb); + final ORB runIt = orb; + new Thread() + { + public void run() + { + runIt.run(); + } + }.start(); + } + } + + return new GiopNamingServiceURLContext(environment, this, orb); + } + + /** + * Check if this ORB is still in use (maybe it is time to shutdown it). This + * method only works when the Classpath CORBA implementation is used + * (otherwise it return without action). The method is called from the close() + * method of the created context. + * + * @param orb + * the ORB that maybe is no longer referenced. + */ + public void checkIfReferenced(ORB orb) + { + synchronized (orbs) + { + // We can only do this with the Classpath implementation. + if (orb instanceof OrbFunctional) + { + OrbFunctional cOrb = (OrbFunctional) orb; + // If there are no connected objects, we can destroy the orb. + if (cOrb.countConnectedObjects() == 0) + { + cOrb.shutdown(false); + cOrb.destroy(); + + Enumeration keys = orbs.keys(); + Object key; + Remove: while (keys.hasMoreElements()) + { + key = keys.nextElement(); + if (orbs.get(key) == orb) + { + orbs.remove(key); + break Remove; + } + } + } + } + } + } + + /** + * Get all properties. + */ + public String getOrbSignature(Map props) + { + TreeMap map = new TreeMap(); + map.putAll(props); + CPStringBuilder b = new CPStringBuilder(50*props.size()); + + Iterator iter = map.entrySet().iterator(); + Map.Entry m; + while (iter.hasNext()) + { + m = (Map.Entry) iter.next(); + b.append(m.getKey()); + b.append('='); + b.append(m.getValue()); + } + return b.toString(); + } +} diff --git a/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceURLContext.java b/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceURLContext.java new file mode 100644 index 000000000..0d2e290b4 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/GiopNamingServiceURLContext.java @@ -0,0 +1,840 @@ +/* GiopNamingServiceURLContext.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.naming.giop; + +import gnu.CORBA.NamingService.Ext; +import gnu.CORBA.NamingService.NameTransformer; + +import java.util.Hashtable; + +import javax.naming.Binding; +import javax.naming.Context; +import javax.naming.ContextNotEmptyException; +import javax.naming.InvalidNameException; +import javax.naming.Name; +import javax.naming.NameAlreadyBoundException; +import javax.naming.NameClassPair; +import javax.naming.NameNotFoundException; +import javax.naming.NameParser; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.OperationNotSupportedException; +import javax.naming.directory.InvalidAttributesException; + +import org.omg.CORBA.ORB; +import org.omg.CORBA.portable.Delegate; +import org.omg.CORBA.portable.ObjectImpl; +import org.omg.CosNaming.BindingIteratorHolder; +import org.omg.CosNaming.BindingListHolder; +import org.omg.CosNaming.NameComponent; +import org.omg.CosNaming.NamingContext; +import org.omg.CosNaming.NamingContextExt; +import org.omg.CosNaming.NamingContextExtHelper; +import org.omg.CosNaming.NamingContextHelper; +import org.omg.CosNaming._NamingContextExtStub; +import org.omg.CosNaming._NamingContextStub; +import org.omg.CosNaming.NamingContextPackage.AlreadyBound; +import org.omg.CosNaming.NamingContextPackage.CannotProceed; +import org.omg.CosNaming.NamingContextPackage.InvalidName; +import org.omg.CosNaming.NamingContextPackage.NotFound; + +/** + * The context to represent the corba naming service. Being the naming service, + * the returned context supports creating the subcontexts, forwarding this task + * to the existing naming service. When listing bindings, it uses the + * {@link Context#BATCHSIZE} property to determine, how many bindings should + * be returned at once (the process is transparend) + * + * @author Audrius Meskauskas (audriusa@Bioinformatics.org) + */ +public class GiopNamingServiceURLContext extends CorbalocParser implements + Context +{ + /** + * This number of bindings will be requested from the naming server at once, + * while the subsequent bindings will be requested via binding iterator one by + * one. Use {@link Context#BATCHSIZE} to override the value of this constant. + */ + public int DEFAULT_BATCH_SIZE = 20; + + /** + * The object request broker, used to access the naming service. This field + * is only initialised when the context is constructed from the URL. + */ + ORB orb; + + /** + * The properties. + */ + Hashtable properties; + + /** + * The parent factory. + */ + GiopNamingServiceFactory factory; + + /** + * The name transformer to obtain the name from its string representation. The + * to_name method of the naming service is avoided as it may be remote and + * hence expensive. The conversion rules are standard and cannot be service + * specific. + */ + static NameTransformer transformer = new NameTransformer(); + + /** + * The batch size for list operations - how many to return at once. + */ + public final int howMany; + + /** + * Creates a new naming context that uses naming service, represented by the + * given CORBA object. + * + * @param props + * the environment table. + * @param aFactory + * parent factory. This reference is used during cleanup. + * @param anOrb + * the associated ORB. This reference is used during cleanup. + */ + public GiopNamingServiceURLContext(Hashtable props, + GiopNamingServiceFactory aFactory, + ORB anOrb) + { + factory = aFactory; + orb = anOrb; + + properties = props; + howMany = getBatchSize(); + } + + public NamingContextExt getService(String address) + { + org.omg.CORBA.Object nsObject = orb.string_to_object(address); + Delegate delegate = ((ObjectImpl) nsObject)._get_delegate(); + + // If the IOR provides the IDL ID, we can check if our name + // service is old NamingContext or new NamingContextExt. + // Not all forms of the URL always provide the IDL id. + if (!nsObject._is_a(NamingContextExtHelper.id()) + && nsObject._is_a(NamingContextHelper.id())) + { + // We are surely working with the old version. + _NamingContextStub stub = new _NamingContextStub(); + stub._set_delegate(delegate); + // The Ext object will add the necessary extensions. + return new Ext(stub); + } + else + { + // We expecte the service to be the NamingContextExt (this is true + // for both Sun's and our implementations). There is no easy way + // to check the version. + _NamingContextExtStub stub = new _NamingContextExtStub(); + stub._set_delegate(delegate); + return stub; + } + } + + /** + * Split the corbaname name into the address of the naming service (first + * part) and the name of the object in the naming service (second part) + */ + public String[] split(String corbaloc) throws InvalidNameException + { + if (corbaloc.endsWith("#")) + corbaloc = corbaloc.substring(0, corbaloc.length() - 1); + + // No name part - parse as corbaname. + if (corbaloc.indexOf('#') < 0) + { + if (!corbaloc.regionMatches(true, 0, pxCORBANAME, 0, + pxCORBANAME.length())) + throw new InvalidNameException(corbaloc + " must start with " + + pxCORBANAME); + corbaloc = pxCORBALOC + corbaloc.substring(pxCORBANAME.length()); + return new String[] { corbaloc, "" }; + } + + return corbaloc(corbaloc, orb); + } + + /** + * Give the specified name for the specified object. The passed name must not + * be already bound to some other object. The components of the name are + * mapped into the components of the CORBA name. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws NameAlreadyBoundException + * if this name is already used to name some object. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void bind(Name name, Object obj) throws NamingException + { + bind(name.toString(), obj); + } + + /** + * Give the specified name for the specified object. The passed name must not + * be already bound to some other object. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws NameAlreadyBoundException + * if this name is already used to name some object. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void bind(String name, Object obj) throws NamingException + { + try + { + String[] n = split(name); + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + getService(n[0]).bind(transformer.toName(n[1]), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Releases all resources, associated with this context. The close() method + * can be called several times, but after it has been once invoked, it is not + * allowed to call any other method of this context. This method destroys + * the ORB, if we have one. + * + * @throws NamingException + */ + public void close() throws NamingException + { + if (orb != null && factory != null) + { + factory.checkIfReferenced(orb); + } + } + + /** + * Not supported. + */ + public Name composeName(Name name, Name prefix) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Not supported + */ + public String composeName(String name1, String name2) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Creates the new naming subcontext and binds it to the current (this) + * context. The returned object will wrap around the newly created CORBA + * subcontext + * + * @param subContext + * the name of the new context being created + * @return the newly created context, bound to the instance of the context on + * that the method has been called + * @throws NameAlreadyBoundException + * if this name is already bound + * @throws InvalidAttributesException + * if the creation of the new context requires the missing mandatory + * attributes + * @throws NamingException + */ + public Context createSubcontext(Name subContext) throws NamingException + { + return createSubcontext(subContext.toString()); + } + + /** + * Creates the new naming subcontext and binds it to the current (this) + * context. The returned object will wrap around the newly created CORBA + * subcontext + * + * @param subContext + * the name of the new context being created + * @return the newly created context, bound to the instance of the context on + * that the method has been called + * @throws NameAlreadyBoundException + * if this name is already bound + * @throws InvalidAttributesException + * if the creation of the new context requires the missing mandatory + * attributes + * @throws NamingException + */ + public Context createSubcontext(String subContext) throws NamingException + { + try + { + String[] n = split(subContext); + org.omg.CORBA.Object subcontext = getService(n[0]).bind_new_context( + transformer.toName(n[1])); + Hashtable clonedProps = new Hashtable(); + clonedProps.putAll(properties); + + // Nulls are passed both for orb and factory, as the child contexts + // need not to do any cleanup. + return new ContextContinuation(subcontext, clonedProps, null, null); + } + catch (AlreadyBound e) + { + throw new NameAlreadyBoundException(subContext); + } + catch (InvalidName e) + { + throw new InvalidNameException(subContext); + } + catch (Exception ex) + { + throw new NamingException(ex.toString()); + } + } + + /** + * Removes the naming subcontext from this naming context. Returns without + * action if such subcontext does not exist. The context being destroyed must + * be empty. + * + * @param subContext + * the name of the subcontext beig removed. + * @throws ContextNotEmptyException + * if the named context is not empty. + * @throws NamingException + */ + public void destroySubcontext(Name subContext) throws NamingException + { + unbind(subContext); + } + + /** + * Removes the naming subcontext from this naming context. Returns without + * action if such subcontext does not exist. The context being destroyed must + * be empty. + * + * @param subContext + * the name of the subcontext beig removed. + * @throws ContextNotEmptyException + * if the named context is not empty. + * @throws NamingException + */ + public void destroySubcontext(String subContext) throws NamingException + { + unbind(subContext); + } + + /** + * Returs the empty string. + */ + public String getNameInNamespace() throws NamingException + { + return ""; + } + + /** + * Not supported. + */ + public NameParser getNameParser(Name name) throws NamingException + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + */ + public NameParser getNameParser(String name) throws NamingException + { + throw new UnsupportedOperationException(); + } + + /** + * Creates and returns the enumeration over the name bindings that are present + * the given subcontext. The enumeration elements have the type of + * {@link NameClassPair}, providing also information about the class of the + * bound object. The behaviour in the case if the bindings are added or + * removed later is not defined. The contents of the subcontexts are not + * included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration list(Name name) throws NamingException + { + return list(name.toString()); + } + + /** + * Creates and returns the enumeration over the name bindings that are present + * the given subcontext. The enumeration elements have the type of + * {@link NameClassPair}, providing also information about the class of the + * bound object. The behaviour in the case if the bindings are added or + * removed later is not defined. The contents of the subcontexts are not + * included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration list(String name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + String [] n = split(name); + NamingContextExt service = getService(n[0]); + + if (n[1].length() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1]))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + + } + + subcontext.list(howMany, bl, bi); + + return new ListEnumeration(bl, bi, howMany); + } + + /** + * Creates and returns the enumeration over the name - object bindings that + * are present the given subcontext. The enumeration elements have the type of + * {@link Binding}, providing also information about the class of the bound + * object. The behaviour in the case if the bindings are added or removed + * later is not defined. The contents of the subcontexts are not included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration listBindings(Name name) throws NamingException + { + return listBindings(name.toString()); + } + + /** + * Creates and returns the enumeration over the name - object bindings that + * are present the given subcontext. The enumeration elements have the type of + * {@link Binding}, providing also information about the class of the bound + * object. The behaviour in the case if the bindings are added or removed + * later is not defined. The contents of the subcontexts are not included. + * + * @param name + * the name of the subcontext + * @return the enumeration over the names, known for the given subcontext. + * @throws NamingException + */ + public NamingEnumeration listBindings(String name) throws NamingException + { + BindingIteratorHolder bi = new BindingIteratorHolder(); + BindingListHolder bl = new BindingListHolder(); + + NamingContext subcontext; + + String [] n = split(name); + NamingContextExt service = getService(n[0]); + + if (n[1].length() == 0) + subcontext = service; + else + { + try + { + subcontext = (NamingContextHelper.narrow(service.resolve_str(n[1]))); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + + } + + subcontext.list(howMany, bl, bi); + + return new ListBindingsEnumeration(bl, bi, howMany, subcontext); + } + + /** + * Gets the previously named object by name. If the passed name is empty, the + * method should return a cloned instance of this naming context. + * + * @param name + * the name of the object being searched in this context + * @return the named object + * @throws NameNotFoundException + * if the name is not found + */ + public Object lookup(Name name) throws NamingException + { + return lookup(name.toString()); + } + + /** + * Gets the previously named object by name. If the passed name is empty, the + * method should return a cloned instance of this naming context. + * + * @param name + * the name of the object being searched in this context + * @return the named object + * @throws NamingException + * if the naming fails. + */ + public Object lookup(String name) throws NamingException + { + try + { + String [] n = split(name); + NamingContextExt service = getService(n[0]); + return service.resolve_str(n[1]); + } + catch (NotFound e) + { + throw new NameNotFoundException(); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Not supported. + */ + public Object lookupLink(Name name) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Not supported. + */ + public Object lookupLink(String name) throws NamingException + { + throw new OperationNotSupportedException(); + } + + /** + * Give the specified name for the specified object. Unlike bind, this method + * silently replaces the existing binding for this name, if one exists. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rebind(Name name, Object obj) throws NamingException + { + rebind(name.toString(), obj); + } + + /** + * Give the specified name for the specified object. Unlike bind, this method + * silently replaces the existing binding for this name, if one exists. + * + * @param name + * the name that will be given to the object (in the scope of this + * context). + * @param obj + * the object being named. + * @throws InvalidAttributesException + * if the object does not supply all required attributes. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rebind(String name, Object obj) throws NamingException + { + try + { + String[] n = split(name); + NamingContextExt service = getService(n[0]); + + org.omg.CORBA.Object object = (org.omg.CORBA.Object) obj; + service.rebind(transformer.toName(n[1]), object); + } + catch (ClassCastException e) + { + throw new NamingException(org.omg.CORBA.Object.class + " required "); + } + catch (InvalidName e) + { + throw new InvalidNameException(); + } + catch (Exception e) + { + throw new NamingException(e.toString()); + } + } + + /** + * Renames the existing binding, removing the existing and giving the new name + * for the same object. + * + * @param oldName + * the existing name of the known object + * @param newName + * the new name of the same object + * @throws NameNotFoundException + * if the oldName is unknown for this context + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rename(Name oldName, Name newName) throws NamingException + { + Object object = lookup(oldName); + unbind(oldName); + bind(newName, object); + } + + /** + * Renames the existing binding, removing the existing and giving the new name + * for the same object. + * + * @param oldName + * the existing name of the known object + * @param newName + * the new name of the same object + * @throws NameNotFoundException + * if the oldName is unknown for this context + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void rename(String oldName, String newName) throws NamingException + { + Object object = lookup(oldName); + unbind(oldName); + bind(newName, object); + } + + /** + * Removes the name - object mapping from the current context. This method + * returns without action if the name is not bound to an object in the + * terminal context, but throws {@link NameNotFoundException} if one of the + * intermadiate contexts does not exist. + * + * @param name + * the name to be removed + * @throws NameNotFoundException + * if one of the intermediate naming contexts does not exist. Will + * not be thrown if just the terminal binding is missing. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void unbind(Name name) throws NamingException + { + unbind(name.toString()); + } + + /** + * Removes the name - object mapping from the current context. This method + * returns without action if the name is not bound to an object in the + * terminal context, but throws {@link NameNotFoundException} if one of the + * intermadiate contexts does not exist. + * + * @param name + * the name to be removed + * @throws NameNotFoundException + * if one of the intermediate naming contexts does not exist. Will + * not be thrown if just the terminal binding is missing. + * @throws NamingException + * if the naming operation has failed due other reasons. + */ + public void unbind(String name) throws NamingException + { + try + { + String[] n = split(name); + NamingContextExt service = getService(n[0]); + + service.unbind(transformer.toName(n[1])); + } + catch (NotFound e) + { + throw new NameNotFoundException(name); + } + catch (CannotProceed e) + { + throw new ContextNotEmptyException(name); + } + catch (InvalidName e) + { + throw new InvalidNameException(name); + } + } + + /** + * Add new environment property to the environment of this context. Both name + * and value of the new property must not be null. If the property is already + * defined, is current value is replaced by the propVal. + * + * @param key + * the name of the new property + * @param value + * the value of the new property + * @return the previous value of this property or null if the property has not + * been previously defined + * @throws NamingException + */ + public Object addToEnvironment(String key, Object value) + throws NamingException + { + if (key == null || value == null) + throw new NullPointerException(); + return properties.put(key, value); + } + + /** + * Returns the environment, associated with this naming context. The returned + * table should never be modified by the caller. Use {@link #addToEnvironment} + * and {@link #removeFromEnvironment} to modify the environement, if needed. + * + * @return the table, representing the environment of this context + * @throws NamingException + */ + public Hashtable getEnvironment() throws NamingException + { + return properties; + } + + /** + * Removes the property with the given name from the environment. Returns + * without action if this property is not defined. + * + * @param propName + * the name of the property being removed. + * @return the value of the property that has been removed or null if the + * property was not defined. + * @throws NamingException + */ + public Object removeFromEnvironment(String propName) throws NamingException + { + return properties.remove(propName); + } + + /** + * Convert the {@link Name} into array of the name components, required to the + * CORBA naming service. First the string representation is obtained, then + * it is converted using parsing rules of the CORBA name. + * + * @param name + * then name to convert + * @return the converted array of components. + */ + public NameComponent[] toGiop(Name name) throws InvalidName + { + return transformer.toName(name.toString()); + } + + /** + * Get the batch size from the environment properties. The batch size is used + * for listing operations. + * + * @return the batch size, or some default value if not specified. + */ + public int getBatchSize() + { + int batchSize = DEFAULT_BATCH_SIZE; + Object bs = properties.get(Context.BATCHSIZE); + if (bs != null) + { + try + { + int b = Integer.parseInt(bs.toString()); + if (b >= 0) + batchSize = b; + } + catch (NumberFormatException e) + { + // OK, use default value. + } + } + return batchSize; + } + +} diff --git a/libjava/classpath/gnu/javax/naming/giop/ListBindingsEnumeration.java b/libjava/classpath/gnu/javax/naming/giop/ListBindingsEnumeration.java new file mode 100644 index 000000000..dd9ed0265 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/ListBindingsEnumeration.java @@ -0,0 +1,118 @@ +/* ListBindingsEnumeration.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.naming.giop; + +import gnu.java.lang.CPStringBuilder; + +import javax.naming.NamingEnumeration; + +import org.omg.CosNaming.Binding; +import org.omg.CosNaming.BindingIteratorHolder; +import org.omg.CosNaming.BindingListHolder; +import org.omg.CosNaming.NamingContext; + +/** + * Iterates over bindings, obtaining values first from the binding list and then + * from the binding iterator. + * + * @author Audrius Meskauskas + */ +public class ListBindingsEnumeration extends GiopNamingEnumeration implements + NamingEnumeration +{ + /** + * The naming service, to resolve the objects. + */ + NamingContext service; + + /** + * Create the new enumeration + * + * @param bh + * holder, containing the first portion of the bindings + * @param bih + * the iterator, containing the remaining bindings + * @param batchSize + * the number of bindings the the iterator will be requested to + * return as a single pack + * @param aService + * the naming service, used to obtain the objects, bound to the + * names. + */ + public ListBindingsEnumeration(BindingListHolder bh, + BindingIteratorHolder bih, int batchSize, + NamingContext aService) + { + super(bh, bih, batchSize); + service = aService; + } + + /** + * Convert from the CORBA binding into the javax.naming binding. As the CORBA + * naming service binding does not contain the object itself, this method + * makes the additional calls to the naming service. + * + * @param binding + * the binding to convert + * @return the value, that must be returned by the {@link #next()}. + */ + public Object convert(Binding binding) + { + CPStringBuilder name = new CPStringBuilder(); + + for (int i = 0; i < binding.binding_name.length; i++) + { + name.append(binding.binding_name[i]); + if (i < binding.binding_name.length - 1) + name.append('/'); + } + + try + { + Object object = service.resolve(binding.binding_name); + return new javax.naming.Binding(name.toString(), object); + } + catch (Exception e) + { + // Probably was removed by the concurent thread. + return null; + } + } + +} diff --git a/libjava/classpath/gnu/javax/naming/giop/ListEnumeration.java b/libjava/classpath/gnu/javax/naming/giop/ListEnumeration.java new file mode 100644 index 000000000..68a40fcf0 --- /dev/null +++ b/libjava/classpath/gnu/javax/naming/giop/ListEnumeration.java @@ -0,0 +1,118 @@ +/* ListEnumeration.java -- handles corbaname: urls + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +odule. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.naming.giop; + +import gnu.java.lang.CPStringBuilder; + +import javax.naming.NameClassPair; +import javax.naming.NamingEnumeration; + +import org.omg.CosNaming.Binding; +import org.omg.CosNaming.BindingIteratorHolder; +import org.omg.CosNaming.BindingListHolder; +import org.omg.CosNaming.BindingType; +import org.omg.CosNaming.NamingContext; + +/** + * Iterates over name class pairs, obtaining values first from the binding list + * and then from the binding iterator. + * + * @author Audrius Meskauskas + */ +public class ListEnumeration extends GiopNamingEnumeration implements + NamingEnumeration +{ + /** + * Create the new enumeration + * + * @param bh + * holder, containing the first portion of the bindings + * @param bih + * the iterator, containing the remaining bindings + * @param batchSize + * the number of bindings the the iterator will be requested to + * return as a single pack + */ + public ListEnumeration(BindingListHolder bh, + BindingIteratorHolder bih, int batchSize) + { + super(bh, bih, batchSize); + } + + /** + * Convert from the CORBA binding into the {@link NameClassPair} that this + * enumeration should return. This method converts into NameClassPair, + * connecting the name components with slashes and setting the class name + * to either NamingContext or GIOP Object. + * + * @param binding + * the binding to convert + * @return the value, that must be returned by the {@link #next()}. + */ + public Object convert(Binding binding) + { + CPStringBuilder name = new CPStringBuilder(); + + for (int i = 0; i < binding.binding_name.length; i++) + { + name.append(binding.binding_name[i]); + if (i < binding.binding_name.length - 1) + name.append('/'); + } + + String className; + + switch (binding.binding_type.value()) + { + case BindingType._ncontext: + className = NamingContext.class.getName(); + break; + case BindingType._nobject: + className = org.omg.CORBA.Object.class.getName(); + break; + default: + className = Object.class.getName(); + break; + } + + NameClassPair pair = new NameClassPair(name.toString(), className); + return pair; + } + +} |