| | |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.opendj.ldap.AbstractSynchronousConnection; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | |
| | | import org.forgerock.opendj.ldap.responses.Responses; |
| | | import org.forgerock.opendj.ldap.responses.Result; |
| | | import org.forgerock.util.promise.Promise; |
| | | import org.forgerock.util.promise.PromiseImpl; |
| | | import org.opends.server.core.AddOperation; |
| | | import org.opends.server.core.BindOperation; |
| | | import org.opends.server.core.CompareOperation; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.core.ExtendedOperation; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchListener; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.protocols.internal.Requests; |
| | | import org.opends.server.types.AuthenticationInfo; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.OperationType; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.types.SearchResultReference; |
| | |
| | | import static org.forgerock.opendj.adapter.server3x.Converters.*; |
| | | import static org.forgerock.opendj.ldap.ByteString.*; |
| | | import static org.forgerock.opendj.ldap.LdapException.*; |
| | | import static org.forgerock.util.promise.Promises.*; |
| | | |
| | | /** This class provides a connection factory and an adapter for the OpenDJ 2.x server. */ |
| | | public final class Adapters { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns a new anonymous connection factory. |
| | | * |
| | | * @return A new anonymous connection factory. |
| | | */ |
| | | public static ConnectionFactory newAnonymousConnectionFactory() { |
| | | InternalClientConnection icc = new InternalClientConnection(new AuthenticationInfo()); |
| | | return newConnectionFactory(icc); |
| | | } |
| | | |
| | | /** |
| | | * Returns a new connection factory for a specified user. |
| | | * |
| | | * @param userDN |
| | | * The specified user's DN. |
| | | * @return a new connection factory. |
| | | */ |
| | | public static ConnectionFactory newConnectionFactoryForUser(final DN userDN) { |
| | | InternalClientConnection icc = null; |
| | | try { |
| | | icc = new InternalClientConnection(userDN); |
| | | } catch (DirectoryException e) { |
| | | throw new IllegalStateException(e.getMessage(), e); |
| | | } |
| | | return newConnectionFactory(icc); |
| | | } |
| | | |
| | | /** |
| | | * Returns a new connection factory. |
| | | * |
| | | * @param icc |
| | |
| | | */ |
| | | public static ConnectionFactory newConnectionFactory(final InternalClientConnection icc) { |
| | | return new ConnectionFactory() { |
| | | |
| | | @Override |
| | | public void close() { |
| | | // Nothing to do. |
| | |
| | | |
| | | @Override |
| | | public Promise<Connection, LdapException> getConnectionAsync() { |
| | | // TODO change the path... |
| | | return newResultPromise(newConnection(icc)); |
| | | final PromiseImpl<Connection, LdapException> promise = PromiseImpl.create(); |
| | | try |
| | | { |
| | | DirectoryServer.getWorkQueue().submitOperation(new AsyncOperation<>(icc, new Runnable() |
| | | { |
| | | @Override |
| | | public void run() |
| | | { |
| | | try |
| | | { |
| | | promise.handleResult(getConnection()); |
| | | } |
| | | catch (LdapException e) |
| | | { |
| | | promise.handleException(e); |
| | | } |
| | | } |
| | | })); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | | promise.handleException(LdapException.newLdapException(e.getResultCode())); |
| | | } |
| | | return promise; |
| | | } |
| | | |
| | | @Override |
| | |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Returns a new root connection. |
| | | * |
| | | * @return A new root connection. |
| | | */ |
| | | public static Connection newRootConnection() { |
| | | return newConnection(InternalClientConnection.getRootConnection()); |
| | | } |
| | | |
| | | /** |
| | | * Returns a new connection for an anonymous user. |
| | | * |
| | | * @return A new connection. |
| | | */ |
| | | public static Connection newAnonymousConnection() { |
| | | return newConnection(new InternalClientConnection(new AuthenticationInfo())); |
| | | } |
| | | |
| | | /** |
| | | * Returns a new connection for a specified user. |
| | | * |
| | | * @param dn |
| | | * The DN of the user. |
| | | * @return A new connection for a specified user. |
| | | * @throws LdapException |
| | | * If no such object. |
| | | */ |
| | | public static Connection newConnectionForUser(final DN dn) throws LdapException { |
| | | try { |
| | | return newConnection(new InternalClientConnection(dn)); |
| | | } catch (DirectoryException e) { |
| | | throw newLdapException(Responses.newResult(ResultCode.NO_SUCH_OBJECT)); |
| | | } |
| | | } |
| | | |
| | | private static Connection newConnection(final InternalClientConnection icc) { |
| | | return new AbstractSynchronousConnection() { |
| | | return new AbstractSynchronousConnection() { |
| | | |
| | | @Override |
| | | public Result search(final SearchRequest request, final SearchResultHandler handler) |
| | | throws LdapException { |
| | | InternalSearchListener internalSearchListener = new InternalSearchListener() { |
| | | @Override |
| | | public Result search(final SearchRequest request, final SearchResultHandler handler) |
| | | throws LdapException { |
| | | InternalSearchListener internalSearchListener = new InternalSearchListener() { |
| | | |
| | | @Override |
| | | public void handleInternalSearchReference( |
| | | InternalSearchOperation searchOperation, |
| | | SearchResultReference searchReference) throws DirectoryException { |
| | | handler.handleReference(from(searchReference)); |
| | | } |
| | | @Override |
| | | public void handleInternalSearchReference( |
| | | InternalSearchOperation searchOperation, |
| | | SearchResultReference searchReference) throws DirectoryException { |
| | | handler.handleReference(from(searchReference)); |
| | | } |
| | | |
| | | @Override |
| | | public void handleInternalSearchEntry(InternalSearchOperation searchOperation, |
| | | SearchResultEntry searchEntry) throws DirectoryException { |
| | | handler.handleEntry(from(searchEntry)); |
| | | } |
| | | }; |
| | | @Override |
| | | public void handleInternalSearchEntry(InternalSearchOperation searchOperation, |
| | | SearchResultEntry searchEntry) throws DirectoryException { |
| | | handler.handleEntry(from(searchEntry)); |
| | | } |
| | | }; |
| | | |
| | | final SearchFilter filter = toSearchFilter(request.getFilter()); |
| | | final org.opends.server.protocols.internal.SearchRequest sr = |
| | | Requests.newSearchRequest(request.getName(), request.getScope(), filter) |
| | | .setDereferenceAliasesPolicy(request.getDereferenceAliasesPolicy()) |
| | | .setSizeLimit(request.getSizeLimit()) |
| | | .setTimeLimit(request.getTimeLimit()) |
| | | .setTypesOnly(request.isTypesOnly()) |
| | | .addAttribute(request.getAttributes()) |
| | | .addControl(to(request.getControls())); |
| | | return getResponseResult(icc.processSearch(sr, internalSearchListener)); |
| | | } |
| | | final SearchFilter filter = toSearchFilter(request.getFilter()); |
| | | final org.opends.server.protocols.internal.SearchRequest sr = |
| | | Requests.newSearchRequest(request.getName(), request.getScope(), filter) |
| | | .setDereferenceAliasesPolicy(request.getDereferenceAliasesPolicy()) |
| | | .setSizeLimit(request.getSizeLimit()) |
| | | .setTimeLimit(request.getTimeLimit()) |
| | | .setTypesOnly(request.isTypesOnly()) |
| | | .addAttribute(request.getAttributes()) |
| | | .addControl(to(request.getControls())); |
| | | return getResponseResult(icc.processSearch(sr, internalSearchListener)); |
| | | } |
| | | |
| | | @Override |
| | | public void removeConnectionEventListener(ConnectionEventListener listener) { |
| | | // Internal client connection don't have any connection events. |
| | | } |
| | | @Override |
| | | public void removeConnectionEventListener(ConnectionEventListener listener) { |
| | | // Internal client connection don't have any connection events. |
| | | } |
| | | |
| | | @Override |
| | | public Result modifyDN(final ModifyDNRequest request) throws LdapException { |
| | | return getResponseResult(icc.processModifyDN(request)); |
| | | } |
| | | @Override |
| | | public Result modifyDN(final ModifyDNRequest request) throws LdapException { |
| | | return getResponseResult(icc.processModifyDN(request)); |
| | | } |
| | | |
| | | @Override |
| | | public Result modify(final ModifyRequest request) throws LdapException { |
| | | return getResponseResult(icc.processModify(request)); |
| | | } |
| | | @Override |
| | | public Result modify(final ModifyRequest request) throws LdapException { |
| | | return getResponseResult(icc.processModify(request)); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isValid() { |
| | | // Always true. |
| | | return true; |
| | | } |
| | | @Override |
| | | public boolean isValid() { |
| | | // Always true. |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isClosed() { |
| | | return false; |
| | | } |
| | | @Override |
| | | public boolean isClosed() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public <R extends ExtendedResult> R extendedRequest(final ExtendedRequest<R> request, |
| | | final IntermediateResponseHandler handler) throws LdapException { |
| | | @Override |
| | | public <R extends ExtendedResult> R extendedRequest(final ExtendedRequest<R> request, |
| | | final IntermediateResponseHandler handler) throws LdapException { |
| | | |
| | | final ExtendedOperation extendedOperation = |
| | | icc.processExtendedOperation(request.getOID(), request.getValue(), |
| | | to(request.getControls())); |
| | | final ExtendedOperation extendedOperation = |
| | | icc.processExtendedOperation(request.getOID(), request.getValue(), |
| | | to(request.getControls())); |
| | | |
| | | final Result result = getResponseResult(extendedOperation); |
| | | final GenericExtendedResult genericExtendedResult = |
| | | Responses.newGenericExtendedResult(result.getResultCode()) |
| | | .setDiagnosticMessage(result.getDiagnosticMessage()).setMatchedDN( |
| | | result.getMatchedDN()).setValue( |
| | | extendedOperation.getResponseValue().toByteString()); |
| | | try { |
| | | R extendedResult = |
| | | request.getResultDecoder().decodeExtendedResult(genericExtendedResult, |
| | | new DecodeOptions()); |
| | | for (final Control control : result.getControls()) { |
| | | extendedResult.addControl(control); |
| | | } |
| | | return extendedResult; |
| | | final Result result = getResponseResult(extendedOperation); |
| | | final GenericExtendedResult genericExtendedResult = |
| | | Responses.newGenericExtendedResult(result.getResultCode()) |
| | | .setDiagnosticMessage(result.getDiagnosticMessage()).setMatchedDN( |
| | | result.getMatchedDN()).setValue( |
| | | extendedOperation.getResponseValue().toByteString()); |
| | | try { |
| | | R extendedResult = |
| | | request.getResultDecoder().decodeExtendedResult(genericExtendedResult, |
| | | new DecodeOptions()); |
| | | for (final Control control : result.getControls()) { |
| | | extendedResult.addControl(control); |
| | | } |
| | | return extendedResult; |
| | | |
| | | } catch (DecodeException e) { |
| | | DN matchedDN = extendedOperation.getMatchedDN(); |
| | | return request.getResultDecoder().newExtendedErrorResult( |
| | | extendedOperation.getResultCode(), |
| | | matchedDN != null ? matchedDN.toString() : null, |
| | | extendedOperation.getErrorMessage().toString()); |
| | | } |
| | | } |
| | | } catch (DecodeException e) { |
| | | DN matchedDN = extendedOperation.getMatchedDN(); |
| | | return request.getResultDecoder().newExtendedErrorResult( |
| | | extendedOperation.getResultCode(), |
| | | matchedDN != null ? matchedDN.toString() : null, |
| | | extendedOperation.getErrorMessage().toString()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public Result delete(final DeleteRequest request) throws LdapException { |
| | | final DeleteOperation deleteOperation = |
| | | icc.processDelete(valueOfObject(request.getName()), to(request.getControls())); |
| | | return getResponseResult(deleteOperation); |
| | | } |
| | | @Override |
| | | public Result delete(final DeleteRequest request) throws LdapException { |
| | | final DeleteOperation deleteOperation = |
| | | icc.processDelete(valueOfObject(request.getName()), to(request.getControls())); |
| | | return getResponseResult(deleteOperation); |
| | | } |
| | | |
| | | @Override |
| | | public CompareResult compare(final CompareRequest request) throws LdapException { |
| | | final CompareOperation compareOperation = |
| | | icc.processCompare(valueOfObject(request.getName()), |
| | | request.getAttributeDescription().toString(), |
| | | request.getAssertionValue(), to(request.getControls())); |
| | | @Override |
| | | public CompareResult compare(final CompareRequest request) throws LdapException { |
| | | final CompareOperation compareOperation = |
| | | icc.processCompare(valueOfObject(request.getName()), |
| | | request.getAttributeDescription().toString(), |
| | | request.getAssertionValue(), to(request.getControls())); |
| | | |
| | | CompareResult result = Responses.newCompareResult(compareOperation.getResultCode()); |
| | | return getResponseResult(compareOperation, result); |
| | | } |
| | | CompareResult result = Responses.newCompareResult(compareOperation.getResultCode()); |
| | | return getResponseResult(compareOperation, result); |
| | | } |
| | | |
| | | @Override |
| | | public void close(final UnbindRequest request, final String reason) { |
| | | // no implementation in open-ds. |
| | | } |
| | | @Override |
| | | public void close(final UnbindRequest request, final String reason) { |
| | | // no implementation in open-ds. |
| | | } |
| | | |
| | | @Override |
| | | public BindResult bind(final BindRequest request) throws LdapException { |
| | | BindOperation bindOperation = null; |
| | | if (request instanceof SimpleBindRequest) { |
| | | bindOperation = |
| | | icc.processSimpleBind(valueOfUtf8(request.getName()), |
| | | ByteString.wrap(((SimpleBindRequest) request).getPassword()), |
| | | to(request.getControls())); |
| | | } else if (request instanceof SASLBindRequest) { |
| | | String serverName = null; |
| | | try { |
| | | serverName = InetAddress.getByName(null).getCanonicalHostName(); |
| | | } catch (UnknownHostException e) { |
| | | // nothing to do. |
| | | } |
| | | BindClient bindClient = request.createBindClient(serverName); |
| | | do { |
| | | final GenericBindRequest genericBindRequest = bindClient.nextBindRequest(); |
| | | bindOperation = |
| | | icc.processSASLBind( |
| | | valueOfUtf8(request.getName()), |
| | | ((SASLBindRequest) request).getSASLMechanism(), |
| | | getCredentials(genericBindRequest.getAuthenticationValue()), |
| | | to(request.getControls())); |
| | | } while (bindOperation.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS); |
| | | @Override |
| | | public BindResult bind(final BindRequest request) throws LdapException { |
| | | BindOperation bindOperation = null; |
| | | if (request instanceof SimpleBindRequest) { |
| | | bindOperation = |
| | | icc.processSimpleBind(valueOfUtf8(request.getName()), |
| | | ByteString.wrap(((SimpleBindRequest) request).getPassword()), |
| | | to(request.getControls())); |
| | | } else if (request instanceof SASLBindRequest) { |
| | | String serverName = null; |
| | | try { |
| | | serverName = InetAddress.getByName(null).getCanonicalHostName(); |
| | | } catch (UnknownHostException e) { |
| | | // nothing to do. |
| | | } |
| | | BindClient bindClient = request.createBindClient(serverName); |
| | | do { |
| | | final GenericBindRequest genericBindRequest = bindClient.nextBindRequest(); |
| | | bindOperation = |
| | | icc.processSASLBind( |
| | | valueOfUtf8(request.getName()), |
| | | ((SASLBindRequest) request).getSASLMechanism(), |
| | | getCredentials(genericBindRequest.getAuthenticationValue()), |
| | | to(request.getControls())); |
| | | } while (bindOperation.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS); |
| | | |
| | | bindClient.dispose(); |
| | | bindClient.dispose(); |
| | | |
| | | } else { // not supported |
| | | throw newLdapException(Responses.newResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED)); |
| | | } |
| | | BindResult result = Responses.newBindResult(bindOperation.getResultCode()); |
| | | result.setServerSASLCredentials(bindOperation.getSASLCredentials()); |
| | | } else { // not supported |
| | | throw newLdapException(Responses.newResult(ResultCode.AUTH_METHOD_NOT_SUPPORTED)); |
| | | } |
| | | BindResult result = Responses.newBindResult(bindOperation.getResultCode()); |
| | | result.setServerSASLCredentials(bindOperation.getSASLCredentials()); |
| | | |
| | | if (result.isSuccess()) { |
| | | return result; |
| | | } else { |
| | | throw newLdapException(result); |
| | | } |
| | | } |
| | | if (result.isSuccess()) { |
| | | return result; |
| | | } else { |
| | | throw newLdapException(result); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void addConnectionEventListener(ConnectionEventListener listener) { |
| | | // Internal client connection don't have any connection events. |
| | | } |
| | | @Override |
| | | public void addConnectionEventListener(ConnectionEventListener listener) { |
| | | // Internal client connection don't have any connection events. |
| | | } |
| | | |
| | | @Override |
| | | public Result add(final AddRequest request) throws LdapException { |
| | | final AddOperation addOperation = |
| | | icc.processAdd(valueOfObject(request.getName()), to(request |
| | | .getAllAttributes()), to(request.getControls())); |
| | | return getResponseResult(addOperation); |
| | | } |
| | | @Override |
| | | public Result add(final AddRequest request) throws LdapException { |
| | | final AddOperation addOperation = |
| | | icc.processAdd(valueOfObject(request.getName()), to(request |
| | | .getAllAttributes()), to(request.getControls())); |
| | | return getResponseResult(addOperation); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return icc.toString(); |
| | | } |
| | | }; |
| | | @Override |
| | | public String toString() { |
| | | return icc.toString(); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * This operation is hack to be able to execute a {@link Runnable} in a |
| | | * Directory Server's worker thread. |
| | | */ |
| | | private static final class AsyncOperation<V> extends org.opends.server.types.AbstractOperation |
| | | { |
| | | private final Runnable runnable; |
| | | |
| | | AsyncOperation(InternalClientConnection icc, Runnable runnable) |
| | | { |
| | | super(icc, icc.nextOperationID(), icc.nextMessageID(), Collections.<org.opends.server.types.Control> emptyList()); |
| | | this.setInternalOperation(true); |
| | | this.runnable = runnable; |
| | | } |
| | | |
| | | @Override |
| | | public void run() |
| | | { |
| | | runnable.run(); |
| | | } |
| | | |
| | | @Override |
| | | public OperationType getOperationType() |
| | | { |
| | | return null; |
| | | } |
| | | @Override |
| | | public List<org.opends.server.types.Control> getResponseControls() |
| | | { |
| | | return Collections.emptyList(); |
| | | } |
| | | @Override |
| | | public void addResponseControl(org.opends.server.types.Control control) |
| | | { |
| | | } |
| | | @Override |
| | | public void removeResponseControl(org.opends.server.types.Control control) |
| | | { |
| | | } |
| | | @Override |
| | | public DN getProxiedAuthorizationDN() |
| | | { |
| | | return null; |
| | | } |
| | | @Override |
| | | public void setProxiedAuthorizationDN(DN proxiedAuthorizationDN) |
| | | { |
| | | } |
| | | @Override |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append(AsyncOperation.class.getSimpleName()); |
| | | } |
| | | } |
| | | } |