/* * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.naming.ldap;import java.io.IOException;import com.sun.jndi.ldap.Ber;import com.sun.jndi.ldap.BerEncoder;/** * Requests that the results of a search operation be sorted by the LDAP server * before being returned. * The sort criteria are specified using an ordered list of one or more sort * keys, with associated sort parameters. * Search results are sorted at the LDAP server according to the parameters * supplied in the sort control and then returned to the requestor. If sorting * is not supported at the server (and the sort control is marked as critical) * then the search operation is not performed and an error is returned. * <p> * The following code sample shows how the class may be used: * <pre> * * // Open an LDAP association * LdapContext ctx = new InitialLdapContext(); * * // Activate sorting * String sortKey = "cn"; * ctx.setRequestControls(new Control[]{ * new SortControl(sortKey, Control.CRITICAL) }); * * // Perform a search * NamingEnumeration results = * ctx.search("", "(objectclass=*)", new SearchControls()); * * // Iterate over search results * while (results != null && results.hasMore()) { * // Display an entry * SearchResult entry = (SearchResult)results.next(); * System.out.println(entry.getName()); * System.out.println(entry.getAttributes()); * * // Handle the entry's response controls (if any) * if (entry instanceof HasControls) { * // ((HasControls)entry).getControls(); * } * } * // Examine the sort control response * Control[] controls = ctx.getResponseControls(); * if (controls != null) { * for (int i = 0; i < controls.length; i++) { * if (controls[i] instanceof SortResponseControl) { * SortResponseControl src = (SortResponseControl)controls[i]; * if (! src.isSorted()) { * throw src.getException(); * } * } else { * // Handle other response controls (if any) * } * } * } * * // Close the LDAP association * ctx.close(); * ... * * </pre> * <p> * This class implements the LDAPv3 Request Control for server-side sorting * as defined in * <a href="http://www.ietf.org/rfc/rfc2891.txt">RFC 2891</a>. * * The control's value has the following ASN.1 definition: * <pre> * * SortKeyList ::= SEQUENCE OF SEQUENCE { * attributeType AttributeDescription, * orderingRule [0] MatchingRuleId OPTIONAL, * reverseOrder [1] BOOLEAN DEFAULT FALSE } * * </pre> * * @since 1.5 * @see SortKey * @see SortResponseControl * @author Vincent Ryan */final public class SortControl extends BasicControl { /** * The server-side sort control's assigned object identifier * is 1.2.840.113556.1.4.473. */ public static final String OID = "1.2.840.113556.1.4.473"; private static final long serialVersionUID = -1965961680233330744L; /** * Constructs a control to sort on a single attribute in ascending order. * Sorting will be performed using the ordering matching rule defined * for use with the specified attribute. * * @param sortBy An attribute ID to sort by. * @param criticality If true then the server must honor the control * and return the search results sorted as * requested or refuse to perform the search. * If false, then the server need not honor the * control. * @exception IOException If an error was encountered while encoding the * supplied arguments into a control. */ public SortControl(String sortBy, boolean criticality) throws IOException { super(OID, criticality, null); super.value = setEncodedValue(new SortKey[]{ new SortKey(sortBy) }); } /** * Constructs a control to sort on a list of attributes in ascending order. * Sorting will be performed using the ordering matching rule defined * for use with each of the specified attributes. * * @param sortBy A non-null list of attribute IDs to sort by. * The list is in order of highest to lowest sort key * precedence. * @param criticality If true then the server must honor the control * and return the search results sorted as * requested or refuse to perform the search. * If false, then the server need not honor the * control. * @exception IOException If an error was encountered while encoding the * supplied arguments into a control. */ public SortControl(String[] sortBy, boolean criticality) throws IOException { super(OID, criticality, null); SortKey[] sortKeys = new SortKey[sortBy.length]; for (int i = 0; i < sortBy.length; i++) { sortKeys[i] = new SortKey(sortBy[i]); } super.value = setEncodedValue(sortKeys); } /** * Constructs a control to sort on a list of sort keys. * Each sort key specifies the sort order and ordering matching rule to use. * * @param sortBy A non-null list of keys to sort by. * The list is in order of highest to lowest sort key * precedence. * @param criticality If true then the server must honor the control * and return the search results sorted as * requested or refuse to perform the search. * If false, then the server need not honor the * control. * @exception IOException If an error was encountered while encoding the * supplied arguments into a control. */ public SortControl(SortKey[] sortBy, boolean criticality) throws IOException { super(OID, criticality, null); super.value = setEncodedValue(sortBy); } /* * Encodes the sort control's value using ASN.1 BER. * The result includes the BER tag and length for the control's value but * does not include the control's object identifer and criticality setting. * * @param sortKeys A non-null list of keys to sort by. * @return A possibly null byte array representing the ASN.1 BER encoded * value of the sort control. * @exception IOException If a BER encoding error occurs. */ private byte[] setEncodedValue(SortKey[] sortKeys) throws IOException { // build the ASN.1 BER encoding BerEncoder ber = new BerEncoder(30 * sortKeys.length + 10); String matchingRule; ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); for (int i = 0; i < sortKeys.length; i++) { ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR); ber.encodeString(sortKeys[i].getAttributeID(), true); // v3 if ((matchingRule = sortKeys[i].getMatchingRuleID()) != null) { ber.encodeString(matchingRule, (Ber.ASN_CONTEXT | 0), true); } if (! sortKeys[i].isAscending()) { ber.encodeBoolean(true, (Ber.ASN_CONTEXT | 1)); } ber.endSeq(); } ber.endSeq(); return ber.getTrimmedBuf(); }}
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.naming.ldap;
import java.io.IOException;
import com.sun.jndi.ldap.Ber;
import com.sun.jndi.ldap.BerEncoder;
/**
* Requests that the results of a search operation be sorted by the LDAP server
* before being returned.
* The sort criteria are specified using an ordered list of one or more sort
* keys, with associated sort parameters.
* Search results are sorted at the LDAP server according to the parameters
* supplied in the sort control and then returned to the requestor. If sorting
* is not supported at the server (and the sort control is marked as critical)
* then the search operation is not performed and an error is returned.
* <p>
* The following code sample shows how the class may be used:
* <pre>
*
* // Open an LDAP association
* LdapContext ctx = new InitialLdapContext();
*
* // Activate sorting
* String sortKey = "cn";
* ctx.setRequestControls(new Control[]{
* new SortControl(sortKey, Control.CRITICAL) });
*
* // Perform a search
* NamingEnumeration results =
* ctx.search("", "(objectclass=*)", new SearchControls());
*
* // Iterate over search results
* while (results != null && results.hasMore()) {
* // Display an entry
* SearchResult entry = (SearchResult)results.next();
* System.out.println(entry.getName());
* System.out.println(entry.getAttributes());
*
* // Handle the entry's response controls (if any)
* if (entry instanceof HasControls) {
* // ((HasControls)entry).getControls();
* }
* }
* // Examine the sort control response
* Control[] controls = ctx.getResponseControls();
* if (controls != null) {
* for (int i = 0; i < controls.length; i++) {
* if (controls[i] instanceof SortResponseControl) {
* SortResponseControl src = (SortResponseControl)controls[i];
* if (! src.isSorted()) {
* throw src.getException();
* }
* } else {
* // Handle other response controls (if any)
* }
* }
* }
*
* // Close the LDAP association
* ctx.close();
* ...
*
* </pre>
* <p>
* This class implements the LDAPv3 Request Control for server-side sorting
* as defined in
* <a href="http://www.ietf.org/rfc/rfc2891.txt">RFC 2891</a>.
*
* The control's value has the following ASN.1 definition:
* <pre>
*
* SortKeyList ::= SEQUENCE OF SEQUENCE {
* attributeType AttributeDescription,
* orderingRule [0] MatchingRuleId OPTIONAL,
* reverseOrder [1] BOOLEAN DEFAULT FALSE }
*
* </pre>
*
* @since 1.5
* @see SortKey
* @see SortResponseControl
* @author Vincent Ryan
*/
final public class SortControl extends BasicControl {
/**
* The server-side sort control's assigned object identifier
* is 1.2.840.113556.1.4.473.
*/
public static final String OID = "1.2.840.113556.1.4.473";
private static final long serialVersionUID = -1965961680233330744L;
/**
* Constructs a control to sort on a single attribute in ascending order.
* Sorting will be performed using the ordering matching rule defined
* for use with the specified attribute.
*
* @param sortBy An attribute ID to sort by.
* @param criticality If true then the server must honor the control
* and return the search results sorted as
* requested or refuse to perform the search.
* If false, then the server need not honor the
* control.
* @exception IOException If an error was encountered while encoding the
* supplied arguments into a control.
*/
public SortControl(String sortBy, boolean criticality) throws IOException {
super(OID, criticality, null);
super.value = setEncodedValue(new SortKey[]{ new SortKey(sortBy) });
}
/**
* Constructs a control to sort on a list of attributes in ascending order.
* Sorting will be performed using the ordering matching rule defined
* for use with each of the specified attributes.
*
* @param sortBy A non-null list of attribute IDs to sort by.
* The list is in order of highest to lowest sort key
* precedence.
* @param criticality If true then the server must honor the control
* and return the search results sorted as
* requested or refuse to perform the search.
* If false, then the server need not honor the
* control.
* @exception IOException If an error was encountered while encoding the
* supplied arguments into a control.
*/
public SortControl(String[] sortBy, boolean criticality)
throws IOException {
super(OID, criticality, null);
SortKey[] sortKeys = new SortKey[sortBy.length];
for (int i = 0; i < sortBy.length; i++) {
sortKeys[i] = new SortKey(sortBy[i]);
}
super.value = setEncodedValue(sortKeys);
}
/**
* Constructs a control to sort on a list of sort keys.
* Each sort key specifies the sort order and ordering matching rule to use.
*
* @param sortBy A non-null list of keys to sort by.
* The list is in order of highest to lowest sort key
* precedence.
* @param criticality If true then the server must honor the control
* and return the search results sorted as
* requested or refuse to perform the search.
* If false, then the server need not honor the
* control.
* @exception IOException If an error was encountered while encoding the
* supplied arguments into a control.
*/
public SortControl(SortKey[] sortBy, boolean criticality)
throws IOException {
super(OID, criticality, null);
super.value = setEncodedValue(sortBy);
}
/*
* Encodes the sort control's value using ASN.1 BER.
* The result includes the BER tag and length for the control's value but
* does not include the control's object identifer and criticality setting.
*
* @param sortKeys A non-null list of keys to sort by.
* @return A possibly null byte array representing the ASN.1 BER encoded
* value of the sort control.
* @exception IOException If a BER encoding error occurs.
*/
private byte[] setEncodedValue(SortKey[] sortKeys) throws IOException {
// build the ASN.1 BER encoding
BerEncoder ber = new BerEncoder(30 * sortKeys.length + 10);
String matchingRule;
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
for (int i = 0; i < sortKeys.length; i++) {
ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
ber.encodeString(sortKeys[i].getAttributeID(), true); // v3
if ((matchingRule = sortKeys[i].getMatchingRuleID()) != null) {
ber.encodeString(matchingRule, (Ber.ASN_CONTEXT | 0), true);
}
if (! sortKeys[i].isAscending()) {
ber.encodeBoolean(true, (Ber.ASN_CONTEXT | 1));
}
ber.endSeq();
}
ber.endSeq();
return ber.getTrimmedBuf();
}
}