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