فهرست منبع

Renamed ApacheDSStartStopBean to ApacheDSContainer and implemented LifeCycle interface.

Luke Taylor 18 سال پیش
والد
کامیت
650a5467e8

+ 105 - 51
core/src/main/java/org/springframework/security/config/ApacheDSStartStopBean.java → core/src/main/java/org/springframework/security/config/ApacheDSContainer.java

@@ -5,8 +5,10 @@ import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.BeansException;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ApplicationContext;
+import org.springframework.context.Lifecycle;
 import org.springframework.core.io.Resource;
 import org.springframework.ldap.core.ContextSource;
+import org.springframework.util.Assert;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
@@ -22,54 +24,132 @@ import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
 import java.util.Properties;
 import java.io.File;
+import java.io.IOException;
 
 /**
- * Starts and stops the embedded apacheDS server defined by the supplied configuration.
- * 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.
+ * Provides lifecycle services for the embedded apacheDS server defined by the supplied configuration.
+ * Used by {@link LdapBeanDefinitionParser}. An instance will be stored in the application context for
+ * each embedded server instance. It will start the server when the context is initialized and shut it down when
+ * it is closed. It is intended for temporary embedded use and will not retain changes across start/stop boundaries. The
+ * working directory is deleted on shutdown.
  *
  * <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.
+ * </p>
+ *
+ *
  *
  * @author Luke Taylor
  * @version $Id$
  */
-class ApacheDSStartStopBean implements InitializingBean, DisposableBean, ApplicationContextAware {
+class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware {
     private Log logger = LogFactory.getLog(getClass());
 
     private MutableServerStartupConfiguration configuration;
     private ApplicationContext ctxt;
     private File workingDir;
-    /** The instance Id of the Apache DS DirectoryServer instance */
-    private String instanceId;
 
     private ContextSource contextSource;
+    private boolean running;
 
-    public ApacheDSStartStopBean(MutableServerStartupConfiguration configuration, ContextSource contextSource) {
+    public ApacheDSContainer(MutableServerStartupConfiguration configuration, ContextSource contextSource) {
         this.configuration = configuration;
         this.contextSource = contextSource;
     }
 
     public void afterPropertiesSet() throws Exception {
+        if (workingDir != null) {
+            return;
+        }
+
         String apacheWorkDir = System.getProperty("apacheDSWorkDir");
 
         if (apacheWorkDir == null) {
             apacheWorkDir = System.getProperty("java.io.tmpdir") + File.separator + "apacheds-spring-security";
         }
 
-        workingDir = new File(apacheWorkDir);
+        setWorkingDirectory(new File(apacheWorkDir));
+        start();
+    }
+
+    public void destroy() throws Exception {
+        stop();
+    }
+
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        ctxt = applicationContext;
+    }
+
+    private static boolean deleteDir(File dir) {
+        if (dir.isDirectory()) {
+            String[] children = dir.list();
+            for (int i=0; i < children.length; i++) {
+                boolean success = deleteDir(new File(dir, children[i]));
+                if (!success) {
+                    return false;
+                }
+            }
+        }
+
+        return dir.delete();
+    }
+
+    public void setWorkingDirectory(File workingDir) {
+        Assert.notNull(workingDir);
+
+        if (workingDir.exists()) {
+            throw new IllegalArgumentException("The specified working directory '" + workingDir.getAbsolutePath() +
+                    "' already exists. Another directory service instance may be using it or it may be from a " +
+                    " previous unclean shutdown. Please confirm and delete it or configure a different " +
+                    "working directory");
+        }
+
+        this.workingDir = workingDir;
 
         configuration.setWorkingDirectory(workingDir);
+    }
+
+
+    public void start() {
+        if (isRunning()) {
+            return;
+        }
+
+        DirectoryService ds = DirectoryService.getInstance(configuration.getInstanceId());
+
+        if (ds.isStarted()) {
+            throw new IllegalStateException("A DirectoryService with Id '" + configuration.getInstanceId() + "' is already running.");
+        }
+
+        logger.info("Starting directory server with Id '" + configuration.getInstanceId() + "'");
+        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());
 
-        // We need this for shutdown
-        instanceId = configuration.getInstanceId();
+        try {
+            new InitialDirContext(env);
+        } catch (NamingException e) {
+            logger.error("Failed to start directory service", e);
+            return;
+        }
 
-        startDirectoryService();
+        running = true;
 
+        try {
+            importLdifs();
+        } catch (Exception e) {
+            logger.error("Failed to import LDIF file(s)", e);
+        }
+    }
+
+    private void importLdifs() throws IOException, NamingException {
         // Import any ldif files
         Resource[] ldifs = ctxt.getResources("classpath:*.ldif");
 
@@ -90,60 +170,34 @@ 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 + "'");
+    public void stop() {
         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);        
-    }
+        ShutdownConfiguration shutdown = new ShutdownConfiguration(configuration.getInstanceId());
+        env.putAll(shutdown.toJndiEnvironment());
 
-    public void destroy() throws Exception {
-        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");
+        logger.info("Shutting down directory server with Id '" + configuration.getInstanceId() + "'");
 
-        ShutdownConfiguration shutdown = new ShutdownConfiguration(instanceId);
-        env.putAll(shutdown.toJndiEnvironment());
+        try {
+            new InitialContext(env);
+        } catch (NamingException e) {
+            logger.error("Failed to shutdown directory server", e);
+            return;
+        }
 
-        logger.info("Shutting down directory server with Id '" + instanceId + "'");
-        new InitialContext(env);
+        running = false;
 
         if (workingDir.exists()) {
             logger.info("Deleting working directory " + workingDir.getAbsolutePath());
             deleteDir(workingDir);
         }
-
     }
 
-    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-        ctxt = applicationContext;
-    }
-
-    public static boolean deleteDir(File dir) {
-        if (dir.isDirectory()) {
-            String[] children = dir.list();
-            for (int i=0; i < children.length; i++) {
-                boolean success = deleteDir(new File(dir, children[i]));
-                if (!success) {
-                    return false;
-                }
-            }
-        }
-
-        return dir.delete();
+    public boolean isRunning() {
+        return running;
     }
 }

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

@@ -34,7 +34,7 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
     /** Defines the Url of the ldap server to use. If not specified, an embedded apache DS instance will be created */
     private static final String URL_ATTRIBUTE = "url";
     private static final String AUTH_TYPE_ATTRIBUTE = "auth";
-    // TODO: Setting login/passwords for non embedded server. 
+    // TODO: Setting login/passwords for non embedded server.
     private static final String PRINCIPAL_ATTRIBUTE = "managerDn";
     private static final String PASSWORD_ATTRIBUTE = "managerPassword";
 
@@ -113,7 +113,7 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
      *
      * @return the BeanDefinition for the ContextSource for the embedded server.
      *
-     * @see ApacheDSStartStopBean
+     * @see ApacheDSContainer
      */
     private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) {
         MutableServerStartupConfiguration configuration = new MutableServerStartupConfiguration();
@@ -158,7 +158,7 @@ public class LdapBeanDefinitionParser extends AbstractBeanDefinitionParser {
         initialDirContextFactory.getPropertyValues().addPropertyValue("managerDn", "uid=admin,ou=system");
         initialDirContextFactory.getPropertyValues().addPropertyValue("managerPassword", "secret");
 
-        RootBeanDefinition apacheDSStartStop = new RootBeanDefinition(ApacheDSStartStopBean.class);
+        RootBeanDefinition apacheDSStartStop = new RootBeanDefinition(ApacheDSContainer.class);
         apacheDSStartStop.getConstructorArgumentValues().addGenericArgumentValue(configuration);
         apacheDSStartStop.getConstructorArgumentValues().addGenericArgumentValue(initialDirContextFactory);