001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2008 Sun Microsystems, Inc.
015 * Portions Copyright 2012-2014 ForgeRock AS.
016 */
017package org.opends.dsml.protocol;
018
019
020
021import java.io.IOException;
022import java.util.List;
023import java.util.Set;
024
025import org.forgerock.i18n.LocalizableMessage;
026import org.forgerock.opendj.ldap.DecodeException;
027import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
028import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
029import org.opends.server.protocols.ldap.LDAPMessage;
030import org.opends.server.protocols.ldap.ProtocolOp;
031import org.opends.server.tools.LDAPConnection;
032import org.forgerock.opendj.ldap.ByteString;
033import org.opends.server.types.LDAPException;
034
035
036/**
037 * This class provides the functionality for the performing an
038 * LDAP EXTENDED operation based on the specified DSML request.
039 */
040public class DSMLExtendedOperation
041{
042  private LDAPConnection connection;
043  private Set<String> stringResponses;
044
045  /**
046   * Create an instance with the specified LDAP connection.
047   *
048   * @param connection    The LDAP connection to send the request on.
049   * @param stringResponses The OIDs of any operations that have results that
050   *                        should be returned as strings instead of binary.
051   */
052  public DSMLExtendedOperation(LDAPConnection connection,
053      Set<String> stringResponses)
054  {
055    this.connection = connection;
056    this.stringResponses = stringResponses;
057  }
058
059
060
061  /**
062   * Determine if the response to a given LDAP extended operation (specified by
063   * OID) should be treated as a string. The default is binary.
064   *
065   * @param oid The OID of the extended operation.
066   * @return <CODE>true</CODE> if the extended operation is known to return a
067   *         string, <CODE>false</CODE> otherwise.
068   */
069  public boolean responseIsString(String oid)
070  {
071    return stringResponses.contains(oid);
072  }
073
074
075
076  /**
077   * Perform the LDAP EXTENDED operation and send the result back to the
078   * client.
079   *
080   * @param  objFactory       The object factory for this operation.
081   * @param  extendedRequest  The extended request for this operation.
082   * @param  controls         Any required controls (e.g. for proxy authz).
083   *
084   * @return  The result of the extended operation.
085   *
086   * @throws  IOException  If an I/O problem occurs.
087   *
088   * @throws  LDAPException  If an error occurs while interacting with an LDAP
089   *                         element.
090   *
091   * @throws  DecodeException  If an error occurs while interacting with an ASN.1
092   *                         element.
093   */
094  public ExtendedResponse doOperation(ObjectFactory objFactory,
095              ExtendedRequest extendedRequest,
096              List<org.opends.server.types.Control> controls)
097    throws IOException, LDAPException, DecodeException
098  {
099    ExtendedResponse extendedResponse = objFactory.createExtendedResponse();
100    extendedResponse.setRequestID(extendedRequest.getRequestID());
101
102    String requestName = extendedRequest.getRequestName();
103    Object value = extendedRequest.getRequestValue();
104    ByteString asnValue = ByteStringUtility.convertValue(value);
105
106    // Create and send the LDAP request to the server.
107    ProtocolOp op = new ExtendedRequestProtocolOp(requestName, asnValue);
108    LDAPMessage msg = new LDAPMessage(DSMLServlet.nextMessageID(), op,
109        controls);
110    connection.getLDAPWriter().writeMessage(msg);
111
112    // Read and decode the LDAP response from the server.
113    LDAPMessage responseMessage = connection.getLDAPReader().readMessage();
114
115    ExtendedResponseProtocolOp extendedOp =
116          responseMessage.getExtendedResponseProtocolOp();
117    int resultCode = extendedOp.getResultCode();
118    LocalizableMessage errorMessage = extendedOp.getErrorMessage();
119
120    // Set the result code and error message for the DSML response.
121    extendedResponse.setResponseName(extendedOp.getOID());
122
123    ByteString rawValue = extendedOp.getValue();
124    value = null;
125    if (rawValue != null)
126    {
127      if (responseIsString(requestName))
128      {
129        value = rawValue.toString();
130      }
131      else
132      {
133        value = rawValue.toByteArray();
134      }
135    }
136    extendedResponse.setResponse(value);
137    extendedResponse.setErrorMessage(
138            errorMessage != null ? errorMessage.toString() : null);
139    ResultCode code = ResultCodeFactory.create(objFactory, resultCode);
140    extendedResponse.setResultCode(code);
141
142    return extendedResponse;
143  }
144
145}
146