donaldp 01/04/28 21:00:17 Added: cadastre .cvsignore build.xml cadastre/src/java/org/apache/avalon/cadastre AbstractContext.java AbstractLocalContext.java AbstractNamespace.java AbstractNamingEnumeration.java AbstractURLContext.java ArrayNamingEnumeration.java DefaultNameParser.java DefaultNamespace.java Namespace.java NamingProvider.java RemoteContext.java cadastre/src/java/org/apache/avalon/cadastre/memory MemoryContext.java MemoryInitialContextFactory.java MemoryNamingEnumeration.java cadastre/src/java/org/apache/avalon/cadastre/rmi RMIInitialContextFactory.java RMINamingProvider.java cadastre/src/java/org/apache/avalon/cadastre/rmi/server RMINamingProviderImpl.java cadastre/src/test/org/apache/avalon/cadastre AbstractContextTestlet.java cadastre/src/test/org/apache/avalon/cadastre/rmi RMIContextTestlet.java cadastre/src/test/org/apache/avalon/cadastre/rmi/server Main.java Log: Check in cadestre A basic JNDI framework. Revision Changes Path 1.1 jakarta-commons-sandbox/cadastre/.cvsignore Index: .cvsignore =================================================================== emacs-jprj.el build dist 1.1 jakarta-commons-sandbox/cadastre/build.xml Index: build.xml =================================================================== <?xml version="1.0"?> <!-- ============================================================================== Cadastre build file Authors: Peter Donald <[EMAIL PROTECTED]> ============================================================================== --> <project default="main" basedir="."> <!-- Give user a chance to override without editing this file (and without typing -D each time he compiles it) --> <property file=".ant.properties"/> <property file="${user.home}/.ant.properties"/> <property name="name" value="cadastre"/> <property name="Name" value="Cadastre"/> <property name="version" value="0.01"/> <property name="year" value="1999-2001"/> <!-- these are here only for those who use jikes compiler. For other developers this part makes no difference. --> <property name="build.compiler.emacs" value="on"/> <property name="build.compiler.warnings" value="true"/> <property name="build.compiler.pedantic" value="true"/> <property name="build.compiler.depend" value="true"/> <property name="build.compiler.fulldepend" value="true"/> <property name="debug" value="off"/> <property name="optimize" value="off"/> <property name="deprecation" value="off"/> <!-- =================================================================== Set the properties for intermediate directory =================================================================== --> <property name="build.dir" value="build"/> <property name="build.lib" value="${build.dir}/lib"/> <property name="build.src" value="${build.dir}/src"/> <property name="build.classes" value="${build.dir}/classes"/> <property name="build.javadocs" value="${build.dir}/javadocs"/> <property name="build.docs" value="${build.dir}/docs"/> <property name="build.xdocs" value="${build.dir}/xdocs"/> <!-- =================================================================== Set the properties for source directories =================================================================== --> <property name="src.dir" value="src"/> <property name="test.dir" value="${src.dir}/test"/> <property name="java.dir" value="${src.dir}/java"/> <property name="lib.dir" value="lib"/> <property name="docs.dir" value="docs"/> <property name="www.dir" value="www"/> <property name="javadocs.dir" value="${docs.dir}/framework/api"/> <property name="skins.dir" value="${src.dir}/skins"/> <property name="avalon.skin" value="${skins.dir}/avalon/"/> <property name="xdocs.dir" value="${src.dir}/xdocs"/> <property name="stylesheets.dir" value="${skins.dir}"/> <property name="dist.name" value="${Name}-${version}"/> <property name="dist.base" value="distributions"/> <path id="project.class.path"> <pathelement path="${java.class.path}" /> <pathelement path="${testlet.location}" /> <!-- <fileset dir="${lib.dir}"> <include name="*.jar" /> </fileset> --> <pathelement path="${build.classes}" /> </path> <!-- =================================================================== Main target =================================================================== --> <target name="main" depends="dist-lite" /> <!-- =================================================================== Help on usage =================================================================== --> <target name="usage"> <echo message=""/> <echo message="${Name} Build file"/> <echo message="-------------------------------------------------------------"/> <echo message=""/> <echo message=" available targets are:"/> <echo message=""/> <echo message=" jar --> generates the ${Name} jar files"/> <echo message=" test --> perform unit tests"/> <echo message=" compile --> compiles the source code"/> <echo message=" javadocs --> generates the API documentation (java 1.2+ only)"/> <echo message=" docs --> generates the ${Name} Documentation"/> <echo message=" main or jars --> generates the ${Name} distribution without the javadocs (default)"/> <echo message=" dist --> generates the ${Name} distribution"/> <echo message=" clean --> cleans up the created directories"/> <echo message=" real-clean --> cleans up all genereated files and directories"/> <echo message=" proposal --> generates the ${Name} proposal distribution without the javadocs"/> <echo message=""/> <echo message="-------------------------------------------------------------"/> <echo message=""/> </target> <target name="help" depends="usage"/> <!-- =================================================================== Set up dist properties =================================================================== --> <target name="setup-properties" > <property name="dist.dir" value="dist"/> <property name="dist.bin" value="${dist.dir}/bin"/> <property name="dist.apps" value="${dist.dir}/apps"/> <property name="dist.lib" value="${dist.dir}/lib"/> <property name="dist.docs" value="${dist.dir}/docs"/> <property name="dist.javadocs" value="${dist.dir}/docs/api"/> <property name="src.dist.dir" value="dist-src"/> <property name="src.dist.src" value="${src.dist.dir}/src"/> <property name="src.dist.docs" value="${src.dist.dir}/docs"/> <property name="src.dist.javadocs" value="${src.dist.dir}/docs/api"/> <property name="src.dist.lib" value="${src.dist.dir}/lib"/> <property name="src.dist.tools" value="${src.dist.dir}/tools"/> </target> <!-- =================================================================== Prepares the build directory =================================================================== --> <target name="prepare" depends="setup-properties"> <tstamp/> <mkdir dir="${build.dir}"/> <available property="testlet.present" classname="org.apache.testlet.Testlet" classpathref="project.class.path" /> </target> <!-- =================================================================== Compiles the source code =================================================================== --> <target name="compile" depends="prepare"> <mkdir dir="${build.classes}"/> <javac srcdir="${java.dir}" destdir="${build.classes}" debug="${debug}" optimize="${optimize}" deprecation="${deprecation}"> <classpath refid="project.class.path" /> </javac> <javac srcdir="${test.dir}" destdir="${build.classes}" debug="${debug}" optimize="${optimize}" deprecation="${deprecation}"> <classpath refid="project.class.path" /> <exclude name="**/*" unless="testlet.present" /> </javac> <rmic base="${build.classes}" classname="org.apache.avalon.cadastre.rmi.server.RMINamingProviderImpl" stubVersion="1.2"> <classpath refid="project.class.path" /> </rmic> </target> <!-- =================================================================== Create the API documentation =================================================================== --> <target name="javadocs"> <delete dir="${build.javadocs}"/> <mkdir dir="${build.javadocs}"/> <javadoc packagenames="org.apache.*" sourcepath="${java.dir}" destdir="${build.javadocs}"> <classpath refid="project.class.path" /> <doclet name="com.sun.tools.doclets.standard.Standard"> <param name="-author"/> <param name="-version"/> <param name="-use"/> <param name="-doctitle" value="${Name}"/> <param name="-windowtitle" value="${Name} API"/> <param name="-bottom" value=""Copyright © 2001 Apache Jakarta Project. All Rights Reserved.""/> </doclet> </javadoc> </target> <!-- =================================================================== Creates all the .jar files =================================================================== --> <target name="jars" depends="compile"> <mkdir dir="${build.lib}"/> <jar jarfile="${build.lib}/cadastre.jar" basedir="${build.classes}"> <include name="org/apache/avalon/cadastre/**"/> <exclude name="**/test/*"/> </jar> </target> <target name="dist-lite" depends="jars"> <!-- <copy file="src/script/run.sh" todir="${build.dir}" /> <chmod perm="u+x" file="${build.dir}/run.sh" /> --> </target> <target name="test" depends="dist-lite"> <echo message="Testing ... 1. 2. 3. Testing" /> <test showSuccess="true" showBanner="false" showTrace="true" forceShowTrace="true" > <classpath refid="project.class.path" /> <testlet>org.apache.avalon.cadastre.rmi.RMIContextTestlet</testlet> </test> </target> <!-- =================================================================== Cleans up build and distribution directories =================================================================== --> <target name="clean" depends="setup-properties"> <delete dir="${build.dir}" /> <delete dir="${dist.dir}" /> <delete> <fileset dir="." includes="**/*~" defaultexcludes="no"/> </delete> </target> </project> 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/AbstractContext.java Index: AbstractContext.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.*; import javax.naming.Context; /** * Abstract JNDI Context that can be inherited from to * provide a particular type of Context. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractContext implements Context { protected Hashtable m_environment; public AbstractContext() { this( new Hashtable() ); } public AbstractContext( final Hashtable environment ) { m_environment = environment; } protected abstract NameParser getNameParser() throws NamingException; /** * Add a key-value pair to environment * * @param key the key * @param value the value * @return the value */ public Object addToEnvironment( final String key, final Object value ) throws NamingException { if( null == m_environment ) m_environment = new Hashtable( 5, 0.75f ); return m_environment.put( key, value ); } /** * Release resources associated with context. * */ public void close() { m_environment = null; } protected boolean isSelf( final Name name ) { return ( name.isEmpty() || name.get( 0 ).equals( "" ) ); } /** * Bind an object to a name. * * @param name the name to bind to * @param object the object * @exception NamingException if an error occurs such as bad name or invalid binding */ public void bind( final String name, final Object object ) throws NamingException { bind( getNameParser().parse( name ), object ); } /** * Bind an object to a name. * * @param name the name to bind to * @param object the object * @exception NamingException if an error occurs such as bad name or invalid binding */ public void bind( final Name name, final Object object ) throws NamingException { bind( name, object, false ); } /** * Helper method to bind */ protected abstract void bind( Name name, Object object, boolean rebind ) throws NamingException; /** * Compose a name form a name and a prefix. * * @param name the name * @param prefix the prefix * @return the composed name * @exception NamingException if a badly formatted name for context */ public String composeName( final String name, final String prefix ) throws NamingException { final NameParser nameParser = getNameParser(); final Name result = composeName( nameParser.parse( name ), nameParser.parse( prefix ) ); return result.toString(); } /** * Compose a name form a name and a prefix. * * @param name the name * @param prefix the prefix * @return the composed name * @exception NamingException if a badly formatted name for context */ public Name composeName( final Name name, final Name prefix ) throws NamingException { final Name result = (Name)(prefix.clone()); result.addAll( name ); return result; } /** * Create a Subcontext. * * @param name the name of subcontext * @return the created context * @exception NamingException if an error occurs (ie context exists, badly formated name etc) */ public Context createSubcontext( final String name ) throws NamingException { return createSubcontext( getNameParser().parse( name ) ); } /** * Destroy a Subcontext. * * @param name the name of subcontext to destroy * @exception NamingException if an error occurs such as malformed name or context not exiting or not empty */ public void destroySubcontext( final String name ) throws NamingException { destroySubcontext( getNameParser().parse( name ) ); } /** * Return a copy of environment. * * @return the environment */ public Hashtable getEnvironment() throws NamingException { if( null == m_environment ) return new Hashtable( 3, 0.75f ); else return (Hashtable)m_environment.clone(); } /** * Get the NameParser for the named context. * * @param name * @return the NameParser * @exception NamingException if an error occurs */ public NameParser getNameParser( final String name ) throws NamingException { return getNameParser( getNameParser().parse( name ) ); } /** * Get the NameParser for the named context. * * @param name * @return the NameParser * @exception NamingException if an error occurs */ public NameParser getNameParser( final Name name ) throws NamingException { if( name.isEmpty() ) { return getNameParser(); } Object object = lookup( name ); if( !(object instanceof Context) ) { object = lookup( getPathName( name ) ); } final Context context = (Context)object; final NameParser parser = context.getNameParser( "" ); context.close(); return parser; } /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration list( final String name ) throws NamingException { return list( getNameParser().parse( name ) ); } /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration listBindings( final String name ) throws NamingException { return listBindings( getNameParser().parse( name ) ); } /** * Get the object named. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookup( final String name ) throws NamingException { return lookup( getNameParser().parse( name ) ); } /** * Get the object named following all links. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookupLink( final String name ) throws NamingException { return lookupLink( getNameParser().parse( name ) ); } /** * Get the object named following all links. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookupLink( final Name name ) throws NamingException { return lookup( name ); } /** * Binds a name to an object, overwriting any existing binding. * * @param name the name * @param object the object * @exception NamingException if an error occurs */ public void rebind( final String name, final Object object ) throws NamingException { rebind( getNameParser().parse( name ), object ); } /** * Binds a name to an object, overwriting any existing binding. * * @param name the name * @param object the object * @exception NamingException if an error occurs */ public void rebind( final Name name, final Object object ) throws NamingException { bind( name, object, true ); } /** * Remove a key-value pair form environment and return it. * * @param key the key * @return the value */ public Object removeFromEnvironment( final String key ) throws NamingException { if( null == m_environment ) return null; return m_environment.remove( key ); } /** * Rename a already bound object * * @param oldName the old name * @param newName the new name * @exception NamingException if an error occurs */ public void rename( final String oldName, final String newName ) throws NamingException { rename( getNameParser().parse( oldName ), getNameParser().parse( newName ) ); } public void rename( final Name oldName, final Name newName ) throws NamingException { if( isSelf( oldName ) || isSelf( newName ) ) { throw new InvalidNameException( "Failed to rebind self" ); } else if( oldName.equals( newName ) ) { throw new InvalidNameException( "Failed to rebind identical names" ); } bind( newName, lookup( oldName ) ); unbind( oldName ); } /** * Unbind a object from a name. * * @param name the name * @exception NamingException if an error occurs */ public void unbind( final String name ) throws NamingException { unbind( getNameParser().parse( name ) ); } protected Name getPathName( final Name name ) throws NamingException { return name.getPrefix( name.size() - 1 ); } protected Name getLeafName( final Name name ) throws NamingException { return name.getSuffix( name.size() - 1 ); } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/AbstractLocalContext.java Index: AbstractLocalContext.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.Context; import javax.naming.InvalidNameException; import javax.naming.NamingEnumeration; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.ContextNotEmptyException; import javax.naming.NameAlreadyBoundException; import javax.naming.NamingException; import javax.naming.NotContextException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.OperationNotSupportedException; /** * Abstract local JNDI Context that can be inherited from to * provide a particular type of Context. These contexts are assumed to be * on the same machine. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractLocalContext extends AbstractContext { protected Context m_parent; protected Namespace m_namespace; public AbstractLocalContext( final Namespace namespace, final Hashtable environment, final Context parent ) { super( environment ); m_namespace = namespace; m_parent = parent; } protected boolean isDestroyableContext( final Object object ) throws NamingException { return getClass().isInstance( object ); } protected abstract Context newContext() throws NamingException; protected abstract Context cloneContext() throws NamingException; /** * Helper method to bind */ protected void bind( final Name name, Object object, final boolean rebind ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to bind self" ); } if( 1 == name.size() ) { boolean alreadyBound = false; try { localLookup( name ); alreadyBound = true; } catch( final NamingException ne ) {} if( !rebind && alreadyBound ) { throw new NameAlreadyBoundException( name.get( 0 ) ); } else { //Should this occur here or in the factories ??? if( object instanceof Referenceable ) { object = ((Referenceable)object).getReference(); } // Call getStateToBind for using any state factories final Name atom = name.getPrefix( 1 ); object = m_namespace.getStateToBind( object, atom, this, m_environment ); doLocalBind( name, object ); } } else { final Context context = lookupSubContext( getPathName( name ) ); if( rebind ) { context.rebind( getLeafName( name ), object ); } else { context.bind( getLeafName( name ), object ); } } } protected abstract void doLocalBind( Name name, Object object ) throws NamingException; public void close() { m_parent = null; m_namespace = null; } /** * Create a Subcontext. * * @param name the name of subcontext * @return the created context * @exception NamingException if an error occurs (ie context exists, badly formated name etc) */ public Context createSubcontext( final Name name ) throws NamingException { final Context context = newContext(); bind( name, context ); return context; } public void destroySubcontext( final Name name ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to destroy self" ); } if( 1 == name.size() ) { Object object = null; try { object = localLookup( name ); } catch( final NamingException ne ) { return; } checkUnbindContext( name, object ); doLocalUnbind( name ); } else { final Context context = lookupSubContext( getPathName( name ) ); Object object = null; final Name atom = getLeafName( name ); try { object = context.lookup( atom ); } catch( final NamingException ne ) { return; } checkUnbindContext( atom, object ); context.destroySubcontext( atom ); } } protected void checkUnbindContext( final Name name, final Object entry ) throws NamingException { if( !isDestroyableContext( entry ) ) { throw new NotContextException( name.toString() ); } final Context context = (Context)entry; if( context.list( "" ).hasMoreElements() ) { throw new ContextNotEmptyException( name.toString() ); } } public String getNameInNamespace() throws NamingException { throw new OperationNotSupportedException( "Namespace has no notion of a 'full name'" ); } protected NameParser getNameParser() throws NamingException { return m_namespace.getNameParser(); } /** * Enumerates the names bound in the named context. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration list( final Name name ) throws NamingException { if( isSelf( name ) ) { return doLocalList(); } else { // Perhaps 'name' names a context final Context context = lookupSubContext( name ); return context.list( "" ); } } protected abstract NamingEnumeration doLocalList() throws NamingException; protected abstract NamingEnumeration doLocalListBindings() throws NamingException; /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration listBindings( final Name name ) throws NamingException { if( isSelf( name ) ) { return doLocalListBindings(); } else { // Perhaps 'name' names a context final Context context = lookupSubContext( name ); return context.listBindings( "" ); } } /** * Get the object named. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookup( final Name name ) throws NamingException { //if it refers to base context return a copy of it. if( isSelf( name ) ) { return cloneContext(); } if( 1 == name.size() ) { return localLookup( name ); } else { final Context context = lookupSubContext( getPathName( name ) ); return context.lookup( getLeafName( name ) ); } } /** * Lookup entry in local context. * * @param name the name in local context (size() == 1) * @return the bound object * @exception NamingException if an error occurs */ protected Object localLookup( final Name name ) throws NamingException { final Object value = doLocalLookup( name ); // Call getObjectInstance for using any object factories try { final Name atom = name.getPrefix( 1 ); return m_namespace.getObjectInstance( value, atom, this, m_environment ); } catch( final Exception e ) { final NamingException ne = new NamingException( "getObjectInstance failed" ); ne.setRootCause( e ); throw ne; } } /** * Actually lookup raw entry in local context. * When overidding this it is not neccesary to resolve references etc. * * @param name the name in local context (size() == 1) * @return the bound object * @exception NamingException if an error occurs */ protected abstract Object doLocalLookup( Name name ) throws NamingException; /** * Lookup a sub-context of current context. * Note that name must have 1 or more elements. * * @param name the name of subcontext * @return the sub-Context * @exception NamingException if an error occurs (like named entry is not a Context) */ protected Context lookupSubContext( final Name name ) throws NamingException { final Name atom = name.getPrefix( 1 ); Object object = localLookup( atom ); if( 1 != name.size() ) { if( !(object instanceof Context) ) { throw new NotContextException( atom.toString() ); } object = ((Context)object).lookup( name.getSuffix( 1 ) ); } if( !(object instanceof Context) ) { throw new NotContextException( name.toString() ); } //((Context)object).close(); return (Context)object; } /** * Unbind a object from a name. * * @param name the name * @exception NamingException if an error occurs */ public void unbind( final Name name ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Cannot unbind self" ); } else if( 1 == name.size() ) { doLocalUnbind( name ); } else { final Context context = lookupSubContext( getPathName ( name ) ); context.unbind( getLeafName( name ) ); } } /** * Actually unbind raw entry in local context. * * @param name the name in local context (size() == 1) * @exception NamingException if an error occurs */ protected abstract void doLocalUnbind( Name name ) throws NamingException; } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/AbstractNamespace.java Index: AbstractNamespace.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.NameParser; import javax.naming.Name; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; import javax.naming.spi.ObjectFactory; import javax.naming.spi.StateFactory; /** * This is the class to extend that provides * basic facilities for Namespace management. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractNamespace implements Namespace { protected ObjectFactory[] m_objectFactorySet; protected StateFactory[] m_stateFactorySet; public Object getStateToBind( final Object object, final Name name, final Context parent, final Hashtable environment ) throws NamingException { //for thread safety so that member variable can be updated //at any time final StateFactory[] stateFactorySet = m_stateFactorySet; for( int i = 0; i < stateFactorySet.length; i++ ) { final Object result = stateFactorySet[ i ].getStateToBind( object, name, parent, environment ); if( null != result ) { return result; } } return object; } public Object getObjectInstance( final Object object, final Name name, final Context parent, final Hashtable environment ) throws Exception { //for thread safety so that member variable can be updated //at any time final ObjectFactory[] objectFactorySet = m_objectFactorySet; for( int i = 0; i < objectFactorySet.length; i++ ) { final Object result = objectFactorySet[ i ].getObjectInstance( object, name, parent, environment ); if( null != result ) { return result; } } return object; } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/AbstractNamingEnumeration.java Index: AbstractNamingEnumeration.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import java.util.Iterator; import java.util.NoSuchElementException; import javax.naming.Binding; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameClassPair; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.spi.NamingManager; /** * Class for building NamingEnumerations. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractNamingEnumeration implements NamingEnumeration { protected Context m_owner; protected Namespace m_namespace; public AbstractNamingEnumeration( final Context owner, final Namespace namespace ) { m_owner = owner; m_namespace = namespace; } public boolean hasMore() throws NamingException { return hasMoreElements(); } public Object nextElement() { try { return next(); } catch( final NamingException ne ) { throw new NoSuchElementException( ne.toString() ); } } protected Object resolve( final String name, final Object object ) throws NamingException { // Call getObjectInstance for using any object factories try { final Name atom = m_owner.getNameParser( name ).parse( name ); return m_namespace. getObjectInstance( object, atom, m_owner, m_owner.getEnvironment() ); } catch( final Exception e ) { final NamingException ne = new NamingException( "getObjectInstance failed" ); ne.setRootCause( e ); throw ne; } } public void close() { m_namespace = null; m_owner = null; } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/AbstractURLContext.java Index: AbstractURLContext.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.*; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.spi.ResolveResult; /** * Abstract JNDI Context that can be inherited from to * provide a particular type of Context. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractURLContext extends AbstractContext implements NameParser { protected final String m_scheme; public AbstractURLContext( final String scheme, final Hashtable environment ) { super( environment ); m_scheme = scheme; } public Name parse( final String name ) throws NamingException { return (new CompositeName().add( name )); } protected NameParser getNameParser() throws NamingException { return this; } /** * Helper method to bind */ protected void bind( final Name name, final Object object, final boolean rebind ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { if( rebind ) { context.rebind( resolveResult.getRemainingName(), object ); } else { context.bind( resolveResult.getRemainingName(), object ); } } finally { context.close(); } } /** * Create a Subcontext. * * @param name the name of subcontext * @return the created context * @exception NamingException if an error occurs (ie context exists, badly formated name etc) */ public Context createSubcontext( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { return context.createSubcontext( resolveResult.getRemainingName() ); } finally { context.close(); } } public void destroySubcontext( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { context.destroySubcontext( resolveResult.getRemainingName() ); } finally { context.close(); } } public String getNameInNamespace() throws NamingException { return ""; } /** * Enumerates the names bound in the named context. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration list( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { return context.list( resolveResult.getRemainingName() ); } finally { context.close(); } } /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration listBindings( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { return context.listBindings( resolveResult.getRemainingName() ); } finally { context.close(); } } /** * Get the object named. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookup( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { return context.lookup( resolveResult.getRemainingName() ); } finally { context.close(); } } /** * Unbind a object from a name. * * @param name the name * @exception NamingException if an error occurs */ public void unbind( final Name name ) throws NamingException { final ResolveResult resolveResult = getBaseURLContext( name, m_environment ); final Context context = (Context)resolveResult.getResolvedObj(); try { context.unbind( resolveResult.getRemainingName() ); } finally { context.close(); } } protected ResolveResult getBaseURLContext( final Name name, final Hashtable environment ) throws NamingException { if( name.isEmpty() ) { throw new InvalidNameException( "Unable to locate URLContext will empty name" ); } final String nameString = name.toString(); int index = nameString.indexOf( ':' ); if( -1 == index ) { throw new InvalidNameException( "Unable to build URLContext as it does not specify scheme" ); } final String scheme = nameString.substring( 0, index ); final int end = getEndIndexOfURLPart( nameString, index + 1 ); final String urlPart = nameString.substring( index + 1, end ); final String namePart = nameString.substring( end ); if( !m_scheme.equals( scheme ) ) { throw new InvalidNameException( "Bad Scheme use to build URLContext (" + scheme + "). " + "Expected " + m_scheme ); } final Context context = newContext( urlPart ); return new ResolveResult( context, new CompositeName( namePart ) ); } /** * Find end index of url part in string. * Default implementation looks for * //.../[name-part] * ///[name-part] * //... (no name part) * [name-part] * * @param name the name * @param index the index where "scheme:" ends * @return the index where url ends * @exception NamingException if an error occurs */ protected int getEndIndexOfURLPart( final String name, final int index ) throws NamingException { int result = 0; //does it start with // if( name.startsWith( "//", index ) ) { //does it have .../ following ??? int end = name.indexOf( "/", index + 2 ); if( -1 != end ) { result = end; } else { result = name.length(); } } return result; } /** * Return a new instance of the base context for a URL. * This must be implemented in particular URLContext. * * @param urlPart the part of url string not including "scheme:" * @return a base URLContext for urlPart * @exception NamingException if an error occurs */ protected abstract Context newContext( String urlPart ) throws NamingException; } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/ArrayNamingEnumeration.java Index: ArrayNamingEnumeration.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.NoSuchElementException; import javax.naming.Binding; import javax.naming.Context; import javax.naming.NamingException; /** * Class for building NamingEnumerations. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ final class ArrayNamingEnumeration extends AbstractNamingEnumeration { protected Object[] m_items; protected int m_index; public ArrayNamingEnumeration( final Context owner, final Namespace namespace, final Object[] items ) { super( owner, namespace ); m_items = items; //m_index = 0; } public boolean hasMoreElements() { return m_index < m_items.length; } public Object next() throws NamingException { if( !hasMore() ) throw new NoSuchElementException(); final Object object = m_items[ m_index++ ]; if( object instanceof Binding ) { final Binding binding = (Binding)object; final Object resolvedObject = resolve( binding.getName(), binding.getObject() ); binding.setObject( resolvedObject ); } return object; } public void close() { super.close(); m_items = null; } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/DefaultNameParser.java Index: DefaultNameParser.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.io.Serializable; import java.util.Properties; import javax.naming.CompoundName; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingException; public class DefaultNameParser implements Serializable, NameParser { protected static Properties c_syntax = new Properties(); static { c_syntax.put( "jndi.syntax.direction", "left_to_right" ); c_syntax.put( "jndi.syntax.ignorecase", "false" ); c_syntax.put( "jndi.syntax.separator", "/" ); } public Name parse( final String name ) throws NamingException { return new CompoundName( name, c_syntax ); } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/DefaultNamespace.java Index: DefaultNamespace.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NameParser; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; import javax.naming.spi.ObjectFactory; import javax.naming.spi.StateFactory; /** * This is the default namespace implementation. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class DefaultNamespace extends AbstractNamespace { protected NameParser m_nameParser; public DefaultNamespace( final NameParser nameParser ) { this( nameParser, new ObjectFactory[ 0 ], new StateFactory[ 0 ] ); } public DefaultNamespace( final NameParser nameParser, final ObjectFactory[] objectFactorySet, final StateFactory[] stateFactorySet ) { m_nameParser = nameParser; m_objectFactorySet = objectFactorySet; m_stateFactorySet = stateFactorySet; } public synchronized void addStateFactory( final StateFactory stateFactory ) { //create new array of factory objects final StateFactory[] stateFactorySet = new StateFactory[ m_stateFactorySet.length + 1 ]; //copy old factory objects to new array System.arraycopy( m_stateFactorySet, 0, stateFactorySet, 0, m_stateFactorySet.length ); //add in new factory at end stateFactorySet[ m_stateFactorySet.length ] = stateFactory; //update factory set m_stateFactorySet = stateFactorySet; } public synchronized void addObjectFactory( final ObjectFactory objectFactory ) { //create new array of factory objects final ObjectFactory[] objectFactorySet = new ObjectFactory[ m_objectFactorySet.length + 1 ]; //copy old factory objects to new array System.arraycopy( m_objectFactorySet, 0, objectFactorySet, 0, m_objectFactorySet.length ); //add in new factory at end objectFactorySet[ m_objectFactorySet.length ] = objectFactory; //update factory set m_objectFactorySet = objectFactorySet; } public NameParser getNameParser() { return m_nameParser; } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/Namespace.java Index: Namespace.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Hashtable; import javax.naming.NameParser; import javax.naming.NamingException; import javax.naming.spi.ObjectFactory; import javax.naming.spi.StateFactory; /** * Interface representing Namespace/NamingSystem. * Associated with each namespace is a name parser, * object factories and state factories. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public interface Namespace extends ObjectFactory, StateFactory { NameParser getNameParser() throws NamingException; } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/NamingProvider.java Index: NamingProvider.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import javax.naming.Context; import javax.naming.Name; import javax.naming.Binding; import javax.naming.NameClassPair; import javax.naming.NameParser; import javax.naming.NamingException; /** * The underlying communication interface for remote contexts. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public interface NamingProvider { NameParser getNameParser() throws NamingException, Exception; void bind( Name name, String className, Object object ) throws NamingException, Exception; void rebind( Name name, String className, Object object ) throws NamingException, Exception; Context createSubcontext( Name name ) throws NamingException, Exception; void destroySubcontext( Name name ) throws NamingException, Exception; NameClassPair[] list( Name name ) throws NamingException, Exception; Binding[] listBindings( Name name ) throws NamingException, Exception; Object lookup( Name name ) throws NamingException, Exception; void unbind( Name name ) throws NamingException, Exception; } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/RemoteContext.java Index: RemoteContext.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.io.Serializable; import java.io.IOException; import java.util.Hashtable; import java.util.Iterator; import java.rmi.MarshalledObject; import javax.naming.*; import javax.naming.Context; /** * Context that hooks up to a remote source. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class RemoteContext extends AbstractContext implements Serializable { public final static String NAMESPACE_NAME = "org.apache.avalon.cadastre.Namespace/NAME"; public final static String NAMESPACE = "org.apache.avalon.cadastre.Namespace"; public final static String NAMING_PROVIDER = "org.apache.avalon.cadastre.NamingProvider"; protected transient NamingProvider m_provider; protected transient NameParser m_nameParser; protected transient Namespace m_namespace; protected Name m_baseName; //for deserialisation public RemoteContext() { } public RemoteContext( final Hashtable environment, final Name baseName ) throws NamingException { super( environment ); m_baseName = baseName; } /** * Helper method to bind */ protected void bind( final Name name, Object object, final boolean rebind ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to bind self" ); } String className = null; object = getNamespace().getStateToBind( object, name, this, m_environment ); if( object instanceof Reference ) { className = ((Reference)object).getClassName(); } else if( object instanceof Referenceable ) { object = ((Referenceable)object).getReference(); className = ((Reference)object).getClassName(); } else { className = object.getClass().getName(); try { object = new MarshalledObject( object ); } catch( final IOException ioe ) { throw new NamingException( "Only Reference, Referenceables and " + "Serializable objects can be bound " + "to context" ); } } try { if( rebind ) { getProvider().rebind( getAbsoluteName( name ), className, object ); } else { getProvider().bind( getAbsoluteName( name ), className, object ); } } catch( final Exception e ) { throw handleException( e ); } } /** * Release resources associated with context. */ public void close() { m_namespace = null; m_environment = null; m_provider = null; } /** * Create a Subcontext. * * @param name the name of subcontext * @return the created context * @exception NamingException if an error occurs (ie context exists, badly formated name etc) */ public Context createSubcontext( final Name name ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to create null subcontext" ); } Context result = null; try { result = getProvider().createSubcontext( getAbsoluteName( name ) ); } catch( final Exception e ) { throw handleException( e ); } fillInContext( result ); return result; } public void destroySubcontext( final Name name ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to destroy self" ); } try { getProvider().destroySubcontext( getAbsoluteName( name ) ); } catch( final Exception e ) { throw handleException( e ); } } public String getNameInNamespace() throws NamingException { return getAbsoluteName( getNameParser().parse( "" ) ).toString(); } /** * Enumerates the names bound in the named context. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration list( final Name name ) throws NamingException { try { final NameClassPair[] result = getProvider().list( getAbsoluteName( name ) ); return new ArrayNamingEnumeration( this, m_namespace, result ); } catch( final Exception e ) { throw handleException( e ); } } /** * Enumerates the names bound in the named context, along with the objects bound to them. * * @param name the name of the context * @return the enumeration * @exception NamingException if an error occurs */ public NamingEnumeration listBindings( final Name name ) throws NamingException { try { final Binding[] result = getProvider().listBindings( getAbsoluteName( name ) ); for( int i = 0; i < result.length; i++ ) { final Object object = result[ i ].getObject(); if( object instanceof Context ) { fillInContext( (Context)object ); } } return new ArrayNamingEnumeration( this, m_namespace, result ); } catch( final Exception e ) { throw handleException( e ); } } /** * Get the object named. * * @param name the name * @return the object * @exception NamingException if an error occurs (ie object name is inavlid or unbound) */ public Object lookup( final Name name ) throws NamingException { if( isSelf( name ) ) { return new RemoteContext( m_environment, m_baseName ); } //TODO: actually do a real-lookup Object object = null; try { object = getProvider().lookup( getAbsoluteName( name ) ); if( object instanceof MarshalledObject ) { object = ((MarshalledObject)object).get(); } object = getNamespace().getObjectInstance( object, name, this, m_environment ); if( object instanceof Context ) { fillInContext( (Context)object ); } } catch( final Exception e ) { throw handleException( e ); } return object; } /** * Unbind a object from a name. * * @param name the name * @exception NamingException if an error occurs */ public void unbind( final Name name ) throws NamingException { if( isSelf( name ) ) { throw new InvalidNameException( "Failed to unbind self" ); } try { getProvider().unbind( getAbsoluteName( name ) ); } catch( final Exception e ) { throw handleException( e ); } } protected void fillInContext( final Context object ) throws NamingException { final Iterator keys = m_environment.keySet().iterator(); while( keys.hasNext() ) { final String key = (String)keys.next(); final Object value = m_environment.get( key ); object.addToEnvironment( key , value ); } } protected Namespace getNamespace() throws NamingException { if( null == m_namespace ) { final Object object = m_environment.get( RemoteContext.NAMESPACE ); if( !(object instanceof Namespace) || null == object ) { throw new ConfigurationException( "Context does not contain Namespace" ); } else { m_namespace = (Namespace)object; } } return m_namespace; } protected NamingProvider getProvider() throws NamingException { if( null == m_provider ) { final Object object = m_environment.get( RemoteContext.NAMING_PROVIDER ); if( !(object instanceof NamingProvider) || null == object ) { throw new ConfigurationException( "Context does not contain provider" ); } else { m_provider = (NamingProvider)object; } } return m_provider; } protected NameParser getNameParser() throws NamingException { if( null == m_nameParser ) { //Make sure provider is valid and returns nameparser try { m_nameParser = getProvider().getNameParser(); } catch( final Exception e ) { throw handleException( e ); } } return m_nameParser; } protected Name getAbsoluteName( final Name name ) throws NamingException { return composeName( name, m_baseName ); } protected NamingException handleException( final Exception e ) { if( e instanceof NamingException ) { return (NamingException)e; } else { return new CommunicationException( e.toString() ); } } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/memory/MemoryContext.java Index: MemoryContext.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.memory; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.NoSuchElementException; import javax.naming.*; import javax.naming.Context; import org.apache.avalon.cadastre.AbstractLocalContext; import org.apache.avalon.cadastre.Namespace; /** * Start of a generic Context implementation. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class MemoryContext extends AbstractLocalContext { protected Hashtable m_bindings; protected MemoryContext( final Namespace namespace, final Hashtable environment, final Context parent, final Hashtable bindings ) { super( namespace, environment, parent ); m_bindings = bindings; } public MemoryContext( final Namespace namespace, final Hashtable environment, final Context parent ) { this( namespace, environment, parent, new Hashtable( 11 ) ); } protected Context newContext() throws NamingException { return new MemoryContext( m_namespace, m_environment, m_parent ); } protected Context cloneContext() throws NamingException { return new MemoryContext( m_namespace, m_environment, m_parent, m_bindings ); } protected void doLocalBind( final Name name, final Object object ) throws NamingException { m_bindings.put( name.get( 0 ), object ); } protected NamingEnumeration doLocalList() throws NamingException { return new MemoryNamingEnumeration( this, m_namespace, m_bindings, false ); } protected NamingEnumeration doLocalListBindings() throws NamingException { return new MemoryNamingEnumeration( this, m_namespace, m_bindings, true ); } /** * Actually lookup raw entry in local context. * When overidding this it is not neccesary to resolve references etc. * * @param name the name in local context (size() == 1) * @return the bound object * @exception NamingException if an error occurs */ protected Object doLocalLookup( final Name name ) throws NamingException { final Object object = m_bindings.get( name.get( 0 ) ); if( null == object ) throw new NameNotFoundException( name.get( 0 ) ); return object; } /** * Actually unbind raw entry in local context. * * @param name the name in local context (size() == 1) * @exception NamingException if an error occurs */ protected void doLocalUnbind( final Name name ) throws NamingException { m_bindings.remove( name.get( 0 ) ); } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/memory/MemoryInitialContextFactory.java Index: MemoryInitialContextFactory.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.memory; import java.util.Hashtable; import java.util.NoSuchElementException; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; import org.apache.avalon.cadastre.DefaultNameParser; import org.apache.avalon.cadastre.DefaultNamespace; /** * Initial context factory for memorycontext. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class MemoryInitialContextFactory implements InitialContextFactory { public Context getInitialContext( final Hashtable environment ) throws NamingException { final DefaultNameParser parser = new DefaultNameParser(); final DefaultNamespace namespace = new DefaultNamespace( parser ); return new MemoryContext( namespace, environment, null ); } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/memory/MemoryNamingEnumeration.java Index: MemoryNamingEnumeration.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.memory; import java.util.Hashtable; import java.util.Iterator; import java.util.NoSuchElementException; import javax.naming.Binding; import javax.naming.Context; import javax.naming.NameClassPair; import javax.naming.NamingException; import org.apache.avalon.cadastre.AbstractNamingEnumeration; import org.apache.avalon.cadastre.Namespace; /** * Class for building NamingEnumerations. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ final class MemoryNamingEnumeration extends AbstractNamingEnumeration { protected Hashtable m_bindings; protected Iterator m_names; protected boolean m_returnBindings; public MemoryNamingEnumeration( final Context owner, final Namespace namespace, final Hashtable bindings, final boolean returnBindings ) { super( owner, namespace ); m_returnBindings = returnBindings; m_bindings = bindings; m_names = m_bindings.keySet().iterator(); } public boolean hasMoreElements() { return m_names.hasNext(); } public Object next() throws NamingException { if( !hasMore() ) throw new NoSuchElementException(); final String name = (String)m_names.next(); Object object = m_bindings.get( name ); if( !m_returnBindings ) { return new NameClassPair( name, object.getClass().getName() ); } else { return new Binding( name, resolve( name, object ) ); } } public void close() { super.close(); m_bindings = null; } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/rmi/RMIInitialContextFactory.java Index: RMIInitialContextFactory.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.rmi; import java.io.BufferedInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.net.Socket; import java.rmi.MarshalledObject; import java.util.Hashtable; import javax.naming.ConfigurationException; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.ServiceUnavailableException; import javax.naming.spi.InitialContextFactory; import org.apache.avalon.cadastre.DefaultNamespace; import org.apache.avalon.cadastre.Namespace; import org.apache.avalon.cadastre.NamingProvider; import org.apache.avalon.cadastre.RemoteContext; /** * Initial context factory for memorycontext. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class RMIInitialContextFactory implements InitialContextFactory { public Context getInitialContext( final Hashtable environment ) throws NamingException { final NamingProvider provider = newNamingProvider( environment ); environment.put( RemoteContext.NAMING_PROVIDER, provider ); final Namespace namespace = newNamespace( environment ); environment.put( RemoteContext.NAMESPACE, namespace ); return new RemoteContext( environment, namespace.getNameParser().parse( "" ) ); } protected NamingProvider newNamingProvider( final Hashtable environment ) throws NamingException { final String url = (String)environment.get( Context.PROVIDER_URL ); if( null == url ) { return newNamingProvider( "localhost", 1977 ); } else { if( !url.startsWith( "rmi://" ) ) { throw new ConfigurationException( "Malformed url - " + url ); } final int index = url.indexOf( ':', 6 ); int end = index; int port = 1977; if( -1 == index ) { end = url.length(); } else { port = Integer.parseInt( url.substring( index + 1 ) ); } final String host = url.substring( 6, end ); return newNamingProvider( host, port ); } } protected NamingProvider newNamingProvider( final String host, final int port ) throws NamingException { Socket socket = null; try { socket = new Socket( host, port ); final ObjectInputStream input = new ObjectInputStream( new BufferedInputStream( socket.getInputStream() ) ); final NamingProvider provider = ((NamingProvider)((MarshalledObject)input.readObject()).get()); socket.close(); return provider; } catch( final Exception e ) { final ServiceUnavailableException sue = new ServiceUnavailableException( e.getMessage() ); sue.setRootCause( e ); throw sue; } finally { if( null != socket ) { try { socket.close(); } catch( final IOException ioe ) {} } } } protected Namespace newNamespace( final Hashtable environment ) throws NamingException { try { final NamingProvider provider = (NamingProvider)environment.get( RemoteContext.NAMING_PROVIDER ); return new DefaultNamespace( provider.getNameParser() ); } catch( final Exception e ) { if( e instanceof NamingException ) { throw (NamingException)e; } else { final ServiceUnavailableException sue = new ServiceUnavailableException( e.getMessage() ); sue.setRootCause( e ); throw sue; } } } } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/rmi/RMINamingProvider.java Index: RMINamingProvider.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.rmi; import java.rmi.Remote; import org.apache.avalon.cadastre.NamingProvider; /** * The underlying communication interface for remote contexts. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public interface RMINamingProvider extends NamingProvider, Remote { } 1.1 jakarta-commons-sandbox/cadastre/src/java/org/apache/avalon/cadastre/rmi/server/RMINamingProviderImpl.java Index: RMINamingProviderImpl.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.rmi.server; import java.io.Serializable; import java.rmi.Remote; import java.util.ArrayList; import javax.naming.Binding; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.Name; import javax.naming.NameClassPair; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import org.apache.avalon.cadastre.RemoteContext; import org.apache.avalon.cadastre.rmi.RMINamingProvider; /** * The RMI implementation of provider. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class RMINamingProviderImpl implements Serializable, RMINamingProvider { protected Context m_root; public RMINamingProviderImpl( final Context root ) { m_root = root; } public NameParser getNameParser() throws NamingException { return m_root.getNameParser( new CompositeName() ); } public void bind( final Name name, final String className, final Object object ) throws NamingException { final Binding binding = new Binding( name.toString(), className, object, true ); m_root.bind( name, binding ); } public void rebind( final Name name, final String className, final Object object ) throws NamingException { final Binding binding = new Binding( name.toString(), className, object, true ); m_root.rebind( name, binding ); } public Context createSubcontext( final Name name ) throws NamingException { m_root.createSubcontext( name ); final RemoteContext context = new RemoteContext( null, name ); return context; } public void destroySubcontext( final Name name ) throws NamingException { m_root.destroySubcontext( name ); } public NameClassPair[] list( final Name name ) throws NamingException { //Remember that the bindings returned by this //actually have a nested Binding as an object final NamingEnumeration enum = m_root.listBindings( name ); final ArrayList pairs = new ArrayList(); while( enum.hasMore() ) { final Binding binding = (Binding)enum.next(); final Object object = binding.getObject(); String className = null; //check if it is an entry or a context if( object instanceof Binding ) { //must be an entry final Binding entry = (Binding)binding.getObject(); className = entry.getObject().getClass().getName(); } else if( object instanceof Context ) { //must be a context className = RemoteContext.class.getName(); } else { className = object.getClass().getName(); } pairs.add( new NameClassPair( binding.getName(), className ) ); } return (NameClassPair[])pairs.toArray( new NameClassPair[ 0 ] ); } public Binding[] listBindings( final Name name ) throws NamingException { //Remember that the bindings returned by this //actually have a nested Binding as an object final NamingEnumeration enum = m_root.listBindings( name ); final ArrayList bindings = new ArrayList(); while( enum.hasMore() ) { final Binding binding = (Binding)enum.next(); Object object = binding.getObject(); String className = null; //check if it is an entry or a context if( object instanceof Binding ) { //must be an entry final Binding entry = (Binding)binding.getObject(); object = entry.getObject(); className = object.getClass().getName(); } else if( object instanceof Context ) { //must be a context className = RemoteContext.class.getName(); object = new RemoteContext( null, name ); } else { className = object.getClass().getName(); } final Binding result = new Binding( binding.getName(), className, object ); bindings.add( result ); } return (Binding[])bindings.toArray( new Binding[ 0 ] ); } public Object lookup( final Name name ) throws NamingException { Object object = m_root.lookup( name ); //check if it is an entry or a context if( object instanceof Binding ) { object = ((Binding)object).getObject(); } else if( object instanceof Context ) { //must be a context object = new RemoteContext( null, name.getPrefix( name.size() - 1 ) ); } return object; } public void unbind( final Name name ) throws NamingException { m_root.unbind( name ); } } 1.1 jakarta-commons-sandbox/cadastre/src/test/org/apache/avalon/cadastre/AbstractContextTestlet.java Index: AbstractContextTestlet.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre; import java.util.Enumeration; import java.util.Hashtable; import javax.naming.*; import org.apache.testlet.*; /** * Unit testing for JNDI system * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public abstract class AbstractContextTestlet extends AbstractTestlet { protected final static Object O1 = "iO1"; protected final static Object O2 = "iO2"; protected final static Object O3 = "iO3"; protected final static Object O4 = "iO4"; protected final static Object O5 = "iO5"; protected final static Object O6 = "iO6"; protected final static Object O7 = "iO7"; protected final static Object O8 = "iO8"; protected Context m_context; public void testBindToDirectContext() throws TestFailedException { try { m_context.bind( "O1", O1 ); assert( "Make sure lookup returns correct object", m_context.lookup("O1").equals( O1 ) ); m_context.bind( "O2", O2 ); m_context.bind( "O3", O3 ); m_context.bind( "O4", O4 ); m_context.bind( "O5", O5 ); m_context.bind( "O6", O6 ); m_context.bind( "O7", O7 ); m_context.bind( "O8", O8 ); assert( "Make sure lookup O2 returns correct object", m_context.lookup("O2").equals( O2 ) ); assert( "Make sure lookup O3 returns correct object", m_context.lookup("O3").equals( O3 ) ); assert( "Make sure lookup O4 returns correct object", m_context.lookup("O4").equals( O4 ) ); assert( "Make sure lookup O5 returns correct object", m_context.lookup("O5").equals( O5 ) ); assert( "Make sure lookup O6 returns correct object", m_context.lookup("O6").equals( O6 ) ); assert( "Make sure lookup O7 returns correct object", m_context.lookup("O7").equals( O7 ) ); assert( "Make sure lookup O8 returns correct object", m_context.lookup("O8").equals( O8 ) ); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testUnBindFromDirectContext() throws TestFailedException { testBindToDirectContext(); try { m_context.unbind("O1"); m_context.unbind("O2"); m_context.unbind("O3"); m_context.unbind("O4"); m_context.unbind("O5"); m_context.unbind("O6"); m_context.unbind("O7"); m_context.unbind("O8"); final Enumeration enum = m_context.list(""); if( enum.hasMoreElements() ) { throw new TestFailedException( "Failed to unbind all test elements: ie " + enum.nextElement() ); } } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testBindToDirectSubContext() throws TestFailedException { try { m_context.createSubcontext( "x" ); m_context.bind( "x/O1", O1 ); assert( "Make sure lookup x/O1 returns correct object", m_context.lookup("x/O1").equals( O1 ) ); assert( "Make sure lookup x/ returns correct object", m_context.lookup("x/") instanceof Context ); assert( "Make sure lookup x returns correct object", m_context.lookup("x") instanceof Context ); m_context.bind( "x/O2", O2 ); assert( "Make sure lookup x/O2 returns correct object", m_context.lookup("x/O2").equals( O2 ) ); assert( "Make sure lookup x/ returns correct object", m_context.lookup("x/") instanceof Context ); assert( "Make sure lookup x returns correct object", m_context.lookup("x") instanceof Context ); m_context.bind( "x/O3", O3 ); assert( "Make sure lookup x/O3 returns correct object", m_context.lookup("x/O3").equals( O3 ) ); assert( "Make sure lookup x/ returns correct object", m_context.lookup("x/") instanceof Context ); assert( "Make sure lookup x returns correct object", m_context.lookup("x") instanceof Context ); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testUnBindFromDirectSubContext() throws TestFailedException { testBindToDirectSubContext(); try { m_context.unbind("x/O1"); m_context.unbind("x/O2"); m_context.unbind("x/O3"); final Enumeration enum = m_context.list("x/"); if( enum.hasMoreElements() ) { throw new TestFailedException( "Failed to unbind all test elements: ie " + enum.nextElement() ); } //unbind a unbound name - OK m_context.unbind("a"); m_context.unbind("x/a"); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testBindToArbitarySubContexts() throws TestFailedException { try { m_context.createSubcontext( "x" ); m_context.createSubcontext( "x/y" ); m_context.bind( "x/y/O1", O1 ); assert( "Make sure lookup x/y/O1 returns correct object", m_context.lookup("x/y/O1").equals( O1 ) ); assert( "Make sure lookup x/y/ returns correct object", m_context.lookup("x/y/") instanceof Context ); assert( "Make sure lookup x/y returns correct object", m_context.lookup("x/y") instanceof Context ); assert( "Make sure lookup x returns correct object", m_context.lookup("x") instanceof Context ); try { m_context.bind( "x/y", O2 ); assert("Bound object to directory x/y.", false ); } catch( final NamingException ne ) {} try { m_context.bind( "x/y/", O2 ); assert("Bound object to directory x/y/.", false ); } catch( final NamingException ne ) {} try { m_context.bind( "x/", O2 ); assert("Bound object to directory x/.", false ); } catch( final NamingException ne ) {} try { m_context.bind( "x", O2 ); assert("Bound object to directory x.", false ); } catch( final NamingException ne ) {} try { m_context.createSubcontext( "z" ); m_context.bind( "z/", O2 ); assert("Bound object to empty name z/.", false ); } catch( final NamingException ne ) {} } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testUnBindFromArbitarySubContext() throws TestFailedException { testBindToArbitarySubContexts(); try { m_context.unbind("x/y/O1"); //unbind non-existants - OK m_context.unbind("x/O2"); m_context.unbind("x/O3"); final Enumeration enum = m_context.list("x/y"); if( enum.hasMoreElements() ) { throw new TestFailedException( "Failed to unbind all test elements: ie " + enum.nextElement() ); } //Not sure if the next is legal???? /* try { m_context.unbind("x"); assert( "Unbound acontext!", false ); } catch( final NamingException ne ) {} */ //unbind a unbound name - OK m_context.unbind("a"); m_context.unbind("x/a"); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testCreateSubContext() throws TestFailedException { try { m_context.createSubcontext( "x" ); assert( "Make sure lookup x returns correct object", m_context.lookup("x") instanceof Context ); m_context.createSubcontext( "x/y" ); assert( "Make sure lookup x/y returns correct object", m_context.lookup("x/y") instanceof Context ); try { m_context.createSubcontext( "z/x/y" ); assert( "Created a subcontext when intermediate contexts not created", false ); } catch( final NamingException ne ) {} try { m_context.createSubcontext( "x/y" ); assert("createSubContext when context alreadty exists.", false ); } catch( final NamingException ne ) {} } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testDestroySubContext() throws TestFailedException { testCreateSubContext(); try { try { m_context.destroySubcontext( "x" ); assert("destroySubContext with existing subContexts.", false ); } catch( final NamingException ne ) {} try { m_context.destroySubcontext( "x/y/" ); assert("destroySubContext with empty subContext name.", false ); } catch( final NamingException ne ) {} m_context.destroySubcontext( "x/y" ); m_context.destroySubcontext( "x" ); try { m_context.lookup("z"); assert("subContext exists after delete.", false ); } catch( final NamingException ne ) {} } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testRenameToDirectContext() throws TestFailedException { try { m_context.bind( "O1", O1 ); m_context.rename( "O1", "+O1" ); assert( "Make sure lookup not null", m_context.lookup("+O1") != null ); assert( "Make sure lookup +O1 returns correct object", m_context.lookup("+O1").equals( O1 ) ); try { m_context.lookup("O1"); assert( "Old name still bound after rename", false ); } catch( final NameNotFoundException nnfe ) {} m_context.bind( "O2", O2 ); m_context.rename( "O2", "+O2" ); assert( "Make sure lookup not null", m_context.lookup("+O2") != null ); assert( "Make sure lookup +O2 returns correct object", m_context.lookup("+O2").equals( O2 ) ); try { m_context.lookup("O2"); assert( "Old name O2 still bound after rename", false ); } catch( final NameNotFoundException nnfe ) {} m_context.bind( "O3", O3 ); m_context.rename( "O3", "+O3" ); assert( "Make sure lookup not null", m_context.lookup("+O3") != null ); assert( "Make sure lookup +O3 returns correct object", m_context.lookup("+O3").equals( O3 ) ); try { m_context.lookup("O3"); assert( "Old name O3 still bound after rename", false ); } catch( final NameNotFoundException nnfe ) {} m_context.bind( "O4", O4 ); m_context.rename( "O4", "+O4" ); assert( "Make sure lookup not null", m_context.lookup("+O4") != null ); assert( "Make sure lookup +04 returns correct object", m_context.lookup("+O4").equals( O4 ) ); try { m_context.lookup("O3"); assert( "Old name O3 still bound after rename", false ); } catch( final NameNotFoundException nnfe ) {} } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } } public void testReBind() throws TestFailedException { try { m_context.bind( "O1", O1 ); assert( "Make sure lookup returns correct object", m_context.lookup("O1").equals( O1 ) ); m_context.bind( "O2", O2 ); m_context.bind( "O3", O3 ); m_context.bind( "O4", O4 ); m_context.bind( "O5", O5 ); m_context.bind( "O6", O6 ); m_context.bind( "O7", O7 ); m_context.bind( "O8", O8 ); assert( "Make sure lookup O2 returns correct object", m_context.lookup("O2").equals( O2 ) ); assert( "Make sure lookup O3 returns correct object", m_context.lookup("O3").equals( O3 ) ); assert( "Make sure lookup O4 returns correct object", m_context.lookup("O4").equals( O4 ) ); assert( "Make sure lookup O5 returns correct object", m_context.lookup("O5").equals( O5 ) ); assert( "Make sure lookup O6 returns correct object", m_context.lookup("O6").equals( O6 ) ); assert( "Make sure lookup O7 returns correct object", m_context.lookup("O7").equals( O7 ) ); assert( "Make sure lookup O8 returns correct object", m_context.lookup("O8").equals( O8 ) ); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } try { m_context.rebind( "O1", O2 ); assert( "Rebind of O1 returns correct object", m_context.lookup("O1").equals( O2 ) ); m_context.rebind( "O2", O3 ); m_context.rebind( "O3", O4 ); m_context.rebind( "O4", O5 ); m_context.rebind( "O5", O6 ); m_context.rebind( "O6", O7 ); m_context.rebind( "O7", O8 ); m_context.rebind( "O8", O1 ); assert( "Rebind of O2 returns correct object", m_context.lookup("O2").equals( O3 ) ); assert( "Rebind of O3 returns correct object", m_context.lookup("O3").equals( O4 ) ); assert( "Rebind of O4 returns correct object", m_context.lookup("O4").equals( O5 ) ); assert( "Rebind of O5 returns correct object", m_context.lookup("O5").equals( O6 ) ); assert( "Rebind of O6 returns correct object", m_context.lookup("O6").equals( O7 ) ); assert( "Rebind of O7 returns correct object", m_context.lookup("O7").equals( O8 ) ); assert( "Rebind of O8 returns correct object", m_context.lookup("O8").equals( O1 ) ); m_context.bind( "x", O1 ); assert( "Make sure lookup x returns correct object", m_context.lookup("x").equals( O1 ) ); m_context.rebind( "x", O8 ); assert( "Rebind of x returns correct object", m_context.lookup("x").equals( O8 ) ); } catch( final NamingException ne ) { throw new TestFailedException( ne.toString() ); } try { m_context.createSubcontext( "x" ); m_context.rebind( "x/", O1 ); assert( "Able to rebind empty name", false ); } catch( final NamingException ne ) {} } } 1.1 jakarta-commons-sandbox/cadastre/src/test/org/apache/avalon/cadastre/rmi/RMIContextTestlet.java Index: RMIContextTestlet.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.rmi; import java.util.Hashtable; import javax.naming.Context; import org.apache.testlet.*; import org.apache.avalon.cadastre.AbstractContextTestlet; import org.apache.avalon.cadastre.rmi.server.Main; /** * Unit testing for JNDI system * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @version $Revision: 1.1 $ */ public class RMIContextTestlet extends AbstractContextTestlet { protected int m_id; protected Main m_server = new Main(); public void initialize() { try { m_server.start(); final Thread thread = new Thread( m_server ); thread.start(); final RMIInitialContextFactory factory = new RMIInitialContextFactory(); final Context context = factory.getInitialContext( new Hashtable() ); m_context = context.createSubcontext( "test" + m_id++ ); context.close(); } catch( final Exception e ) { System.out.println( "Failed test initialisation " + e ); e.printStackTrace(); } } public void destroy() { try { m_context.close(); m_context = null; m_server.stop(); } catch( final Exception e ) { } } } 1.1 jakarta-commons-sandbox/cadastre/src/test/org/apache/avalon/cadastre/rmi/server/Main.java Index: Main.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cadastre.rmi.server; import java.io.IOException; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.rmi.MarshalledObject; import java.rmi.server.UnicastRemoteObject; import org.apache.avalon.cadastre.DefaultNameParser; import org.apache.avalon.cadastre.DefaultNamespace; import org.apache.avalon.cadastre.memory.MemoryContext; import org.apache.avalon.cadastre.memory.MemoryInitialContextFactory; public class Main implements Runnable { public static void main( final String[] args ) throws Exception { final Main main = new Main(); main.start(); main.accept(); } protected boolean m_debug = true; protected RMINamingProviderImpl m_server; protected ServerSocket m_serverSocket; protected MarshalledObject m_serverStub; protected boolean m_running; protected boolean m_initialized; public void init() throws Exception { if( m_initialized ) return; try { if( m_debug ) System.out.println( "Starting server on port " + 1977 ); m_serverSocket = new ServerSocket( 1977 ); m_initialized = true; } catch( final IOException ioe ) { if( m_debug ) System.out.println( "Failed starting server" ); throw ioe; } } public void start() throws Exception { init(); export(); } public void export() throws Exception { final DefaultNameParser parser = new DefaultNameParser(); final DefaultNamespace namespace = new DefaultNamespace( parser ); final MemoryContext context = new MemoryContext( namespace, null, null ); m_server = new RMINamingProviderImpl( context ); // Start listener try { // Export server if( m_debug ) System.out.println( "Exporting RMI object on port " + 1099 ); m_serverStub = new MarshalledObject( UnicastRemoteObject.exportObject( m_server, 1099 ) ); } catch( final IOException ioe ) { if( m_debug ) System.out.println( "Failed exporting object" ); throw ioe; } } public void dispose() throws Exception { if( m_debug ) System.out.println( "Shutting down server" ); m_running = false; final ServerSocket serverSocket = m_serverSocket; m_serverSocket = null; serverSocket.close(); if( m_debug ) System.out.println( "Server shutdown" ); } public void stop() throws Exception { if( m_debug ) System.out.println( "Stopping" ); m_running = false; if( m_debug ) System.out.println( "Unexporting object" ); UnicastRemoteObject.unexportObject( m_server, true ); m_serverStub = null; if( m_debug ) System.out.println( "Server stopped" ); } public void accept() { m_running = true; while( m_running ) { // Accept a connection try { final Socket socket = m_serverSocket.accept(); if( m_debug ) System.out.println( "Accepted Connection" ); final ObjectOutputStream output = new ObjectOutputStream( socket.getOutputStream() ); output.writeObject( m_serverStub ); socket.close(); } catch( final IOException ioe ) { if( false == m_running ) break; ioe.printStackTrace(); } } } public void run() { accept(); } }