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