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 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2015 ForgeRock AS. 016 */ 017package org.opends.server.controls; 018 019import org.forgerock.i18n.LocalizableMessage; 020 021import org.forgerock.i18n.slf4j.LocalizedLogger; 022import static org.opends.messages.ProtocolMessages.*; 023import static org.opends.server.util.ServerConstants.OID_PAGED_RESULTS_CONTROL; 024 025import org.forgerock.opendj.io.*; 026import org.opends.server.types.*; 027import org.forgerock.opendj.ldap.ResultCode; 028import org.forgerock.opendj.ldap.ByteString; 029import java.io.IOException; 030 031/** 032 * This class represents a paged results control value as defined in 033 * RFC 2696. 034 * 035 * The searchControlValue is an OCTET STRING wrapping the BER-encoded 036 * version of the following SEQUENCE: 037 * 038 * <pre> 039 * realSearchControlValue ::= SEQUENCE { 040 * size INTEGER (0..maxInt), 041 * -- requested page size from client 042 * -- result set size estimate from server 043 * cookie OCTET STRING 044 * } 045 * </pre> 046 */ 047public class PagedResultsControl extends Control 048{ 049 /** 050 * ControlDecoder implementation to decode this control from a ByteString. 051 */ 052 private static final class Decoder 053 implements ControlDecoder<PagedResultsControl> 054 { 055 /** {@inheritDoc} */ 056 public PagedResultsControl decode(boolean isCritical, ByteString value) 057 throws DirectoryException 058 { 059 if (value == null) 060 { 061 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_NULL.get(); 062 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 063 } 064 065 ASN1Reader reader = ASN1.getReader(value); 066 try 067 { 068 reader.readStartSequence(); 069 } 070 catch (Exception e) 071 { 072 logger.traceException(e); 073 074 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE.get(e); 075 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 076 } 077 078 int size; 079 try 080 { 081 size = (int)reader.readInteger(); 082 } 083 catch (Exception e) 084 { 085 logger.traceException(e); 086 087 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SIZE.get(e); 088 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 089 } 090 091 ByteString cookie; 092 try 093 { 094 cookie = reader.readOctetString(); 095 } 096 catch (Exception e) 097 { 098 logger.traceException(e); 099 100 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_COOKIE.get(e); 101 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 102 } 103 104 try 105 { 106 reader.readEndSequence(); 107 } 108 catch (Exception e) 109 { 110 logger.traceException(e); 111 112 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE.get(e); 113 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 114 } 115 116 return new PagedResultsControl(isCritical, size, cookie); 117 } 118 119 public String getOID() 120 { 121 return OID_PAGED_RESULTS_CONTROL; 122 } 123 124 } 125 126 /** 127 * The Control Decoder that can be used to decode this control. 128 */ 129 public static final ControlDecoder<PagedResultsControl> DECODER = 130 new Decoder(); 131 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 132 133 134 135 /** 136 * The control value size element, which is either the requested page size 137 * from the client, or the result set size estimate from the server. 138 */ 139 private int size; 140 141 142 /** 143 * The control value cookie element. 144 */ 145 private ByteString cookie; 146 147 148 /** 149 * Creates a new paged results control with the specified information. 150 * 151 * @param isCritical Indicates whether this control should be considered 152 * critical in processing the request. 153 * @param size The size element. 154 * @param cookie The cookie element. 155 */ 156 public PagedResultsControl(boolean isCritical, int size, 157 ByteString cookie) 158 { 159 super(OID_PAGED_RESULTS_CONTROL, isCritical); 160 161 162 this.size = size; 163 if(cookie == null) 164 { 165 this.cookie=ByteString.empty(); 166 } 167 else 168 { 169 this.cookie = cookie; 170 } 171 } 172 173 174 /** 175 * Writes this control's value to an ASN.1 writer. The value (if any) must be 176 * written as an ASN1OctetString. 177 * 178 * @param writer The ASN.1 output stream to write to. 179 * @throws IOException If a problem occurs while writing to the stream. 180 */ 181 @Override 182 public void writeValue(ASN1Writer writer) throws IOException { 183 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 184 185 writer.writeStartSequence(); 186 writer.writeInteger(size); 187 writer.writeOctetString(cookie); 188 writer.writeEndSequence(); 189 190 writer.writeEndSequence(); 191 } 192 193 194 /** 195 * Get the control value size element, which is either the requested page size 196 * from the client, or the result set size estimate from the server. 197 * @return The control value size element. 198 */ 199 public int getSize() 200 { 201 return size; 202 } 203 204 205 206 /** 207 * Get the control value cookie element. 208 * @return The control value cookie element. 209 */ 210 public ByteString getCookie() 211 { 212 return cookie; 213 } 214}