opendj3/opendj-ldap-sdk/pom.xml
@@ -46,7 +46,7 @@ <dependency> <groupId>org.glassfish.grizzly</groupId> <artifactId>grizzly-framework</artifactId> <version>2.1.9</version> <version>${grizzlyFrameworkVersion}</version> <scope>compile</scope> </dependency> <dependency> opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/ConnectionSecurityLayerFilter.java
@@ -49,11 +49,10 @@ private static final int BUFFER_SIZE = 4096; private final byte[] buffer = new byte[BUFFER_SIZE]; private final ConnectionSecurityLayer layer; private final MemoryManager<?> memoryManager; public Decoder(final ConnectionSecurityLayer layer, final MemoryManager<?> memoryManager) { this.layer = layer; this.memoryManager = memoryManager; setMemoryManager(memoryManager); } public String getName() { @@ -67,7 +66,7 @@ @Override public TransformationResult<Buffer, Buffer> transformImpl(final AttributeStorage storage, final Buffer input) { final MemoryManager<?> memoryManager = obtainMemoryManager(storage); final int len = Math.min(buffer.length, input.remaining()); input.get(buffer, 0, len); @@ -89,11 +88,10 @@ private static final int BUFFER_SIZE = 4096; private final byte[] buffer = new byte[BUFFER_SIZE]; private final ConnectionSecurityLayer layer; private final MemoryManager<?> memoryManager; private Encoder(final ConnectionSecurityLayer layer, final MemoryManager<?> memoryManager) { this.layer = layer; this.memoryManager = memoryManager; setMemoryManager(memoryManager); } public String getName() { @@ -107,7 +105,7 @@ @Override public TransformationResult<Buffer, Buffer> transformImpl(final AttributeStorage storage, final Buffer input) { final MemoryManager<?> memoryManager = obtainMemoryManager(storage); final int len = Math.min(buffer.length, input.remaining()); input.get(buffer, 0, len); opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPClientFilter.java
@@ -157,8 +157,7 @@ bindClient.getConnectionSecurityLayer(); if (l != null) { // The connection needs to be secured by // the SASL // mechanism. // the SASL mechanism. ldapConnection .installFilter(new ConnectionSecurityLayerFilter(l, ctx.getConnection().getTransport() @@ -451,8 +450,7 @@ final Connection<?> connection = ctx.getConnection(); if (!connection.isOpen()) { // Grizzly doens't not deregister the read interest from the // selector so closing the connection results in an // EOFException. // selector so closing the connection results in an EOFException. // Just ignore errors on closed connections. return; } opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnection.java
@@ -139,10 +139,8 @@ if (pendingRequest == null) { // There has never been a request with the specified message ID or // the // response has already been received and handled. We can ignore // this // abandon request. // the response has already been received and handled. We can ignore // this abandon request. // Message ID will be -1 since no request was sent. return new CompletedFutureResult<Void>((Void) null); @@ -280,8 +278,7 @@ final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter(); try { // Use the bind client to get the initial request instead of // using the // bind request passed to this method. // using the bind request passed to this method. final GenericBindRequest initialRequest = context.nextBindRequest(); ldapWriter.bindRequest(asn1Writer, messageID, 3, initialRequest); connection.write(asn1Writer.getBuffer(), null); @@ -723,15 +720,11 @@ connectionInvalidReason = reason; } else { // Connection termination was triggered remotely. We don't want // to // blindly pass on the result code to requests since it could be // confused for a genuine response. For example, if the // disconnect // contained the invalidCredentials result code then this could // be // misinterpreted as a genuine authentication failure for // subsequent // bind requests. // to blindly pass on the result code to requests since it could // be confused for a genuine response. For example, if the // disconnect contained the invalidCredentials result code then // this could be misinterpreted as a genuine authentication // failure for subsequent bind requests. connectionInvalidReason = Responses.newResult(ResultCode.CLIENT_SIDE_SERVER_DOWN) .setDiagnosticMessage("Connection closed by server"); @@ -762,12 +755,7 @@ // Underlying channel prob blown up. Just ignore. } } try { connection.close(); } catch (final IOException e) { // Ignore. } connection.closeSilently(); // Notify listeners. if (notifyClose) { @@ -817,8 +805,7 @@ int filterIndex = oldFilterChain.size() - 1; if (filter instanceof SSLFilter) { // Beneath any ConnectionSecurityLayerFilters if present, // otherwise // beneath the LDAP filter. // otherwise beneath the LDAP filter. for (int i = oldFilterChain.size() - 2; i >= 0; i--) { if (!(oldFilterChain.get(i) instanceof ConnectionSecurityLayerFilter)) { filterIndex = i + 1; opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPConnectionFactoryImpl.java
@@ -45,7 +45,6 @@ import org.forgerock.opendj.ldap.requests.Requests; import org.forgerock.opendj.ldap.requests.StartTLSExtendedRequest; import org.forgerock.opendj.ldap.responses.ExtendedResult; import org.forgerock.opendj.ldap.responses.Result; import org.glassfish.grizzly.CompletionHandler; import org.glassfish.grizzly.EmptyCompletionHandler; import org.glassfish.grizzly.filterchain.FilterChain; @@ -53,144 +52,142 @@ import org.glassfish.grizzly.filterchain.TransportFilter; import org.glassfish.grizzly.nio.transport.TCPNIOTransport; import com.forgerock.opendj.util.CompletedFutureResult; import com.forgerock.opendj.util.FutureResultTransformer; import com.forgerock.opendj.util.RecursiveFutureResult; import com.forgerock.opendj.util.AsynchronousFutureResult; /** * LDAP connection factory implementation. */ public final class LDAPConnectionFactoryImpl implements ConnectionFactory { @SuppressWarnings("rawtypes") private final class ConnectionCompletionHandler implements CompletionHandler<org.glassfish.grizzly.Connection> { private final FutureResultTransformer<Result, Connection> startTLSFutureResult; private final RecursiveFutureResult<LDAPConnection, ExtendedResult> connectionFutureResult; private LDAPConnection connection; private ConnectionCompletionHandler(final ResultHandler<? super Connection> handler) { this.startTLSFutureResult = new FutureResultTransformer<Result, Connection>(handler) { @Override protected ErrorResultException transformErrorResult( final ErrorResultException errorResult) { // Ensure that the connection is closed. try { if (connection != null) { connection.close(); } } catch (final Exception e) { // Ignore. } return errorResult; } @Override protected LDAPConnection transformResult(final Result result) throws ErrorResultException { return connection; } }; this.connectionFutureResult = new RecursiveFutureResult<LDAPConnection, ExtendedResult>(startTLSFutureResult) { @Override protected FutureResult<? extends ExtendedResult> chainResult( final LDAPConnection innerResult, final ResultHandler<? super ExtendedResult> handler) throws ErrorResultException { connection = innerResult; if (options.getSSLContext() != null && options.useStartTLS()) { // Chain StartTLS extended request. final StartTLSExtendedRequest startTLS = Requests.newStartTLSExtendedRequest(options.getSSLContext()); startTLS.addEnabledCipherSuite(options .getEnabledCipherSuites() .toArray( new String[options.getEnabledCipherSuites().size()])); startTLS.addEnabledProtocol(options.getEnabledProtocols().toArray( new String[options.getEnabledProtocols().size()])); return connection.extendedRequestAsync(startTLS, null, handler); } else if (options.getSSLContext() != null) { // Install SSL/TLS layer. try { connection.startTLS(options.getSSLContext(), options .getEnabledProtocols(), options .getEnabledCipherSuites(), new EmptyCompletionHandler<SSLEngine>() { @Override public void completed(final SSLEngine result) { handler.handleResult(null); } @Override public void failed(final Throwable throwable) { handler.handleErrorResult(newErrorResult( ResultCode.CLIENT_SIDE_CONNECT_ERROR, throwable.getMessage(), throwable)); } }); return null; } catch (final IOException ioe) { throw newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR, ioe .getMessage(), ioe); } } else { // Plain connection. handler.handleResult(null); return new CompletedFutureResult<ExtendedResult>( (ExtendedResult) null); } } }; startTLSFutureResult.setFutureResult(connectionFutureResult); } /** * {@inheritDoc} * Adapts a Grizzly connection completion handler to an LDAP connection * asynchronous future result. */ @Override @SuppressWarnings("rawtypes") private final class CompletionHandlerAdapter implements CompletionHandler<org.glassfish.grizzly.Connection> { private final AsynchronousFutureResult<? super Connection> future; private CompletionHandlerAdapter(final AsynchronousFutureResult<? super Connection> future) { this.future = future; } public void cancelled() { // Ignore this. } /** * {@inheritDoc} */ @Override public void completed(final org.glassfish.grizzly.Connection connection) { connectionFutureResult.handleResult(adaptConnection(connection)); public void completed(final org.glassfish.grizzly.Connection result) { // Adapt the connection. final LDAPConnection connection = adaptConnection(result); // Plain connection. if (options.getSSLContext() == null) { onSuccess(connection); return; } /** * {@inheritDoc} */ // Start TLS or install SSL layer asynchronously. // Give up immediately if the future has been cancelled. if (future.isCancelled()) { connection.close(); return; } if (options.useStartTLS()) { // Chain StartTLS extended request. final StartTLSExtendedRequest startTLS = Requests.newStartTLSExtendedRequest(options.getSSLContext()); startTLS.addEnabledCipherSuite(options.getEnabledCipherSuites().toArray( new String[options.getEnabledCipherSuites().size()])); startTLS.addEnabledProtocol(options.getEnabledProtocols().toArray( new String[options.getEnabledProtocols().size()])); final ResultHandler<ExtendedResult> handler = new ResultHandler<ExtendedResult>() { public void handleErrorResult(final ErrorResultException error) { onFailure(connection, error); } public void handleResult(final ExtendedResult result) { onSuccess(connection); } }; connection.extendedRequestAsync(startTLS, null, handler); } else { // Install SSL/TLS layer. try { connection.startTLS(options.getSSLContext(), options.getEnabledProtocols(), options.getEnabledCipherSuites(), new EmptyCompletionHandler<SSLEngine>() { @Override public void completed(final SSLEngine result) { onSuccess(connection); } @Override public void failed(final Throwable throwable) { connectionFutureResult.handleErrorResult(adaptConnectionException(throwable)); onFailure(connection, throwable); } /** * {@inheritDoc} */ @Override public void updated(final org.glassfish.grizzly.Connection connection) { }); } catch (final IOException e) { onFailure(connection, e); } } } public void failed(final Throwable throwable) { // Adapt and forward. future.handleErrorResult(adaptConnectionException(throwable)); } public void updated(final org.glassfish.grizzly.Connection result) { // Ignore this. } private LDAPConnection adaptConnection(final org.glassfish.grizzly.Connection<?> connection) { // Test shows that its much faster with non block writes but risk // running out of memory if the server is slow. connection.configureBlocking(true); connection.setProcessor(defaultFilterChain); final LDAPConnection ldapConnection = new LDAPConnection(connection, options); clientFilter.registerConnection(connection, ldapConnection); return ldapConnection; } private ErrorResultException adaptConnectionException(Throwable t) { if (t instanceof ExecutionException) { t = t.getCause(); } if (t instanceof ErrorResultException) { return (ErrorResultException) t; } else { return newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR, t.getMessage(), t); } } private void onFailure(final LDAPConnection connection, final Throwable t) { // Abort connection attempt due to error. connection.close(); future.handleErrorResult(adaptConnectionException(t)); } private void onSuccess(final LDAPConnection connection) { future.handleResult(connection); // Close the connection if the future was cancelled. if (future.isCancelled()) { connection.close(); } } }; private final LDAPClientFilter clientFilter; private final FilterChain defaultFilterChain; private final LDAPOptions options; private final SocketAddress socketAddress; private final TCPNIOTransport transport; private final FilterChain defaultFilterChain; private final LDAPClientFilter clientFilter; private final LDAPOptions options; /** * Creates a new LDAP connection factory implementation which can be used to @@ -223,7 +220,7 @@ public Connection getConnection() throws ErrorResultException { try { return getConnectionAsync(null).get(); } catch (InterruptedException e) { } catch (final InterruptedException e) { throw newErrorResult(ResultCode.CLIENT_SIDE_USER_CANCELLED, e); } } @@ -234,14 +231,11 @@ @Override public FutureResult<Connection> getConnectionAsync( final ResultHandler<? super Connection> handler) { final ConnectionCompletionHandler ch = new ConnectionCompletionHandler(handler); try { ch.connectionFutureResult.setFutureResult(transport.connect(socketAddress, ch)); return ch.startTLSFutureResult; } catch (final IOException e) { final ErrorResultException result = adaptConnectionException(e); return new CompletedFutureResult<Connection>(result); } final AsynchronousFutureResult<Connection> future = new AsynchronousFutureResult<Connection>(handler); final CompletionHandlerAdapter cha = new CompletionHandlerAdapter(future); transport.connect(socketAddress, cha); return future; } /** @@ -264,23 +258,4 @@ builder.append(')'); return builder.toString(); } private LDAPConnection adaptConnection(final org.glassfish.grizzly.Connection<?> connection) { // Test shows that its much faster with non block writes but risk // running out of memory if the server is slow. connection.configureBlocking(true); connection.setProcessor(defaultFilterChain); final LDAPConnection ldapConnection = new LDAPConnection(connection, options); clientFilter.registerConnection(connection, ldapConnection); return ldapConnection; } private ErrorResultException adaptConnectionException(Throwable t) { if (t instanceof ExecutionException) { t = t.getCause(); } return newErrorResult(ResultCode.CLIENT_SIDE_CONNECT_ERROR, t.getMessage(), t); } } opendj3/opendj-ldap-sdk/src/main/java/com/forgerock/opendj/ldap/LDAPServerFilter.java
@@ -80,7 +80,6 @@ import org.glassfish.grizzly.ssl.SSLFilter; import org.glassfish.grizzly.ssl.SSLUtils; import com.forgerock.opendj.util.StaticUtils; import com.forgerock.opendj.util.Validator; /** @@ -589,28 +588,21 @@ clientContext.close(); // Notify the server connection: it may be null if disconnect is // invoked // during accept. // invoked during accept. final ServerConnection<Integer> serverConnection = clientContext.getServerConnection(); if (serverConnection != null) { serverConnection.handleConnectionClosed(messageID, unbindRequest); } // If this close was a result of an unbind request then the // connection // won't actually be closed yet. To avoid TIME_WAIT TCP state, let // the // client disconnect. // connection won't actually be closed yet. To avoid TIME_WAIT TCP // state, let the client disconnect. if (unbindRequest != null) { return; } // Close the connection. try { connection.close(); } catch (final IOException e) { StaticUtils.DEBUG_LOG.warning("Error closing connection: " + e); } connection.closeSilently(); } } @@ -622,19 +614,14 @@ clientContext.close(); // Notify the server connection: it may be null if disconnect is // invoked // during accept. // invoked during accept. final ServerConnection<Integer> serverConnection = clientContext.getServerConnection(); if (serverConnection != null) { serverConnection.handleConnectionDisconnected(resultCode, message); } // Close the connection. try { connection.close(); } catch (final IOException e) { StaticUtils.DEBUG_LOG.warning("Error closing connection: " + e); } connection.closeSilently(); } } @@ -646,19 +633,14 @@ clientContext.close(); // Notify the server connection: it may be null if disconnect is // invoked // during accept. // invoked during accept. final ServerConnection<Integer> serverConnection = clientContext.getServerConnection(); if (serverConnection != null) { serverConnection.handleConnectionError(error); } // Close the connection. try { connection.close(); } catch (final IOException e) { StaticUtils.DEBUG_LOG.warning("Error closing connection: " + e); } connection.closeSilently(); } } opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/AuthenticatedConnectionFactory.java
@@ -208,6 +208,8 @@ final StringBuilder builder = new StringBuilder(); builder.append("AuthenticatedConnectionFactory("); builder.append(String.valueOf(parentFactory)); builder.append(", "); builder.append(request); builder.append(')'); return builder.toString(); } opendj3/opendj-ldap-sdk/src/site/xdoc/index.xml.vm
@@ -109,9 +109,7 @@ <ul> <li><a href="http://builds.forgerock.org/view/OpenDJ/job/OpenDJ3/lastStableBuild/org.forgerock.opendj$opendj-ldap-sdk/artifact/org.forgerock.opendj/opendj-ldap-sdk/${currentSDKversion}/opendj-ldap-sdk-${currentSDKversion}.jar">opendj-ldap-sdk-${currentSDKversion}.jar</a> - OpenDJ LDAP SDK</li> <li><a href="http://maven.forgerock.org/repo/releases/org/forgerock/commons/i18n-core/${i18nFrameworkVersion}/i18n-core-${i18nFrameworkVersion}.jar">i18n-core-${i18nFrameworkVersion}.jar</a> - ForgeRock Commons I18N Framework</li> <li><a href="http://search.maven.org/remotecontent?filepath=org/glassfish/grizzly/grizzly-framework/2.1.7/grizzly-framework-2.1.7.jar">grizzly-framework-2.1.7.jar</a> - Grizzly IO Framework</li> <li><a href="http://search.maven.org/remotecontent?filepath=org/glassfish/gmbal/gmbal-api-only/3.0.0-b023/gmbal-api-only-3.0.0-b023.jar">gmbal-api-only-3.0.0-b023.jar</a> - Glassfish Management API</li> <li><a href="http://search.maven.org/remotecontent?filepath=org/glassfish/external/management-api/3.0.0-b012/management-api-3.0.0-b012.jar">management-api-3.0.0-b012.jar</a> - Glassfish Common Management API</li> <li><a href="http://search.maven.org/remotecontent?filepath=org/glassfish/grizzly/grizzly-framework/${grizzlyFrameworkVersion}/grizzly-framework-${grizzlyFrameworkVersion}.jar">grizzly-framework-${grizzlyFrameworkVersion}.jar</a> - Grizzly IO Framework</li> </ul> </subsection> <subsection name="Build"> opendj3/opendj-ldap-sdk/src/test/java/org/forgerock/opendj/ldap/ConnectionFactoryTestCase.java
@@ -163,8 +163,7 @@ // startTLS + SASL confidentiality // Use IP address here so that DIGEST-MD5 host verification works if // local // host name is not localhost (e.g. on some machines it might be // local host name is not localhost (e.g. on some machines it might be // localhost.localdomain). factories[6][0] = new AuthenticatedConnectionFactory(new LDAPConnectionFactory(new InetSocketAddress( @@ -291,8 +290,7 @@ @Test(enabled = false) public void testSchemaUsage() throws Exception { // Create a connection factory: this should always use the default // schema, // even if it is updated. // schema, even if it is updated. final ConnectionFactory factory = new LDAPConnectionFactory("localhost", TestCaseUtils.getLdapPort()); final Schema defaultSchema = Schema.getDefaultSchema(); opendj3/pom.xml
@@ -108,6 +108,7 @@ <docTargetVersion>2.5.0</docTargetVersion> <siteDistributionURL>scp://forgerock.org/var/www/vhosts/opendj.forgerock.org/httpdocs</siteDistributionURL> <i18nFrameworkVersion>1.4.0</i18nFrameworkVersion> <grizzlyFrameworkVersion>2.2.18</grizzlyFrameworkVersion> <gaId>UA-23412190-8</gaId> <!-- Release date is specified only when building the documentation opendj3/src/main/docbkx/dev-guide/chap-get-sdk.xml
@@ -158,21 +158,16 @@ </step> <step> <para> Add the OpenDJ LDAP SDK for the APIs, the I18N core library, Grizzly I/O framework for the transport, and GlassFish management APIs to your CLASSPATH, typically found under and Grizzly I/O framework for the transport to your CLASSPATH, typically found under <filename>opendj-ldap-toolkit-<?eval ${currentSDKversion}?>/lib/</filename>.</para> <screen>(UNIX) $ export CLASSPATH=/path/to/lib/gmbal-api-only-3.0.0-b023.jar:$CLASSPATH $ export CLASSPATH=/path/to/lib/grizzly-framework-2.1.9.jar:$CLASSPATH $ export CLASSPATH=/path/to/lib/grizzly-framework-<?eval ${grizzlyFrameworkVersion}?>.jar:$CLASSPATH $ export CLASSPATH=/path/to/lib/i18n-core-1.4.0.jar:$CLASSPATH $ export CLASSPATH=/path/to/lib/management-api-3.0.0-b012.jar:$CLASSPATH $ export CLASSPATH=/path/to/lib/opendj-ldap-sdk-<?eval ${currentSDKversion}?>.jar:$CLASSPATH </screen> <screen>(Windows) C:\>set CLASSPATH=\\path\to\lib\gmbal-api-only-3.0.0-b023.jar:%CLASSPATH% C:\>set CLASSPATH=\\path\to\lib\grizzly-framework-2.1.9.jar:%CLASSPATH% C:\>set CLASSPATH=\\path\to\lib\grizzly-framework-<?eval ${grizzlyFrameworkVersion}?>.jar:%CLASSPATH% C:\>set CLASSPATH=\\path\to\lib\i18n-core-1.4.0.jar:%CLASSPATH% C:\>set CLASSPATH=\\path\to\lib\management-api-3.0.0-b012.jar:%CLASSPATH% C:\>set CLASSPATH=\\path\to\lib\opendj-ldap-sdk-<?eval ${currentSDKversion}?>.jar:%CLASSPATH%</screen> </step> </procedure> @@ -241,10 +236,8 @@ <step> <para>Set your CLASSPATH to include the OpenDJ LDAP SDK library, <filename>opendj-ldap-sdk-<?eval ${currentSDKVersion}?>.jar</filename>, the I18N core library, <filename>i18n-core-1.4.0.jar</filename>, the Grizzly framework, <filename>grizzly-framework-2.1.9.jar</filename>, and the GlassFish management APIs, <filename>gmbal-api-only-3.0.0-b023.jar</filename> & <filename>management-api-3.0.0-b012.jar</filename> the I18N core library, <filename>i18n-core-1.4.0.jar</filename>, and the Grizzly framework, <filename>grizzly-framework-<?eval ${grizzlyFrameworkVersion}?>.jar</filename> under <filename>opendj-ldap-toolkit-<?eval ${currentSDKversion}?>/lib/</filename>.</para> </step> </procedure>