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-2016 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 /** ControlDecoder implementation to decode this control from a ByteString. */ 050 private static final class Decoder 051 implements ControlDecoder<PagedResultsControl> 052 { 053 @Override 054 public PagedResultsControl decode(boolean isCritical, ByteString value) 055 throws DirectoryException 056 { 057 if (value == null) 058 { 059 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_NULL.get(); 060 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message); 061 } 062 063 ASN1Reader reader = ASN1.getReader(value); 064 try 065 { 066 reader.readStartSequence(); 067 } 068 catch (Exception e) 069 { 070 logger.traceException(e); 071 072 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE.get(e); 073 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 074 } 075 076 int size; 077 try 078 { 079 size = (int)reader.readInteger(); 080 } 081 catch (Exception e) 082 { 083 logger.traceException(e); 084 085 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SIZE.get(e); 086 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 087 } 088 089 ByteString cookie; 090 try 091 { 092 cookie = reader.readOctetString(); 093 } 094 catch (Exception e) 095 { 096 logger.traceException(e); 097 098 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_COOKIE.get(e); 099 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 100 } 101 102 try 103 { 104 reader.readEndSequence(); 105 } 106 catch (Exception e) 107 { 108 logger.traceException(e); 109 110 LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE.get(e); 111 throw new DirectoryException(ResultCode.PROTOCOL_ERROR, message, e); 112 } 113 114 return new PagedResultsControl(isCritical, size, cookie); 115 } 116 117 @Override 118 public String getOID() 119 { 120 return OID_PAGED_RESULTS_CONTROL; 121 } 122 123 } 124 125 /** The Control Decoder that can be used to decode this control. */ 126 public static final ControlDecoder<PagedResultsControl> DECODER = 127 new Decoder(); 128 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 129 130 131 132 /** 133 * The control value size element, which is either the requested page size 134 * from the client, or the result set size estimate from the server. 135 */ 136 private int size; 137 138 139 /** The control value cookie element. */ 140 private ByteString cookie; 141 142 143 /** 144 * Creates a new paged results control with the specified information. 145 * 146 * @param isCritical Indicates whether this control should be considered 147 * critical in processing the request. 148 * @param size The size element. 149 * @param cookie The cookie element. 150 */ 151 public PagedResultsControl(boolean isCritical, int size, 152 ByteString cookie) 153 { 154 super(OID_PAGED_RESULTS_CONTROL, isCritical); 155 156 157 this.size = size; 158 if(cookie == null) 159 { 160 this.cookie=ByteString.empty(); 161 } 162 else 163 { 164 this.cookie = cookie; 165 } 166 } 167 168 @Override 169 public void writeValue(ASN1Writer writer) throws IOException { 170 writer.writeStartSequence(ASN1.UNIVERSAL_OCTET_STRING_TYPE); 171 172 writer.writeStartSequence(); 173 writer.writeInteger(size); 174 writer.writeOctetString(cookie); 175 writer.writeEndSequence(); 176 177 writer.writeEndSequence(); 178 } 179 180 181 /** 182 * Get the control value size element, which is either the requested page size 183 * from the client, or the result set size estimate from the server. 184 * @return The control value size element. 185 */ 186 public int getSize() 187 { 188 return size; 189 } 190 191 192 193 /** 194 * Get the control value cookie element. 195 * @return The control value cookie element. 196 */ 197 public ByteString getCookie() 198 { 199 return cookie; 200 } 201}