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}