From 288851e601ed14742b0ba0bfbc54a2846c2017b4 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Wed, 16 Dec 2009 22:56:49 +0000
Subject: [PATCH] Consolidate various utility factories into Connections class.
---
sdk/src/org/opends/sdk/ConnectionPool.java | 7
sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java | 34 +-
sdk/src/org/opends/sdk/Connections.java | 176 ++++++++++++++++
sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java | 394 +++++++++++++++++++++++++++++++++++
4 files changed, 590 insertions(+), 21 deletions(-)
diff --git a/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java b/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
new file mode 100644
index 0000000..329715a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
@@ -0,0 +1,394 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.Collection;
+
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.CompareResult;
+import org.opends.sdk.responses.Result;
+import org.opends.sdk.responses.SearchResultEntry;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.FutureResultTransformer;
+import com.sun.opends.sdk.util.RecursiveFutureResult;
+
+
+
+/**
+ * An authenticated connection factory can be used to create
+ * pre-authenticated connections to a Directory Server.
+ * <p>
+ * The connections returned by an authenticated connection factory
+ * support all operations with the exception of Bind requests. Attempts
+ * to perform a Bind will result in an {@code
+ * UnsupportedOperationException}.
+ * <p>
+ * If the Bind request fails for some reason (e.g. invalid credentials),
+ * then the connection attempt will fail and an {@code
+ * ErrorResultException} will be thrown.
+ */
+final class AuthenticatedConnectionFactory extends
+ AbstractConnectionFactory<AsynchronousConnection>
+{
+
+ private final BindRequest request;
+
+ private final ConnectionFactory<?> parentFactory;
+
+
+
+ /**
+ * Creates a new authenticated connection factory which will obtain
+ * connections using the provided connection factory and immediately
+ * perform the provided Bind request.
+ *
+ * @param factory
+ * The connection factory to use for connecting to the
+ * Directory Server.
+ * @param request
+ * The Bind request to use for authentication.
+ */
+ AuthenticatedConnectionFactory(ConnectionFactory<?> factory,
+ BindRequest request) throws NullPointerException
+ {
+ this.parentFactory = factory;
+
+ // FIXME: should do a defensive copy.
+ this.request = request;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+ ResultHandler<? super AsynchronousConnection> handler)
+ {
+ FutureResultImpl future = new FutureResultImpl(request, handler);
+ future.futureConnectionResult.setFutureResult(parentFactory
+ .getAsynchronousConnection(future.futureConnectionResult));
+ return future.futureBindResult;
+ }
+
+
+
+ /**
+ * An authenticated asynchronous connection supports all operations
+ * except Bind operations.
+ */
+ public static final class AuthenticatedAsynchronousConnection
+ implements AsynchronousConnection
+ {
+
+ private final AsynchronousConnection connection;
+
+
+
+ private AuthenticatedAsynchronousConnection(
+ AsynchronousConnection connection)
+ {
+ this.connection = connection;
+ }
+
+
+
+ public void abandon(AbandonRequest request)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ connection.abandon(request);
+ }
+
+
+
+ public FutureResult<Result> add(AddRequest request,
+ ResultHandler<Result> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.add(request, handler);
+ }
+
+
+
+ public void addConnectionEventListener(
+ ConnectionEventListener listener) throws IllegalStateException,
+ NullPointerException
+ {
+ connection.addConnectionEventListener(listener);
+ }
+
+
+
+ /**
+ * Bind operations are not supported by pre-authenticated
+ * connections. This method will always throw {@code
+ * UnsupportedOperationException}.
+ */
+ public FutureResult<BindResult> bind(BindRequest request,
+ ResultHandler<? super BindResult> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ public void close()
+ {
+ connection.close();
+ }
+
+
+
+ public void close(UnbindRequest request, String reason)
+ throws NullPointerException
+ {
+ connection.close(request, reason);
+ }
+
+
+
+ public FutureResult<CompareResult> compare(CompareRequest request,
+ ResultHandler<? super CompareResult> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.compare(request, handler);
+ }
+
+
+
+ public FutureResult<Result> delete(DeleteRequest request,
+ ResultHandler<Result> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.delete(request, handler);
+ }
+
+
+
+ public <R extends Result> FutureResult<R> extendedRequest(
+ ExtendedRequest<R> request, ResultHandler<? super R> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.extendedRequest(request, handler);
+ }
+
+
+
+ public FutureResult<Result> modify(ModifyRequest request,
+ ResultHandler<Result> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.modify(request, handler);
+ }
+
+
+
+ public FutureResult<Result> modifyDN(ModifyDNRequest request,
+ ResultHandler<Result> handler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.modifyDN(request, handler);
+ }
+
+
+
+ public void removeConnectionEventListener(
+ ConnectionEventListener listener) throws NullPointerException
+ {
+ connection.removeConnectionEventListener(listener);
+ }
+
+
+
+ public FutureResult<Result> search(SearchRequest request,
+ ResultHandler<Result> resultHandler,
+ SearchResultHandler searchResulthandler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.search(request, resultHandler,
+ searchResulthandler);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isClosed()
+ {
+ return connection.isClosed();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<RootDSE> readRootDSE(
+ ResultHandler<RootDSE> handler)
+ throws UnsupportedOperationException, IllegalStateException
+ {
+ return connection.readRootDSE(handler);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<SearchResultEntry> readEntry(DN name,
+ Collection<String> attributeDescriptions,
+ ResultHandler<? super SearchResultEntry> resultHandler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.readEntry(name, attributeDescriptions,
+ resultHandler);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<SearchResultEntry> searchSingleEntry(
+ SearchRequest request,
+ ResultHandler<? super SearchResultEntry> resultHandler)
+ throws UnsupportedOperationException, IllegalStateException,
+ NullPointerException
+ {
+ return connection.searchSingleEntry(request, resultHandler);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<Schema> readSchemaForEntry(DN name,
+ ResultHandler<Schema> handler)
+ throws UnsupportedOperationException, IllegalStateException
+ {
+ return connection.readSchemaForEntry(name, handler);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public FutureResult<Schema> readSchema(DN name,
+ ResultHandler<Schema> handler)
+ throws UnsupportedOperationException, IllegalStateException
+ {
+ return connection.readSchema(name, handler);
+ }
+
+ }
+
+
+
+ private static final class FutureResultImpl
+ {
+ private final FutureResultTransformer<BindResult, AsynchronousConnection> futureBindResult;
+
+ private final RecursiveFutureResult<AsynchronousConnection, BindResult> futureConnectionResult;
+
+ private final BindRequest bindRequest;
+
+ private AsynchronousConnection connection;
+
+
+
+ private FutureResultImpl(BindRequest request,
+ ResultHandler<? super AsynchronousConnection> handler)
+ {
+ this.bindRequest = request;
+ this.futureBindResult = new FutureResultTransformer<BindResult, AsynchronousConnection>(
+ handler)
+ {
+
+ protected ErrorResultException transformErrorResult(
+ ErrorResultException errorResult)
+ {
+ // Ensure that the connection is closed.
+ try
+ {
+ connection.close();
+ connection = null;
+ }
+ catch (Exception e)
+ {
+ // Ignore.
+ }
+ return errorResult;
+ }
+
+
+
+ protected AsynchronousConnection transformResult(
+ BindResult result) throws ErrorResultException
+ {
+ // FIXME: should make the result unmodifiable.
+ return new AuthenticatedAsynchronousConnection(connection);
+ }
+
+ };
+ this.futureConnectionResult = new RecursiveFutureResult<AsynchronousConnection, BindResult>(
+ futureBindResult)
+ {
+
+ protected FutureResult<? extends BindResult> chainResult(
+ AsynchronousConnection innerResult,
+ ResultHandler<? super BindResult> handler)
+ throws ErrorResultException
+ {
+ connection = innerResult;
+ return connection.bind(bindRequest, handler);
+ }
+ };
+ futureBindResult.setFutureResult(futureConnectionResult);
+ }
+
+ }
+
+}
diff --git a/sdk/src/org/opends/sdk/ConnectionPool.java b/sdk/src/org/opends/sdk/ConnectionPool.java
index e002423..dc22fae 100644
--- a/sdk/src/org/opends/sdk/ConnectionPool.java
+++ b/sdk/src/org/opends/sdk/ConnectionPool.java
@@ -48,7 +48,7 @@
/**
* A simple connection pool implementation.
*/
-public final class ConnectionPool extends
+final class ConnectionPool extends
AbstractConnectionFactory<AsynchronousConnection>
{
private final ConnectionFactory<?> connectionFactory;
@@ -499,15 +499,14 @@
/**
* Creates a new connection pool which will maintain {@code poolSize}
* connections created using the provided connection factory.
- *
+ *
* @param connectionFactory
* The connection factory to use for creating new
* connections.
* @param poolSize
* The maximum size of the connection pool.
*/
- public ConnectionPool(ConnectionFactory<?> connectionFactory,
- int poolSize)
+ ConnectionPool(ConnectionFactory<?> connectionFactory, int poolSize)
{
this.connectionFactory = connectionFactory;
this.poolSize = poolSize;
diff --git a/sdk/src/org/opends/sdk/Connections.java b/sdk/src/org/opends/sdk/Connections.java
new file mode 100644
index 0000000..4c95187
--- /dev/null
+++ b/sdk/src/org/opends/sdk/Connections.java
@@ -0,0 +1,176 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.opends.sdk.requests.BindRequest;
+import org.opends.sdk.requests.SearchRequest;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * This class contains methods for creating and manipulating connection
+ * factories and connections.
+ */
+public final class Connections
+{
+ // Prevent instantiation.
+ private Connections()
+ {
+ // Do nothing.
+ }
+
+
+
+ /**
+ * Creates a new authenticated connection factory which will obtain
+ * connections using the provided connection factory and immediately
+ * perform the provided Bind request.
+ * <p>
+ * The connections returned by an authenticated connection factory
+ * support all operations with the exception of Bind requests.
+ * Attempts to perform a Bind will result in an {@code
+ * UnsupportedOperationException}.
+ * <p>
+ * If the Bind request fails for some reason (e.g. invalid
+ * credentials), then the connection attempt will fail and an {@code
+ * ErrorResultException} will be thrown.
+ *
+ * @param factory
+ * The connection factory to use for connecting to the
+ * Directory Server.
+ * @param request
+ * The Bind request to use for authentication.
+ * @return The new connection pool.
+ * @throws NullPointerException
+ * If {@code factory} or {@code request} was {@code null}.
+ */
+ public static ConnectionFactory<AsynchronousConnection> newAuthenticatedConnectionFactory(
+ ConnectionFactory<?> factory, BindRequest request)
+ throws NullPointerException
+ {
+ Validator.ensureNotNull(factory, request);
+
+ return new AuthenticatedConnectionFactory(factory, request);
+ }
+
+
+
+ /**
+ * Creates a new connection pool which will maintain {@code poolSize}
+ * connections created using the provided connection factory.
+ *
+ * @param factory
+ * The connection factory to use for creating new
+ * connections.
+ * @param poolSize
+ * The maximum size of the connection pool.
+ * @return The new connection pool.
+ * @throws IllegalArgumentException
+ * If {@code poolSize} is negative.
+ * @throws NullPointerException
+ * If {@code factory} was {@code null}.
+ */
+ public static ConnectionFactory<AsynchronousConnection> newConnectionPool(
+ ConnectionFactory<?> factory, int poolSize)
+ throws IllegalArgumentException, NullPointerException
+ {
+ Validator.ensureNotNull(factory);
+ Validator.ensureTrue(poolSize >= 0, "negative pool size");
+ return new ConnectionPool(factory, poolSize);
+ }
+
+
+
+ /**
+ * Creates a new heart-beat connection factory which will create
+ * connections using the provided connection factory and periodically
+ * ping any created connections in order to detect that they are still
+ * alive.
+ *
+ * @param factory
+ * The connection factory to use for creating connections.
+ * @param timeout
+ * The time to wait between keepalive pings.
+ * @param unit
+ * The time unit of the timeout argument.
+ * @return The heart-beat connection factory.
+ * @throws IllegalArgumentException
+ * If {@code timeout} was negative.
+ * @throws NullPointerException
+ * If {@code factory} or {@code unit} was {@code null}.
+ */
+ public static ConnectionFactory<AsynchronousConnection> newHeartBeatConnectionFactory(
+ ConnectionFactory<?> factory, long timeout, TimeUnit unit)
+ {
+ Validator.ensureNotNull(factory, unit);
+ Validator.ensureTrue(timeout >= 0, "negative timeout");
+
+ return new HeartBeatConnectionFactory(factory, timeout, unit);
+ }
+
+
+
+ /**
+ * Creates a new heart-beat connection factory which will create
+ * connections using the provided connection factory and periodically
+ * ping any created connections using the specified search request in
+ * order to detect that they are still alive.
+ *
+ * @param factory
+ * The connection factory to use for creating connections.
+ * @param timeout
+ * The time to wait between keepalive pings.
+ * @param unit
+ * The time unit of the timeout argument.
+ * @param heartBeat
+ * The search request to use when pinging connections.
+ * @return The heart-beat connection factory.
+ * @throws IllegalArgumentException
+ * If {@code timeout} was negative.
+ * @throws NullPointerException
+ * If {@code factory}, {@code unit}, or {@code heartBeat}
+ * was {@code null}.
+ */
+ public static ConnectionFactory<AsynchronousConnection> newHeartBeatConnectionFactory(
+ ConnectionFactory<?> factory, long timeout, TimeUnit unit,
+ SearchRequest heartBeat) throws NullPointerException
+ {
+ Validator.ensureNotNull(factory, unit, heartBeat);
+ Validator.ensureTrue(timeout >= 0, "negative timeout");
+
+ return new HeartBeatConnectionFactory(factory, timeout, unit,
+ heartBeat);
+ }
+
+}
diff --git a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
index d917444..285633c 100644
--- a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
@@ -32,13 +32,13 @@
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.opends.sdk.requests.*;
import org.opends.sdk.responses.*;
import org.opends.sdk.schema.Schema;
import com.sun.opends.sdk.util.FutureResultTransformer;
-import com.sun.opends.sdk.util.Validator;
@@ -46,12 +46,12 @@
* An heart beat connection factory can be used to create connections
* that sends a periodic search request to a Directory Server.
*/
-public class HeartBeatConnectionFactory extends
+final class HeartBeatConnectionFactory extends
AbstractConnectionFactory<AsynchronousConnection>
{
private final SearchRequest heartBeat;
- private final int interval;
+ private final long interval;
private final List<AsynchronousConnectionImpl> activeConnections;
@@ -63,8 +63,6 @@
// FIXME: use a single global scheduler?
- // FIXME: change timeout parameters to long+TimeUnit.
-
/**
* Creates a new heart-beat connection factory which will create
* connections using the provided connection factory and periodically
@@ -73,13 +71,15 @@
*
* @param connectionFactory
* The connection factory to use for creating connections.
- * @param interval
- * The period between keepalive pings.
+ * @param timeout
+ * The time to wait between keepalive pings.
+ * @param unit
+ * The time unit of the timeout argument.
*/
- public HeartBeatConnectionFactory(
- ConnectionFactory<?> connectionFactory, int interval)
+ HeartBeatConnectionFactory(ConnectionFactory<?> connectionFactory,
+ long timeout, TimeUnit unit)
{
- this(connectionFactory, DEFAULT_SEARCH, interval);
+ this(connectionFactory, timeout, unit, DEFAULT_SEARCH);
}
@@ -98,18 +98,18 @@
*
* @param connectionFactory
* The connection factory to use for creating connections.
+ * @param timeout
+ * The time to wait between keepalive pings.
+ * @param unit
+ * The time unit of the timeout argument.
* @param heartBeat
* The search request to use when pinging connections.
- * @param interval
- * The period between keepalive pings.
*/
- public HeartBeatConnectionFactory(
- ConnectionFactory<?> connectionFactory, SearchRequest heartBeat,
- int interval)
+ HeartBeatConnectionFactory(ConnectionFactory<?> connectionFactory,
+ long timeout, TimeUnit unit, SearchRequest heartBeat)
{
- Validator.ensureNotNull(connectionFactory, heartBeat);
this.heartBeat = heartBeat;
- this.interval = interval;
+ this.interval = unit.toMillis(timeout);
this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
this.parentFactory = connectionFactory;
--
Gitblit v1.10.0