diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java index 5b1a7bc59db..6f264a4b01e 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/server/UnboundIdContainerTests.java @@ -15,43 +15,76 @@ */ package org.springframework.security.ldap.server; +import com.unboundid.ldap.sdk.LDAPException; import java.io.IOException; import java.net.ServerSocket; import java.util.ArrayList; import java.util.List; import org.junit.Test; - import org.springframework.context.support.GenericApplicationContext; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; /** * @author Eddú Meléndez + * @author Shay Dratler */ public class UnboundIdContainerTests { + private final String validLdifClassPath = "classpath:test-server.ldif"; + private final String validRootDn = "dc=springframework,dc=org"; + private final String validLdifFileClassPathTop = "classpath:test-server-custom-attribute-types.ldif"; + @Test public void startLdapServer() throws Exception { - UnboundIdContainer server = new UnboundIdContainer("dc=springframework,dc=org", - "classpath:test-server.ldif"); - server.setApplicationContext(new GenericApplicationContext()); - List ports = getDefaultPorts(1); - server.setPort(ports.get(0)); + UnboundIdContainer server = new UnboundIdContainer( + validRootDn, validLdifClassPath); + createAndRunServer(server); + } + + @Test + public void afterPropertiesSetWhenPortIsZeroThenRandomPortIsSelected() throws Exception { + UnboundIdContainer server = new UnboundIdContainer(validRootDn, validLdifClassPath); + server.setApplicationContext(new GenericApplicationContext()); + server.setPort(0); try { server.afterPropertiesSet(); - assertThat(server.getPort()).isEqualTo(ports.get(0)); + assertThat(server.getPort()).isNotEqualTo(0); } finally { server.destroy(); } } @Test - public void afterPropertiesSetWhenPortIsZeroThenRandomPortIsSelected() throws Exception { - UnboundIdContainer server = new UnboundIdContainer("dc=springframework,dc=org", null); + public void startLdapServerWithoutLdif() throws Exception { + UnboundIdContainer server = new UnboundIdContainer( + validRootDn, null); + createAndRunServer(server); + } + + @Test + public void startLdapServerMixedLdif() throws Exception { + UnboundIdContainer server = new UnboundIdContainer( + validRootDn, validLdifFileClassPathTop); + server.setApplicationContext(new GenericApplicationContext()); server.setPort(0); + try { + server.afterPropertiesSet(); + failBecauseExceptionWasNotThrown(LDAPException.class); + } catch (Exception e) { + assertThat(e.getCause()).isInstanceOf(LDAPException.class); + } finally { + server.destroy(); + } + } + @Test + public void missingContextInInit() { + UnboundIdContainer server = new UnboundIdContainer(validRootDn, null); + server.setPort(0); try { server.afterPropertiesSet(); assertThat(server.getPort()).isNotEqualTo(0); @@ -60,6 +93,38 @@ public void afterPropertiesSetWhenPortIsZeroThenRandomPortIsSelected() throws Ex } } + @Test + public void testMissingLdapFile() { + UnboundIdContainer server = new UnboundIdContainer(validRootDn, "classpath:missing-file.ldif"); + server.setApplicationContext(new GenericApplicationContext()); + server.setPort(0); + try { + server.afterPropertiesSet(); + failBecauseExceptionWasNotThrown(IllegalArgumentException.class); + } catch (Exception e) { + assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class); + assertThat(e.getMessage()).contains("Unable to load LDIF classpath:missing-file.ldif"); + } finally { + server.destroy(); + } + } + + + @Test + public void testInvalidLdapFile() { + UnboundIdContainer server = new UnboundIdContainer(validRootDn, "classpath:test-server-malformed.txt"); + server.setApplicationContext(new GenericApplicationContext()); + server.setPort(0); + try { + server.afterPropertiesSet(); + failBecauseExceptionWasNotThrown(LDAPException.class); + } catch (Exception e) { + assertThat(e.getCause()).isInstanceOf(LDAPException.class); + } finally { + server.destroy(); + } + } + private List getDefaultPorts(int count) throws IOException { List connections = new ArrayList<>(); List availablePorts = new ArrayList<>(count); @@ -77,4 +142,17 @@ private List getDefaultPorts(int count) throws IOException { } } + private void createAndRunServer(UnboundIdContainer server) throws IOException { + server.setApplicationContext(new GenericApplicationContext()); + List ports = getDefaultPorts(1); + server.setPort(ports.get(0)); + + try { + server.afterPropertiesSet(); + assertThat(server.getPort()).isEqualTo(ports.get(0)); + } finally { + server.destroy(); + } + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java b/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java index aaa54ee4136..c277b6ad59c 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java +++ b/ldap/src/main/java/org/springframework/security/ldap/server/UnboundIdContainer.java @@ -15,8 +15,10 @@ */ package org.springframework.security.ldap.server; -import java.io.InputStream; +import static org.springframework.util.StringUtils.isEmpty; +import java.io.IOException; +import java.io.InputStream; import com.unboundid.ldap.listener.InMemoryDirectoryServer; import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; import com.unboundid.ldap.listener.InMemoryListenerConfig; @@ -24,7 +26,6 @@ import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldif.LDIFReader; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; @@ -36,6 +37,7 @@ /** * @author Eddú Meléndez + * @contributer Shay Dratler */ public class UnboundIdContainer implements InitializingBean, DisposableBean, Lifecycle, ApplicationContextAware { @@ -57,6 +59,7 @@ public UnboundIdContainer(String defaultPartitionSuffix, String ldif) { this.ldif = ldif; } + public int getPort() { return this.port; } @@ -67,7 +70,9 @@ public void setPort(int port) { @Override public void destroy() { - stop(); + if (null != directoryServer) { + stop(); + } } @Override @@ -85,7 +90,6 @@ public void start() { if (isRunning()) { return; } - try { InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(this.defaultPartitionSuffix); config.addAdditionalBindCredentials("uid=admin,ou=system", "secret"); @@ -109,22 +113,36 @@ public void start() { } catch (LDAPException ex) { throw new RuntimeException("Server startup failed", ex); } - } private void importLdif(InMemoryDirectoryServer directoryServer) { if (StringUtils.hasText(this.ldif)) { try { - Resource[] resources = this.context.getResources(this.ldif); - if (resources.length > 0 && resources[0].exists()) { - try (InputStream inputStream = resources[0].getInputStream()) { - directoryServer.importFromLDIF(false, new LDIFReader(inputStream)); - } + Resource resource = locateResource(); + try (InputStream inputStream = resource.getInputStream()) { + directoryServer.importFromLDIF(false, new LDIFReader(inputStream)); } } catch (Exception ex) { throw new IllegalStateException("Unable to load LDIF " + this.ldif, ex); } } + + } + + private Resource locateResource() throws IOException, NullPointerException { + Resource[] resources = this.context.getResources(this.ldif); + if (0 == resources.length) { + throw new IllegalArgumentException("requested resource is not found"); + } + for (Resource resource : resources) { + if (!isEmpty(resource.getFilename()) + && resource.isFile() + && resource.exists() + && resource.isReadable()) { + return resource; + } + } + throw new IllegalArgumentException("Unable to load LDIF :" + this.ldif); } @Override