You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/06/13 05:11:16 UTC

svn commit: r190336 - in /directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server: ./ interceptor/ invocation/ jndi/

Author: trustin
Date: Sun Jun 12 20:11:14 2005
New Revision: 190336

URL: http://svn.apache.org/viewcvs?rev=190336&view=rev
Log:
Resolved: DIREVE-160 Make CoreContextFactory more extensible  

Added:
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java   (with props)
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java   (with props)
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java   (with props)
Removed:
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/BackendSubsystem.java
Modified:
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/AbstractCoreTest.java
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/RootNexus.java
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/interceptor/InterceptorChain.java
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/invocation/Invocation.java
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java
    directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/AbstractCoreTest.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/AbstractCoreTest.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/AbstractCoreTest.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/AbstractCoreTest.java Sun Jun 12 20:11:14 2005
@@ -272,13 +272,9 @@
         Hashtable env = new Hashtable();
 
         env.put( Context.PROVIDER_URL, "ou=system" );
-
         env.put( Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
-
         env.putAll( new ShutdownConfiguration().toJndiEnvironment() );
-
         env.put( Context.SECURITY_PRINCIPAL, "uid=admin,ou=system" );
-
         env.put( Context.SECURITY_CREDENTIALS, "secret" );
 
         try { new InitialContext( env ); } catch( Exception e ) {}

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/RootNexus.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/RootNexus.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/RootNexus.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/RootNexus.java Sun Jun 12 20:11:14 2005
@@ -83,6 +83,7 @@
      */
     public RootNexus( SystemPartition system, Attributes rootDSE )
     {
+        System.out.println( "new RootNexus()" );
         if ( null != s_singleton )
         {
             throw new IllegalStateException();
@@ -115,25 +116,6 @@
 
         // register will add to the list of namingContexts as well
         register( this.system );
-
-        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable() {
-            public void run()
-            {
-                try
-                {
-                    if ( ! isClosed() )
-                    {
-                        RootNexus.this.close();
-                    }
-                }
-                catch ( NamingException e )
-                {
-                    e.printStackTrace();
-                    // @todo again we need to monitor this failure and report
-                    // that it occured on shutdown specifically
-                }
-            }
-        }, "RootNexusShutdownHook" ) );
     }
 
 
@@ -547,7 +529,6 @@
             try
             {
                 store.sync();
-
                 store.close();
             }
             catch ( NamingException e )

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/interceptor/InterceptorChain.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/interceptor/InterceptorChain.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/interceptor/InterceptorChain.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/interceptor/InterceptorChain.java Sun Jun 12 20:11:14 2005
@@ -40,10 +40,6 @@
  * Manages the chain of {@link Interceptor}s.  <tt>InterceptorChain</tt>
  * is also an {@link Interceptor}, and thus you can create hiararchical
  * interceptor structure to break down complex interceptors.
- * <p/>
- * {@link org.apache.ldap.server.jndi.JndiProvider#invoke(Invocation)}
- * redirects {@link Invocation}s to {@link #process(NextInterceptor, Invocation)}
- * and the chain starts.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/invocation/Invocation.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/invocation/Invocation.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/invocation/Invocation.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/invocation/Invocation.java Sun Jun 12 20:11:14 2005
@@ -26,9 +26,8 @@
 
 
 /**
- * Represents a method invocation on {@link BackingStore}s. You can perform any
- * {@link BackingStore} calls by invoking {@link
- * org.apache.ldap.server.jndi.JndiProvider#invoke(Invocation)}.<p/>
+ * Represents a method invocation on {@link BackingStore}s.
+ * <p/>
  * This class is abstract, and developers should extend this class to
  * represent the actual method invocations.
  *

Added: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java?rev=190336&view=auto
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java (added)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java Sun Jun 12 20:11:14 2005
@@ -0,0 +1,96 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.jndi;
+
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.ldap.server.configuration.Configuration;
+import org.apache.ldap.server.configuration.ShutdownConfiguration;
+import org.apache.ldap.server.configuration.StartupConfiguration;
+import org.apache.ldap.server.configuration.SyncConfiguration;
+
+
+/**
+ * A server-side provider implementation of a InitialContextFactory.  Can be
+ * utilized via JNDI API in the standard fashion:
+ *
+ * <code>
+ * Hashtable env = new Hashtable();
+ * env.put( Context.PROVIDER_URL, "ou=system" );
+ * env.put(
+ * Context.INITIAL_CONTEXT_FACTORY, "org.apache.ldap.server.jndi.CoreContextFactory" );
+ * InitialContext initialContext = new InitialContext( env );
+ * </code>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ * 
+ * @see javax.naming.spi.InitialContextFactory
+ */
+public abstract class AbstractContextFactory implements InitialContextFactory
+{
+    // ------------------------------------------------------------------------
+    // Members
+    // ------------------------------------------------------------------------
+
+    /** The singleton JndiProvider instance */
+    private static final JndiProvider provider = new JndiProvider();
+
+    /**
+     * Default constructor that sets the provider of this ServerContextFactory.
+     */
+    public AbstractContextFactory()
+    {
+    }
+    
+    public final synchronized Context getInitialContext( Hashtable env ) throws NamingException
+    {
+        Configuration cfg = Configuration.toConfiguration( env );
+        
+        if( cfg instanceof ShutdownConfiguration )
+        {
+            provider.shutdown();
+        }
+        else if( cfg instanceof SyncConfiguration )
+        {
+            provider.sync();
+        }
+        else if( cfg instanceof StartupConfiguration )
+        {
+            // fire up the backend subsystem if we need to
+            provider.startup( this, env );
+        }
+        else
+        {
+            throw new NamingException( "Unknown configuration: " + cfg );
+        }
+        
+        return provider.getLdapContext();
+    }
+    
+    protected abstract void beforeStartup( ContextFactoryContext ctx ) throws NamingException;
+    protected abstract void afterStartup( ContextFactoryContext ctx ) throws NamingException;
+    protected abstract void beforeShutdown( ContextFactoryContext ctx ) throws NamingException;
+    protected abstract void afterShutdown( ContextFactoryContext ctx ) throws NamingException;
+    protected abstract void beforeSync( ContextFactoryContext ctx ) throws NamingException;
+    protected abstract void afterSync( ContextFactoryContext ctx ) throws NamingException;
+}

Propchange: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/AbstractContextFactory.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java?rev=190336&view=auto
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java (added)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java Sun Jun 12 20:11:14 2005
@@ -0,0 +1,71 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.jndi;
+
+import java.util.Hashtable;
+
+import javax.naming.NamingException;
+
+import org.apache.ldap.server.RootNexus;
+import org.apache.ldap.server.SystemPartition;
+import org.apache.ldap.server.configuration.StartupConfiguration;
+import org.apache.ldap.server.invocation.Invocation;
+import org.apache.ldap.server.schema.GlobalRegistries;
+
+public interface ContextFactoryContext
+{
+    /**
+     * Returns the initial context environment of this context factory.
+     */
+    Hashtable getEnvironment();
+    
+    /**
+     * Returns the startup configuration of this context factory.
+     */
+    StartupConfiguration getConfiguration();
+    
+    /**
+     * Returns the system partition used by this context factory.
+     */
+    SystemPartition getSystemPartition();
+
+    /**
+     * Returns the registries for system schema objects
+     */
+    GlobalRegistries getGlobalRegistries();
+
+    /**
+     * Returns the root nexus of this context factory.
+     */
+    RootNexus getRootNexus();
+    
+    /**
+     * Returns <tt>true</tt> if this context is started for the first time
+     * and bootstrap entries have been created.
+     */
+    boolean isFirstStart();
+    
+    /**
+     * Returns <tt>true</tt> if this context is started.
+     */
+    boolean isStarted();
+    
+    /**
+     * Invokes {@link Invocation} to this context.
+     */
+    Object invoke( Invocation call ) throws NamingException;
+}

Propchange: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/ContextFactoryContext.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/CoreContextFactory.java Sun Jun 12 20:11:14 2005
@@ -16,56 +16,9 @@
  */
 package org.apache.ldap.server.jndi;
 
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.naming.Context;
-import javax.naming.Name;
 import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
 import javax.naming.spi.InitialContextFactory;
 
-import org.apache.ldap.common.exception.LdapAuthenticationNotSupportedException;
-import org.apache.ldap.common.exception.LdapConfigurationException;
-import org.apache.ldap.common.exception.LdapNoPermissionException;
-import org.apache.ldap.common.message.LockableAttributesImpl;
-import org.apache.ldap.common.message.ResultCodeEnum;
-import org.apache.ldap.common.name.DnParser;
-import org.apache.ldap.common.name.LdapName;
-import org.apache.ldap.common.name.NameComponentNormalizer;
-import org.apache.ldap.common.schema.AttributeType;
-import org.apache.ldap.common.schema.Normalizer;
-import org.apache.ldap.common.util.DateUtils;
-import org.apache.ldap.server.ApplicationPartition;
-import org.apache.ldap.server.ContextPartition;
-import org.apache.ldap.server.RootNexus;
-import org.apache.ldap.server.SystemPartition;
-import org.apache.ldap.server.configuration.Configuration;
-import org.apache.ldap.server.configuration.ContextPartitionConfiguration;
-import org.apache.ldap.server.configuration.ShutdownConfiguration;
-import org.apache.ldap.server.configuration.StartupConfiguration;
-import org.apache.ldap.server.configuration.SyncConfiguration;
-import org.apache.ldap.server.db.Database;
-import org.apache.ldap.server.db.DefaultSearchEngine;
-import org.apache.ldap.server.db.ExpressionEnumerator;
-import org.apache.ldap.server.db.ExpressionEvaluator;
-import org.apache.ldap.server.db.SearchEngine;
-import org.apache.ldap.server.db.jdbm.JdbmDatabase;
-import org.apache.ldap.server.interceptor.InterceptorChain;
-import org.apache.ldap.server.interceptor.InterceptorContext;
-import org.apache.ldap.server.schema.AttributeTypeRegistry;
-import org.apache.ldap.server.schema.ConcreteNameComponentNormalizer;
-import org.apache.ldap.server.schema.GlobalRegistries;
-import org.apache.ldap.server.schema.MatchingRuleRegistry;
-import org.apache.ldap.server.schema.OidRegistry;
-import org.apache.ldap.server.schema.bootstrap.BootstrapRegistries;
-import org.apache.ldap.server.schema.bootstrap.BootstrapSchemaLoader;
-
 
 /**
  * A server-side provider implementation of a InitialContextFactory.  Can be
@@ -83,593 +36,36 @@
  * @version $Rev$
  * @see javax.naming.spi.InitialContextFactory
  */
-public class CoreContextFactory implements InitialContextFactory
+public class CoreContextFactory extends AbstractContextFactory implements InitialContextFactory
 {
-    /*
-     * @todo this class needs to be better broken down - its in disarray; too much
-     * fuctionality in one place which can be better organized
-     */
-
-    /** shorthand reference to the authentication type property */
-    private static final String TYPE = Context.SECURITY_AUTHENTICATION;
-
-    /** shorthand reference to the authentication credentials property */
-    private static final String CREDS = Context.SECURITY_CREDENTIALS;
-
-    /** shorthand reference to the authentication principal property */
-    protected static final String PRINCIPAL = Context.SECURITY_PRINCIPAL;
-
-    /** shorthand reference to the admin principal name */
-    protected static final String ADMIN = SystemPartition.ADMIN_PRINCIPAL;
-
-    /** shorthand reference to the admin principal distinguished name */
-    protected static final Name ADMIN_NAME = SystemPartition.getAdminDn();
-
-    // ------------------------------------------------------------------------
-    // Members
-    // ------------------------------------------------------------------------
-
-    /** The singleton JndiProvider instance */
-    protected JndiProvider provider = null;
-
-    /** the initial context environment that fired up the backend subsystem */
-    protected Hashtable initialEnv;
-    
-    /** the configuration */
-    protected StartupConfiguration configuration;
-
-    /** the system partition used by the context factory */
-    protected SystemPartition system;
-
-    /** the registries for system schema objects */
-    protected GlobalRegistries globalRegistries;
-
-    /** the root nexus */
-    protected RootNexus nexus;
-
-    /** whether or not server is started for the first time */
-    protected boolean createMode;
-
-
     /**
-     * Default constructor that sets the provider of this ServerContextFactory.
+     * Creates a new instance.
      */
     public CoreContextFactory()
     {
-        JndiProvider.setProviderOn( this );
     }
 
-
-    /**
-     * Enables this ServerContextFactory with a handle to the JndiProvider singleton.
-     *
-     * @param provider the system's singleton BackendSubsystem service.
-     */
-    void setProvider( JndiProvider provider )
+    protected void beforeStartup( ContextFactoryContext ctx ) throws NamingException
     {
-        this.provider = provider;
-    }
-
-
-    public Context getInitialContext( Hashtable env ) throws NamingException
-    {
-
-        Configuration cfg = Configuration.toConfiguration( env );
-        
-        Context ctx;
-        if( cfg instanceof ShutdownConfiguration )
-        {
-            if ( this.provider == null )
-            {
-                return new DeadContext();
-            }
-
-            try
-            {
-                this.provider.shutdown();
-                return new DeadContext();
-            }
-            catch ( Throwable t )
-            {
-                t.printStackTrace();
-            }
-            finally
-            {
-                provider = null;
-                initialEnv = null;
-                configuration = null;
-            }
-        }
-        else if( cfg instanceof SyncConfiguration )
-        {
-            if ( this.provider == null )
-            {
-                return new DeadContext();
-            }
-            
-            provider.sync();
-            return provider.getLdapContext( env );
-        }
-        
-        StartupConfiguration startupCfg = ( StartupConfiguration ) cfg;
-
-        checkSecuritySettings( env );
-
-        if ( isAnonymous( env ) )
-        {
-            env.put( PRINCIPAL, "" );
-        }
-
-        // fire up the backend subsystem if we need to
-        if ( null == provider )
-        {
-            // we need to check this here instead of in AuthenticationService
-            // because otherwise we are going to start up the system incorrectly
-            if ( isAnonymous( env ) && !startupCfg.isAllowAnonymousAccess() )
-            {
-                throw new LdapNoPermissionException(
-                        "ApacheDS is configured to disallow anonymous access" );
-            }
-
-            startupCfg.validate();
-            this.initialEnv = env;
-            this.configuration = startupCfg;
-            initialize();
-
-            createMode = createBootstrapEntries();
-
-            /*
-             * Unfortunately to test non-root user startup of the core and make sure
-             * all the appropriate functionality is there we need to load more user
-             * entries at startup due to a chicken and egg like problem.  The value
-             * of this property is a list of attributes to be added.
-             */
-            
-            Iterator i = configuration.getTestEntries().iterator();
-            while( i.hasNext() )
-            {
-                Attributes entry = ( Attributes ) i.next();
-                entry.put( "creatorsName", ADMIN );
-                entry.put( "createTimestamp", DateUtils.getGeneralizedTime() );
-                
-                Attribute dn = entry.remove( "dn" );
-                AttributeTypeRegistry registry = globalRegistries.getAttributeTypeRegistry();
-                NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( registry );
-                DnParser parser = new DnParser( ncn );
-                Name ndn = parser.parse( ( String ) dn.get() );
-                
-                nexus.add( ( String ) dn.get(), ndn, entry );
-            }
-        }
-
-        ctx = ( ServerContext ) provider.getLdapContext( env );
-
-        return ctx;
     }
 
-
-    /**
-     * Checks to make sure security environment parameters are set correctly.
-     *
-     * @throws javax.naming.NamingException if the security settings are not correctly configured.
-     */
-    protected void checkSecuritySettings( Hashtable env ) throws NamingException
+    protected void afterStartup( ContextFactoryContext ctx ) throws NamingException
     {
-        if ( env.containsKey( TYPE ) && env.get( TYPE ) != null )
-        {
-            /*
-             * If bind is simple make sure we have the credentials and the
-             * principal name set within the environment, otherwise complain
-             */
-            if ( env.get( TYPE ).equals( "simple" ) )
-            {
-                if ( !env.containsKey( CREDS ) )
-                {
-                    throw new LdapConfigurationException( "missing required "
-                            + CREDS + " property for simple authentication" );
-                }
-
-                if ( !env.containsKey( PRINCIPAL ) )
-                {
-                    throw new LdapConfigurationException( "missing required "
-                            + PRINCIPAL + " property for simple authentication" );
-                }
-            }
-            /*
-             * If bind is none make sure credentials and the principal
-             * name are NOT set within the environment, otherwise complain
-             */
-            else if ( env.get( TYPE ).equals( "none" ) )
-            {
-                if ( env.containsKey( CREDS ) )
-                {
-                    throw new LdapConfigurationException( "ambiguous bind "
-                            + "settings encountered where bind is anonymous yet "
-                            + CREDS + " property is set" );
-                }
-                if ( env.containsKey( PRINCIPAL ) )
-                {
-                    throw new LdapConfigurationException( "ambiguous bind "
-                            + "settings encountered where bind is anonymous yet "
-                            + PRINCIPAL + " property is set" );
-                }
-            }
-            /*
-             * If bind is anything other than simple or none we need to
-             * complain because SASL is not a supported auth method yet
-             */
-            else
-            {
-                throw new LdapAuthenticationNotSupportedException( ResultCodeEnum.AUTHMETHODNOTSUPPORTED );
-            }
-        }
-        else if ( env.containsKey( CREDS ) )
-        {
-            if ( !env.containsKey( PRINCIPAL ) )
-            {
-                throw new LdapConfigurationException( "credentials provided "
-                        + "without principal name property: " + PRINCIPAL );
-            }
-        }
     }
-
-
-    /**
-     * Checks to see if an anonymous bind is being attempted.
-     *
-     * @return true if bind is anonymous, false otherwise
-     */
-    protected boolean isAnonymous( Hashtable env )
+    
+    protected void beforeShutdown( ContextFactoryContext ctx ) throws NamingException
     {
-
-        if ( env.containsKey( TYPE ) && env.get( TYPE ) != null )
-        {
-            if ( env.get( TYPE ).equals( "none" ) )
-            {
-                return true;
-            }
-
-            return false;
-        }
-
-        if ( env.containsKey( CREDS ) )
-        {
-            return false;
-        }
-
-        return true;
     }
-
-
-    /**
-     * Returns true if we had to create the bootstrap entries on the first
-     * start of the server.  Otherwise if all entries exist, meaning none
-     * had to be created, then we are not starting for the first time.
-     *
-     * @throws javax.naming.NamingException
-     */
-    private boolean createBootstrapEntries() throws NamingException
+    
+    protected void afterShutdown( ContextFactoryContext ctx ) throws NamingException
     {
-        boolean isFirstStart = false;
-
-        // -------------------------------------------------------------------
-        // create admin entry
-        // -------------------------------------------------------------------
-
-        /*
-         * If the admin entry is there, then the database was already created
-         */
-        if ( nexus.hasEntry( ADMIN_NAME ) )
-        {
-            isFirstStart = false;
-        }
-        else
-        {
-            isFirstStart = true;
-
-            Attributes attributes = new LockableAttributesImpl();
-
-            attributes.put( "objectClass", "top" );
-
-            attributes.put( "objectClass", "person" );
-
-            attributes.put( "objectClass", "organizationalPerson" );
-
-            attributes.put( "objectClass", "inetOrgPerson" );
-
-            attributes.put( "uid", SystemPartition.ADMIN_UID );
-
-            attributes.put( "userPassword", SystemPartition.ADMIN_PW );
-
-            attributes.put( "displayName", "Directory Superuser" );
-
-            attributes.put( "creatorsName", ADMIN );
-
-            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
-
-            attributes.put( "displayName", "Directory Superuser" );
-
-            nexus.add( ADMIN, ADMIN_NAME, attributes );
-        }
-
-        // -------------------------------------------------------------------
-        // create system users area
-        // -------------------------------------------------------------------
-
-        if ( nexus.hasEntry( new LdapName( "ou=users,ou=system" ) ) )
-        {
-            isFirstStart = false;
-        }
-        else
-        {
-            isFirstStart = true;
-
-            Attributes attributes = new LockableAttributesImpl();
-
-            attributes.put( "objectClass", "top" );
-
-            attributes.put( "objectClass", "organizationalUnit" );
-
-            attributes.put( "ou", "users" );
-
-            attributes.put( "creatorsName", ADMIN );
-
-            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
-
-            nexus.add( "ou=users,ou=system", new LdapName( "ou=users,ou=system" ), attributes );
-        }
-
-        // -------------------------------------------------------------------
-        // create system groups area
-        // -------------------------------------------------------------------
-
-        if ( nexus.hasEntry( new LdapName( "ou=groups,ou=system" ) ) )
-        {
-            isFirstStart = false;
-        }
-        else
-        {
-            isFirstStart = true;
-
-            Attributes attributes = new LockableAttributesImpl();
-
-            attributes.put( "objectClass", "top" );
-
-            attributes.put( "objectClass", "organizationalUnit" );
-
-            attributes.put( "ou", "groups" );
-
-            attributes.put( "creatorsName", ADMIN );
-
-            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
-
-            nexus.add( "ou=groups,ou=system", new LdapName( "ou=groups,ou=system" ), attributes );
-        }
-
-        // -------------------------------------------------------------------
-        // create system preferences area
-        // -------------------------------------------------------------------
-
-        if ( nexus.hasEntry( new LdapName( "prefNodeName=sysPrefRoot,ou=system" ) ) )
-        {
-            isFirstStart = false;
-        }
-        else
-        {
-            isFirstStart = true;
-
-            Attributes attributes = new LockableAttributesImpl();
-
-            attributes.put( "objectClass", "top" );
-
-            attributes.put( "objectClass", "prefNode" );
-
-            attributes.put( "objectClass", "extensibleObject" );
-
-            attributes.put( "prefNodeName", "sysPrefRoot" );
-
-            attributes.put( "creatorsName", ADMIN );
-
-            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
-
-            LdapName dn = new LdapName( "prefNodeName=sysPrefRoot,ou=system" );
-
-            nexus.add( "prefNodeName=sysPrefRoot,ou=system", dn, attributes );
-        }
-
-        return isFirstStart;
     }
-
-
-    /**
-     * Kicks off the initialization of the entire system.
-     *
-     * @throws javax.naming.NamingException if there are problems along the way
-     */
-    protected void initialize() throws NamingException
+    
+    protected void beforeSync( ContextFactoryContext ctx ) throws NamingException
     {
-        // --------------------------------------------------------------------
-        // Load the schema here and check that it is ok!
-        // --------------------------------------------------------------------
-
-        BootstrapRegistries bootstrapRegistries = new BootstrapRegistries();
-
-        BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
-        loader.load( configuration.getBootstrapSchemas(), bootstrapRegistries );
-
-        List errors = bootstrapRegistries.checkRefInteg();
-
-        if ( !errors.isEmpty() )
-        {
-            NamingException e = new NamingException();
-
-            e.setRootCause( ( Throwable ) errors.get( 0 ) );
-
-            throw e;
-        }
-
-        // --------------------------------------------------------------------
-        // Fire up the system partition
-        // --------------------------------------------------------------------
-
-        File workDir = configuration.getWorkingDirectory();
-
-        LdapName suffix = new LdapName();
-
-        suffix.add( SystemPartition.SUFFIX );
-
-        Database db = new JdbmDatabase( suffix, suffix, workDir.getPath() );
-
-        AttributeTypeRegistry attributeTypeRegistry;
-
-        attributeTypeRegistry = bootstrapRegistries .getAttributeTypeRegistry();
-
-        OidRegistry oidRegistry;
-
-        oidRegistry = bootstrapRegistries.getOidRegistry();
-
-        ExpressionEvaluator evaluator;
-
-        evaluator = new ExpressionEvaluator( db, oidRegistry, attributeTypeRegistry );
-
-        ExpressionEnumerator enumerator;
-
-        enumerator = new ExpressionEnumerator( db, attributeTypeRegistry, evaluator );
-
-        SearchEngine eng = new DefaultSearchEngine( db, evaluator, enumerator );
-
-        AttributeType[] attributes = new AttributeType[]
-        {
-            attributeTypeRegistry.lookup( SystemPartition.ALIAS_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.EXISTANCE_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.HIERARCHY_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.NDN_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.ONEALIAS_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.SUBALIAS_OID ),
-            attributeTypeRegistry.lookup( SystemPartition.UPDN_OID )
-        };
-
-        system = new SystemPartition( db, eng, attributes );
-        globalRegistries = new GlobalRegistries( system, bootstrapRegistries );
-        nexus = new RootNexus( system, new LockableAttributesImpl() );
-        provider = new JndiProvider( nexus );
-
-        // --------------------------------------------------------------------
-        // Adding interceptors
-        // --------------------------------------------------------------------
-        InterceptorChain interceptor = configuration.getInterceptors();
-        interceptor.init( new InterceptorContext( configuration, system, globalRegistries, nexus ) );
-
-        provider.setInterceptor( interceptor );
-
-        // fire up the app partitions now!
-        startUpAppPartitions();
     }
 
-    /**
-     * Starts up all the application partitions that will be attached to naming contexts in the system.  Partition
-     * database files are created within a subdirectory immediately under the Eve working directory base.
-     *
-     * @throws javax.naming.NamingException if there are problems creating and starting these new application
-     *                                      partitions
-     */
-    protected void startUpAppPartitions() throws NamingException
+    protected void afterSync( ContextFactoryContext ctx ) throws NamingException
     {
-        OidRegistry oidRegistry = globalRegistries.getOidRegistry();
-        AttributeTypeRegistry attributeTypeRegistry;
-        attributeTypeRegistry = globalRegistries.getAttributeTypeRegistry();
-        MatchingRuleRegistry reg = globalRegistries.getMatchingRuleRegistry();
-
-        File workDir = configuration.getWorkingDirectory();
-
-        Iterator i = configuration.getContextPartitionConfigurations().iterator();
-        while( i.hasNext() )
-        {
-            ContextPartitionConfiguration cfg = ( ContextPartitionConfiguration ) i.next();
-            
-            // ----------------------------------------------------------------
-            // create working directory under eve directory for app partition
-            // ----------------------------------------------------------------
-
-            File partitionWorkDir = new File( workDir.getPath() + File.separator + cfg.getName() );
-            partitionWorkDir.mkdirs();
-
-            // ----------------------------------------------------------------
-            // create the database/store
-            // ----------------------------------------------------------------
-
-            Name upSuffix = new LdapName( cfg.getSuffix() );
-            Normalizer dnNorm = reg.lookup( "distinguishedNameMatch" ) .getNormalizer();
-            Name normSuffix = new LdapName( ( String ) dnNorm.normalize( cfg.getSuffix() ) );
-            Database db = new JdbmDatabase( upSuffix, normSuffix, partitionWorkDir.getPath() );
-
-            // ----------------------------------------------------------------
-            // create the search engine using db, enumerators and evaluators
-            // ----------------------------------------------------------------
-
-            ExpressionEvaluator evaluator;
-            evaluator = new ExpressionEvaluator( db, oidRegistry, attributeTypeRegistry );
-            ExpressionEnumerator enumerator;
-            enumerator = new ExpressionEnumerator( db, attributeTypeRegistry, evaluator );
-            SearchEngine eng = new DefaultSearchEngine( db, evaluator, enumerator );
-
-            // ----------------------------------------------------------------
-            // fill up a list with the AttributeTypes for the system indices
-            // ----------------------------------------------------------------
-
-            ArrayList attributeTypeList = new ArrayList();
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.ALIAS_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.EXISTANCE_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.HIERARCHY_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.NDN_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.ONEALIAS_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.SUBALIAS_OID ) );
-            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.UPDN_OID ) );
-
-            // ----------------------------------------------------------------
-            // if user indices are specified add those attribute types as well
-            // ----------------------------------------------------------------
-
-            Iterator j = cfg.getIndexedAttributes().iterator();
-            while( j.hasNext() )
-            {
-                String attribute = ( String ) j.next();
-                attributeTypeList.add( attributeTypeRegistry
-                        .lookup( attribute ) );
-            }
-
-            // ----------------------------------------------------------------
-            // fire up the appPartition & register it with the nexus
-            // ----------------------------------------------------------------
-
-            AttributeType[] indexTypes = ( AttributeType[] ) attributeTypeList
-                    .toArray( new AttributeType[attributeTypeList.size()] );
-
-            ContextPartition partition = cfg.getContextPartition();
-
-            if ( partition == null )
-            {
-                // If custom partition is not defined, use the ApplicationPartion.
-                partition = new ApplicationPartition( db, eng, indexTypes );
-            }
-
-            // Initialize the partition
-            try
-            {
-                partition.init( upSuffix, normSuffix );
-                nexus.register( partition );
-            }
-            catch ( Exception e )
-            {
-                throw ( NamingException ) new NamingException(
-                        "Failed to initialize custom partition." ).initCause( e );
-            }
-
-            // ----------------------------------------------------------------
-            // add the nexus context entry
-            // ----------------------------------------------------------------
-
-            partition.add( cfg.getSuffix(), normSuffix, cfg.getContextEntry() );
-        }
     }
 }

Modified: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java?rev=190336&r1=190335&r2=190336&view=diff
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java (original)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/JndiProvider.java Sun Jun 12 20:11:14 2005
@@ -16,26 +16,53 @@
  */
 package org.apache.ldap.server.jndi;
 
-import org.apache.ldap.common.filter.ExprNode;
-import org.apache.ldap.server.BackendSubsystem;
-import org.apache.ldap.server.ContextPartition;
-import org.apache.ldap.server.PartitionNexus;
-import org.apache.ldap.server.RootNexus;
-import org.apache.ldap.server.interceptor.Interceptor;
-import org.apache.ldap.server.interceptor.InterceptorChain;
-import org.apache.ldap.server.invocation.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
 
 import javax.naming.Context;
 import javax.naming.Name;
-import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
-import javax.naming.directory.ModificationItem;
-import javax.naming.directory.SearchControls;
 import javax.naming.ldap.LdapContext;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
+
+import org.apache.ldap.common.exception.LdapAuthenticationNotSupportedException;
+import org.apache.ldap.common.exception.LdapConfigurationException;
+import org.apache.ldap.common.exception.LdapNoPermissionException;
+import org.apache.ldap.common.message.LockableAttributesImpl;
+import org.apache.ldap.common.message.ResultCodeEnum;
+import org.apache.ldap.common.name.DnParser;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.common.name.NameComponentNormalizer;
+import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.common.schema.Normalizer;
+import org.apache.ldap.common.util.DateUtils;
+import org.apache.ldap.server.ApplicationPartition;
+import org.apache.ldap.server.ContextPartition;
+import org.apache.ldap.server.PartitionNexus;
+import org.apache.ldap.server.RootNexus;
+import org.apache.ldap.server.SystemPartition;
+import org.apache.ldap.server.configuration.Configuration;
+import org.apache.ldap.server.configuration.ContextPartitionConfiguration;
+import org.apache.ldap.server.configuration.StartupConfiguration;
+import org.apache.ldap.server.db.Database;
+import org.apache.ldap.server.db.DefaultSearchEngine;
+import org.apache.ldap.server.db.ExpressionEnumerator;
+import org.apache.ldap.server.db.ExpressionEvaluator;
+import org.apache.ldap.server.db.SearchEngine;
+import org.apache.ldap.server.db.jdbm.JdbmDatabase;
+import org.apache.ldap.server.interceptor.InterceptorChain;
+import org.apache.ldap.server.interceptor.InterceptorContext;
+import org.apache.ldap.server.invocation.Invocation;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.schema.ConcreteNameComponentNormalizer;
+import org.apache.ldap.server.schema.GlobalRegistries;
+import org.apache.ldap.server.schema.MatchingRuleRegistry;
+import org.apache.ldap.server.schema.OidRegistry;
+import org.apache.ldap.server.schema.bootstrap.BootstrapRegistries;
+import org.apache.ldap.server.schema.bootstrap.BootstrapSchemaLoader;
 
 
 /**
@@ -44,236 +71,608 @@
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class JndiProvider implements BackendSubsystem
+class JndiProvider implements ContextFactoryContext
 {
-    /** Singleton instance of this class */
-    private static JndiProvider s_singleton;
+    /** shorthand reference to the authentication type property */
+    private static final String TYPE = Context.SECURITY_AUTHENTICATION;
+
+    /** shorthand reference to the authentication credentials property */
+    private static final String CREDS = Context.SECURITY_CREDENTIALS;
+
+    /** shorthand reference to the authentication principal property */
+    private static final String PRINCIPAL = Context.SECURITY_PRINCIPAL;
+
+    /** shorthand reference to the admin principal name */
+    private static final String ADMIN = SystemPartition.ADMIN_PRINCIPAL;
+
+    /** shorthand reference to the admin principal distinguished name */
+    private static final Name ADMIN_NAME = SystemPartition.getAdminDn();
+
+    private AbstractContextFactory factory;
     
+    /** the initial context environment that fired up the backend subsystem */
+    private Hashtable environment;
+    
+    /** the configuration */
+    private StartupConfiguration configuration;
+
+    /** the system partition used by the context factory */
+    private SystemPartition systemPartition;
+
+    /** the registries for system schema objects */
+    private GlobalRegistries globalRegistries;
+
+    /** the root nexus */
+    private RootNexus rootNexus;
+
+    /** whether or not server is started for the first time */
+    private boolean firstStart;
+
     /** The interceptor (or interceptor chain) for this provider */
-    private Interceptor interceptor;
-    /** RootNexus as it was given to us by the ServiceManager */
-    private RootNexus nexus;
+    private InterceptorChain interceptorChain;
+    
     /** PartitionNexus proxy wrapping nexus to inject services */
-    private PartitionNexus proxy;
+    private final PartitionNexus proxy = new RootNexusProxy(this);
 
     /** whether or not this instance has been shutdown */
-    private boolean isShutdown = false;
+    private boolean started = false;
 
 
     // ------------------------------------------------------------------------
     // Constructor
     // ------------------------------------------------------------------------
 
-
     /**
-     * Creates a singlton instance of the BackendSubsystem.  In the words of
-     * the Highlander, "there can only be one."
-     *
-     * @throws IllegalStateException if another JndiProvider has already
-     * been instantiated.
+     * Creates a new instance.
      */
-    public JndiProvider( RootNexus nexus )
+    public JndiProvider()
     {
-        if ( s_singleton != null )
-        {
-            throw new IllegalStateException(
-                "Cannot instantiate more than one JndiProvider!" );
-        }
-
-        s_singleton = this;
-        this.nexus = nexus;
-        this.interceptor = new InterceptorChain();
-        this.proxy = new PartitionNexusImpl();
+        // Register shutdown hook.
+        Runtime.getRuntime().addShutdownHook( new Thread( new Runnable() {
+            public void run()
+            {
+                try
+                {
+                    shutdown();
+                }
+                catch( NamingException e )
+                {
+                    e.printStackTrace();
+                }
+            }
+        }, "ApacheDS Shutdown Hook" ) );
     }
 
-
     // ------------------------------------------------------------------------
-    // Static Package Friendly Methods
+    // BackendSubsystem Interface Method Implemetations
     // ------------------------------------------------------------------------
 
-
-    /**
-     * Enables a ServerContextFactory with a handle to the system wide
-     * JndiProvider instance.
-     *
-     * @param factory the ServerContextFactory to enable
-     */
-    static void setProviderOn( CoreContextFactory factory )
+    public synchronized LdapContext getLdapContext() throws NamingException
     {
-        factory.setProvider( s_singleton );
+        if ( !started )
+        {
+            return new DeadContext();
+        }
+
+        return new ServerLdapContext( proxy, environment );
     }
 
+    public synchronized void startup( AbstractContextFactory factory, Hashtable env ) throws NamingException
+    {
+        if( started )
+        {
+            return;
+        }
 
-    // ------------------------------------------------------------------------
-    // BackendSubsystem Interface Method Implemetations
-    // ------------------------------------------------------------------------
+        StartupConfiguration cfg = ( StartupConfiguration ) Configuration.toConfiguration( env );
 
+        checkSecuritySettings( env );
 
-    /**
-     * @see org.apache.ldap.server.BackendSubsystem#getLdapContext(Hashtable)
-     */
-    public LdapContext getLdapContext( Hashtable env ) throws NamingException
-    {
-        if ( this.isShutdown )
+        if ( isAnonymous( env ) )
         {
-            throw new IllegalStateException( "Eve has been shutdown!" );
+            env.put( PRINCIPAL, "" );
         }
 
-        return new ServerLdapContext( proxy, env );
-    }
+        // we need to check this here instead of in AuthenticationService
+        // because otherwise we are going to start up the system incorrectly
+        if ( isAnonymous( env ) && !cfg.isAllowAnonymousAccess() )
+        {
+            throw new LdapNoPermissionException(
+                    "ApacheDS is configured to disallow anonymous access" );
+        }
 
+        cfg.validate();
+        this.environment = env;
+        this.configuration = cfg;
+        
+        factory.beforeStartup( this );
+        try
+        {
+            initialize();
+            firstStart = createBootstrapEntries();
+            createTestEntries();
+            this.factory = factory;
+            started = true;
+        }
+        finally
+        {
+            factory.afterStartup( this );
+        }
+    }
 
-    public void sync() throws NamingException
+    public synchronized void sync() throws NamingException
     {
-        if ( this.isShutdown )
+        if ( !started )
         {
-            throw new IllegalStateException( "Eve has been shutdown!" );
+            return;
         }
 
-        this.nexus.sync();
+        factory.beforeSync( this );
+        try
+        {
+            this.rootNexus.sync();
+        }
+        finally
+        {
+            factory.afterSync( this );
+        }
     }
 
 
-    public void shutdown() throws NamingException
+    public synchronized void shutdown() throws NamingException
     {
-        if ( this.isShutdown )
+        if ( !started )
         {
-            throw new IllegalStateException( "Eve has been shutdown!" );
+            return;
         }
 
-        this.nexus.sync();
-        this.nexus.close();
-        this.nexus = null;
-        this.proxy = null;
-        this.interceptor.destroy();
-        this.interceptor = null;
-        this.isShutdown = true;
-        s_singleton = null;
+        factory.beforeShutdown( this );
+        try
+        {
+            this.rootNexus.sync();
+            this.rootNexus.close();
+            this.interceptorChain.destroy();
+            this.started = false;
+        }
+        finally
+        {
+            environment = null;
+            configuration = null;
+            factory.afterShutdown( this );
+        }
     }
     
-    public Interceptor getInterceptor()
+    
+    public Hashtable getEnvironment()
     {
-        return interceptor;
+        return ( Hashtable ) environment.clone();
     }
-
-    public void setInterceptor( Interceptor interceptor )
+    
+    public StartupConfiguration getConfiguration()
     {
-        if( interceptor == null )
-        {
-            throw new NullPointerException( "interceptor" );
-        }
-        this.interceptor = interceptor;
+        return configuration;
+    }
+    
+    public SystemPartition getSystemPartition()
+    {
+        return systemPartition;
     }
 
+    public GlobalRegistries getGlobalRegistries()
+    {
+        return globalRegistries;
+    }
 
+    public RootNexus getRootNexus()
+    {
+        return rootNexus;
+    }
+    
+    public boolean isFirstStart()
+    {
+        return firstStart;
+    }
+    
+    public boolean isStarted()
+    {
+        return started;
+    }
+    
     public Object invoke( Invocation call ) throws NamingException
     {
-        interceptor.process( null, call );
+        if( !started )
+        {
+            throw new IllegalStateException( "ApacheDS is not started yet." );
+        }
+        
+        interceptorChain.process( null, call );
         return call.getReturnValue();
     }
 
     /**
-     * A dead context is requested and returned when we shutdown the system. It
-     * prevents a {@link javax.naming.NoInitialContextException} from being
-     * thrown by InitialContext or one of its subclasses.
+     * Checks to make sure security environment parameters are set correctly.
      *
-     * @return a unusable dead context
+     * @throws javax.naming.NamingException if the security settings are not correctly configured.
      */
-    public Context getDeadContext()
+    private void checkSecuritySettings( Hashtable env ) throws NamingException
     {
-        return new DeadContext();
+        if ( env.containsKey( TYPE ) && env.get( TYPE ) != null )
+        {
+            /*
+             * If bind is simple make sure we have the credentials and the
+             * principal name set within the environment, otherwise complain
+             */
+            if ( env.get( TYPE ).equals( "simple" ) )
+            {
+                if ( !env.containsKey( CREDS ) )
+                {
+                    throw new LdapConfigurationException( "missing required "
+                            + CREDS + " property for simple authentication" );
+                }
+
+                if ( !env.containsKey( PRINCIPAL ) )
+                {
+                    throw new LdapConfigurationException( "missing required "
+                            + PRINCIPAL + " property for simple authentication" );
+                }
+            }
+            /*
+             * If bind is none make sure credentials and the principal
+             * name are NOT set within the environment, otherwise complain
+             */
+            else if ( env.get( TYPE ).equals( "none" ) )
+            {
+                if ( env.containsKey( CREDS ) )
+                {
+                    throw new LdapConfigurationException( "ambiguous bind "
+                            + "settings encountered where bind is anonymous yet "
+                            + CREDS + " property is set" );
+                }
+                if ( env.containsKey( PRINCIPAL ) )
+                {
+                    throw new LdapConfigurationException( "ambiguous bind "
+                            + "settings encountered where bind is anonymous yet "
+                            + PRINCIPAL + " property is set" );
+                }
+            }
+            /*
+             * If bind is anything other than simple or none we need to
+             * complain because SASL is not a supported auth method yet
+             */
+            else
+            {
+                throw new LdapAuthenticationNotSupportedException( ResultCodeEnum.AUTHMETHODNOTSUPPORTED );
+            }
+        }
+        else if ( env.containsKey( CREDS ) )
+        {
+            if ( !env.containsKey( PRINCIPAL ) )
+            {
+                throw new LdapConfigurationException( "credentials provided "
+                        + "without principal name property: " + PRINCIPAL );
+            }
+        }
     }
-    
-    private class PartitionNexusImpl implements PartitionNexus
+
+
+    /**
+     * Returns true if we had to create the bootstrap entries on the first
+     * start of the server.  Otherwise if all entries exist, meaning none
+     * had to be created, then we are not starting for the first time.
+     *
+     * @throws javax.naming.NamingException
+     */
+    private boolean createBootstrapEntries() throws NamingException
     {
+        boolean firstStart = false;
 
-        public LdapContext getLdapContext() {
-            return nexus.getLdapContext();
-        }
+        // -------------------------------------------------------------------
+        // create admin entry
+        // -------------------------------------------------------------------
+
+        /*
+         * If the admin entry is there, then the database was already created
+         */
+        if ( !rootNexus.hasEntry( ADMIN_NAME ) )
+        {
+            firstStart = true;
 
-        public Name getMatchedDn(Name dn, boolean normalized) throws NamingException {
-            return ( Name ) JndiProvider.this.invoke( new GetMatchedDN( dn, normalized ) );
-        }
+            Attributes attributes = new LockableAttributesImpl();
+            attributes.put( "objectClass", "top" );
+            attributes.put( "objectClass", "person" );
+            attributes.put( "objectClass", "organizationalPerson" );
+            attributes.put( "objectClass", "inetOrgPerson" );
+            attributes.put( "uid", SystemPartition.ADMIN_UID );
+            attributes.put( "userPassword", SystemPartition.ADMIN_PW );
+            attributes.put( "displayName", "Directory Superuser" );
+            attributes.put( "creatorsName", ADMIN );
+            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
+            attributes.put( "displayName", "Directory Superuser" );
+            
+            rootNexus.add( ADMIN, ADMIN_NAME, attributes );
+        }
+
+        // -------------------------------------------------------------------
+        // create system users area
+        // -------------------------------------------------------------------
 
-        public Name getSuffix(Name dn, boolean normalized) throws NamingException {
-            return ( Name ) JndiProvider.this.invoke( new GetSuffix( dn, normalized ) );
-        }
+        if ( !rootNexus.hasEntry( new LdapName( "ou=users,ou=system" ) ) )
+        {
+            firstStart = true;
+            
+            Attributes attributes = new LockableAttributesImpl();
+            attributes.put( "objectClass", "top" );
+            attributes.put( "objectClass", "organizationalUnit" );
+            attributes.put( "ou", "users" );
+            attributes.put( "creatorsName", ADMIN );
+            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
+
+            rootNexus.add( "ou=users,ou=system", new LdapName( "ou=users,ou=system" ), attributes );
+        }
+
+        // -------------------------------------------------------------------
+        // create system groups area
+        // -------------------------------------------------------------------
 
-        public Iterator listSuffixes(boolean normalized) throws NamingException {
-            return ( Iterator ) JndiProvider.this.invoke( new ListSuffixes( normalized ) );
-        }
+        if ( !rootNexus.hasEntry( new LdapName( "ou=groups,ou=system" ) ) )
+        {
+            firstStart = true;
 
-        public void register(ContextPartition partition) {
-            nexus.register( partition );
-        }
+            Attributes attributes = new LockableAttributesImpl();
+            attributes.put( "objectClass", "top" );
+            attributes.put( "objectClass", "organizationalUnit" );
+            attributes.put( "ou", "groups" );
+            attributes.put( "creatorsName", ADMIN );
+            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
 
-        public void unregister(ContextPartition partition) {
-            nexus.unregister( partition );
+            rootNexus.add( "ou=groups,ou=system", new LdapName( "ou=groups,ou=system" ), attributes );
         }
 
-        public void delete(Name name) throws NamingException {
-            JndiProvider.this.invoke( new Delete( name ) );
-        }
+        // -------------------------------------------------------------------
+        // create system preferences area
+        // -------------------------------------------------------------------
 
-        public void add(String upName, Name normName, Attributes entry) throws NamingException {
-            JndiProvider.this.invoke( new Add( upName, normName, entry ) );
-        }
+        if ( !rootNexus.hasEntry( new LdapName( "prefNodeName=sysPrefRoot,ou=system" ) ) )
+        {
+            firstStart = true;
 
-        public void modify(Name name, int modOp, Attributes mods) throws NamingException {
-            JndiProvider.this.invoke( new Modify( name, modOp, mods ) );
-        }
+            Attributes attributes = new LockableAttributesImpl();
+            attributes.put( "objectClass", "top" );
+            attributes.put( "objectClass", "prefNode" );
+            attributes.put( "objectClass", "extensibleObject" );
+            attributes.put( "prefNodeName", "sysPrefRoot" );
+            attributes.put( "creatorsName", ADMIN );
+            attributes.put( "createTimestamp", DateUtils.getGeneralizedTime() );
 
-        public void modify(Name name, ModificationItem[] mods) throws NamingException {
-            JndiProvider.this.invoke( new ModifyMany( name, mods ) );
-        }
+            LdapName dn = new LdapName( "prefNodeName=sysPrefRoot,ou=system" );
 
-        public NamingEnumeration list(Name base) throws NamingException {
-            return ( NamingEnumeration ) JndiProvider.this.invoke( new List( base ) );
+            rootNexus.add( "prefNodeName=sysPrefRoot,ou=system", dn, attributes );
         }
 
-        public NamingEnumeration search(Name base, Map env, ExprNode filter, SearchControls searchCtls) throws NamingException {
-            return ( NamingEnumeration ) JndiProvider.this.invoke( new Search( base, env, filter, searchCtls ) );
-        }
+        return firstStart;
+    }
 
-        public Attributes lookup(Name name) throws NamingException {
-            return ( Attributes ) JndiProvider.this.invoke( new Lookup( name ) );
-        }
 
-        public Attributes lookup(Name dn, String[] attrIds) throws NamingException {
-            return ( Attributes ) JndiProvider.this.invoke( new LookupWithAttrIds( dn, attrIds ) );
+    private void createTestEntries() throws NamingException
+    {
+        /*
+         * Unfortunately to test non-root user startup of the core and make sure
+         * all the appropriate functionality is there we need to load more user
+         * entries at startup due to a chicken and egg like problem.  The value
+         * of this property is a list of attributes to be added.
+         */
+        Iterator i = configuration.getTestEntries().iterator();
+        while( i.hasNext() )
+        {
+            Attributes entry = ( Attributes ) i.next();
+            entry.put( "creatorsName", ADMIN );
+            entry.put( "createTimestamp", DateUtils.getGeneralizedTime() );
+            
+            Attribute dn = entry.remove( "dn" );
+            AttributeTypeRegistry registry = globalRegistries.getAttributeTypeRegistry();
+            NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( registry );
+            DnParser parser = new DnParser( ncn );
+            Name ndn = parser.parse( ( String ) dn.get() );
+            
+            rootNexus.add( ( String ) dn.get(), ndn, entry );
         }
+    }
 
-        public boolean hasEntry(Name name) throws NamingException {
-            return Boolean.TRUE.equals( JndiProvider.this.invoke( new HasEntry( name ) ) );
-        }
+    /**
+     * Kicks off the initialization of the entire system.
+     *
+     * @throws javax.naming.NamingException if there are problems along the way
+     */
+    private void initialize() throws NamingException
+    {
+        // --------------------------------------------------------------------
+        // Load the schema here and check that it is ok!
+        // --------------------------------------------------------------------
 
-        public boolean isSuffix(Name name) throws NamingException {
-            return Boolean.TRUE.equals( JndiProvider.this.invoke( new IsSuffix( name ) ) );
-        }
+        BootstrapRegistries bootstrapRegistries = new BootstrapRegistries();
 
-        public void modifyRn(Name name, String newRn, boolean deleteOldRn) throws NamingException {
-            JndiProvider.this.invoke( new ModifyRN( name, newRn, deleteOldRn ) );
-        }
+        BootstrapSchemaLoader loader = new BootstrapSchemaLoader();
+        loader.load( configuration.getBootstrapSchemas(), bootstrapRegistries );
 
-        public void move(Name oriChildName, Name newParentName) throws NamingException {
-            JndiProvider.this.invoke( new Move( oriChildName, newParentName ) );
-        }
+        java.util.List errors = bootstrapRegistries.checkRefInteg();
+
+        if ( !errors.isEmpty() )
+        {
+            NamingException e = new NamingException();
+
+            e.setRootCause( ( Throwable ) errors.get( 0 ) );
 
-        public void move(Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn) throws NamingException {
-            JndiProvider.this.invoke( new MoveAndModifyRN( oriChildName, newParentName, newRn, deleteOldRn ) );
+            throw e;
         }
 
-        public void sync() throws NamingException {
-            nexus.sync();
+        // --------------------------------------------------------------------
+        // Fire up the system partition
+        // --------------------------------------------------------------------
+
+        File workDir = configuration.getWorkingDirectory();
+
+        LdapName suffix = new LdapName();
+        suffix.add( SystemPartition.SUFFIX );
+
+        Database db = new JdbmDatabase( suffix, suffix, workDir.getPath() );
+        AttributeTypeRegistry attributeTypeRegistry = bootstrapRegistries .getAttributeTypeRegistry();
+        OidRegistry oidRegistry = bootstrapRegistries.getOidRegistry();
+        ExpressionEvaluator evaluator = new ExpressionEvaluator( db, oidRegistry, attributeTypeRegistry );
+        ExpressionEnumerator enumerator = new ExpressionEnumerator( db, attributeTypeRegistry, evaluator );
+        SearchEngine eng = new DefaultSearchEngine( db, evaluator, enumerator );
+
+        AttributeType[] attributes = new AttributeType[]
+        {
+            attributeTypeRegistry.lookup( SystemPartition.ALIAS_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.EXISTANCE_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.HIERARCHY_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.NDN_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.ONEALIAS_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.SUBALIAS_OID ),
+            attributeTypeRegistry.lookup( SystemPartition.UPDN_OID )
+        };
+
+        systemPartition = new SystemPartition( db, eng, attributes );
+        globalRegistries = new GlobalRegistries( systemPartition, bootstrapRegistries );
+        rootNexus = new RootNexus( systemPartition, new LockableAttributesImpl() );
+        interceptorChain = configuration.getInterceptors();
+        interceptorChain.init( new InterceptorContext( configuration, systemPartition, globalRegistries, rootNexus ) );
+
+        // fire up the app partitions now!
+        startUpAppPartitions();
+    }
+
+    /**
+     * Starts up all the application partitions that will be attached to naming contexts in the system.  Partition
+     * database files are created within a subdirectory immediately under the Eve working directory base.
+     *
+     * @throws javax.naming.NamingException if there are problems creating and starting these new application
+     *                                      partitions
+     */
+    private void startUpAppPartitions() throws NamingException
+    {
+        OidRegistry oidRegistry = globalRegistries.getOidRegistry();
+        AttributeTypeRegistry attributeTypeRegistry;
+        attributeTypeRegistry = globalRegistries.getAttributeTypeRegistry();
+        MatchingRuleRegistry reg = globalRegistries.getMatchingRuleRegistry();
+
+        File workDir = configuration.getWorkingDirectory();
+
+        Iterator i = configuration.getContextPartitionConfigurations().iterator();
+        while( i.hasNext() )
+        {
+            ContextPartitionConfiguration cfg = ( ContextPartitionConfiguration ) i.next();
+            
+            // ----------------------------------------------------------------
+            // create working directory under eve directory for app partition
+            // ----------------------------------------------------------------
+
+            File partitionWorkDir = new File( workDir.getPath() + File.separator + cfg.getName() );
+            partitionWorkDir.mkdirs();
+
+            // ----------------------------------------------------------------
+            // create the database/store
+            // ----------------------------------------------------------------
+
+            Name upSuffix = new LdapName( cfg.getSuffix() );
+            Normalizer dnNorm = reg.lookup( "distinguishedNameMatch" ) .getNormalizer();
+            Name normSuffix = new LdapName( ( String ) dnNorm.normalize( cfg.getSuffix() ) );
+            Database db = new JdbmDatabase( upSuffix, normSuffix, partitionWorkDir.getPath() );
+
+            // ----------------------------------------------------------------
+            // create the search engine using db, enumerators and evaluators
+            // ----------------------------------------------------------------
+
+            ExpressionEvaluator evaluator;
+            evaluator = new ExpressionEvaluator( db, oidRegistry, attributeTypeRegistry );
+            ExpressionEnumerator enumerator;
+            enumerator = new ExpressionEnumerator( db, attributeTypeRegistry, evaluator );
+            SearchEngine eng = new DefaultSearchEngine( db, evaluator, enumerator );
+
+            // ----------------------------------------------------------------
+            // fill up a list with the AttributeTypes for the system indices
+            // ----------------------------------------------------------------
+
+            ArrayList attributeTypeList = new ArrayList();
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.ALIAS_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.EXISTANCE_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.HIERARCHY_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.NDN_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.ONEALIAS_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.SUBALIAS_OID ) );
+            attributeTypeList.add( attributeTypeRegistry.lookup( SystemPartition.UPDN_OID ) );
+
+            // ----------------------------------------------------------------
+            // if user indices are specified add those attribute types as well
+            // ----------------------------------------------------------------
+
+            Iterator j = cfg.getIndexedAttributes().iterator();
+            while( j.hasNext() )
+            {
+                String attribute = ( String ) j.next();
+                attributeTypeList.add( attributeTypeRegistry
+                        .lookup( attribute ) );
+            }
+
+            // ----------------------------------------------------------------
+            // fire up the appPartition & register it with the nexus
+            // ----------------------------------------------------------------
+
+            AttributeType[] indexTypes = ( AttributeType[] ) attributeTypeList
+                    .toArray( new AttributeType[attributeTypeList.size()] );
+
+            ContextPartition partition = cfg.getContextPartition();
+
+            if ( partition == null )
+            {
+                // If custom partition is not defined, use the ApplicationPartion.
+                partition = new ApplicationPartition( db, eng, indexTypes );
+            }
+
+            // Initialize the partition
+            try
+            {
+                partition.init( upSuffix, normSuffix );
+                rootNexus.register( partition );
+            }
+            catch ( Exception e )
+            {
+                throw ( NamingException ) new NamingException(
+                        "Failed to initialize custom partition." ).initCause( e );
+            }
+
+            // ----------------------------------------------------------------
+            // add the nexus context entry
+            // ----------------------------------------------------------------
+
+            partition.add( cfg.getSuffix(), normSuffix, cfg.getContextEntry() );
         }
+    }
 
-        public void close() throws NamingException {
-            nexus.close();
+
+    /**
+     * Checks to see if an anonymous bind is being attempted.
+     *
+     * @return true if bind is anonymous, false otherwise
+     */
+    private static boolean isAnonymous( Hashtable env )
+    {
+
+        if ( env.containsKey( TYPE ) && env.get( TYPE ) != null )
+        {
+            if ( env.get( TYPE ).equals( "none" ) )
+            {
+                return true;
+            }
+
+            return false;
         }
 
-        public boolean isClosed() {
-            return nexus.isClosed();
+        if ( env.containsKey( CREDS ) )
+        {
+            return false;
         }
-        
+
+        return true;
     }
 }

Added: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java?rev=190336&view=auto
==============================================================================
--- directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java (added)
+++ directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java Sun Jun 12 20:11:14 2005
@@ -0,0 +1,146 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.jndi;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import javax.naming.ldap.LdapContext;
+
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.server.ContextPartition;
+import org.apache.ldap.server.PartitionNexus;
+import org.apache.ldap.server.invocation.Add;
+import org.apache.ldap.server.invocation.Delete;
+import org.apache.ldap.server.invocation.GetMatchedDN;
+import org.apache.ldap.server.invocation.GetSuffix;
+import org.apache.ldap.server.invocation.HasEntry;
+import org.apache.ldap.server.invocation.IsSuffix;
+import org.apache.ldap.server.invocation.List;
+import org.apache.ldap.server.invocation.ListSuffixes;
+import org.apache.ldap.server.invocation.Lookup;
+import org.apache.ldap.server.invocation.LookupWithAttrIds;
+import org.apache.ldap.server.invocation.Modify;
+import org.apache.ldap.server.invocation.ModifyMany;
+import org.apache.ldap.server.invocation.ModifyRN;
+import org.apache.ldap.server.invocation.Move;
+import org.apache.ldap.server.invocation.MoveAndModifyRN;
+import org.apache.ldap.server.invocation.Search;
+
+class RootNexusProxy implements PartitionNexus
+{
+    private final JndiProvider provider;
+
+    RootNexusProxy( JndiProvider provider )
+    {
+        this.provider = provider;
+    }
+
+    public LdapContext getLdapContext() {
+        return this.provider.getRootNexus().getLdapContext();
+    }
+
+    public Name getMatchedDn(Name dn, boolean normalized) throws NamingException {
+        return ( Name ) this.provider.invoke( new GetMatchedDN( dn, normalized ) );
+    }
+
+    public Name getSuffix(Name dn, boolean normalized) throws NamingException {
+        return ( Name ) this.provider.invoke( new GetSuffix( dn, normalized ) );
+    }
+
+    public Iterator listSuffixes(boolean normalized) throws NamingException {
+        return ( Iterator ) this.provider.invoke( new ListSuffixes( normalized ) );
+    }
+
+    public void register(ContextPartition partition) {
+        this.provider.getRootNexus().register( partition );
+    }
+
+    public void unregister(ContextPartition partition) {
+        this.provider.getRootNexus().unregister( partition );
+    }
+
+    public void delete(Name name) throws NamingException {
+        this.provider.invoke( new Delete( name ) );
+    }
+
+    public void add(String upName, Name normName, Attributes entry) throws NamingException {
+        this.provider.invoke( new Add( upName, normName, entry ) );
+    }
+
+    public void modify(Name name, int modOp, Attributes mods) throws NamingException {
+        this.provider.invoke( new Modify( name, modOp, mods ) );
+    }
+
+    public void modify(Name name, ModificationItem[] mods) throws NamingException {
+        this.provider.invoke( new ModifyMany( name, mods ) );
+    }
+
+    public NamingEnumeration list(Name base) throws NamingException {
+        return ( NamingEnumeration ) this.provider.invoke( new List( base ) );
+    }
+
+    public NamingEnumeration search(Name base, Map env, ExprNode filter, SearchControls searchCtls) throws NamingException {
+        return ( NamingEnumeration ) this.provider.invoke( new Search( base, env, filter, searchCtls ) );
+    }
+
+    public Attributes lookup(Name name) throws NamingException {
+        return ( Attributes ) this.provider.invoke( new Lookup( name ) );
+    }
+
+    public Attributes lookup(Name dn, String[] attrIds) throws NamingException {
+        return ( Attributes ) this.provider.invoke( new LookupWithAttrIds( dn, attrIds ) );
+    }
+
+    public boolean hasEntry(Name name) throws NamingException {
+        return Boolean.TRUE.equals( this.provider.invoke( new HasEntry( name ) ) );
+    }
+
+    public boolean isSuffix(Name name) throws NamingException {
+        return Boolean.TRUE.equals( this.provider.invoke( new IsSuffix( name ) ) );
+    }
+
+    public void modifyRn(Name name, String newRn, boolean deleteOldRn) throws NamingException {
+        this.provider.invoke( new ModifyRN( name, newRn, deleteOldRn ) );
+    }
+
+    public void move(Name oriChildName, Name newParentName) throws NamingException {
+        this.provider.invoke( new Move( oriChildName, newParentName ) );
+    }
+
+    public void move(Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn) throws NamingException {
+        this.provider.invoke( new MoveAndModifyRN( oriChildName, newParentName, newRn, deleteOldRn ) );
+    }
+
+    public void sync() throws NamingException {
+        this.provider.sync();
+    }
+
+    public void close() throws NamingException {
+        this.provider.shutdown();
+    }
+
+    public boolean isClosed() {
+        return this.provider.getRootNexus().isClosed();
+    }
+}
\ No newline at end of file

Propchange: directory/apacheds/branches/direve-158/core/src/main/java/org/apache/ldap/server/jndi/RootNexusProxy.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision