diff --git a/spring-ldap/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java index c2ab5a82..fc5a9075 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java @@ -61,478 +61,455 @@ import org.springframework.ldap.support.LdapUtils; * @author Adam Skogman * @author Ulrik Sandberg */ -public abstract class AbstractContextSource implements ContextSource, - InitializingBean { - - private static final Class DEFAULT_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory.class; - - private static final Class DEFAULT_DIR_OBJECT_FACTORY = DefaultDirObjectFactory.class; - - private Class dirObjectFactory = DEFAULT_DIR_OBJECT_FACTORY; - - private Class contextFactory = DEFAULT_CONTEXT_FACTORY; - - private DistinguishedName base = DistinguishedName.EMPTY_PATH; - - protected String userDn = ""; - - protected String password = ""; - - private String[] urls; - - private boolean pooled = true; - - private Hashtable baseEnv = new Hashtable(); - - private Hashtable anonymousEnv; - - private AuthenticationSource authenticationSource; - - private boolean cacheEnvironmentProperties = true; - - private boolean anonymousReadOnly = false; - - private static final Log log = LogFactory.getLog(LdapContextSource.class); - - public static final String SUN_LDAP_POOLING_FLAG = "com.sun.jndi.ldap.connect.pool"; - - private static final String JDK_142 = "1.4.2"; - - /* - * (non-Javadoc) - * - * @see org.springframework.ldap.core.ContextSource#getReadOnlyContext() - */ - public DirContext getReadOnlyContext() { - if (!anonymousReadOnly) { - return createContext(getAuthenticatedEnv()); - } else { - return createContext(getAnonymousEnv()); - } - } - - /* - * (non-Javadoc) - * - * @see org.springframework.ldap.core.ContextSource#getReadWriteContext() - */ - public DirContext getReadWriteContext() { - return createContext(getAuthenticatedEnv()); - } - - /** - * Default implementation of setting the environment up to be authenticated. - * Override in subclass if necessary. - * - * @param env - * the environment to modify. - */ - protected void setupAuthenticatedEnvironment(Hashtable env) { - env - .put(Context.SECURITY_PRINCIPAL, authenticationSource - .getPrincipal()); - log.debug("Principal: '" + userDn + "'"); - env.put(Context.SECURITY_CREDENTIALS, authenticationSource - .getCredentials()); - } - - /** - * Close the context and swallow any exceptions. - * - * @param ctx - * the DirContext to close. - */ - private void closeContext(DirContext ctx) { - if (ctx != null) { - try { - ctx.close(); - } catch (Exception e) { - } - } - } - - /** - * Assemble a valid url String from all registered urls to add as - * PROVIDER_URL to the environment. - * - * @param ldapUrls - * all individual url Strings. - * @return the full url String - */ - protected String assembleProviderUrlString(String[] ldapUrls) { - StringBuffer providerUrlBuffer = new StringBuffer(1024); - for (int i = 0; i < ldapUrls.length; i++) { - providerUrlBuffer.append(ldapUrls[i]); - if (!DistinguishedName.EMPTY_PATH.equals(base)) { - if (!ldapUrls[i].endsWith("/")) { - providerUrlBuffer.append("/"); - } - } - providerUrlBuffer.append(base.toUrl()); - providerUrlBuffer.append(' '); - } - return providerUrlBuffer.toString().trim(); - } - - /** - * Set the base suffix from which all operations should origin. If a base - * suffix is set, you will not have to (and, indeed, must not) specify the - * full distinguished names in any operations performed. - * - * @param base - * the base suffix. - */ - public void setBase(String base) { - this.base = new DistinguishedName(base); - } - - /** - * Get the base suffix from which all operations should originate. If a base - * suffix is set, you will not have to (and, indeed, must not) specify the - * full distinguished names in any operations performed. - * - * @return the base suffix - */ - protected DistinguishedName getBase() { - return base; - } - - /** - * Create a DirContext using the supplied environment. - * - * @param environment - * the Ldap environment to use when creating the - * DirContext. - * @return a new DirContext implpementation initialized with the supplied - * environment. - */ - DirContext createContext(Hashtable environment) { - DirContext ctx = null; - - try { - ctx = getDirContextInstance(environment); - - if (log.isInfoEnabled()) { - Hashtable ctxEnv = ctx.getEnvironment(); - String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); - log.debug("Got Ldap context on server '" + ldapUrl + "'"); - } - - return ctx; - } catch (NamingException e) { - closeContext(ctx); - throw LdapUtils.convertLdapException(e); - } - } - - /** - * Set the context factory. Default is com.sun.jndi.ldap.LdapCtxFactory. - * - * @param contextFactory - * the context factory used when creating Contexts. - */ - public void setContextFactory(Class contextFactory) { - this.contextFactory = contextFactory; - } - - /** - * Get the context factory. - * - * @return the context factory used when creating Contexts. - */ - public Class getContextFactory() { - return contextFactory; - } - - /** - * Set the DirObjectFactory to use. Default is - * {@link DefaultDirObjectFactory}. The specified class needs to be an - * implementation of javax.naming.spi.DirObjectFactory. Note: Setting - * this value to null may have cause connection leaks when using - * ContextMapper methods in LdapTemplate. - * - * @param dirObjectFactory - * the DirObjectFactory to be used. Null means that no - * DirObjectFactory will be used. - */ - public void setDirObjectFactory(Class dirObjectFactory) { - this.dirObjectFactory = dirObjectFactory; - } - - /** - * Get the DirObjectFactory to use. - * - * @return the DirObjectFactory to be used. null means that - * no DirObjectFactory will be used. - */ - public Class getDirObjectFactory() { - return dirObjectFactory; - } - - /** - * Checks that all necessary data is set and that there is no compatibility - * issues, after which the instance is initialized. Note that you need to - * call this method explicitly after setting all desired properties if using - * the class outside of a Spring Context. - */ - public void afterPropertiesSet() throws Exception { - if (ArrayUtils.isEmpty(urls)) { - throw new IllegalArgumentException( - "At least one server url must be set"); - } - - if (!DistinguishedName.EMPTY_PATH.equals(base) - && getJdkVersion().compareTo(JDK_142) < 0) { - throw new IllegalArgumentException( - "Base path is not supported for JDK versions < 1.4.2"); - } - - if (authenticationSource == null) { - log.debug("AuthenticationSource not set - " - + "using default implementation"); - if (StringUtils.isBlank(userDn)) { - log - .info("Property 'userDn' not set - " - + "anonymous context will be used for read-write operations"); - } else if (StringUtils.isBlank(password)) { - log.info("Property 'password' not set - " - + "blank password will be used"); - } - authenticationSource = new SimpleAuthenticationSource(); - } - - if (cacheEnvironmentProperties) { - anonymousEnv = setupAnonymousEnv(); - } - } - - private Hashtable setupAnonymousEnv() { - if (pooled) { - baseEnv.put(SUN_LDAP_POOLING_FLAG, "true"); - log.debug("Using LDAP pooling."); - } else { - log.debug("Not using LDAP pooling"); - } - - Hashtable env = new Hashtable(baseEnv); - - env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory.getName()); - env.put(Context.PROVIDER_URL, assembleProviderUrlString(urls)); - - if (dirObjectFactory != null) { - env.put(Context.OBJECT_FACTORIES, dirObjectFactory.getName()); - } - - if (!DistinguishedName.EMPTY_PATH.equals(base)) { - // Save the base path for use in the DefaultDirObjectFactory. - env.put(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY, base); - } - - log.debug("Trying provider Urls: " + assembleProviderUrlString(urls)); - - return env; - } - - /** - * Set the password (credentials) to use for getting authenticated contexts. - * - * @param password - * the password. - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * Set the user distinguished name (principal) to use for getting - * authenticated contexts. - * - * @param userDn - * the user distinguished name. - */ - public void setUserDn(String userDn) { - this.userDn = userDn; - } - - /** - * Set the user distinguished name (principal) to use for getting - * authenticated contexts. - * - * @param userName - * the user distinguished name. - * @deprecated Use {@link #setUserDn(String)} instead. - */ - public void setUserName(String userName) { - setUserDn(userName); - } - - /** - * Set the urls of the LDAP servers. Use this method if several servers are - * required. - * - * @param urls - * the urls of all servers. - */ - public void setUrls(String[] urls) { - this.urls = urls; - } - - /** - * Get the urls of the LDAP servers. - * - * @return the urls of all servers. - */ - public String[] getUrls() { - return urls; - } - - /** - * Set the url of the LDAP server. Utility method if only one server is - * used. - * - * @param url - * the url of the LDAP server. - */ - public void setUrl(String url) { - this.urls = new String[] { url }; - } - - /** - * Set whether the pooling flag should be set. Default is true. Note that - * since LDAP pooling is system wide, full configuration of this needs be - * done using system parameters as specified in the LDAP/JNDI documentation. - * Also note, that pooling is done on user dn basis, i.e. each individually - * authenticated connection will be pooled separately. This means that LDAP - * pooling will be most efficient using anonymous connections or connections - * authenticated using one single system user. - * - * @param pooled - * whether Contexts should be pooled. - */ - public void setPooled(boolean pooled) { - this.pooled = pooled; - } - - /** - * Get whether the pooling flag should be set. - * - * @return whether Contexts should be pooled. - */ - public boolean isPooled() { - return pooled; - } - - /** - * If any custom environment properties are needed, these can be set using - * this method. - * - * @param baseEnvironmentProperties - */ - public void setBaseEnvironmentProperties(Map baseEnvironmentProperties) { - this.baseEnv = new Hashtable(baseEnvironmentProperties); - } - - String getJdkVersion() { - return JdkVersion.getJavaVersion(); - } - - protected Hashtable getAnonymousEnv() { - if (cacheEnvironmentProperties) { - return anonymousEnv; - } else { - return setupAnonymousEnv(); - } - } - - protected Hashtable getAuthenticatedEnv() { - // The authenticated environment should always be rebuilt. - Hashtable env = new Hashtable(getAnonymousEnv()); - setupAuthenticatedEnvironment(env); - return env; - } - - /** - * Set the authentication source to use when retrieving user principal and - * credentials. - * - * @param authenticationSource - * the {@link AuthenticationSource} that will provide user info. - */ - public void setAuthenticationSource( - AuthenticationSource authenticationSource) { - this.authenticationSource = authenticationSource; - } - - /** - * Get the authentication source. - * - * @return the {@link AuthenticationSource} that will provide user info. - */ - public AuthenticationSource getAuthenticationSource() { - return authenticationSource; - } - - /** - * Set whether environment properties should be cached between requsts for - * anonymous environment. Default is true; setting this - * property to false causes the environment Hashmap to be - * rebuilt from the current property settings of this instance between each - * request for an anonymous environment. - * - * @param cacheEnvironmentProperties - * true causes that the anonymous environment - * properties should be cached, false causes the - * Hashmap to be rebuilt for each request. - */ - public void setCacheEnvironmentProperties(boolean cacheEnvironmentProperties) { - this.cacheEnvironmentProperties = cacheEnvironmentProperties; - } - - /** - * Set whether an anonymous environment should be used for read-only - * operations. Default is false. - * - * @param anonymousReadOnly - * true if an anonymous environment should be used - * for read-only operations, false otherwise. - */ - public void setAnonymousReadOnly(boolean anonymousReadOnly) { - this.anonymousReadOnly = anonymousReadOnly; - } - - /** - * Get whether an anonymous environment should be used for read-only - * operations. - * - * @return true if an anonymous environment should be used - * for read-only operations, false otherwise. - */ - public boolean isAnonymousReadOnly() { - return anonymousReadOnly; - } - - /** - * Implement in subclass to create a DirContext of the desired type (e.g. - * InitialDirContext or InitialLdapContext). - * - * @param environment - * the environment to use when creating the instance. - * @return a new DirContext instance. - * @throws NamingException - * if one is encountered when creating the instance. - */ - protected abstract DirContext getDirContextInstance(Hashtable environment) - throws NamingException; - - class SimpleAuthenticationSource implements AuthenticationSource { - - public String getPrincipal() { - return userDn; - } - - public String getCredentials() { - return password; - } - - } +public abstract class AbstractContextSource implements ContextSource, InitializingBean { + + private static final Class DEFAULT_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory.class; + + private static final Class DEFAULT_DIR_OBJECT_FACTORY = DefaultDirObjectFactory.class; + + private Class dirObjectFactory = DEFAULT_DIR_OBJECT_FACTORY; + + private Class contextFactory = DEFAULT_CONTEXT_FACTORY; + + private DistinguishedName base = DistinguishedName.EMPTY_PATH; + + protected String userDn = ""; + + protected String password = ""; + + private String[] urls; + + private boolean pooled = true; + + private Hashtable baseEnv = new Hashtable(); + + private Hashtable anonymousEnv; + + private AuthenticationSource authenticationSource; + + private boolean cacheEnvironmentProperties = true; + + private boolean anonymousReadOnly = false; + + private static final Log log = LogFactory.getLog(LdapContextSource.class); + + public static final String SUN_LDAP_POOLING_FLAG = "com.sun.jndi.ldap.connect.pool"; + + private static final String JDK_142 = "1.4.2"; + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.core.ContextSource#getReadOnlyContext() + */ + public DirContext getReadOnlyContext() { + if (!anonymousReadOnly) { + return createContext(getAuthenticatedEnv()); + } + else { + return createContext(getAnonymousEnv()); + } + } + + /* + * (non-Javadoc) + * + * @see org.springframework.ldap.core.ContextSource#getReadWriteContext() + */ + public DirContext getReadWriteContext() { + return createContext(getAuthenticatedEnv()); + } + + /** + * Default implementation of setting the environment up to be authenticated. + * Override in subclass if necessary. + * + * @param env the environment to modify. + */ + protected void setupAuthenticatedEnvironment(Hashtable env) { + env.put(Context.SECURITY_PRINCIPAL, authenticationSource.getPrincipal()); + log.debug("Principal: '" + userDn + "'"); + env.put(Context.SECURITY_CREDENTIALS, authenticationSource.getCredentials()); + } + + /** + * Close the context and swallow any exceptions. + * + * @param ctx the DirContext to close. + */ + private void closeContext(DirContext ctx) { + if (ctx != null) { + try { + ctx.close(); + } + catch (Exception e) { + } + } + } + + /** + * Assemble a valid url String from all registered urls to add as + * PROVIDER_URL to the environment. + * + * @param ldapUrls all individual url Strings. + * @return the full url String + */ + protected String assembleProviderUrlString(String[] ldapUrls) { + StringBuffer providerUrlBuffer = new StringBuffer(1024); + for (int i = 0; i < ldapUrls.length; i++) { + providerUrlBuffer.append(ldapUrls[i]); + if (!DistinguishedName.EMPTY_PATH.equals(base)) { + if (!ldapUrls[i].endsWith("/")) { + providerUrlBuffer.append("/"); + } + } + providerUrlBuffer.append(base.toUrl()); + providerUrlBuffer.append(' '); + } + return providerUrlBuffer.toString().trim(); + } + + /** + * Set the base suffix from which all operations should origin. If a base + * suffix is set, you will not have to (and, indeed, must not) specify the + * full distinguished names in any operations performed. + * + * @param base the base suffix. + */ + public void setBase(String base) { + this.base = new DistinguishedName(base); + } + + /** + * Get the base suffix from which all operations should originate. If a base + * suffix is set, you will not have to (and, indeed, must not) specify the + * full distinguished names in any operations performed. + * + * @return the base suffix + */ + protected DistinguishedName getBase() { + return base; + } + + /** + * Create a DirContext using the supplied environment. + * + * @param environment the Ldap environment to use when creating the + * DirContext. + * @return a new DirContext implpementation initialized with the supplied + * environment. + */ + DirContext createContext(Hashtable environment) { + DirContext ctx = null; + + try { + ctx = getDirContextInstance(environment); + + if (log.isInfoEnabled()) { + Hashtable ctxEnv = ctx.getEnvironment(); + String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); + log.debug("Got Ldap context on server '" + ldapUrl + "'"); + } + + return ctx; + } + catch (NamingException e) { + closeContext(ctx); + throw LdapUtils.convertLdapException(e); + } + } + + /** + * Set the context factory. Default is com.sun.jndi.ldap.LdapCtxFactory. + * + * @param contextFactory the context factory used when creating Contexts. + */ + public void setContextFactory(Class contextFactory) { + this.contextFactory = contextFactory; + } + + /** + * Get the context factory. + * + * @return the context factory used when creating Contexts. + */ + public Class getContextFactory() { + return contextFactory; + } + + /** + * Set the DirObjectFactory to use. Default is + * {@link DefaultDirObjectFactory}. The specified class needs to be an + * implementation of javax.naming.spi.DirObjectFactory. Note: Setting + * this value to null may have cause connection leaks when using + * ContextMapper methods in LdapTemplate. + * + * @param dirObjectFactory the DirObjectFactory to be used. Null means that + * no DirObjectFactory will be used. + */ + public void setDirObjectFactory(Class dirObjectFactory) { + this.dirObjectFactory = dirObjectFactory; + } + + /** + * Get the DirObjectFactory to use. + * + * @return the DirObjectFactory to be used. null means that + * no DirObjectFactory will be used. + */ + public Class getDirObjectFactory() { + return dirObjectFactory; + } + + /** + * Checks that all necessary data is set and that there is no compatibility + * issues, after which the instance is initialized. Note that you need to + * call this method explicitly after setting all desired properties if using + * the class outside of a Spring Context. + */ + public void afterPropertiesSet() throws Exception { + if (ArrayUtils.isEmpty(urls)) { + throw new IllegalArgumentException("At least one server url must be set"); + } + + if (!DistinguishedName.EMPTY_PATH.equals(base) && getJdkVersion().compareTo(JDK_142) < 0) { + throw new IllegalArgumentException("Base path is not supported for JDK versions < 1.4.2"); + } + + if (authenticationSource == null) { + log.debug("AuthenticationSource not set - " + "using default implementation"); + if (StringUtils.isBlank(userDn)) { + log.info("Property 'userDn' not set - " + "anonymous context will be used for read-write operations"); + } + else if (StringUtils.isBlank(password)) { + log.info("Property 'password' not set - " + "blank password will be used"); + } + authenticationSource = new SimpleAuthenticationSource(); + } + + if (cacheEnvironmentProperties) { + anonymousEnv = setupAnonymousEnv(); + } + } + + private Hashtable setupAnonymousEnv() { + if (pooled) { + baseEnv.put(SUN_LDAP_POOLING_FLAG, "true"); + log.debug("Using LDAP pooling."); + } + else { + baseEnv.remove(SUN_LDAP_POOLING_FLAG); + log.debug("Not using LDAP pooling"); + } + + Hashtable env = new Hashtable(baseEnv); + + env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactory.getName()); + env.put(Context.PROVIDER_URL, assembleProviderUrlString(urls)); + + if (dirObjectFactory != null) { + env.put(Context.OBJECT_FACTORIES, dirObjectFactory.getName()); + } + + if (!DistinguishedName.EMPTY_PATH.equals(base)) { + // Save the base path for use in the DefaultDirObjectFactory. + env.put(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY, base); + } + + log.debug("Trying provider Urls: " + assembleProviderUrlString(urls)); + + return env; + } + + /** + * Set the password (credentials) to use for getting authenticated contexts. + * + * @param password the password. + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Set the user distinguished name (principal) to use for getting + * authenticated contexts. + * + * @param userDn the user distinguished name. + */ + public void setUserDn(String userDn) { + this.userDn = userDn; + } + + /** + * Set the user distinguished name (principal) to use for getting + * authenticated contexts. + * + * @param userName the user distinguished name. + * @deprecated Use {@link #setUserDn(String)} instead. + */ + public void setUserName(String userName) { + setUserDn(userName); + } + + /** + * Set the urls of the LDAP servers. Use this method if several servers are + * required. + * + * @param urls the urls of all servers. + */ + public void setUrls(String[] urls) { + this.urls = urls; + } + + /** + * Get the urls of the LDAP servers. + * + * @return the urls of all servers. + */ + public String[] getUrls() { + return urls; + } + + /** + * Set the url of the LDAP server. Utility method if only one server is + * used. + * + * @param url the url of the LDAP server. + */ + public void setUrl(String url) { + this.urls = new String[] { url }; + } + + /** + * Set whether the pooling flag should be set. Default is true. Note that + * since LDAP pooling is system wide, full configuration of this needs be + * done using system parameters as specified in the LDAP/JNDI documentation. + * Also note, that pooling is done on user dn basis, i.e. each individually + * authenticated connection will be pooled separately. This means that LDAP + * pooling will be most efficient using anonymous connections or connections + * authenticated using one single system user. + * + * @param pooled whether Contexts should be pooled. + */ + public void setPooled(boolean pooled) { + this.pooled = pooled; + } + + /** + * Get whether the pooling flag should be set. + * + * @return whether Contexts should be pooled. + */ + public boolean isPooled() { + return pooled; + } + + /** + * If any custom environment properties are needed, these can be set using + * this method. + * + * @param baseEnvironmentProperties + */ + public void setBaseEnvironmentProperties(Map baseEnvironmentProperties) { + this.baseEnv = new Hashtable(baseEnvironmentProperties); + } + + String getJdkVersion() { + return JdkVersion.getJavaVersion(); + } + + protected Hashtable getAnonymousEnv() { + if (cacheEnvironmentProperties) { + return anonymousEnv; + } + else { + return setupAnonymousEnv(); + } + } + + protected Hashtable getAuthenticatedEnv() { + // The authenticated environment should always be rebuilt. + Hashtable env = new Hashtable(getAnonymousEnv()); + setupAuthenticatedEnvironment(env); + return env; + } + + /** + * Set the authentication source to use when retrieving user principal and + * credentials. + * + * @param authenticationSource the {@link AuthenticationSource} that will + * provide user info. + */ + public void setAuthenticationSource(AuthenticationSource authenticationSource) { + this.authenticationSource = authenticationSource; + } + + /** + * Get the authentication source. + * + * @return the {@link AuthenticationSource} that will provide user info. + */ + public AuthenticationSource getAuthenticationSource() { + return authenticationSource; + } + + /** + * Set whether environment properties should be cached between requsts for + * anonymous environment. Default is true; setting this + * property to false causes the environment Hashmap to be + * rebuilt from the current property settings of this instance between each + * request for an anonymous environment. + * + * @param cacheEnvironmentProperties true causes that the + * anonymous environment properties should be cached, false + * causes the Hashmap to be rebuilt for each request. + */ + public void setCacheEnvironmentProperties(boolean cacheEnvironmentProperties) { + this.cacheEnvironmentProperties = cacheEnvironmentProperties; + } + + /** + * Set whether an anonymous environment should be used for read-only + * operations. Default is false. + * + * @param anonymousReadOnly true if an anonymous environment + * should be used for read-only operations, false otherwise. + */ + public void setAnonymousReadOnly(boolean anonymousReadOnly) { + this.anonymousReadOnly = anonymousReadOnly; + } + + /** + * Get whether an anonymous environment should be used for read-only + * operations. + * + * @return true if an anonymous environment should be used + * for read-only operations, false otherwise. + */ + public boolean isAnonymousReadOnly() { + return anonymousReadOnly; + } + + /** + * Implement in subclass to create a DirContext of the desired type (e.g. + * InitialDirContext or InitialLdapContext). + * + * @param environment the environment to use when creating the instance. + * @return a new DirContext instance. + * @throws NamingException if one is encountered when creating the instance. + */ + protected abstract DirContext getDirContextInstance(Hashtable environment) throws NamingException; + + class SimpleAuthenticationSource implements AuthenticationSource { + + public String getPrincipal() { + return userDn; + } + + public String getCredentials() { + return password; + } + + } } diff --git a/spring-ldap/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java b/spring-ldap/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java index 5300cf88..84bbd4dd 100644 --- a/spring-ldap/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java +++ b/spring-ldap/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java @@ -16,6 +16,7 @@ package org.springframework.ldap.core.support; +import java.util.HashMap; import java.util.Hashtable; import javax.naming.Context; @@ -37,265 +38,278 @@ import com.sun.jndi.ldap.ctl.ResponseControlFactory; */ public class LdapContextSourceTest extends TestCase { - private LdapContextSource tested; + private LdapContextSource tested; - protected void setUp() throws Exception { - tested = new LdapContextSource(); - } + protected void setUp() throws Exception { + tested = new LdapContextSource(); + } - protected void tearDown() throws Exception { - tested = null; - } + protected void tearDown() throws Exception { + tested = null; + } - public void testAfterPropertiesSet_NoUrl() throws Exception { - try { - tested.afterPropertiesSet(); - fail("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + public void testAfterPropertiesSet_NoUrl() throws Exception { + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - public void testAfterPropertiesSet_BaseAndTooEarlyJdk() throws Exception { - tested = new LdapContextSource() { - String getJdkVersion() { - return "1.4.1_03"; - } - }; + public void testAfterPropertiesSet_BaseAndTooEarlyJdk() throws Exception { + tested = new LdapContextSource() { + String getJdkVersion() { + return "1.4.1_03"; + } + }; - tested.setUrl("http://ldap.example.com:389"); - tested.setBase("dc=jayway,dc=se"); - try { - tested.afterPropertiesSet(); - fail("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + tested.setUrl("http://ldap.example.com:389"); + tested.setBase("dc=jayway,dc=se"); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - public void testGetAnonymousEnv() throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - tested.setUserDn("cn=Some User"); - tested.setPassword("secret"); - tested.afterPropertiesSet(); - Hashtable env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertNull(env.get(Context.SECURITY_PRINCIPAL)); - assertNull(env.get(Context.SECURITY_CREDENTIALS)); + public void testGetAnonymousEnv() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserDn("cn=Some User"); + tested.setPassword("secret"); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); - // check that base was added to environment - assertEquals(new DistinguishedName("dc=example,dc=se"), env - .get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + // check that base was added to environment + assertEquals(new DistinguishedName("dc=example,dc=se"), env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - // Verify that changing values does not change the environment values. - tested.setBase("dc=other,dc=se"); - tested.setUrl("ldap://ldap2.example.com:389"); - tested.setPooled(false); + // Verify that changing values does not change the environment values. + tested.setBase("dc=other,dc=se"); + tested.setUrl("ldap://ldap2.example.com:389"); + tested.setPooled(false); - env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertNull(env.get(Context.SECURITY_PRINCIPAL)); - assertNull(env.get(Context.SECURITY_CREDENTIALS)); + env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); - assertEquals(new DistinguishedName("dc=example,dc=se"), env - .get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + assertEquals(new DistinguishedName("dc=example,dc=se"), env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - public void testGetAnonymousEnvWithNoBaseSet() throws Exception { - tested.setUrl("ldap://ldap.example.com:389"); - tested.afterPropertiesSet(); - Hashtable env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap.example.com:389", env - .get(Context.PROVIDER_URL)); + public void testGetAnonymousEnvWithNoBaseSet() throws Exception { + tested.setUrl("ldap://ldap.example.com:389"); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389", env.get(Context.PROVIDER_URL)); - // check that base was not added to environment - assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + // check that base was not added to environment + assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - public void testGetAnonymousEnvWithEmptyBaseSet() throws Exception { - tested.setUrl("ldap://ldap.example.com:389"); - tested.setBase(null); - tested.afterPropertiesSet(); - Hashtable env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap.example.com:389", env - .get(Context.PROVIDER_URL)); + public void testGetAnonymousEnvWithBaseEnvironment() throws Exception { + tested.setUrl("ldap://ldap.example.com:389"); + HashMap map = new HashMap(); + map.put(LdapContextSource.SUN_LDAP_POOLING_FLAG, "true"); + tested.setBaseEnvironmentProperties(map); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + } - // check that base was not added to environment - assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + public void testGetAnonymousEnvWithPoolingInBaseEnvironmentAndPoolingOff() throws Exception { + tested.setUrl("ldap://ldap.example.com:389"); + HashMap map = new HashMap(); + map.put(LdapContextSource.SUN_LDAP_POOLING_FLAG, "true"); + tested.setBaseEnvironmentProperties(map); + tested.setPooled(false); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389", env.get(Context.PROVIDER_URL)); + assertNull(env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + } - public void testOldJdkWithNoBaseSetShouldWork() throws Exception { - tested = new LdapContextSource() { - String getJdkVersion() { - return "1.3"; - } - }; - tested.setUrl("ldap://ldap.example.com:389"); - tested.afterPropertiesSet(); + public void testGetAnonymousEnvWithEmptyBaseSet() throws Exception { + tested.setUrl("ldap://ldap.example.com:389"); + tested.setBase(null); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389", env.get(Context.PROVIDER_URL)); - // check that base was not added to environment - Hashtable env = tested.getAnonymousEnv(); - assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + // check that base was not added to environment + assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - public void testOldJdkWithBaseSetShouldNotWork() throws Exception { - tested = new LdapContextSource() { - String getJdkVersion() { - return "1.3"; - } - }; - tested.setUrl("ldap://ldap.example.com:389"); - tested.setBase("dc=example,dc=com"); - try { - tested.afterPropertiesSet(); - fail("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + public void testOldJdkWithNoBaseSetShouldWork() throws Exception { + tested = new LdapContextSource() { + String getJdkVersion() { + return "1.3"; + } + }; + tested.setUrl("ldap://ldap.example.com:389"); + tested.afterPropertiesSet(); - public void testOldJdkWithBaseSetToEmptyPathShouldWork() throws Exception { - tested = new LdapContextSource() { - String getJdkVersion() { - return "1.3"; - } - }; - tested.setUrl("ldap://ldap.example.com:389"); - tested.setBase(null); - tested.afterPropertiesSet(); - - // check that base was not added to environment - Hashtable env = tested.getAnonymousEnv(); - assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + // check that base was not added to environment + Hashtable env = tested.getAnonymousEnv(); + assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - public void testGetAuthenticatedEnv() throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - tested.setUserDn("cn=Some User"); - tested.setPassword("secret"); - tested.afterPropertiesSet(); + public void testOldJdkWithBaseSetShouldNotWork() throws Exception { + tested = new LdapContextSource() { + String getJdkVersion() { + return "1.3"; + } + }; + tested.setUrl("ldap://ldap.example.com:389"); + tested.setBase("dc=example,dc=com"); + try { + tested.afterPropertiesSet(); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - Hashtable env = tested.getAuthenticatedEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); - assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); + public void testOldJdkWithBaseSetToEmptyPathShouldWork() throws Exception { + tested = new LdapContextSource() { + String getJdkVersion() { + return "1.3"; + } + }; + tested.setUrl("ldap://ldap.example.com:389"); + tested.setBase(null); + tested.afterPropertiesSet(); - // check that base was added to environment - assertEquals(new DistinguishedName("dc=example,dc=se"), env - .get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); - } + // check that base was not added to environment + Hashtable env = tested.getAnonymousEnv(); + assertNull(env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - public void testGetAuthenticatedEnv_DummyAuthenticationProvider() - throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); - tested.setAuthenticationSource(authenticationProvider); - authenticationProvider.setPrincipal("cn=Some User"); - authenticationProvider.setCredentials("secret"); - tested.afterPropertiesSet(); + public void testGetAuthenticatedEnv() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserDn("cn=Some User"); + tested.setPassword("secret"); + tested.afterPropertiesSet(); - Hashtable env = tested.getAuthenticatedEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); - assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); - } + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); - public void testGetAuthenticatedEnv_DummyAuthenticationProvider_Changed() - throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); - tested.setAuthenticationSource(authenticationProvider); - authenticationProvider.setPrincipal("cn=Some User"); - authenticationProvider.setCredentials("secret"); - tested.afterPropertiesSet(); + // check that base was added to environment + assertEquals(new DistinguishedName("dc=example,dc=se"), env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); + } - authenticationProvider.setPrincipal("cn=Some Other User"); - authenticationProvider.setCredentials("other secret"); + public void testGetAuthenticatedEnv_DummyAuthenticationProvider() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); + tested.setAuthenticationSource(authenticationProvider); + authenticationProvider.setPrincipal("cn=Some User"); + authenticationProvider.setCredentials("secret"); + tested.afterPropertiesSet(); - Hashtable env = tested.getAuthenticatedEnv(); - assertEquals("cn=Some Other User", env.get(Context.SECURITY_PRINCIPAL)); - assertEquals("other secret", env.get(Context.SECURITY_CREDENTIALS)); - } + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); + } - public void testGetAnonymousEnvWhenCacheIsOff() throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - tested.setUserDn("cn=Some User"); - tested.setPassword("secret"); - tested.setCacheEnvironmentProperties(false); - tested.afterPropertiesSet(); - Hashtable env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertNull(env.get(Context.SECURITY_PRINCIPAL)); - assertNull(env.get(Context.SECURITY_CREDENTIALS)); + public void testGetAuthenticatedEnv_DummyAuthenticationProvider_Changed() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); + tested.setAuthenticationSource(authenticationProvider); + authenticationProvider.setPrincipal("cn=Some User"); + authenticationProvider.setCredentials("secret"); + tested.afterPropertiesSet(); - tested.setUrl("ldap://ldap2.example.com:389"); - env = tested.getAnonymousEnv(); - assertEquals("ldap://ldap2.example.com:389/dc=example,dc=se", env - .get(Context.PROVIDER_URL)); - } + authenticationProvider.setPrincipal("cn=Some Other User"); + authenticationProvider.setCredentials("other secret"); - public void testSetResponseControlFactoryToNull() throws Exception { - tested.setResponseControlFactory(null); - assertNotNull(tested.getResponseControlFactory()); - assertEquals(ResponseControlFactory.class, tested - .getResponseControlFactory()); - } + Hashtable env = tested.getAuthenticatedEnv(); + assertEquals("cn=Some Other User", env.get(Context.SECURITY_PRINCIPAL)); + assertEquals("other secret", env.get(Context.SECURITY_CREDENTIALS)); + } - public void testSetValidResponseControlFactory() throws Exception { - Class validClass = ControlFactory.class; - tested.setResponseControlFactory(validClass); - assertEquals(validClass, tested.getResponseControlFactory()); - } + public void testGetAnonymousEnvWhenCacheIsOff() throws Exception { + tested.setBase("dc=example,dc=se"); + tested.setUrl("ldap://ldap.example.com:389"); + tested.setPooled(true); + tested.setUserDn("cn=Some User"); + tested.setPassword("secret"); + tested.setCacheEnvironmentProperties(false); + tested.afterPropertiesSet(); + Hashtable env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); + assertNull(env.get(Context.SECURITY_PRINCIPAL)); + assertNull(env.get(Context.SECURITY_CREDENTIALS)); - public void testSetInvalidResponseControlFactory() throws Exception { - try { - Class invalidClass = Control.class; - tested.setResponseControlFactory(invalidClass); - fail("IllegalArgumentException expected"); - } catch (IllegalArgumentException expected) { - assertTrue(true); - } - } + tested.setUrl("ldap://ldap2.example.com:389"); + env = tested.getAnonymousEnv(); + assertEquals("ldap://ldap2.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); + } - private class DummyAuthenticationProvider implements AuthenticationSource { - private String principal; + public void testSetResponseControlFactoryToNull() throws Exception { + tested.setResponseControlFactory(null); + assertNotNull(tested.getResponseControlFactory()); + assertEquals(ResponseControlFactory.class, tested.getResponseControlFactory()); + } - private String credentials; + public void testSetValidResponseControlFactory() throws Exception { + Class validClass = ControlFactory.class; + tested.setResponseControlFactory(validClass); + assertEquals(validClass, tested.getResponseControlFactory()); + } - public void setCredentials(String credentials) { - this.credentials = credentials; - } + public void testSetInvalidResponseControlFactory() throws Exception { + try { + Class invalidClass = Control.class; + tested.setResponseControlFactory(invalidClass); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException expected) { + assertTrue(true); + } + } - public void setPrincipal(String principal) { - this.principal = principal; - } + private class DummyAuthenticationProvider implements AuthenticationSource { + private String principal; - public String getPrincipal() { - return principal; - } + private String credentials; - public String getCredentials() { - return credentials; - } - } + public void setCredentials(String credentials) { + this.credentials = credentials; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + public String getPrincipal() { + return principal; + } + + public String getCredentials() { + return credentials; + } + } }