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-2016 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 /** ControlDecoder implementation to decode this control from a ByteString. */ 062 private static final class Decoder 063 implements ControlDecoder<VLVResponseControl> 064 { 065 @Override 066 public VLVResponseControl decode(boolean isCritical, ByteString value) 067 throws DirectoryException 068 { 069 if (value == null) 070 { 071 LocalizableMessage message = INFO_VLVRES_CONTROL_NO_VALUE.get(); 072 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 073 } 074 075 ASN1Reader reader = ASN1.getReader(value); 076 try 077 { 078 reader.readStartSequence(); 079 080 int targetPosition = (int)reader.readInteger(); 081 int contentCount = (int)reader.readInteger(); 082 int vlvResultCode = (int)reader.readInteger(); 083 084 ByteString contextID = null; 085 if (reader.hasNextElement()) 086 { 087 contextID = reader.readOctetString(); 088 } 089 090 return new VLVResponseControl(isCritical, targetPosition, 091 contentCount, vlvResultCode, contextID); 092 } 093 catch (Exception e) 094 { 095 LocalizableMessage message = 096 INFO_VLVRES_CONTROL_CANNOT_DECODE_VALUE.get(getExceptionMessage(e)); 097 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 098 } 099 } 100 101 @Override 102 public String getOID() 103 { 104 return OID_VLV_RESPONSE_CONTROL; 105 } 106 } 107 108 /** The Control Decoder that can be used to decode this control. */ 109 public static final ControlDecoder<VLVResponseControl> DECODER = 110 new Decoder(); 111 112 /** The context ID for this VLV response control. */ 113 private ByteString contextID; 114 115 /** The content count estimating the total number of entries in the result set. */ 116 private int contentCount; 117 118 /** The offset of the target entry in the result set. */ 119 private int targetPosition; 120 121 /** The result code for the VLV operation. */ 122 private int vlvResultCode; 123 124 125 126 /** 127 * Creates a new VLV response control with the provided information. 128 * 129 * @param targetPosition The position of the target entry in the result set. 130 * @param contentCount The content count estimating the total number of 131 * entries in the result set. 132 * @param vlvResultCode The result code for the VLV operation. 133 */ 134 public VLVResponseControl(int targetPosition, int contentCount, 135 int vlvResultCode) 136 { 137 this(false, targetPosition, contentCount, vlvResultCode, null); 138 } 139 140 141 142 /** 143 * Creates a new VLV response control with the provided information. 144 * 145 * @param isCritical Indicates whether the control should be considered 146 * critical. 147 * @param targetPosition The position of the target entry in the result set. 148 * @param contentCount The content count estimating the total number of 149 * entries in the result set. 150 * @param vlvResultCode The result code for the VLV operation. 151 * @param contextID The context ID for this VLV response control. 152 */ 153 public VLVResponseControl(boolean isCritical, int targetPosition, 154 int contentCount, int vlvResultCode, 155 ByteString contextID) 156 { 157 super(OID_VLV_RESPONSE_CONTROL, isCritical); 158 159 this.targetPosition = targetPosition; 160 this.contentCount = contentCount; 161 this.vlvResultCode = vlvResultCode; 162 this.contextID = contextID; 163 } 164 165 166 167 /** 168 * Retrieves the position of the target entry in the result set. 169 * 170 * @return The position of the target entry in the result set. 171 */ 172 public int getTargetPosition() 173 { 174 return targetPosition; 175 } 176 177 178 179 /** 180 * Retrieves the estimated total number of entries in the result set. 181 * 182 * @return The estimated total number of entries in the result set. 183 */ 184 public int getContentCount() 185 { 186 return contentCount; 187 } 188 189 190 191 /** 192 * Retrieves the result code for the VLV operation. 193 * 194 * @return The result code for the VLV operation. 195 */ 196 public int getVLVResultCode() 197 { 198 return vlvResultCode; 199 } 200 201 202 203 /** 204 * Retrieves a context ID value that should be included in the next request 205 * to retrieve a page of the same result set. 206 * 207 * @return A context ID value that should be included in the next request to 208 * retrieve a page of the same result set, or {@code null} if there 209 * is no context ID. 210 */ 211 public ByteString getContextID() 212 { 213 return contextID; 214 } 215 216 217 218 /** 219 * Writes this control's value to an ASN.1 writer. The value (if any) must be 220 * written as an ASN1OctetString. 221 * 222 * @param writer The ASN.1 writer to use. 223 * @throws IOException If a problem occurs while writing to the stream. 224 */ 225 @Override 226 protected void writeValue(ASN1Writer writer) throws IOException { 227 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 228 229 writer.writeStartSequence(); 230 writer.writeInteger(targetPosition); 231 writer.writeInteger(contentCount); 232 writer.writeEnumerated(vlvResultCode); 233 if (contextID != null) 234 { 235 writer.writeOctetString(contextID); 236 } 237 writer.writeEndSequence(); 238 239 writer.writeEndSequence(); 240 } 241 242 243 244 /** 245 * Appends a string representation of this VLV request control to the provided 246 * buffer. 247 * 248 * @param buffer The buffer to which the information should be appended. 249 */ 250 @Override 251 public void toString(StringBuilder buffer) 252 { 253 buffer.append("VLVResponseControl(targetPosition="); 254 buffer.append(targetPosition); 255 buffer.append(", contentCount="); 256 buffer.append(contentCount); 257 buffer.append(", vlvResultCode="); 258 buffer.append(vlvResultCode); 259 260 if (contextID != null) 261 { 262 buffer.append(", contextID="); 263 buffer.append(contextID); 264 } 265 266 buffer.append(")"); 267 } 268} 269