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