Explorar el Código

Minor imrovements to configuration of embedded apache server.

Luke Taylor hace 18 años
padre
commit
a4266f3fb8

+ 46 - 19
core/src/main/java/org/springframework/security/config/ApacheDSStartStopBean.java

@@ -13,9 +13,11 @@ import org.apache.directory.server.configuration.MutableServerStartupConfigurati
 import org.apache.directory.server.jndi.ServerContextFactory;
 import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
 import org.apache.directory.server.core.configuration.ShutdownConfiguration;
+import org.apache.directory.server.core.DirectoryService;
 
 import javax.naming.Context;
 import javax.naming.InitialContext;
+import javax.naming.NamingException;
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 import java.util.Properties;
@@ -23,7 +25,15 @@ import java.io.File;
 
 /**
  * Starts and stops the embedded apacheDS server defined by the supplied configuration.
- * Used by {@link LdapBeanDefinitionParser}.
+ * Used by {@link LdapBeanDefinitionParser}. An instance will be stored in the context for
+ * each embedded server instance and its InitializingBean and DisposableBean implementations
+ * used to start and stop the server, respectively.
+ *
+ * <p>
+ * If used repeatedly in a single JVM process with the same configuration (for example, when
+ * repeatedly loading an application context during testing), it's important that the
+ * application context is closed to allow the bean to be disposed of and the server shutdown
+ * prior to attempting to start it again.
  *
  * @author Luke Taylor
  * @version $Id$
@@ -34,13 +44,17 @@ class ApacheDSStartStopBean implements InitializingBean, DisposableBean, Applica
     private MutableServerStartupConfiguration configuration;
     private ApplicationContext ctxt;
     private File workingDir;
+    /** The instance Id of the Apache DS DirectoryServer instance */
+    private String instanceId;
+
+    private ContextSource contextSource;
 
-    public ApacheDSStartStopBean(MutableServerStartupConfiguration configuration) {
+    public ApacheDSStartStopBean(MutableServerStartupConfiguration configuration, ContextSource contextSource) {
         this.configuration = configuration;
+        this.contextSource = contextSource;
     }
 
     public void afterPropertiesSet() throws Exception {
-        Properties env = new Properties();
         String apacheWorkDir = System.getProperty("apacheDSWorkDir");
 
         if (apacheWorkDir == null) {
@@ -49,26 +63,20 @@ class ApacheDSStartStopBean implements InitializingBean, DisposableBean, Applica
 
         workingDir = new File(apacheWorkDir);
 
-//        if (workingDir.exists()) {
-//            logger.info("Deleting existing working directory " + workingDir.getAbsolutePath());
-//            deleteDir(workingDir);
-//        }
-
         configuration.setWorkingDirectory(workingDir);
 
-        env.put(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName());
-        env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
-        env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
-        env.setProperty(Context.SECURITY_CREDENTIALS, "secret");
-        env.putAll(configuration.toJndiEnvironment());
+        // We need this for shutdown
+        instanceId = configuration.getInstanceId();
 
-        DirContext serverContext = new InitialDirContext(env);
+        startDirectoryService();
 
         // Import any ldif files
         Resource[] ldifs = ctxt.getResources("classpath:*.ldif");
 
-
-        DirContext dirContext = ((ContextSource)ctxt.getBean("contextSource")).getReadWriteContext();
+        // Note that we can't just import using the ServerContext returned
+        // from starting Apace DS, apparently because of the long-running issue DIRSERVER-169.
+        // We need a standard context.
+        DirContext dirContext = contextSource.getReadWriteContext();
 
         if(ldifs != null && ldifs.length > 0) {
             try {
@@ -82,6 +90,25 @@ class ApacheDSStartStopBean implements InitializingBean, DisposableBean, Applica
 
     }
 
+    private void startDirectoryService() throws NamingException {
+        DirectoryService ds = DirectoryService.getInstance(instanceId);
+
+        if (ds.isStarted()) {
+            throw new IllegalStateException("A DirectoryService with Id '" + instanceId + "' is already running.");
+        }
+
+        logger.info("Starting directory server with Id '" + instanceId + "'");
+        Properties env = new Properties();
+
+        env.setProperty(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName());
+        env.setProperty(Context.SECURITY_AUTHENTICATION, "simple");
+        env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
+        env.setProperty(Context.SECURITY_CREDENTIALS, "secret");
+        env.putAll(configuration.toJndiEnvironment());
+
+        new InitialDirContext(env);        
+    }
+
     public void destroy() throws Exception {
         Properties env = new Properties();
         env.setProperty(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName());
@@ -89,14 +116,14 @@ class ApacheDSStartStopBean implements InitializingBean, DisposableBean, Applica
         env.setProperty(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
         env.setProperty(Context.SECURITY_CREDENTIALS, "secret");
 
-        ShutdownConfiguration shutdown = new ShutdownConfiguration();
+        ShutdownConfiguration shutdown = new ShutdownConfiguration(instanceId);
         env.putAll(shutdown.toJndiEnvironment());
 
-        logger.info("Shutting down server...");
+        logger.info("Shutting down directory server with Id '" + instanceId + "'");
         new InitialContext(env);
 
         if (workingDir.exists()) {
-            logger.info("Deleting working directory after shutting down " + workingDir.getAbsolutePath());
+            logger.info("Deleting working directory " + workingDir.getAbsolutePath());
             deleteDir(workingDir);
         }
 

+ 7 - 2
core/src/main/java/org/springframework/security/config/LdapBeanDefinitionParser.java

@@ -4,7 +4,6 @@ import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 import org.springframework.util.StringUtils;
 import org.springframework.security.ldap.DefaultInitialDirContextFactory;
@@ -113,6 +112,8 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
      * @param parserContext
      *
      * @return the BeanDefinition for the ContextSource for the embedded server.
+     *
+     * @see ApacheDSStartStopBean
      */
     private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) {
         MutableServerStartupConfiguration configuration = new MutableServerStartupConfiguration();
@@ -145,6 +146,10 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
 
         //TODO: Allow port configuration
         configuration.setLdapPort(3389);
+        // We shut down the server ourself when the app context is closed so we don't need
+        // the extra shutdown hook from apache DS itself.
+        configuration.setShutdownHookEnabled(false);
+        configuration.setExitVmOnShutdown(false);
         configuration.setContextPartitionConfigurations(partitions);
 
         RootBeanDefinition initialDirContextFactory = new RootBeanDefinition(DefaultInitialDirContextFactory.class);
@@ -155,6 +160,7 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
 
         RootBeanDefinition apacheDSStartStop = new RootBeanDefinition(ApacheDSStartStopBean.class);
         apacheDSStartStop.getConstructorArgumentValues().addGenericArgumentValue(configuration);
+        apacheDSStartStop.getConstructorArgumentValues().addGenericArgumentValue(initialDirContextFactory);
 
         if (parserContext.getRegistry().containsBeanDefinition("_apacheDSStartStopBean")) {
             //TODO: Appropriate exception
@@ -163,7 +169,6 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
 
         parserContext.getRegistry().registerBeanDefinition("_apacheDSStartStopBean", apacheDSStartStop);
 
-
         return initialDirContextFactory;
     }