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 2008-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2015 ForgeRock AS.
016 */
017package org.opends.server.controls;
018import org.forgerock.i18n.LocalizableMessage;
019
020
021import java.io.IOException;
022
023import org.forgerock.opendj.io.*;
024import org.opends.server.types.Control;
025import org.opends.server.types.DirectoryException;
026import org.forgerock.opendj.ldap.ByteString;
027import org.forgerock.opendj.ldap.ResultCode;
028
029import static org.opends.messages.ProtocolMessages.*;
030import static org.opends.server.util.ServerConstants.*;
031import static org.opends.server.util.StaticUtils.*;
032
033
034
035/**
036 * This class implements the server-side sort response control as defined in RFC
037 * 2891 section 1.2.  The ASN.1 description for the control value is:
038 * <BR><BR>
039 * <PRE>
040 * SortResult ::= SEQUENCE {
041 *    sortResult  ENUMERATED {
042 *        success                   (0), -- results are sorted
043 *        operationsError           (1), -- server internal failure
044 *        timeLimitExceeded         (3), -- timelimit reached before
045 *                                       -- sorting was completed
046 *        strongAuthRequired        (8), -- refused to return sorted
047 *                                       -- results via insecure
048 *                                       -- protocol
049 *        adminLimitExceeded       (11), -- too many matching entries
050 *                                       -- for the server to sort
051 *        noSuchAttribute          (16), -- unrecognized attribute
052 *                                       -- type in sort key
053 *        inappropriateMatching    (18), -- unrecognized or
054 *                                       -- inappropriate matching
055 *                                       -- rule in sort key
056 *        insufficientAccessRights (50), -- refused to return sorted
057 *                                       -- results to this client
058 *        busy                     (51), -- too busy to process
059 *        unwillingToPerform       (53), -- unable to sort
060 *        other                    (80)
061 *        },
062 *  attributeType [0] AttributeDescription OPTIONAL }
063 * </PRE>
064 */
065public class ServerSideSortResponseControl
066       extends Control
067{
068  /**
069   * ControlDecoder implementation to decode this control from a ByteString.
070   */
071  private static final class Decoder
072      implements ControlDecoder<ServerSideSortResponseControl>
073  {
074    /** {@inheritDoc} */
075    public ServerSideSortResponseControl decode(boolean isCritical,
076                                                ByteString value)
077        throws DirectoryException
078    {
079      if (value == null)
080      {
081        LocalizableMessage message = INFO_SORTRES_CONTROL_NO_VALUE.get();
082        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
083      }
084
085      ASN1Reader reader = ASN1.getReader(value);
086      try
087      {
088        reader.readStartSequence();
089        int resultCode = (int)reader.readInteger();
090
091        String attributeType = null;
092        if(reader.hasNextElement())
093        {
094          attributeType = reader.readOctetStringAsString();
095        }
096
097        return new ServerSideSortResponseControl(isCritical,
098            resultCode,
099            attributeType);
100      }
101      catch (Exception e)
102      {
103        LocalizableMessage message =
104            INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE.get(
105                getExceptionMessage(e));
106        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e);
107      }
108    }
109
110    public String getOID()
111    {
112      return OID_SERVER_SIDE_SORT_RESPONSE_CONTROL;
113    }
114
115  }
116
117  /**
118   * The Control Decoder that can be used to decode this control.
119   */
120  public static final ControlDecoder<ServerSideSortResponseControl> DECODER =
121    new Decoder();
122
123  /**
124   * The BER type to use when encoding the attribute type element.
125   */
126  private static final byte TYPE_ATTRIBUTE_TYPE = (byte) 0x80;
127
128
129
130  /** The result code for the sort result. */
131  private int resultCode;
132
133  /** The attribute type for the sort result. */
134  private String attributeType;
135
136
137
138  /**
139   * Creates a new server-side sort response control based on the provided
140   * result code and attribute type.
141   *
142   * @param  resultCode     The result code for the sort result.
143   * @param  attributeType  The attribute type for the sort result (or
144   *                        {@code null} if there is none).
145   */
146  public ServerSideSortResponseControl(int resultCode, String attributeType)
147  {
148    this(false, resultCode, attributeType);
149  }
150
151
152
153  /**
154   * Creates a new server-side sort response control with the provided
155   * information.
156   *
157   * @param  isCritical     Indicates whether support for this control should be
158   *                        considered a critical part of the server processing.
159   * @param  resultCode     The result code for the sort result.
160   * @param  attributeType  The attribute type for the sort result.
161   */
162  public ServerSideSortResponseControl(boolean isCritical,
163                                       int resultCode,
164                                       String attributeType)
165  {
166    super(OID_SERVER_SIDE_SORT_RESPONSE_CONTROL, isCritical);
167
168    this.resultCode    = resultCode;
169    this.attributeType = attributeType;
170  }
171
172
173
174  /**
175   * Retrieves the result code for this sort result.
176   *
177   * @return  The result code for this sort result.
178   */
179  public int getResultCode()
180  {
181    return resultCode;
182  }
183
184
185
186  /**
187   * Retrieves the attribute type for this sort result.
188   *
189   * @return  The attribute type for this sort result, or {@code null} if there
190   *          is none.
191   */
192  public String getAttributeType()
193  {
194    return attributeType;
195  }
196
197
198
199  /**
200   * Writes this control's value to an ASN.1 writer. The value (if any) must be
201   * written as an ASN1OctetString.
202   *
203   * @param writer The ASN.1 writer to use.
204   * @throws IOException If a problem occurs while writing to the stream.
205   */
206  @Override
207  protected void writeValue(ASN1Writer writer) throws IOException {
208    writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE);
209
210    writer.writeStartSequence();
211    writer.writeEnumerated(resultCode);
212    if (attributeType != null)
213    {
214      writer.writeOctetString(TYPE_ATTRIBUTE_TYPE, attributeType);
215    }
216    writer.writeEndSequence();
217
218    writer.writeEndSequence();
219  }
220
221
222
223  /**
224   * Appends a string representation of this server-side sort response control
225   * to the provided buffer.
226   *
227   * @param  buffer  The buffer to which the information should be appended.
228   */
229  @Override
230  public void toString(StringBuilder buffer)
231  {
232    buffer.append("ServerSideSortResponseControl(resultCode=");
233    buffer.append(resultCode);
234
235    if (attributeType != null)
236    {
237      buffer.append(", attributeType=");
238      buffer.append(attributeType);
239    }
240
241    buffer.append(")");
242  }
243}
244