1. /*
  2. * @(#)PagedResultsControl.java 1.4 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.naming.ldap;
  8. import java.io.IOException;
  9. import com.sun.jndi.ldap.Ber;
  10. import com.sun.jndi.ldap.BerEncoder;
  11. /**
  12. * Requests that the results of a search operation be returned by the LDAP
  13. * server in batches of a specified size.
  14. * The requestor controls the rate at which batches are returned by the rate
  15. * at which it invokes search operations.
  16. * <p>
  17. * The following code sample shows how the class may be used:
  18. * <pre>
  19. *
  20. * // Open an LDAP association
  21. * LdapContext ctx = new InitialLdapContext();
  22. *
  23. * // Activate paged results
  24. * int pageSize = 20; // 20 entries per page
  25. * byte[] cookie = null;
  26. * int total;
  27. * ctx.setRequestControls(new Control[]{
  28. * new PagedResultsControl(pageSize, Control.CRITICAL) });
  29. *
  30. * do {
  31. * // Perform the search
  32. * NamingEnumeration results =
  33. * ctx.search("", "(objectclass=*)", new SearchControls());
  34. *
  35. * // Iterate over a batch of search results
  36. * while (results != null && results.hasMore()) {
  37. * // Display an entry
  38. * SearchResult entry = (SearchResult)results.next();
  39. * System.out.println(entry.getName());
  40. * System.out.println(entry.getAttributes());
  41. *
  42. * // Handle the entry's response controls (if any)
  43. * if (entry instanceof HasControls) {
  44. * // ((HasControls)entry).getControls();
  45. * }
  46. * }
  47. * // Examine the paged results control response
  48. * Control[] controls = ctx.getResponseControls();
  49. * if (controls != null) {
  50. * for (int i = 0; i < controls.length; i++) {
  51. * if (controls[i] instanceof PagedResultsResponseControl) {
  52. * PagedResultsResponseControl prrc =
  53. * (PagedResultsResponseControl)controls[i];
  54. * total = prrc.getResultSize();
  55. * cookie = prrc.getCookie();
  56. * } else {
  57. * // Handle other response controls (if any)
  58. * }
  59. * }
  60. * }
  61. *
  62. * // Re-activate paged results
  63. * ctx.setRequestControls(new Control[]{
  64. * new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
  65. * } while (cookie != null);
  66. *
  67. * // Close the LDAP association
  68. * ctx.close();
  69. * ...
  70. *
  71. * </pre>
  72. * <p>
  73. * This class implements the LDAPv3 Control for paged-results as defined in
  74. * <a href="http://www.ietf.org/rfc/rfc2696.txt">RFC 2696</a>.
  75. *
  76. * The control's value has the following ASN.1 definition:
  77. * <pre>
  78. *
  79. * realSearchControlValue ::= SEQUENCE {
  80. * size INTEGER (0..maxInt),
  81. * -- requested page size from client
  82. * -- result set size estimate from server
  83. * cookie OCTET STRING
  84. * }
  85. *
  86. * </pre>
  87. *
  88. * @since 1.5
  89. * @see PagedResultsResponseControl
  90. * @author Vincent Ryan
  91. */
  92. final public class PagedResultsControl extends BasicControl {
  93. /**
  94. * The paged-results control's assigned object identifier
  95. * is 1.2.840.113556.1.4.319.
  96. */
  97. public static final String OID = "1.2.840.113556.1.4.319";
  98. private static final byte[] EMPTY_COOKIE = new byte[0];
  99. private static final long serialVersionUID = 6684806685736844298L;
  100. /**
  101. * Constructs a control to set the number of entries to be returned per
  102. * page of results.
  103. *
  104. * @param pageSize The number of entries to return in a page.
  105. * @param criticality If true then the server must honor the control
  106. * and return search results as indicated by
  107. * pageSize or refuse to perform the search.
  108. * If false, then the server need not honor the
  109. * control.
  110. * @exception IOException If an error was encountered while encoding the
  111. * supplied arguments into a control.
  112. */
  113. public PagedResultsControl(int pageSize, boolean criticality)
  114. throws IOException {
  115. super(OID, criticality, null);
  116. value = setEncodedValue(pageSize, EMPTY_COOKIE);
  117. }
  118. /**
  119. * Constructs a control to set the number of entries to be returned per
  120. * page of results. The cookie is provided by the server and may be
  121. * obtained from the paged-results response control.
  122. * <p>
  123. * A sequence of paged-results can be abandoned by setting the pageSize
  124. * to zero and setting the cookie to the last cookie received from the
  125. * server.
  126. *
  127. * @param pageSize The number of entries to return in a page.
  128. * @param cookie A possibly null server-generated cookie.
  129. * @param criticality If true then the server must honor the control
  130. * and return search results as indicated by
  131. * pageSize or refuse to perform the search.
  132. * If false, then the server need not honor the
  133. * control.
  134. * @exception IOException If an error was encountered while encoding the
  135. * supplied arguments into a control.
  136. */
  137. public PagedResultsControl(int pageSize, byte[] cookie,
  138. boolean criticality) throws IOException {
  139. super(OID, criticality, null);
  140. if (cookie == null) {
  141. cookie = EMPTY_COOKIE;
  142. }
  143. value = setEncodedValue(pageSize, cookie);
  144. }
  145. /*
  146. * Encodes the paged-results control's value using ASN.1 BER.
  147. * The result includes the BER tag and length for the control's value but
  148. * does not include the control's object identifier and criticality setting.
  149. *
  150. * @param pageSize The number of entries to return in a page.
  151. * @param cookie A non-null server-generated cookie.
  152. * @return A possibly null byte array representing the ASN.1 BER encoded
  153. * value of the LDAP paged-results control.
  154. * @exception IOException If a BER encoding error occurs.
  155. */
  156. private byte[] setEncodedValue(int pageSize, byte[] cookie)
  157. throws IOException {
  158. // build the ASN.1 encoding
  159. BerEncoder ber = new BerEncoder(10 + cookie.length);
  160. ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
  161. ber.encodeInt(pageSize);
  162. ber.encodeOctetString(cookie, Ber.ASN_OCTET_STR);
  163. ber.endSeq();
  164. return ber.getTrimmedBuf();
  165. }
  166. }