diff --git a/java-sdk/ldapjdk/src/main/java/netscape/ldap/LDAPControl.java b/java-sdk/ldapjdk/src/main/java/netscape/ldap/LDAPControl.java index a2deb9f..ac0f698 100644 --- a/java-sdk/ldapjdk/src/main/java/netscape/ldap/LDAPControl.java +++ b/java-sdk/ldapjdk/src/main/java/netscape/ldap/LDAPControl.java @@ -51,6 +51,7 @@ import netscape.ldap.ber.stream.BERTag; import netscape.ldap.client.JDAPBERTagDecoder; import netscape.ldap.controls.LDAPEntryChangeControl; +import netscape.ldap.controls.LDAPPagedResultsControl; import netscape.ldap.controls.LDAPPasswordExpiredControl; import netscape.ldap.controls.LDAPPasswordExpiringControl; import netscape.ldap.controls.LDAPSortControl; @@ -534,6 +535,8 @@ public String toString() { LDAPSortControl.class ); LDAPControl.register( LDAPVirtualListResponse.VIRTUALLISTRESPONSE, LDAPVirtualListResponse.class ); + LDAPControl.register( LDAPPagedResultsControl.PAGEDSEARCH, + LDAPPagedResultsControl.class ); } catch (LDAPException e) { } } diff --git a/java-sdk/ldapjdk/src/main/java/netscape/ldap/controls/LDAPPagedResultsControl.java b/java-sdk/ldapjdk/src/main/java/netscape/ldap/controls/LDAPPagedResultsControl.java new file mode 100644 index 0000000..ef83ded --- /dev/null +++ b/java-sdk/ldapjdk/src/main/java/netscape/ldap/controls/LDAPPagedResultsControl.java @@ -0,0 +1,244 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +package netscape.ldap.controls; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import netscape.ldap.LDAPControl; +import netscape.ldap.LDAPException; +import netscape.ldap.ber.stream.BERElement; +import netscape.ldap.ber.stream.BERInteger; +import netscape.ldap.ber.stream.BEROctetString; +import netscape.ldap.ber.stream.BERSequence; +import netscape.ldap.client.JDAPBERTagDecoder; + +/** + * Represents an LDAP v3 server control that specifies a simple pagd result + * manipulation, which allows your LDAP client to get entries in multiple chunks + * (The OID for this control is 1.2.840.113556.1.4.319). + *

+ * + * To use paged search you create a "paged search" control that specifies + * the page size and the cookie from last search. You include the control in a + * search request. When a search is performed only a page is returned to the client + * and a new search has to be performed to access the following elements. + *

+ * + * + * When constructing an LDAPPagedResultsControl object, + * you can specify the following information: + *

+ * + *

+ *

+ * + * For example: + *

+ * ...
+ *      LDAPConnection ld = new LDAPConnection();
+ * 
+ *      try {
+ *          // Connect to server.
+ *          ld.connect(3,"ds.example.com", 3389, "cn=Directory Manager", "Secret.123");
+ *
+ *          LDAPPagedResultsControl pagecon = new LDAPPagedResultsControl(false, 3);
+ *          // Set the search constraints to use that control.
+ *          LDAPSearchConstraints cons = new LDAPSearchConstraints();
+ *          cons.setBatchSize(1);
+ *          cons.setServerControls(pagecon);
+ * 
+ *          // Start the paged search.
+ *          String cookie = null;
+ *          int pag = 1;
+ *          do{
+ *              LDAPSearchResults res = ld.search("ou=certificateRepository,ou=ca,dc=ca,dc=pki,dc=example,dc=com",
+ *                      LDAPv3.SCOPE_SUB, "(objectClass=certificateRecord)", null, false, cons);
+ * 
+ *              // Loop through the incoming results.
+ *              while (res.hasMoreElements()) {
+ *                  LDAPEntry entry = res.next();
+ *                  System.out.println("DN: " + entry.getDN());
+ *              }
+ *              for (LDAPControl c: res.getResponseControls()){
+ *                  if(c.getID().equals(LDAPPagedResultsControl.PAGEDSEARCH)){
+ *                      LDAPPagedResultsControl resC = (LDAPPagedResultsControl) c;
+ *                      cookie = resC.getCookie();
+ *                      System.out.println("The control for pag " + pag + " return a total or " + resC.getPageSize() + " and cookie " + resC.getCookie());
+ *                      if(cookie!=null){
+ *                          pagecon = new LDAPPagedResultsControl(false, 3, cookie);
+ *                          cons.setServerControls(pagecon);
+ *                      }
+ *                  }
+ *              }
+ *              pag++;
+ *          } while (cookie != null && !cookie.isEmpty());
+ *      } catch (Exception e) {
+ *          e.printStackTrace();
+ *      }
+ * 
+ * + * + * + * @see netscape.ldap.LDAPControl + * + * @author Marco Fargetta + */ +public class LDAPPagedResultsControl extends LDAPControl { + public final static String PAGEDSEARCH = "1.2.840.113556.1.4.319"; + private int m_pageSize; + private String m_cookie; + + /** + * Constructs an LDAPPagedResultsControl object + * that specifies a paged search. + * + * @param oid the oid of this control + * @param critical true if this control is critical to the search + * @param value the value associated with this control + * + * @see netscape.ldap.LDAPcontrol + * + * @throws LDAPException + * @throws IOException If value contains an invalid BER sequence. + * + * @see netscape.ldap.LDAPControl#register + */ + public LDAPPagedResultsControl(String oid, boolean critical, byte[] vals) + throws LDAPException, IOException { + super(oid, critical, vals); + if(!oid.equals(PAGEDSEARCH)) { + throw new LDAPException("oid must be LDAPPagedResultsControl.PAGEDSEARCH", + LDAPException.PARAM_ERROR); + } + + ByteArrayInputStream inStream = new ByteArrayInputStream( vals ); + JDAPBERTagDecoder decoder = new JDAPBERTagDecoder(); + int[] nRead = { 0 }; + + /* A sequence */ + BERSequence seq = (BERSequence) BERElement.getElement(decoder, inStream, nRead); + m_pageSize = ((BERInteger)seq.elementAt(0)).getValue(); + if(seq.size() == 1) { + return; + } + BEROctetString t = (BEROctetString)seq.elementAt(1); + byte[] cookie = t.getValue(); + m_cookie = cookie == null ? null : new String(t.getValue(), StandardCharsets.UTF_8); + } + + /** + * Constructs an LDAPPagedResultsControl object without a cookie. + * + * This is equivalent to + * LDAPPagedResultsControl(critical, pageSize, null) + * + * @param critical true if this control is critical to the search + * @param pageSize the number of entries to be returned with the following + * search request + * + * @see netscape.ldap.LDAPControl + */ + public LDAPPagedResultsControl(boolean critical, int pageSize) { + this(critical, pageSize, null); + } + + /** + * Constructs an LDAPPagedResultsControl. + * + * @param critical true if this control is critical to the search + * @param pageSize the number of entries to be returned with the following + * search request + * @param cookie The cookie to access the next entries. This is an opaque value + * returned by the server or null for the initial search + * + * @see netscape.ldap.LDAPControl + */ + public LDAPPagedResultsControl(boolean critical, int pageSize, String cookie) { + super(PAGEDSEARCH, critical, null); + this.m_pageSize = pageSize; + this.m_cookie = cookie; + m_value = generateNextPageValues(pageSize, cookie); + } + + /** + * Encode the parameters as requested for the control + * + * @param pageSize the number of entries to be returned with the following + * search request + * @param cookie The cookie to access the next entries (it is an opaque value + * returned by the server) + * @return + */ + private byte[] generateNextPageValues(int pageSize, String cookie) { + + BERSequence seq = new BERSequence(); + seq.addElement(new BERInteger(pageSize)); + if(cookie != null) { + seq.addElement(new BEROctetString(cookie)); + } else { + seq.addElement(new BEROctetString("")); + } + BEROctetString controlValue = new BEROctetString(flattenBER(seq)); + return controlValue.getValue(); + } + + /** + * Gets the page size for the search request. + * + * @return the number of entries to be returned when a search is requested to the server and + * the number of entries available when returned from the server. + */ + public int getPageSize() { + return m_pageSize; + } + + /** + * Gets the cookie for the following search request. + * + * @return the cookie to use for the following request or null if all entries + * have been returned. + */ + public String getCookie() { + return m_cookie; + } +}