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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.server.controls; 028import org.forgerock.i18n.LocalizableMessage; 029 030 031import java.io.IOException; 032 033import org.forgerock.opendj.io.*; 034import org.opends.server.types.*; 035import org.forgerock.opendj.ldap.ResultCode; 036import org.forgerock.opendj.ldap.ByteString; 037import static org.opends.messages.ProtocolMessages.*; 038import static org.opends.server.util.ServerConstants.*; 039import static org.opends.server.util.StaticUtils.*; 040 041 042 043/** 044 * This class implements the virtual list view response controls as defined in 045 * draft-ietf-ldapext-ldapv3-vlv. The ASN.1 description for the control value 046 * is: 047 * <BR><BR> 048 * <PRE> 049 * VirtualListViewResponse ::= SEQUENCE { 050 * targetPosition INTEGER (0 .. maxInt), 051 * contentCount INTEGER (0 .. maxInt), 052 * virtualListViewResult ENUMERATED { 053 * success (0), 054 * operationsError (1), 055 * protocolError (3), 056 * unwillingToPerform (53), 057 * insufficientAccessRights (50), 058 * timeLimitExceeded (3), 059 * adminLimitExceeded (11), 060 * inappropriateMatching (18), 061 * sortControlMissing (60), 062 * offsetRangeError (61), 063 * other(80), 064 * ... }, 065 * contextID OCTET STRING OPTIONAL } 066 * </PRE> 067 */ 068public class VLVResponseControl 069 extends Control 070{ 071 /** 072 * ControlDecoder implementation to decode this control from a ByteString. 073 */ 074 private static final class Decoder 075 implements ControlDecoder<VLVResponseControl> 076 { 077 /** {@inheritDoc} */ 078 public VLVResponseControl decode(boolean isCritical, ByteString value) 079 throws DirectoryException 080 { 081 if (value == null) 082 { 083 LocalizableMessage message = INFO_VLVRES_CONTROL_NO_VALUE.get(); 084 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 085 } 086 087 ASN1Reader reader = ASN1.getReader(value); 088 try 089 { 090 reader.readStartSequence(); 091 092 int targetPosition = (int)reader.readInteger(); 093 int contentCount = (int)reader.readInteger(); 094 int vlvResultCode = (int)reader.readInteger(); 095 096 ByteString contextID = null; 097 if (reader.hasNextElement()) 098 { 099 contextID = reader.readOctetString(); 100 } 101 102 return new VLVResponseControl(isCritical, targetPosition, 103 contentCount, vlvResultCode, contextID); 104 } 105 catch (Exception e) 106 { 107 LocalizableMessage message = 108 INFO_VLVRES_CONTROL_CANNOT_DECODE_VALUE.get(getExceptionMessage(e)); 109 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 110 } 111 } 112 113 /** {@inheritDoc} */ 114 public String getOID() 115 { 116 return OID_VLV_RESPONSE_CONTROL; 117 } 118 } 119 120 /** 121 * The Control Decoder that can be used to decode this control. 122 */ 123 public static final ControlDecoder<VLVResponseControl> DECODER = 124 new Decoder(); 125 126 /** The context ID for this VLV response control. */ 127 private ByteString contextID; 128 129 /** The content count estimating the total number of entries in the result set. */ 130 private int contentCount; 131 132 /** The offset of the target entry in the result set. */ 133 private int targetPosition; 134 135 /** The result code for the VLV operation. */ 136 private int vlvResultCode; 137 138 139 140 /** 141 * Creates a new VLV response control with the provided information. 142 * 143 * @param targetPosition The position of the target entry in the result set. 144 * @param contentCount The content count estimating the total number of 145 * entries in the result set. 146 * @param vlvResultCode The result code for the VLV operation. 147 */ 148 public VLVResponseControl(int targetPosition, int contentCount, 149 int vlvResultCode) 150 { 151 this(false, targetPosition, contentCount, vlvResultCode, null); 152 } 153 154 155 156 /** 157 * Creates a new VLV response control with the provided information. 158 * 159 * @param isCritical Indicates whether the control should be considered 160 * critical. 161 * @param targetPosition The position of the target entry in the result set. 162 * @param contentCount The content count estimating the total number of 163 * entries in the result set. 164 * @param vlvResultCode The result code for the VLV operation. 165 * @param contextID The context ID for this VLV response control. 166 */ 167 public VLVResponseControl(boolean isCritical, int targetPosition, 168 int contentCount, int vlvResultCode, 169 ByteString contextID) 170 { 171 super(OID_VLV_RESPONSE_CONTROL, isCritical); 172 173 this.targetPosition = targetPosition; 174 this.contentCount = contentCount; 175 this.vlvResultCode = vlvResultCode; 176 this.contextID = contextID; 177 } 178 179 180 181 /** 182 * Retrieves the position of the target entry in the result set. 183 * 184 * @return The position of the target entry in the result set. 185 */ 186 public int getTargetPosition() 187 { 188 return targetPosition; 189 } 190 191 192 193 /** 194 * Retrieves the estimated total number of entries in the result set. 195 * 196 * @return The estimated total number of entries in the result set. 197 */ 198 public int getContentCount() 199 { 200 return contentCount; 201 } 202 203 204 205 /** 206 * Retrieves the result code for the VLV operation. 207 * 208 * @return The result code for the VLV operation. 209 */ 210 public int getVLVResultCode() 211 { 212 return vlvResultCode; 213 } 214 215 216 217 /** 218 * Retrieves a context ID value that should be included in the next request 219 * to retrieve a page of the same result set. 220 * 221 * @return A context ID value that should be included in the next request to 222 * retrieve a page of the same result set, or {@code null} if there 223 * is no context ID. 224 */ 225 public ByteString getContextID() 226 { 227 return contextID; 228 } 229 230 231 232 /** 233 * Writes this control's value to an ASN.1 writer. The value (if any) must be 234 * written as an ASN1OctetString. 235 * 236 * @param writer The ASN.1 writer to use. 237 * @throws IOException If a problem occurs while writing to the stream. 238 */ 239 @Override 240 protected void writeValue(ASN1Writer writer) throws IOException { 241 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 242 243 writer.writeStartSequence(); 244 writer.writeInteger(targetPosition); 245 writer.writeInteger(contentCount); 246 writer.writeEnumerated(vlvResultCode); 247 if (contextID != null) 248 { 249 writer.writeOctetString(contextID); 250 } 251 writer.writeEndSequence(); 252 253 writer.writeEndSequence(); 254 } 255 256 257 258 /** 259 * Appends a string representation of this VLV request control to the provided 260 * buffer. 261 * 262 * @param buffer The buffer to which the information should be appended. 263 */ 264 @Override 265 public void toString(StringBuilder buffer) 266 { 267 buffer.append("VLVResponseControl(targetPosition="); 268 buffer.append(targetPosition); 269 buffer.append(", contentCount="); 270 buffer.append(contentCount); 271 buffer.append(", vlvResultCode="); 272 buffer.append(vlvResultCode); 273 274 if (contextID != null) 275 { 276 buffer.append(", contextID="); 277 buffer.append(contextID); 278 } 279 280 buffer.append(")"); 281 } 282} 283