You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/06/11 07:36:57 UTC
[james-project] 01/18: JAMES-3594 Implement ReadOnlyLDAPUsersDAO
with UnboundID library
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 393c65a6e5196b8b167e679784957c290c7c976f
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Jun 6 13:13:53 2021 +0700
JAMES-3594 Implement ReadOnlyLDAPUsersDAO with UnboundID library
---
pom.xml | 6 +-
server/data/data-ldap/pom.xml | 4 +
.../user/ldap/LdapRepositoryConfiguration.java | 22 +-
.../apache/james/user/ldap/ReadOnlyLDAPUser.java | 76 ++--
.../james/user/ldap/ReadOnlyLDAPUsersDAO.java | 266 ++++-------
.../apache/james/user/ldap/api/LdapConstants.java | 32 --
.../user/ldap/retry/DoublingRetrySchedule.java | 99 ----
.../user/ldap/retry/ExceptionRetryHandler.java | 131 ------
.../ldap/retry/api/ExceptionRetryingProxy.java | 49 --
.../james/user/ldap/retry/api/RetryHandler.java | 52 ---
.../james/user/ldap/retry/api/RetrySchedule.java | 35 --
.../ldap/retry/naming/LoggingRetryHandler.java | 54 ---
.../retry/naming/NamingExceptionRetryHandler.java | 72 ---
.../user/ldap/retry/naming/RetryingContext.java | 497 ---------------------
.../retry/naming/directory/RetryingDirContext.java | 407 -----------------
.../retry/naming/ldap/RetryingLdapContext.java | 129 ------
.../user/ldap/retry/DoublingRetryScheduleTest.java | 71 ---
.../user/ldap/retry/ExceptionRetryHandlerTest.java | 153 -------
.../naming/NamingExceptionRetryHandlerTest.java | 92 ----
19 files changed, 132 insertions(+), 2115 deletions(-)
diff --git a/pom.xml b/pom.xml
index f7bc55a..21e035a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2105,7 +2105,6 @@
<artifactId>metrics-elasticsearch-reporter</artifactId>
<version>${es-reporter.version}</version>
</dependency>
-
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
@@ -2153,6 +2152,11 @@
<version>2.9.2</version>
</dependency>
<dependency>
+ <groupId>com.unboundid</groupId>
+ <artifactId>unboundid-ldapsdk</artifactId>
+ <version>6.0.0</version>
+ </dependency>
+ <dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
diff --git a/server/data/data-ldap/pom.xml b/server/data/data-ldap/pom.xml
index 88492e1..aec06a1 100644
--- a/server/data/data-ldap/pom.xml
+++ b/server/data/data-ldap/pom.xml
@@ -70,6 +70,10 @@
<artifactId>guavate</artifactId>
</dependency>
<dependency>
+ <groupId>com.unboundid</groupId>
+ <artifactId>unboundid-ldapsdk</artifactId>
+ </dependency>
+ <dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
index f526cd2..efc79ed 100644
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
+++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
@@ -32,9 +32,8 @@ import com.google.common.base.Preconditions;
public class LdapRepositoryConfiguration {
public static final String SUPPORTS_VIRTUAL_HOSTING = "supportsVirtualHosting";
- private static final boolean NO_CONNECTION_POOL = false;
- private static final int NO_CONNECTION_TIMEOUT = -1;
- private static final int NO_READ_TIME_OUT = -1;
+ private static final int NO_CONNECTION_TIMEOUT = 0;
+ private static final int NO_READ_TIME_OUT = 0;
private static final boolean ENABLE_VIRTUAL_HOSTING = true;
private static final ReadOnlyLDAPGroupRestriction NO_RESTRICTION = new ReadOnlyLDAPGroupRestriction(null);
private static final String NO_FILTER = null;
@@ -134,7 +133,6 @@ public class LdapRepositoryConfiguration {
userBase.get(),
userIdAttribute.get(),
userObjectClass.get(),
- NO_CONNECTION_POOL,
NO_CONNECTION_TIMEOUT,
NO_READ_TIME_OUT,
maxRetries.get(),
@@ -160,7 +158,6 @@ public class LdapRepositoryConfiguration {
String userIdAttribute = configuration.getString("[@userIdAttribute]");
String userObjectClass = configuration.getString("[@userObjectClass]");
// Default is to use connection pooling
- boolean useConnectionPool = configuration.getBoolean("[@useConnectionPool]", NO_CONNECTION_POOL);
int connectionTimeout = configuration.getInt("[@connectionTimeout]", NO_CONNECTION_TIMEOUT);
int readTimeout = configuration.getInt("[@readTimeout]", NO_READ_TIME_OUT);
// Default maximum retries is 1, which allows an alternate connection to
@@ -193,7 +190,6 @@ public class LdapRepositoryConfiguration {
userBase,
userIdAttribute,
userObjectClass,
- useConnectionPool,
connectionTimeout,
readTimeout,
maxRetries,
@@ -251,9 +247,6 @@ public class LdapRepositoryConfiguration {
*/
private final String userObjectClass;
- // Use a connection pool. Default is true.
- private final boolean useConnectionPool;
-
// The connection timeout in milliseconds.
// A value of less than or equal to zero means to use the network protocol's
// (i.e., TCP's) timeout value.
@@ -290,7 +283,7 @@ public class LdapRepositoryConfiguration {
private final Optional<Username> administratorId;
private LdapRepositoryConfiguration(String ldapHost, String principal, String credentials, String userBase, String userIdAttribute,
- String userObjectClass, boolean useConnectionPool, int connectionTimeout, int readTimeout,
+ String userObjectClass, int connectionTimeout, int readTimeout,
int maxRetries, boolean supportsVirtualHosting, long retryStartInterval, long retryMaxInterval,
int scale, ReadOnlyLDAPGroupRestriction restriction, String filter,
Optional<String> administratorId) throws ConfigurationException {
@@ -300,7 +293,6 @@ public class LdapRepositoryConfiguration {
this.userBase = userBase;
this.userIdAttribute = userIdAttribute;
this.userObjectClass = userObjectClass;
- this.useConnectionPool = useConnectionPool;
this.connectionTimeout = connectionTimeout;
this.readTimeout = readTimeout;
this.maxRetries = maxRetries;
@@ -351,9 +343,6 @@ public class LdapRepositoryConfiguration {
return userObjectClass;
}
- public boolean useConnectionPool() {
- return useConnectionPool;
- }
public int getConnectionTimeout() {
return connectionTimeout;
@@ -400,8 +389,7 @@ public class LdapRepositoryConfiguration {
if (o instanceof LdapRepositoryConfiguration) {
LdapRepositoryConfiguration that = (LdapRepositoryConfiguration) o;
- return Objects.equals(this.useConnectionPool, that.useConnectionPool)
- && Objects.equals(this.connectionTimeout, that.connectionTimeout)
+ return Objects.equals(this.connectionTimeout, that.connectionTimeout)
&& Objects.equals(this.readTimeout, that.readTimeout)
&& Objects.equals(this.maxRetries, that.maxRetries)
&& Objects.equals(this.supportsVirtualHosting, that.supportsVirtualHosting)
@@ -423,7 +411,7 @@ public class LdapRepositoryConfiguration {
@Override
public final int hashCode() {
- return Objects.hash(ldapHost, principal, credentials, userBase, userIdAttribute, userObjectClass, useConnectionPool,
+ return Objects.hash(ldapHost, principal, credentials, userBase, userIdAttribute, userObjectClass,
connectionTimeout, readTimeout, maxRetries, supportsVirtualHosting, retryStartInterval, retryMaxInterval, scale,
restriction, filter, administratorId);
}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java
index 6946fa6..6125fb9 100644
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java
+++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUser.java
@@ -21,13 +21,14 @@ package org.apache.james.user.ldap;
import java.io.Serializable;
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.ldap.LdapContext;
-
import org.apache.james.core.Username;
import org.apache.james.user.api.model.User;
-import org.apache.james.user.ldap.api.LdapConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.unboundid.ldap.sdk.BindResult;
+import com.unboundid.ldap.sdk.LDAPConnectionPool;
+import com.unboundid.ldap.sdk.LDAPException;
/**
* Encapsulates the details of a user as taken from an LDAP compliant directory.
@@ -38,14 +39,13 @@ import org.apache.james.user.ldap.api.LdapConstants;
* means of authenticating the user against the LDAP server. Consequently
* invocations of the contract method {@link User#setPassword(String)} always
* returns <code>false</code>.
- *
- * @see SimpleLDAPConnection
+ *
* @see ReadOnlyUsersLDAPRepository
*
*/
public class ReadOnlyLDAPUser implements User, Serializable {
- // private static final long serialVersionUID = -6712066073820393235L;
- private static final long serialVersionUID = -5201235065842464013L;
+ private static final long serialVersionUID = -5201235065842464014L;
+ public static final Logger LOGGER = LoggerFactory.getLogger(ReadOnlyLDAPUser.class);
/**
* The user's identifier or name. This is the value that is returned by the
@@ -55,31 +55,28 @@ public class ReadOnlyLDAPUser implements User, Serializable {
* <code>"myorg.com"</code>, the user's email address will be
* <code>"john.bold@myorg.com"</code>.
*/
- private Username userName;
+ private final Username userName;
/**
* The distinguished name of the user-record in the LDAP directory.
*/
- private String userDN;
+ private final String userDN;
/**
* The context for the LDAP server from which to retrieve the
* user's details.
*/
- private LdapContext ldapContext = null;
-
- /**
- * Creates a new instance of ReadOnlyLDAPUser.
- *
- */
- private ReadOnlyLDAPUser() {
- super();
- }
+ private final LDAPConnectionPool connectionPool;
/**
* Constructs an instance for the given user-details, and which will
* authenticate against the given host.
- *
+ *
+ * @param connectionPool
+ * The connectionPool for the LDAP server on which the user details are held.
+ * This is also the host against which the user will be
+ * authenticated, when {@link #verifyPassword(String)} is
+ * invoked.
* @param userName
* The user-identifier/name. This is the value with which the
* field will be initialised, and which will be
@@ -87,18 +84,11 @@ public class ReadOnlyLDAPUser implements User, Serializable {
* @param userDN
* The distinguished (unique-key) of the user details as stored
* on the LDAP directory.
- * @param ldapContext
- * The context for the LDAP server on which the user details are held.
- * This is also the host against which the user will be
- * authenticated, when {@link #verifyPassword(String)} is
- * invoked.
- * @throws NamingException
*/
- public ReadOnlyLDAPUser(Username userName, String userDN, LdapContext ldapContext) {
- this();
+ public ReadOnlyLDAPUser(Username userName, String userDN, LDAPConnectionPool connectionPool) {
this.userName = userName;
this.userDN = userDN;
- this.ldapContext = ldapContext;
+ this.connectionPool = connectionPool;
}
/**
@@ -139,27 +129,13 @@ public class ReadOnlyLDAPUser implements User, Serializable {
*/
@Override
public boolean verifyPassword(String password) {
- boolean result = false;
- LdapContext ldapContext = null;
try {
- ldapContext = this.ldapContext.newInstance(null);
- ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION,
- LdapConstants.SECURITY_AUTHENTICATION_SIMPLE);
- ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
- ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
- ldapContext.reconnect(null);
- result = true;
- } catch (NamingException exception) {
- // no-op
- } finally {
- if (null != ldapContext) {
- try {
- ldapContext.close();
- } catch (NamingException ex) {
- // no-op
- }
- }
+ BindResult bindResult = connectionPool.bindAndRevertAuthentication(userDN, password);
+ return bindResult.getResultCode()
+ .intValue() == 0;
+ } catch (LDAPException e) {
+ LOGGER.error("Unexpected error upon authentication", e);
+ return false;
}
- return result;
}
}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
index 678a96a..fb450d0 100644
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
+++ b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
@@ -19,26 +19,18 @@
package org.apache.james.user.ldap;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.Properties;
import java.util.Set;
+import javax.annotation.PreDestroy;
import javax.inject.Inject;
-import javax.naming.Context;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.InitialLdapContext;
-import javax.naming.ldap.LdapContext;
+import javax.net.SocketFactory;
import org.apache.commons.configuration2.HierarchicalConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
@@ -49,39 +41,26 @@ import org.apache.james.core.Username;
import org.apache.james.lifecycle.api.Configurable;
import org.apache.james.user.api.UsersRepositoryException;
import org.apache.james.user.api.model.User;
-import org.apache.james.user.ldap.api.LdapConstants;
-import org.apache.james.user.ldap.retry.DoublingRetrySchedule;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.apache.james.user.ldap.retry.naming.ldap.RetryingLdapContext;
import org.apache.james.user.lib.UsersDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.fge.lambdas.Throwing;
import com.github.steveash.guavate.Guavate;
-import com.google.common.base.Strings;
+import com.unboundid.ldap.sdk.LDAPConnection;
+import com.unboundid.ldap.sdk.LDAPConnectionOptions;
+import com.unboundid.ldap.sdk.LDAPConnectionPool;
+import com.unboundid.ldap.sdk.LDAPException;
+import com.unboundid.ldap.sdk.SearchResult;
+import com.unboundid.ldap.sdk.SearchResultEntry;
+import com.unboundid.ldap.sdk.SearchScope;
public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
private static final Logger LOGGER = LoggerFactory.getLogger(ReadOnlyLDAPUsersDAO.class);
- // The name of the factory class which creates the initial context
- // for the LDAP service provider
- private static final String INITIAL_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
-
- private static final String PROPERTY_NAME_CONNECTION_POOL = "com.sun.jndi.ldap.connect.pool";
- private static final String PROPERTY_NAME_CONNECT_TIMEOUT = "com.sun.jndi.ldap.connect.timeout";
- private static final String PROPERTY_NAME_READ_TIMEOUT = "com.sun.jndi.ldap.read.timeout";
-
- /**
- * The context for the LDAP server. This is the connection that is built
- * from the configuration attributes "ldapHost",
- * "principal" and "credentials".
- */
- private LdapContext ldapContext;
- // The schedule for retry attempts
- private RetrySchedule schedule = null;
-
private LdapRepositoryConfiguration ldapConfiguration;
+ private String filterTemplate;
+ private LDAPConnectionPool ldapConnectionPool;
@Inject
public ReadOnlyLDAPUsersDAO() {
@@ -91,8 +70,6 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
/**
* Extracts the parameters required by the repository instance from the
* James server configuration data. The fields extracted include
- * {@link LdapRepositoryConfiguration#ldapHost}, {@link LdapRepositoryConfiguration#userIdAttribute}, {@link LdapRepositoryConfiguration#userBase},
- * {@link LdapRepositoryConfiguration#principal}, {@link LdapRepositoryConfiguration#credentials} and {@link LdapRepositoryConfiguration#restriction}.
*
* @param configuration
* An encapsulation of the James server configuration data.
@@ -104,11 +81,6 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
public void configure(LdapRepositoryConfiguration configuration) {
ldapConfiguration = configuration;
-
- schedule = new DoublingRetrySchedule(
- configuration.getRetryStartInterval(),
- configuration.getRetryMaxInterval(),
- configuration.getScale());
}
/**
@@ -120,63 +92,34 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
* specified LDAP host.
*/
public void init() throws Exception {
+
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(this.getClass().getName() + ".init()" + '\n' + "LDAP host: " + ldapConfiguration.getLdapHost()
+ '\n' + "User baseDN: " + ldapConfiguration.getUserBase() + '\n' + "userIdAttribute: "
+ ldapConfiguration.getUserIdAttribute() + '\n' + "Group restriction: " + ldapConfiguration.getRestriction()
- + '\n' + "UseConnectionPool: " + ldapConfiguration.useConnectionPool() + '\n' + "connectionTimeout: "
+ + '\n' + "connectionTimeout: "
+ ldapConfiguration.getConnectionTimeout() + '\n' + "readTimeout: " + ldapConfiguration.getReadTimeout()
- + '\n' + "retrySchedule: " + schedule + '\n' + "maxRetries: " + ldapConfiguration.getMaxRetries() + '\n');
+ + '\n' + "maxRetries: " + ldapConfiguration.getMaxRetries() + '\n');
}
- // Setup the initial LDAP context
- updateLdapContext();
- }
-
- protected void updateLdapContext() throws NamingException {
- ldapContext = computeLdapContext();
- }
+ filterTemplate = "(&({0}={1})(objectClass={2})" + StringUtils.defaultString(ldapConfiguration.getFilter(), "") + ")";
- /**
- * Answers a new LDAP/JNDI context using the specified user credentials.
- *
- * @return an LDAP directory context
- * @throws NamingException
- * Propagated from underlying LDAP communication API.
- */
- protected LdapContext computeLdapContext() throws NamingException {
- return new RetryingLdapContext(schedule, ldapConfiguration.getMaxRetries()) {
+ LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions();
+ connectionOptions.setConnectTimeoutMillis(ldapConfiguration.getConnectionTimeout());
+ connectionOptions.setResponseTimeoutMillis(ldapConfiguration.getReadTimeout());
- @Override
- public Context newDelegate() throws NamingException {
- return new InitialLdapContext(getContextEnvironment(), null);
- }
- };
+ URI uri = new URI(ldapConfiguration.getLdapHost());
+ SocketFactory socketFactory = null;
+ LDAPConnection ldapConnection = new LDAPConnection(socketFactory, connectionOptions, uri.getHost(), uri.getPort(), ldapConfiguration.getPrincipal(), ldapConfiguration.getCredentials());
+ ldapConnectionPool = new LDAPConnectionPool(ldapConnection, 4);
+ // TODO implement retries
}
- protected Properties getContextEnvironment() {
- Properties props = new Properties();
- props.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
- props.put(Context.PROVIDER_URL, Optional.ofNullable(ldapConfiguration.getLdapHost())
- .orElse(""));
- if (Strings.isNullOrEmpty(ldapConfiguration.getCredentials())) {
- props.put(Context.SECURITY_AUTHENTICATION, LdapConstants.SECURITY_AUTHENTICATION_NONE);
- } else {
- props.put(Context.SECURITY_AUTHENTICATION, LdapConstants.SECURITY_AUTHENTICATION_SIMPLE);
- props.put(Context.SECURITY_PRINCIPAL, Optional.ofNullable(ldapConfiguration.getPrincipal())
- .orElse(""));
- props.put(Context.SECURITY_CREDENTIALS, ldapConfiguration.getCredentials());
- }
- // The following properties are specific to com.sun.jndi.ldap.LdapCtxFactory
- props.put(PROPERTY_NAME_CONNECTION_POOL, String.valueOf(ldapConfiguration.useConnectionPool()));
- if (ldapConfiguration.getConnectionTimeout() > -1) {
- props.put(PROPERTY_NAME_CONNECT_TIMEOUT, String.valueOf(ldapConfiguration.getConnectionTimeout()));
- }
- if (ldapConfiguration.getReadTimeout() > -1) {
- props.put(PROPERTY_NAME_READ_TIMEOUT, Integer.toString(ldapConfiguration.getReadTimeout()));
- }
- return props;
+ @PreDestroy
+ void dispose() {
+ ldapConnectionPool.close();
}
+
/**
* Indicates if the user with the specified DN can be found in the group
* membership map-as encapsulated by the specified parameter map.
@@ -209,29 +152,20 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
return result;
}
- /**
- * Gets all the user entities taken from the LDAP server, as taken from the
- * search-context given by the value of the attribute {@link LdapRepositoryConfiguration#userBase}.
- *
- * @return A set containing all the relevant users found in the LDAP
- * directory.
- * @throws NamingException
- * Propagated from the LDAP communication layer.
- */
- private Set<String> getAllUsersFromLDAP() throws NamingException {
- Set<String> result = new HashSet<>();
-
- SearchControls sc = new SearchControls();
- sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
- sc.setReturningAttributes(new String[] { "distinguishedName" });
- NamingEnumeration<SearchResult> sr = ldapContext.search(ldapConfiguration.getUserBase(), "(objectClass="
- + ldapConfiguration.getUserObjectClass() + ")", sc);
- while (sr.hasMore()) {
- SearchResult r = sr.next();
- result.add(r.getNameInNamespace());
- }
+ private Set<String> getAllUsersFromLDAP() throws LDAPException {
+ LDAPConnection connection = ldapConnectionPool.getConnection();
+ try {
+ SearchResult searchResult = connection.search(ldapConfiguration.getUserBase(),
+ SearchScope.SUB,
+ filterTemplate);
- return result;
+ return searchResult.getSearchEntries()
+ .stream()
+ .map(entry -> entry.getObjectClassAttribute().getName())
+ .collect(Guavate.toImmutableSet());
+ } finally {
+ ldapConnectionPool.releaseConnection(connection);
+ }
}
/**
@@ -245,11 +179,10 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
* is to be extracted from the LDAP repository.
* @return A collection of {@link ReadOnlyLDAPUser}s as taken from the LDAP
* server.
- * @throws NamingException
+ * @throws LDAPException
* Propagated from the underlying LDAP communication layer.
*/
- private Collection<ReadOnlyLDAPUser> buildUserCollection(Collection<String> userDNs)
- throws NamingException {
+ private Collection<ReadOnlyLDAPUser> buildUserCollection(Collection<String> userDNs) throws LDAPException {
List<ReadOnlyLDAPUser> results = new ArrayList<>();
for (String userDN : userDNs) {
@@ -260,42 +193,34 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
return results;
}
- /**
- * For a given name, this method makes ldap search in userBase with filter {@link LdapRepositoryConfiguration#userIdAttribute}=name
- * and objectClass={@link LdapRepositoryConfiguration#userObjectClass} and builds {@link User} based on search result.
- *
- * @param name
- * The userId which should be value of the field {@link LdapRepositoryConfiguration#userIdAttribute}
- * @return A {@link ReadOnlyLDAPUser} instance which is initialized with the
- * userId of this user and ldap connection information with which
- * the user was searched. Return null if such a user was not found.
- * @throws NamingException
- * Propagated by the underlying LDAP communication layer.
- */
- private ReadOnlyLDAPUser searchAndBuildUser(Username name) throws NamingException {
- SearchControls sc = new SearchControls();
- sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
- sc.setReturningAttributes(new String[] { ldapConfiguration.getUserIdAttribute() });
- sc.setCountLimit(1);
-
- String filterTemplate = "(&({0}={1})(objectClass={2})" +
- StringUtils.defaultString(ldapConfiguration.getFilter(), "") +
- ")";
-
- String sanitizedFilter = FilterEncoder.format(
- filterTemplate,
- ldapConfiguration.getUserIdAttribute(),
- name.asString(),
- ldapConfiguration.getUserObjectClass());
-
- NamingEnumeration<SearchResult> sr = ldapContext.search(ldapConfiguration.getUserBase(), sanitizedFilter, sc);
-
- if (!sr.hasMore()) {
- return null;
+ private ReadOnlyLDAPUser searchAndBuildUser(Username name) throws LDAPException {
+ LDAPConnection connection = ldapConnectionPool.getConnection();
+ try {
+ String sanitizedFilter = FilterEncoder.format(
+ filterTemplate,
+ ldapConfiguration.getUserIdAttribute(),
+ name.asString(),
+ ldapConfiguration.getUserObjectClass());
+
+ SearchResult searchResult = connection.search(ldapConfiguration.getUserBase(),
+ SearchScope.SUB,
+ sanitizedFilter,
+ ldapConfiguration.getUserIdAttribute());
+
+ return searchResult.getSearchEntries()
+ .stream()
+ .map(entry -> new ReadOnlyLDAPUser(
+ Username.of(entry.getAttribute(ldapConfiguration.getUserIdAttribute()).getName()),
+ entry.getDN(),
+ ldapConnectionPool))
+ .findFirst()
+ .orElse(null);
+ } finally {
+ ldapConnectionPool.releaseConnection(connection);
}
- SearchResult r = sr.next();
- Attribute userName = r.getAttributes().get(ldapConfiguration.getUserIdAttribute());
+ /*
+ TODO implement restrictions
if (!ldapConfiguration.getRestriction().isActivated()
|| userInGroupsMembershipList(r.getNameInNamespace(), ldapConfiguration.getRestriction().getGroupMembershipLists(ldapContext))) {
@@ -303,31 +228,20 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
}
return null;
+ */
}
- /**
- * Given a userDN, this method retrieves the user attributes from the LDAP
- * server, so as to extract the items that are of interest to James.
- * Specifically it extracts the userId, which is extracted from the LDAP
- * attribute whose name is given by the value of the field
- * {@link LdapRepositoryConfiguration#userIdAttribute}.
- *
- * @param userDN
- * The distinguished-name of the user whose details are to be
- * extracted from the LDAP repository.
- * @return A {@link ReadOnlyLDAPUser} instance which is initialized with the
- * userId of this user and ldap connection information with which
- * the userDN and attributes were obtained.
- * @throws NamingException
- * Propagated by the underlying LDAP communication layer.
- */
- private Optional<ReadOnlyLDAPUser> buildUser(String userDN) throws NamingException {
- Attributes userAttributes = ldapContext.getAttributes(userDN);
- Optional<Attribute> userName = Optional.ofNullable(userAttributes.get(ldapConfiguration.getUserIdAttribute()));
- return userName
- .map(Throwing.<Attribute, String>function(u -> u.get().toString()).sneakyThrow())
- .map(Username::of)
- .map(username -> new ReadOnlyLDAPUser(username, userDN, ldapContext));
+ private Optional<ReadOnlyLDAPUser> buildUser(String userDN) throws LDAPException {
+ LDAPConnection connection = ldapConnectionPool.getConnection();
+ try {
+ SearchResultEntry userAttributes = connection.getEntry(userDN);
+ Optional<String> userName = Optional.ofNullable(userAttributes.getAttributeValue(ldapConfiguration.getUserIdAttribute()));
+ return userName
+ .map(Username::of)
+ .map(username -> new ReadOnlyLDAPUser(username, userDN, ldapConnectionPool));
+ } finally {
+ ldapConnectionPool.releaseConnection(connection);
+ }
}
@Override
@@ -342,7 +256,7 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
.map(Throwing.function(this::buildUser).sneakyThrow())
.flatMap(Optional::stream)
.count());
- } catch (NamingException e) {
+ } catch (LDAPException e) {
throw new UsersRepositoryException("Unable to retrieve user count from ldap", e);
}
}
@@ -351,7 +265,7 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
public Optional<User> getUserByName(Username name) throws UsersRepositoryException {
try {
return Optional.ofNullable(searchAndBuildUser(name));
- } catch (NamingException e) {
+ } catch (LDAPException e) {
throw new UsersRepositoryException("Unable to retrieve user from ldap", e);
}
}
@@ -362,19 +276,22 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
return buildUserCollection(getValidUsers())
.stream()
.map(ReadOnlyLDAPUser::getUserName)
- .collect(Guavate.toImmutableList())
.iterator();
- } catch (NamingException namingException) {
+ } catch (LDAPException namingException) {
throw new UsersRepositoryException(
"Unable to retrieve users list from LDAP due to unknown naming error.",
namingException);
}
}
- private Collection<String> getValidUsers() throws NamingException {
- Set<String> userDNs = getAllUsersFromLDAP();
- Collection<String> validUserDNs;
+ private Collection<String> getValidUsers() throws LDAPException {
+ return getAllUsersFromLDAP();
+ /*
+ TODO Implement restrictions
+ */
+ /*
+ Collection<String> validUserDNs;
if (ldapConfiguration.getRestriction().isActivated()) {
Map<String, Collection<String>> groupMembershipList = ldapConfiguration.getRestriction()
.getGroupMembershipLists(ldapContext);
@@ -392,6 +309,7 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO, Configurable {
validUserDNs = userDNs;
}
return validUserDNs;
+ */
}
@Override
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/api/LdapConstants.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/api/LdapConstants.java
deleted file mode 100644
index 1227bca..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/api/LdapConstants.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.api;
-
-/**
- * <code>LdapConstants</code>
- */
-public interface LdapConstants {
-
- // The authentication mechanisms for the provider to use
- String SECURITY_AUTHENTICATION_NONE = "none";
- String SECURITY_AUTHENTICATION_SIMPLE = "simple";
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/DoublingRetrySchedule.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/DoublingRetrySchedule.java
deleted file mode 100644
index f9e435e..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/DoublingRetrySchedule.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry;
-
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-
-
-/**
- * <code>DoublingRetrySchedule</code> is an implementation of <code>RetrySchedule</code> that
- * returns the lesser of an interval that is double the proceeding interval and the maximum interval.
- *
- * <p>When the initial interval is 0, the next interval is 1.
- *
- * <p>A multiplier can be specified to scale the results.
- */
-/**
- * <code>DoublingRetrySchedule</code>
- */
-public class DoublingRetrySchedule implements RetrySchedule {
-
- private long startInterval = 0;
- private long maxInterval = 0;
- private long multiplier = 1;
-
- /**
- * Creates a new instance of DoublingRetrySchedule.
- *
- */
- private DoublingRetrySchedule() {
- }
-
- /**
- * Creates a new instance of DoublingRetrySchedule.
- *
- * @param startInterval
- * The interval for an index of 0
- * @param maxInterval
- * The maximum interval for any index
- */
- public DoublingRetrySchedule(long startInterval, long maxInterval) {
- this(startInterval, maxInterval, 1);
- }
-
- /**
- * Creates a new instance of DoublingRetrySchedule.
- *
- * @param startInterval
- * The interval for an index of 0
- * @param maxInterval
- * The maximum interval for any index
- * @param multiplier
- * The multiplier to apply to the result
- */
- public DoublingRetrySchedule(long startInterval, long maxInterval, int multiplier) {
- this();
- this.startInterval = Math.max(0, startInterval);
- this.maxInterval = Math.max(0, maxInterval);
- this.multiplier = Math.max(1, multiplier);
- }
-
- @Override
- public long getInterval(int index) {
- if (startInterval > 0) {
- return getInterval(index, startInterval);
- }
- return index == 0 ? 0 : getInterval(index - 1, 1);
- }
-
- private long getInterval(int index, long startInterval) {
- return multiplier * Math.min((long) (startInterval * Math.pow(2, index)), maxInterval);
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("DoublingRetrySchedule [startInterval=").append(startInterval).append(
- ", maxInterval=").append(maxInterval).append(", multiplier=").append(multiplier).append("]");
- return builder.toString();
- }
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/ExceptionRetryHandler.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/ExceptionRetryHandler.java
deleted file mode 100644
index 218048b..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/ExceptionRetryHandler.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry;
-
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetryHandler;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-
-/**
- * Abstract class <code>ExceptionRetryHandler</code> retries the behaviour defined in abstract method
- * <code>operation()</code> implemented in a concrete subclass when nominated subclasses of <code>Exception</code>
- * are thrown. The intervals between retries are defined by a <code>RetrySchedule</code>.
- * <p>
- * Concrete subclasses are proxies that forward work via the <code>operation()</code> to a delegate
- * instance for which retry behaviour is required. Both the proxy and the delegate implement the
- * same interfaces.
- * <p>
- * The method stubs required to perform the proxy call via <code>operation()</code> may be generated by many means,
- * including explicit code, a <code>DynamicProxy</code> and compile time aspect injection.
- *
- * @see org.apache.james.user.ldap.retry.naming.RetryingContext
- */
-public abstract class ExceptionRetryHandler implements RetryHandler {
-
- private Class<?>[] exceptionClasses = null;
-
- private ExceptionRetryingProxy proxy = null;
- private RetrySchedule schedule;
- private int maxRetries = 0;
-
- /**
- * Creates a new instance of ExceptionRetryHandler.
- *
- */
- private ExceptionRetryHandler() {
- super();
- }
-
-
- /**
- * Creates a new instance of ExceptionRetryHandler.
- *
- * @param exceptionClasses
- * @param proxy
- * @param maxRetries
- */
- public ExceptionRetryHandler(Class<?>[] exceptionClasses, ExceptionRetryingProxy proxy, RetrySchedule schedule, int maxRetries) {
- this();
- this.exceptionClasses = exceptionClasses;
- this.proxy = proxy;
- this.schedule = schedule;
- this.maxRetries = maxRetries;
- }
-
- @Override
- public Object perform() throws Exception {
- boolean success = false;
- Object result = null;
- int retryCount = 0;
- while (!success) {
- try {
- if (retryCount > 0) {
- proxy.resetDelegate();
- }
- result = operation();
- success = true;
-
- } catch (Exception ex) {
- if (retryCount >= maxRetries || !isRetryable(ex)) {
- throw ex;
- }
- postFailure(ex, retryCount);
- try {
- Thread.sleep(getRetryInterval(retryCount));
- } catch (InterruptedException ex1) {
- // no-op
- }
- retryCount = maxRetries < 0 ? maxRetries
- : retryCount + 1;
- }
- }
- return result;
- }
-
- /**
- * @param ex
- * The <code>Throwable</code> to test
- *
- * @return true if the array of exception classes contains <strong>ex</strong>
- */
- private boolean isRetryable(Throwable ex) {
- boolean isRetryable = false;
- for (int i = 0; !isRetryable && i < exceptionClasses.length; i++) {
- isRetryable = exceptionClasses[i].isInstance(ex);
- }
- return isRetryable;
- }
-
- @Override
- public void postFailure(Exception ex, int retryCount) {
- // no-op
- }
-
- @Override
- public abstract Object operation() throws Exception;
-
- /**
- * @return the retryInterval
- */
- public long getRetryInterval(int retryCount) {
- return schedule.getInterval(retryCount);
- }
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/ExceptionRetryingProxy.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/ExceptionRetryingProxy.java
deleted file mode 100644
index fb41fe9..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/ExceptionRetryingProxy.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.api;
-
-
-/**
- * <code>ExceptionRetryingProxy</code> defines the behaviour for a
- * proxy that can retry <codeException</code> and its subclasses.
- */
-public interface ExceptionRetryingProxy {
- /**
- * @return a new instance that the proxy delegates to
- * @throws Exception
- */
- Object newDelegate() throws Exception;
-
- /**
- * @return the current instance of the proxy delegate
- * @throws Exception
- */
- Object getDelegate();
-
- /**
- * Resets the delegate instance to a state from which it can perform the
- * operations delegated to it.
- *
- * @throws Exception
- */
- void resetDelegate() throws Exception;
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetryHandler.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetryHandler.java
deleted file mode 100644
index 77f7e56..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetryHandler.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.api;
-
-
-/**
- * <code>RetryHandler</code>
- */
-public interface RetryHandler {
-
- /**
- * @return the result of invoking an operation
- * @throws Exception
- */
- Object perform() throws Exception;
-
- /**
- * A hook invoked each time an operation fails if a retry is scheduled
- *
- * @param ex
- * The <code>Exception</code> thrown when the operation was invoked
- * @param retryCount
- * The number of times
- */
- void postFailure(Exception ex, int retryCount);
-
- /**
- * Encapsulates desired behaviour
- * @return The result of performing the behaviour
- * @throws Exception
- */
- Object operation() throws Exception;
-
-}
\ No newline at end of file
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetrySchedule.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetrySchedule.java
deleted file mode 100644
index 6607925..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/api/RetrySchedule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.api;
-
-/**
- * <code>RetrySchedule</code>
- */
-public interface RetrySchedule {
- /**
- * Returns the interval time in milliseconds at the specified zero based index.
- *
- * @param index
- * @return
- */
- long getInterval(int index);
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/LoggingRetryHandler.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/LoggingRetryHandler.java
deleted file mode 100644
index e9af6f4..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/LoggingRetryHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming;
-
-import javax.naming.NamingException;
-
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Abstract class <code>LoggingRetryHandler</code> implements logging of failures
- */
-public abstract class LoggingRetryHandler extends NamingExceptionRetryHandler {
- private static final Logger LOGGER = LoggerFactory.getLogger(LoggingRetryHandler.class);
-
- /**
- * Creates a new instance of LoggingRetryHandler.
- *
- * @param exceptionClasses
- * @param proxy
- * @param maxRetries
- */
- public LoggingRetryHandler(Class<?>[] exceptionClasses, ExceptionRetryingProxy proxy,
- RetrySchedule schedule, int maxRetries) {
- super(exceptionClasses, proxy, schedule, maxRetries);
- }
-
- @Override
- public void postFailure(NamingException ex, int retryCount) {
- super.postFailure(ex, retryCount);
- LOGGER.info("Retry failure. Retrying in {} seconds", getRetryInterval(retryCount) / 1000, ex);
- }
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandler.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandler.java
deleted file mode 100644
index 368b5d2..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandler.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming;
-
-import javax.naming.NamingException;
-
-import org.apache.james.user.ldap.retry.ExceptionRetryHandler;
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-
-/**
- * Abstract class <code>NamingExceptionRetryHandler</code> narrows the set of Exceptions throwable
- * by <code>perform</code> to <code>NamingException</code> and its subclasses.
- * <p><code>RuntimeException</code>s are <strong>not</strong> retried.
- *
- * @see org.apache.james.user.ldap.retry.ExceptionRetryHandler
- *
- */
-public abstract class NamingExceptionRetryHandler extends ExceptionRetryHandler {
-
- /**
- * Creates a new instance of NamingExceptionRetryHandler.
- *
- * @param exceptionClasses
- * @param proxy
- * @param schedule
- * @param maxRetries
- */
- public NamingExceptionRetryHandler(Class<?>[] exceptionClasses, ExceptionRetryingProxy proxy,
- RetrySchedule schedule, int maxRetries) {
- super(exceptionClasses, proxy, schedule, maxRetries);
- }
-
- @Override
- public Object perform() throws NamingException {
- try {
- return super.perform();
- } catch (RuntimeException ex) {
- throw ex;
- } catch (Exception ex) {
- // Should only ever be a NamingException
- throw ((NamingException) ex);
- }
- }
-
- @Override
- public void postFailure(Exception ex, int retryCount) {
- postFailure(((NamingException) ex), retryCount);
- }
-
- public void postFailure(NamingException ex, int retryCount) {
- // no-op
- }
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/RetryingContext.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/RetryingContext.java
deleted file mode 100644
index 65bbd1a..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/RetryingContext.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming;
-
-import java.util.Hashtable;
-
-import javax.naming.Binding;
-import javax.naming.CommunicationException;
-import javax.naming.Context;
-import javax.naming.Name;
-import javax.naming.NameClassPair;
-import javax.naming.NameParser;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.NoInitialContextException;
-import javax.naming.ServiceUnavailableException;
-
-import org.apache.james.user.ldap.retry.ExceptionRetryHandler;
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-
-/**
- * <code>RetryingContext</code> retries the methods defined by <code>javax.naming.Context</code>
- * according to the specified schedule.
- *
- * @see ExceptionRetryHandler
- * @see org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy
- * @see javax.naming.Context
- */
-public abstract class RetryingContext implements Context, ExceptionRetryingProxy {
-
- public static final Class<?>[] DEFAULT_EXCEPTION_CLASSES = new Class<?>[] {
- CommunicationException.class,
- ServiceUnavailableException.class,
- NoInitialContextException.class };
-
- private Context delegate = null;
- private RetrySchedule schedule = null;
- private int maxRetries = 0;
-
- /**
- * Creates a new instance of RetryingContext.
- *
- * @throws NamingException
- *
- */
- private RetryingContext() {
- super();
- }
-
- /**
- * Creates a new instance of RetryingContext using the default exception
- * classes thrown when an external interruption to services on which we
- * depend occurs.
- *
- * @param schedule
- * @param maxRetries
- * @throws NamingException
- */
- public RetryingContext(RetrySchedule schedule, int maxRetries)
- throws NamingException {
- this(DEFAULT_EXCEPTION_CLASSES, schedule, maxRetries);
- }
-
- /**
- * Creates a new instance of RetryingContext.
- *
- * @param exceptionClasses
- * @param schedule
- * @param maxRetries
- * @throws NamingException
- */
- public RetryingContext(Class<?>[] exceptionClasses, RetrySchedule schedule, int maxRetries)
- throws NamingException {
- this();
- this.schedule = schedule;
- this.maxRetries = maxRetries;
- this.delegate = (Context) new LoggingRetryHandler(exceptionClasses, this,
- this.schedule, this.maxRetries) {
-
- @Override
- public Object operation() throws Exception {
- return newDelegate();
- }
- }.perform();
- }
-
- @Override
- public Object addToEnvironment(final String propName, final Object propVal)
- throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().addToEnvironment(propName, propVal);
- }
- }.perform();
- }
-
- @Override
- public void bind(final Name name, final Object obj) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().bind(name, obj);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void bind(final String name, final Object obj) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().bind(name, obj);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void close() throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().close();
- return null;
- }
- }.perform();
- }
-
- @Override
- public Name composeName(final Name name, final Name prefix) throws NamingException {
- return (Name) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().composeName(name, prefix);
- }
- }.perform();
- }
-
- @Override
- public String composeName(final String name, final String prefix) throws NamingException {
- return (String) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().composeName(name, prefix);
- }
- }.perform();
- }
-
- @Override
- public Context createSubcontext(final Name name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public Context newDelegate() throws NamingException {
- return context.createSubcontext(name);
- }
- };
- }
-
- @Override
- public Context createSubcontext(final String name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public Context newDelegate() throws NamingException {
- return context.createSubcontext(name);
- }
- };
- }
-
- @Override
- public void destroySubcontext(final Name name) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().destroySubcontext(name);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void destroySubcontext(final String name) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().destroySubcontext(name);
- return null;
- }
- }.perform();
- }
-
- @Override
- public Hashtable<?, ?> getEnvironment() throws NamingException {
- return (Hashtable<?, ?>) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().getEnvironment();
- }
- }.perform();
- }
-
- @Override
- public String getNameInNamespace() throws NamingException {
- return (String) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().getNameInNamespace();
- }
- }.perform();
- }
-
- @Override
- public NameParser getNameParser(final Name name) throws NamingException {
- return (NameParser) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().getNameParser(name);
- }
- }.perform();
- }
-
- @Override
- public NameParser getNameParser(final String name) throws NamingException {
- return (NameParser) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().getNameParser(name);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<NameClassPair> list(final Name name) throws NamingException {
- return (NamingEnumeration<NameClassPair>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().list(name);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<NameClassPair> list(final String name) throws NamingException {
- return (NamingEnumeration<NameClassPair>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().list(name);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<Binding> listBindings(final Name name) throws NamingException {
- return (NamingEnumeration<Binding>) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES,
- this, schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().listBindings(name);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<Binding> listBindings(final String name) throws NamingException {
- return (NamingEnumeration<Binding>) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES,
- this, schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().listBindings(name);
- }
- }.perform();
- }
-
- @Override
- public Object lookup(final Name name) throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().lookup(name);
- }
- }.perform();
- }
-
- @Override
- public Object lookup(final String name) throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().lookup(name);
- }
- }.perform();
- }
-
- @Override
- public Object lookupLink(final Name name) throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().lookupLink(name);
- }
- }.perform();
- }
-
- @Override
- public Object lookupLink(final String name) throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().lookupLink(name);
- }
- }.perform();
- }
-
- @Override
- public void rebind(final Name name, final Object obj) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().rebind(name, obj);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void rebind(final String name, final Object obj) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().rebind(name, obj);
- return null;
- }
- }.perform();
- }
-
- @Override
- public Object removeFromEnvironment(final String propName) throws NamingException {
- return new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- return getDelegate().removeFromEnvironment(propName);
- }
- }.perform();
- }
-
- @Override
- public void rename(final Name oldName, final Name newName) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().rename(oldName, newName);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void rename(final String oldName, final String newName) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().rename(oldName, newName);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void unbind(final Name name) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries
- ) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().unbind(name);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void unbind(final String name) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, schedule, maxRetries) {
-
- @Override
- public Object operation() throws NamingException {
- getDelegate().unbind(name);
- return null;
- }
- }.perform();
- }
-
- @Override
- public Context getDelegate() {
- return delegate;
- }
-
-
- @Override
- public void resetDelegate() throws Exception {
- if (null != delegate) {
- delegate.close();
- }
- delegate = (Context)newDelegate();
- }
-
- /**
- * @return the schedule
- */
- public RetrySchedule getSchedule() {
- return schedule;
- }
-
- /**
- * @return the maxRetries
- */
- public int getMaxRetries() {
- return maxRetries;
- }
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/directory/RetryingDirContext.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/directory/RetryingDirContext.java
deleted file mode 100644
index 72c1679..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/directory/RetryingDirContext.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming.directory;
-
-import javax.naming.Context;
-import javax.naming.Name;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.ModificationItem;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-
-import org.apache.james.user.ldap.retry.ExceptionRetryHandler;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.apache.james.user.ldap.retry.naming.LoggingRetryHandler;
-import org.apache.james.user.ldap.retry.naming.RetryingContext;
-
-/**
- * <code>RetryingDirContext</code> retries the methods defined by <code>javax.naming.directory.DirContext</code>
- * according to the specified schedule.
- *
- * @see ExceptionRetryHandler
- * @see org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy
- * @see javax.naming.directory.DirContext
- */
-public abstract class RetryingDirContext extends RetryingContext implements DirContext {
-
-
- /**
- * Creates a new instance of RetryingDirContext.
- *
- * @param schedule
- * @param maxRetries
- * @throws NamingException
- */
- public RetryingDirContext(RetrySchedule schedule, int maxRetries)
- throws NamingException {
- super(schedule, maxRetries);
- }
-
- @Override
- public void bind(final Name name, final Object obj, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).bind(name, obj, attrs);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void bind(final String name, final Object obj, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).bind(name, obj, attrs);
- return null;
- }
- }.perform();
- }
-
- @Override
- public DirContext createSubcontext(final Name name, final Attributes attrs)
- throws NamingException {
- return (DirContext) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).createSubcontext(name, attrs);
- }
- }.perform();
- }
-
- @Override
- public DirContext createSubcontext(final String name, final Attributes attrs)
- throws NamingException {
- return (DirContext) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).createSubcontext(name, attrs);
- }
- }.perform();
- }
-
- @Override
- public Attributes getAttributes(final Name name) throws NamingException {
- return (Attributes) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).getAttributes(name);
- }
- }.perform();
- }
-
- @Override
- public Attributes getAttributes(final String name) throws NamingException {
- return (Attributes) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).getAttributes(name);
- }
- }.perform();
- }
-
- @Override
- public Attributes getAttributes(final Name name, final String[] attrIds) throws NamingException {
- return (Attributes) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).getAttributes(name, attrIds);
- }
- }.perform();
- }
-
- @Override
- public Attributes getAttributes(final String name, final String[] attrIds)
- throws NamingException {
- return (Attributes) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this,
- getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).getAttributes(name, attrIds);
- }
- }.perform();
- }
-
- @Override
- public DirContext getSchema(final Name name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingDirContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public DirContext newDelegate() throws NamingException {
- return ((DirContext) context).getSchema(name);
- }
- };
- }
-
- @Override
- public DirContext getSchema(final String name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingDirContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public DirContext newDelegate() throws NamingException {
- return ((DirContext) context).getSchema(name);
- }
- };
- }
-
- @Override
- public DirContext getSchemaClassDefinition(final Name name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingDirContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public DirContext newDelegate() throws NamingException {
- return ((DirContext) context).getSchemaClassDefinition(name);
- }
- };
- }
-
- @Override
- public DirContext getSchemaClassDefinition(final String name) throws NamingException {
- final Context context = getDelegate();
- return new RetryingDirContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public DirContext newDelegate() throws NamingException {
- return ((DirContext) context).getSchemaClassDefinition(name);
- }
- };
- }
-
- @Override
- public void modifyAttributes(final Name name, final ModificationItem[] mods)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).modifyAttributes(name, mods);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void modifyAttributes(final String name, final ModificationItem[] mods)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).modifyAttributes(name, mods);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void modifyAttributes(final Name name, final int modOp, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).modifyAttributes(name, modOp, attrs);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void modifyAttributes(final String name, final int modOp, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).modifyAttributes(name, modOp, attrs);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void rebind(final Name name, final Object obj, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).rebind(name, obj, attrs);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void rebind(final String name, final Object obj, final Attributes attrs)
- throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- ((DirContext) getDelegate()).rebind(name, obj, attrs);
- return null;
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final Name name,
- final Attributes matchingAttributes)
- throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, matchingAttributes);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final String name,
- final Attributes matchingAttributes)
- throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, matchingAttributes);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final Name name,
- final Attributes matchingAttributes,
- String[] attributesToReturn) throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, matchingAttributes);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final String name,
- final Attributes matchingAttributes,
- final String[] attributesToReturn) throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, matchingAttributes,
- attributesToReturn);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final Name name, final String filter,
- final SearchControls cons)
- throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, filter, cons);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final String name, final String filter,
- final SearchControls cons)
- throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, filter, cons);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final Name name, final String filterExpr,
- final Object[] filterArgs, final SearchControls cons) throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, filterExpr, filterArgs, cons);
- }
- }.perform();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public NamingEnumeration<SearchResult> search(final String name, final String filterExpr,
- final Object[] filterArgs, final SearchControls cons) throws NamingException {
- return (NamingEnumeration<SearchResult>) new LoggingRetryHandler(
- DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
-
- @Override
- public Object operation() throws NamingException {
- return ((DirContext) getDelegate()).search(name, filterExpr, filterArgs, cons);
- }
- }.perform();
- }
-
-}
diff --git a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/ldap/RetryingLdapContext.java b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/ldap/RetryingLdapContext.java
deleted file mode 100644
index 0355c09..0000000
--- a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/retry/naming/ldap/RetryingLdapContext.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming.ldap;
-
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.ldap.Control;
-import javax.naming.ldap.ExtendedRequest;
-import javax.naming.ldap.ExtendedResponse;
-import javax.naming.ldap.LdapContext;
-
-import org.apache.james.user.ldap.retry.ExceptionRetryHandler;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.apache.james.user.ldap.retry.naming.LoggingRetryHandler;
-import org.apache.james.user.ldap.retry.naming.directory.RetryingDirContext;
-
-/**
- * <code>RetryingLdapContext</code> retries the methods defined by <code>javax.naming.ldap.LdapContext</code>
- * according to the specified schedule.
- *
- * @see ExceptionRetryHandler
- * @see org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy
- * @see javax.naming.ldap.LdapContext
- */
-public abstract class RetryingLdapContext extends RetryingDirContext implements LdapContext {
-
- /**
- * Creates a new instance of RetryingLdapContext.
- *
- * @param maxRetries
- * @throws NamingException
- */
- public RetryingLdapContext(RetrySchedule schedule, int maxRetries) throws NamingException {
- super(schedule, maxRetries);
- }
-
- @Override
- public ExtendedResponse extendedOperation(final ExtendedRequest request) throws NamingException {
- return (ExtendedResponse) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- return ((LdapContext) getDelegate()).extendedOperation(request);
- }
- }.perform();
- }
-
- @Override
- public Control[] getConnectControls() throws NamingException {
- return (Control[]) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- return ((LdapContext) getDelegate()).getConnectControls();
- }
- }.perform();
- }
-
- @Override
- public Control[] getRequestControls() throws NamingException {
- return (Control[]) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- return ((LdapContext) getDelegate()).getRequestControls();
- }
- }.perform();
- }
-
- @Override
- public Control[] getResponseControls() throws NamingException {
- return (Control[]) new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- return ((LdapContext) getDelegate()).getResponseControls();
- }
- }.perform();
- }
-
- @Override
- public LdapContext newInstance(final Control[] requestControls) throws NamingException {
- final Context context = getDelegate();
- return new RetryingLdapContext(getSchedule(), getMaxRetries()) {
-
- @Override
- public Context newDelegate() throws NamingException {
- return ((LdapContext) context).newInstance(requestControls);
- }
- };
- }
-
- @Override
- public void reconnect(final Control[] connCtls) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- ((LdapContext) getDelegate()).reconnect(connCtls);
- return null;
- }
- }.perform();
- }
-
- @Override
- public void setRequestControls(final Control[] requestControls) throws NamingException {
- new LoggingRetryHandler(DEFAULT_EXCEPTION_CLASSES, this, getSchedule(), getMaxRetries()) {
- @Override
- public Object operation() throws NamingException {
- ((LdapContext) getDelegate()).setRequestControls(requestControls);
- return null;
- }
- }.perform();
- }
-
-}
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/DoublingRetryScheduleTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/DoublingRetryScheduleTest.java
deleted file mode 100644
index 7ec732c..0000000
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/DoublingRetryScheduleTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.junit.jupiter.api.Test;
-
-class DoublingRetryScheduleTest {
-
- @Test
- void testDoublingRetrySchedule() {
- assertThat(RetrySchedule.class.isAssignableFrom(DoublingRetrySchedule.class)).isTrue();
- assertThat(new DoublingRetrySchedule(0, 0).getInterval(0)).isEqualTo(0);
- assertThat(new DoublingRetrySchedule(-1, -1).getInterval(0)).isEqualTo(0);
- assertThat(new DoublingRetrySchedule(-1, 0).getInterval(0)).isEqualTo(0);
- assertThat(new DoublingRetrySchedule(0, -1).getInterval(0)).isEqualTo(0);
- }
-
- @Test
- void testGetInterval() {
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(0)).isEqualTo(0);
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(1)).isEqualTo(1);
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(2)).isEqualTo(2);
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(3)).isEqualTo(4);
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(4)).isEqualTo(8);
- assertThat(new DoublingRetrySchedule(0, 8).getInterval(5)).isEqualTo(8);
-
- assertThat(new DoublingRetrySchedule(1, 8).getInterval(0)).isEqualTo(1);
- assertThat(new DoublingRetrySchedule(1, 8).getInterval(1)).isEqualTo(2);
- assertThat(new DoublingRetrySchedule(1, 8).getInterval(2)).isEqualTo(4);
- assertThat(new DoublingRetrySchedule(1, 8).getInterval(3)).isEqualTo(8);
- assertThat(new DoublingRetrySchedule(1, 8).getInterval(4)).isEqualTo(8);
-
- assertThat(new DoublingRetrySchedule(3, 12).getInterval(0)).isEqualTo(3);
- assertThat(new DoublingRetrySchedule(3, 12).getInterval(1)).isEqualTo(6);
- assertThat(new DoublingRetrySchedule(3, 12).getInterval(2)).isEqualTo(12);
- assertThat(new DoublingRetrySchedule(3, 12).getInterval(3)).isEqualTo(12);
-
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(0)).isEqualTo(0);
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(1)).isEqualTo(1000);
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(2)).isEqualTo(2000);
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(3)).isEqualTo(4000);
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(4)).isEqualTo(8000);
- assertThat(new DoublingRetrySchedule(0, 8, 1000).getInterval(5)).isEqualTo(8000);
- }
-
- @Test
- void testToString() {
- assertThat(new DoublingRetrySchedule(0, 1).toString())
- .isEqualTo("DoublingRetrySchedule [startInterval=0, maxInterval=1, multiplier=1]");
- }
-}
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/ExceptionRetryHandlerTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/ExceptionRetryHandlerTest.java
deleted file mode 100644
index f3d921d..0000000
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/ExceptionRetryHandlerTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.Context;
-
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetryHandler;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-class ExceptionRetryHandlerTest {
- private static class TestRetryingProxy implements ExceptionRetryingProxy {
-
- @Override
- public Context getDelegate() {
- return null;
- }
-
- @Override
- public Context newDelegate() {
- return null;
- }
-
- @Override
- public void resetDelegate() {
- }
- }
-
- private Class<?>[] exceptionClasses = null;
- private ExceptionRetryingProxy proxy = null;
- private RetrySchedule schedule = null;
-
- @BeforeEach
- void setUp() {
- exceptionClasses = new Class<?>[]{Exception.class};
- proxy = new TestRetryingProxy();
- schedule = i -> i;
- }
-
- @Test
- void testExceptionRetryHandler() {
- assertThat(RetryHandler.class.isAssignableFrom(new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return null;
- }
- }.getClass())).isTrue();
- }
-
- @Test
- void testPerform() throws Exception {
- Object result = new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return "Hi!";
- }
- }.perform();
- assertThat(result).isEqualTo("Hi!");
-
- try {
- new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() throws Exception {
- throw new Exception();
- }
- }.perform();
- } catch (Exception ex) {
- // no-op
- }
- assertThat(result).isEqualTo("Hi!");
- }
-
- @Test
- void testPostFailure() {
- final List<Exception> results = new ArrayList<>();
- RetryHandler handler = new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 7) {
-
- @Override
- public void postFailure(Exception ex, int retryCount) {
- super.postFailure(ex, retryCount);
- results.add(ex);
- }
-
- @Override
- public Object operation() throws Exception {
- throw new Exception();
- }
- };
- try {
- handler.perform();
- } catch (Exception ex) {
- // no-op
- }
- assertThat(results.size()).isEqualTo(7);
- }
-
- @Test
- void testOperation() throws Exception {
- RetryHandler handler = new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return "Hi!";
- }
- };
- assertThat(handler.operation()).isEqualTo("Hi!");
- }
-
- @Test
- void testGetRetryInterval() {
- ExceptionRetryHandler handler = new ExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return null;
- }
- };
- assertThat(handler.getRetryInterval(8)).isEqualTo(8);
- }
-}
diff --git a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandlerTest.java b/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandlerTest.java
deleted file mode 100644
index 59c8fb8..0000000
--- a/server/data/data-ldap/src/test/java/org/apache/james/user/ldap/retry/naming/NamingExceptionRetryHandlerTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.james.user.ldap.retry.naming;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import javax.naming.Context;
-import javax.naming.NamingException;
-
-import org.apache.james.user.ldap.retry.api.ExceptionRetryingProxy;
-import org.apache.james.user.ldap.retry.api.RetryHandler;
-import org.apache.james.user.ldap.retry.api.RetrySchedule;
-import org.junit.jupiter.api.Test;
-
-class NamingExceptionRetryHandlerTest {
-
- private static class TestRetryingProxy implements ExceptionRetryingProxy {
- @Override
- public Context getDelegate() {
- return null;
- }
-
- @Override
- public Context newDelegate() {
- return null;
- }
-
- @Override
- public void resetDelegate() {
- }
- }
-
- private static final Class<?>[] exceptionClasses = new Class<?>[]{NamingException.class};
- private static final ExceptionRetryingProxy proxy = new TestRetryingProxy();
- private static final RetrySchedule schedule = i -> i;
-
- @Test
- void testExceptionRetryHandler() {
- assertThat(RetryHandler.class.isAssignableFrom(new NamingExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return null;
- }
- }.getClass())).isTrue();
- }
-
- @Test
- void testPerform() throws NamingException {
- Object result = new NamingExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() {
- return "Hi!";
- }
- }.perform();
- assertThat(result).isEqualTo("Hi!");
-
- try {
- new NamingExceptionRetryHandler(
- exceptionClasses, proxy, schedule, 0) {
-
- @Override
- public Object operation() throws Exception {
- throw new NamingException();
- }
- }.perform();
- } catch (NamingException ex) {
- // no-op
- }
- assertThat(result).isEqualTo("Hi!");
- }
-}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org