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