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-2016 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  /** ControlDecoder implementation to decode this control from a ByteString. */
069  private static final class Decoder
070      implements ControlDecoder<ServerSideSortResponseControl>
071  {
072    @Override
073    public ServerSideSortResponseControl decode(boolean isCritical,
074                                                ByteString value)
075        throws DirectoryException
076    {
077      if (value == null)
078      {
079        LocalizableMessage message = INFO_SORTRES_CONTROL_NO_VALUE.get();
080        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message);
081      }
082
083      ASN1Reader reader = ASN1.getReader(value);
084      try
085      {
086        reader.readStartSequence();
087        int resultCode = (int)reader.readInteger();
088
089        String attributeType = null;
090        if(reader.hasNextElement())
091        {
092          attributeType = reader.readOctetStringAsString();
093        }
094
095        return new ServerSideSortResponseControl(isCritical,
096            resultCode,
097            attributeType);
098      }
099      catch (Exception e)
100      {
101        LocalizableMessage message =
102            INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE.get(
103                getExceptionMessage(e));
104        throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e);
105      }
106    }
107
108    @Override
109    public String getOID()
110    {
111      return OID_SERVER_SIDE_SORT_RESPONSE_CONTROL;
112    }
113
114  }
115
116  /** The Control Decoder that can be used to decode this control. */
117  public static final ControlDecoder<ServerSideSortResponseControl> DECODER =
118    new Decoder();
119
120  /** The BER type to use when encoding the attribute type element. */
121  private static final byte TYPE_ATTRIBUTE_TYPE = (byte) 0x80;
122
123
124
125  /** The result code for the sort result. */
126  private int resultCode;
127
128  /** The attribute type for the sort result. */
129  private String attributeType;
130
131
132
133  /**
134   * Creates a new server-side sort response control based on the provided
135   * result code and attribute type.
136   *
137   * @param  resultCode     The result code for the sort result.
138   * @param  attributeType  The attribute type for the sort result (or
139   *                        {@code null} if there is none).
140   */
141  public ServerSideSortResponseControl(int resultCode, String attributeType)
142  {
143    this(false, resultCode, attributeType);
144  }
145
146
147
148  /**
149   * Creates a new server-side sort response control with the provided
150   * information.
151   *
152   * @param  isCritical     Indicates whether support for this control should be
153   *                        considered a critical part of the server processing.
154   * @param  resultCode     The result code for the sort result.
155   * @param  attributeType  The attribute type for the sort result.
156   */
157  public ServerSideSortResponseControl(boolean isCritical,
158                                       int resultCode,
159                                       String attributeType)
160  {
161    super(OID_SERVER_SIDE_SORT_RESPONSE_CONTROL, isCritical);
162
163    this.resultCode    = resultCode;
164    this.attributeType = attributeType;
165  }
166
167
168
169  /**
170   * Retrieves the result code for this sort result.
171   *
172   * @return  The result code for this sort result.
173   */
174  public int getResultCode()
175  {
176    return resultCode;
177  }
178
179
180
181  /**
182   * Retrieves the attribute type for this sort result.
183   *
184   * @return  The attribute type for this sort result, or {@code null} if there
185   *          is none.
186   */
187  public String getAttributeType()
188  {
189    return attributeType;
190  }
191
192
193
194  /**
195   * Writes this control's value to an ASN.1 writer. The value (if any) must be
196   * written as an ASN1OctetString.
197   *
198   * @param writer The ASN.1 writer to use.
199   * @throws IOException If a problem occurs while writing to the stream.
200   */
201  @Override
202  protected void writeValue(ASN1Writer writer) throws IOException {
203    writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE);
204
205    writer.writeStartSequence();
206    writer.writeEnumerated(resultCode);
207    if (attributeType != null)
208    {
209      writer.writeOctetString(TYPE_ATTRIBUTE_TYPE, attributeType);
210    }
211    writer.writeEndSequence();
212
213    writer.writeEndSequence();
214  }
215
216
217
218  /**
219   * Appends a string representation of this server-side sort response control
220   * to the provided buffer.
221   *
222   * @param  buffer  The buffer to which the information should be appended.
223   */
224  @Override
225  public void toString(StringBuilder buffer)
226  {
227    buffer.append("ServerSideSortResponseControl(resultCode=");
228    buffer.append(resultCode);
229
230    if (attributeType != null)
231    {
232      buffer.append(", attributeType=");
233      buffer.append(attributeType);
234    }
235
236    buffer.append(")");
237  }
238}
239