blob: f13a2f1f6b83b463971dd49049aedefd28c18848 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.naming.ldap;
27
28import java.io.IOException;
29import com.sun.jndi.ldap.Ber;
30import com.sun.jndi.ldap.BerEncoder;
31
32/**
33 * Requests that the results of a search operation be sorted by the LDAP server
34 * before being returned.
35 * The sort criteria are specified using an ordered list of one or more sort
36 * keys, with associated sort parameters.
37 * Search results are sorted at the LDAP server according to the parameters
38 * supplied in the sort control and then returned to the requestor. If sorting
39 * is not supported at the server (and the sort control is marked as critical)
40 * then the search operation is not performed and an error is returned.
41 * <p>
42 * The following code sample shows how the class may be used:
43 * <pre>
44 *
45 * // Open an LDAP association
46 * LdapContext ctx = new InitialLdapContext();
47 *
48 * // Activate sorting
49 * String sortKey = "cn";
50 * ctx.setRequestControls(new Control[]{
51 * new SortControl(sortKey, Control.CRITICAL) });
52 *
53 * // Perform a search
54 * NamingEnumeration results =
55 * ctx.search("", "(objectclass=*)", new SearchControls());
56 *
57 * // Iterate over search results
58 * while (results != null && results.hasMore()) {
59 * // Display an entry
60 * SearchResult entry = (SearchResult)results.next();
61 * System.out.println(entry.getName());
62 * System.out.println(entry.getAttributes());
63 *
64 * // Handle the entry's response controls (if any)
65 * if (entry instanceof HasControls) {
66 * // ((HasControls)entry).getControls();
67 * }
68 * }
69 * // Examine the sort control response
70 * Control[] controls = ctx.getResponseControls();
71 * if (controls != null) {
72 * for (int i = 0; i < controls.length; i++) {
73 * if (controls[i] instanceof SortResponseControl) {
74 * SortResponseControl src = (SortResponseControl)controls[i];
75 * if (! src.isSorted()) {
76 * throw src.getException();
77 * }
78 * } else {
79 * // Handle other response controls (if any)
80 * }
81 * }
82 * }
83 *
84 * // Close the LDAP association
85 * ctx.close();
86 * ...
87 *
88 * </pre>
89 * <p>
90 * This class implements the LDAPv3 Request Control for server-side sorting
91 * as defined in
92 * <a href="http://www.ietf.org/rfc/rfc2891.txt">RFC 2891</a>.
93 *
94 * The control's value has the following ASN.1 definition:
95 * <pre>
96 *
97 * SortKeyList ::= SEQUENCE OF SEQUENCE {
98 * attributeType AttributeDescription,
99 * orderingRule [0] MatchingRuleId OPTIONAL,
100 * reverseOrder [1] BOOLEAN DEFAULT FALSE }
101 *
102 * </pre>
103 *
104 * @since 1.5
105 * @see SortKey
106 * @see SortResponseControl
107 * @author Vincent Ryan
108 */
109final public class SortControl extends BasicControl {
110
111 /**
112 * The server-side sort control's assigned object identifier
113 * is 1.2.840.113556.1.4.473.
114 */
115 public static final String OID = "1.2.840.113556.1.4.473";
116
117 private static final long serialVersionUID = -1965961680233330744L;
118
119 /**
120 * Constructs a control to sort on a single attribute in ascending order.
121 * Sorting will be performed using the ordering matching rule defined
122 * for use with the specified attribute.
123 *
124 * @param sortBy An attribute ID to sort by.
125 * @param criticality If true then the server must honor the control
126 * and return the search results sorted as
127 * requested or refuse to perform the search.
128 * If false, then the server need not honor the
129 * control.
130 * @exception IOException If an error was encountered while encoding the
131 * supplied arguments into a control.
132 */
133 public SortControl(String sortBy, boolean criticality) throws IOException {
134
135 super(OID, criticality, null);
136 super.value = setEncodedValue(new SortKey[]{ new SortKey(sortBy) });
137 }
138
139 /**
140 * Constructs a control to sort on a list of attributes in ascending order.
141 * Sorting will be performed using the ordering matching rule defined
142 * for use with each of the specified attributes.
143 *
144 * @param sortBy A non-null list of attribute IDs to sort by.
145 * The list is in order of highest to lowest sort key
146 * precedence.
147 * @param criticality If true then the server must honor the control
148 * and return the search results sorted as
149 * requested or refuse to perform the search.
150 * If false, then the server need not honor the
151 * control.
152 * @exception IOException If an error was encountered while encoding the
153 * supplied arguments into a control.
154 */
155 public SortControl(String[] sortBy, boolean criticality)
156 throws IOException {
157
158 super(OID, criticality, null);
159 SortKey[] sortKeys = new SortKey[sortBy.length];
160 for (int i = 0; i < sortBy.length; i++) {
161 sortKeys[i] = new SortKey(sortBy[i]);
162 }
163 super.value = setEncodedValue(sortKeys);
164 }
165
166 /**
167 * Constructs a control to sort on a list of sort keys.
168 * Each sort key specifies the sort order and ordering matching rule to use.
169 *
170 * @param sortBy A non-null list of keys to sort by.
171 * The list is in order of highest to lowest sort key
172 * precedence.
173 * @param criticality If true then the server must honor the control
174 * and return the search results sorted as
175 * requested or refuse to perform the search.
176 * If false, then the server need not honor the
177 * control.
178 * @exception IOException If an error was encountered while encoding the
179 * supplied arguments into a control.
180 */
181 public SortControl(SortKey[] sortBy, boolean criticality)
182 throws IOException {
183
184 super(OID, criticality, null);
185 super.value = setEncodedValue(sortBy);
186 }
187
188 /*
189 * Encodes the sort control's value using ASN.1 BER.
190 * The result includes the BER tag and length for the control's value but
191 * does not include the control's object identifer and criticality setting.
192 *
193 * @param sortKeys A non-null list of keys to sort by.
194 * @return A possibly null byte array representing the ASN.1 BER encoded
195 * value of the sort control.
196 * @exception IOException If a BER encoding error occurs.
197 */
198 private byte[] setEncodedValue(SortKey[] sortKeys) throws IOException {
199
200 // build the ASN.1 BER encoding
201 BerEncoder ber = new BerEncoder(30 * sortKeys.length + 10);
202 String matchingRule;
203
204 ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
205
206 for (int i = 0; i < sortKeys.length; i++) {
207 ber.beginSeq(Ber.ASN_SEQUENCE | Ber.ASN_CONSTRUCTOR);
208 ber.encodeString(sortKeys[i].getAttributeID(), true); // v3
209
210 if ((matchingRule = sortKeys[i].getMatchingRuleID()) != null) {
211 ber.encodeString(matchingRule, (Ber.ASN_CONTEXT | 0), true);
212 }
213 if (! sortKeys[i].isAscending()) {
214 ber.encodeBoolean(true, (Ber.ASN_CONTEXT | 1));
215 }
216 ber.endSeq();
217 }
218 ber.endSeq();
219
220 return ber.getTrimmedBuf();
221 }
222}