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
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.controls;
028 import org.opends.messages.Message;
029
030 import static org.opends.server.loggers.debug.DebugLogger.*;
031 import org.opends.server.loggers.debug.DebugTracer;
032 import org.opends.server.types.DebugLogLevel;
033 import static org.opends.messages.ProtocolMessages.*;
034 import static org.opends.server.protocols.ldap.LDAPResultCode.PROTOCOL_ERROR;
035 import static org.opends.server.util.ServerConstants.OID_PAGED_RESULTS_CONTROL;
036
037 import org.opends.server.protocols.asn1.ASN1Element;
038 import org.opends.server.protocols.asn1.ASN1Integer;
039 import org.opends.server.protocols.asn1.ASN1OctetString;
040 import org.opends.server.protocols.asn1.ASN1Sequence;
041 import org.opends.server.types.Control;
042 import org.opends.server.types.LDAPException;
043
044 import java.util.ArrayList;
045
046 /**
047 * This class represents a paged results control value as defined in
048 * RFC 2696.
049 *
050 * The searchControlValue is an OCTET STRING wrapping the BER-encoded
051 * version of the following SEQUENCE:
052 *
053 * realSearchControlValue ::= SEQUENCE {
054 * size INTEGER (0..maxInt),
055 * -- requested page size from client
056 * -- result set size estimate from server
057 * cookie OCTET STRING
058 * }
059 *
060 */
061 public class PagedResultsControl extends Control
062 {
063 /**
064 * The tracer object for the debug logger.
065 */
066 private static final DebugTracer TRACER = getTracer();
067
068
069
070 /**
071 * The control value size element, which is either the requested page size
072 * from the client, or the result set size estimate from the server.
073 */
074 private int size;
075
076
077 /**
078 * The control value cookie element.
079 */
080 private ASN1OctetString cookie;
081
082
083 /**
084 * Creates a new paged results control with the specified information.
085 *
086 * @param isCritical Indicates whether this control should be considered
087 * critical in processing the request.
088 * @param size The size element.
089 * @param cookie The cookie element.
090 */
091 public PagedResultsControl(boolean isCritical, int size,
092 ASN1OctetString cookie)
093 {
094 super(OID_PAGED_RESULTS_CONTROL, isCritical);
095
096
097 this.size = size;
098 this.cookie = cookie;
099
100 this.setValue(encode());
101 }
102
103
104 /**
105 * Creates a new paged results control by decoding the given information.
106 *
107 * @param isCritical Indicates whether the control is considered
108 * critical in processing the request.
109 * @param value The value of the control.
110 *
111 * @throws LDAPException If a problem occurs while attempting to decode the
112 * provided information as a paged results control.
113 */
114 public PagedResultsControl(boolean isCritical, ASN1OctetString value)
115 throws LDAPException
116 {
117 super(OID_PAGED_RESULTS_CONTROL, isCritical, value);
118
119 if (value == null)
120 {
121 Message message = ERR_LDAP_PAGED_RESULTS_DECODE_NULL.get();
122 throw new LDAPException(PROTOCOL_ERROR, message);
123 }
124
125 ArrayList<ASN1Element> elements;
126 try
127 {
128 ASN1Element sequence = ASN1Element.decode(value.value());
129 elements = sequence.decodeAsSequence().elements();
130 }
131 catch (Exception e)
132 {
133 if (debugEnabled())
134 {
135 TRACER.debugCaught(DebugLogLevel.ERROR, e);
136 }
137
138 Message message =
139 ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE.get(String.valueOf(e));
140 throw new LDAPException(PROTOCOL_ERROR, message, e);
141 }
142
143 int numElements = elements.size();
144 if (numElements != 2)
145 {
146 Message message =
147 ERR_LDAP_PAGED_RESULTS_DECODE_INVALID_ELEMENT_COUNT.get(numElements);
148 throw new LDAPException(PROTOCOL_ERROR, message);
149 }
150
151 try
152 {
153 size = elements.get(0).decodeAsInteger().intValue();
154 }
155 catch (Exception e)
156 {
157 if (debugEnabled())
158 {
159 TRACER.debugCaught(DebugLogLevel.ERROR, e);
160 }
161
162 Message message =
163 ERR_LDAP_PAGED_RESULTS_DECODE_SIZE.get(String.valueOf(e));
164 throw new LDAPException(PROTOCOL_ERROR, message, e);
165 }
166
167 try
168 {
169 cookie = elements.get(1).decodeAsOctetString();
170 }
171 catch (Exception e)
172 {
173 if (debugEnabled())
174 {
175 TRACER.debugCaught(DebugLogLevel.ERROR, e);
176 }
177
178 Message message =
179 ERR_LDAP_PAGED_RESULTS_DECODE_COOKIE.get(String.valueOf(e));
180 throw new LDAPException(PROTOCOL_ERROR, message, e);
181 }
182 }
183
184
185 /**
186 * Encodes this control value to an ASN.1 element.
187 *
188 * @return The ASN.1 element containing the encoded control value.
189 */
190 public ASN1OctetString encode()
191 {
192 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
193 elements.add(new ASN1Integer(size));
194 elements.add(cookie);
195
196 ASN1Sequence sequence = new ASN1Sequence(elements);
197 return new ASN1OctetString(sequence.encode());
198 }
199
200
201 /**
202 * Get the control value size element, which is either the requested page size
203 * from the client, or the result set size estimate from the server.
204 * @return The control value size element.
205 */
206 public int getSize()
207 {
208 return size;
209 }
210
211
212
213 /**
214 * Get the control value cookie element.
215 * @return The control value cookie element.
216 */
217 public ASN1OctetString getCookie()
218 {
219 return cookie;
220 }
221 }