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
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.controls;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    
034    import org.opends.server.protocols.asn1.ASN1Element;
035    import org.opends.server.protocols.asn1.ASN1Enumerated;
036    import org.opends.server.protocols.asn1.ASN1OctetString;
037    import org.opends.server.protocols.asn1.ASN1Sequence;
038    import org.opends.server.protocols.ldap.LDAPResultCode;
039    import org.opends.server.types.Control;
040    import org.opends.server.types.LDAPException;
041    
042    import static org.opends.messages.ProtocolMessages.*;
043    import static org.opends.server.util.ServerConstants.*;
044    import static org.opends.server.util.StaticUtils.*;
045    
046    
047    
048    /**
049     * This class implements the server-side sort response control as defined in RFC
050     * 2891 section 1.2.  The ASN.1 description for the control value is:
051     * <BR><BR>
052     * <PRE>
053     * SortResult ::= SEQUENCE {
054     *    sortResult  ENUMERATED {
055     *        success                   (0), -- results are sorted
056     *        operationsError           (1), -- server internal failure
057     *        timeLimitExceeded         (3), -- timelimit reached before
058     *                                       -- sorting was completed
059     *        strongAuthRequired        (8), -- refused to return sorted
060     *                                       -- results via insecure
061     *                                       -- protocol
062     *        adminLimitExceeded       (11), -- too many matching entries
063     *                                       -- for the server to sort
064     *        noSuchAttribute          (16), -- unrecognized attribute
065     *                                       -- type in sort key
066     *        inappropriateMatching    (18), -- unrecognized or
067     *                                       -- inappropriate matching
068     *                                       -- rule in sort key
069     *        insufficientAccessRights (50), -- refused to return sorted
070     *                                       -- results to this client
071     *        busy                     (51), -- too busy to process
072     *        unwillingToPerform       (53), -- unable to sort
073     *        other                    (80)
074     *        },
075     *  attributeType [0] AttributeDescription OPTIONAL }
076     * </PRE>
077     */
078    public class ServerSideSortResponseControl
079           extends Control
080    {
081      /**
082       * The BER type to use when encoding the attribute type element.
083       */
084      private static final byte TYPE_ATTRIBUTE_TYPE = (byte) 0x80;
085    
086    
087    
088      // The result code for the sort result.
089      private int resultCode;
090    
091      // The attribute type for the sort result.
092      private String attributeType;
093    
094    
095    
096      /**
097       * Creates a new server-side sort response control based on the provided
098       * result code and attribute type.
099       *
100       * @param  resultCode     The result code for the sort result.
101       * @param  attributeType  The attribute type for the sort result (or
102       *                        {@code null} if there is none).
103       */
104      public ServerSideSortResponseControl(int resultCode, String attributeType)
105      {
106        super(OID_SERVER_SIDE_SORT_RESPONSE_CONTROL, false,
107              encodeControlValue(resultCode, attributeType));
108    
109        this.resultCode    = resultCode;
110        this.attributeType = attributeType;
111      }
112    
113    
114    
115      /**
116       * Creates a new server-side sort response control with the provided
117       * information.
118       *
119       * @param  oid            The OID to use for this control.
120       * @param  isCritical     Indicates whether support for this control should be
121       *                        considered a critical part of the server processing.
122       * @param  controlValue   The encoded value for this control.
123       * @param  resultCode     The result code for the sort result.
124       * @param  attributeType  The attribute type for the sort result.
125       */
126      private ServerSideSortResponseControl(String oid, boolean isCritical,
127                                            ASN1OctetString controlValue,
128                                            int resultCode,
129                                            String attributeType)
130      {
131        super(oid, isCritical, controlValue);
132    
133        this.resultCode    = resultCode;
134        this.attributeType = attributeType;
135      }
136    
137    
138    
139      /**
140       * Retrieves the result code for this sort result.
141       *
142       * @return  The result code for this sort result.
143       */
144      public int getResultCode()
145      {
146        return resultCode;
147      }
148    
149    
150    
151      /**
152       * Retrieves the attribute type for this sort result.
153       *
154       * @return  The attribute type for this sort result, or {@code null} if there
155       *          is none.
156       */
157      public String getAttributeType()
158      {
159        return attributeType;
160      }
161    
162    
163    
164      /**
165       * Encodes the provided set of result codes and attribute types in a manner
166       * suitable for use as the value of this control.
167       *
168       * @param  resultCode     The result code for the sort result.
169       * @param  attributeType  The attribute type for the sort result, or
170       *                        {@code null} if there is none.
171       *
172       * @return  The ASN.1 octet string containing the encoded sort result.
173       */
174      private static ASN1OctetString encodeControlValue(int resultCode,
175                                                        String attributeType)
176      {
177        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
178        elements.add(new ASN1Enumerated(resultCode));
179    
180        if (attributeType != null)
181        {
182          elements.add(new ASN1OctetString(TYPE_ATTRIBUTE_TYPE, attributeType));
183        }
184    
185        return new ASN1OctetString(new ASN1Sequence(elements).encode());
186      }
187    
188    
189    
190      /**
191       * Creates a new server-side sort response control from the contents of the
192       * provided control.
193       *
194       * @param  control  The generic control containing the information to use to
195       *                  create this server-side sort response control.  It must
196       *                  not be {@code null}.
197       *
198       * @return  The server-side sort response control decoded from the provided
199       *          control.
200       *
201       * @throws  LDAPException  If this control cannot be decoded as a valid
202       *                         server-side sort response control.
203       */
204      public static ServerSideSortResponseControl decodeControl(Control control)
205             throws LDAPException
206      {
207        ASN1OctetString controlValue = control.getValue();
208        if (controlValue == null)
209        {
210          Message message = INFO_SORTRES_CONTROL_NO_VALUE.get();
211          throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message);
212        }
213    
214        try
215        {
216          ArrayList<ASN1Element> elements =
217               ASN1Sequence.decodeAsSequence(control.getValue().value()).elements();
218          int resultCode = elements.get(0).decodeAsEnumerated().intValue();
219    
220          String attributeType = null;
221          if (elements.size() > 1)
222          {
223            attributeType = elements.get(1).decodeAsOctetString().stringValue();
224          }
225    
226          return new ServerSideSortResponseControl(control.getOID(),
227                                                   control.isCritical(),
228                                                   control.getValue(), resultCode,
229                                                   attributeType);
230        }
231        catch (Exception e)
232        {
233          Message message =
234              INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE.get(getExceptionMessage(e));
235          throw new LDAPException(LDAPResultCode.PROTOCOL_ERROR, message, e);
236        }
237      }
238    
239    
240    
241      /**
242       * Retrieves a string representation of this server-side sort response
243       * control.
244       *
245       * @return  A string representation of this server-side sort response control.
246       */
247      public String toString()
248      {
249        StringBuilder buffer = new StringBuilder();
250        toString(buffer);
251        return buffer.toString();
252      }
253    
254    
255    
256      /**
257       * Appends a string representation of this server-side sort response control
258       * to the provided buffer.
259       *
260       * @param  buffer  The buffer to which the information should be appended.
261       */
262      public void toString(StringBuilder buffer)
263      {
264        buffer.append("ServerSideSortResponseControl(resultCode=");
265        buffer.append(resultCode);
266    
267        if (attributeType != null)
268        {
269          buffer.append(", attributeType=");
270          buffer.append(attributeType);
271        }
272    
273        buffer.append(")");
274      }
275    }
276