2010-03-02 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Controls / LdapVirtualListControl.cs
blob9aa97a812d81747ed1c08bdef16d5a5a49014e55
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc. www.novell.com
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
24 // Novell.Directory.Ldap.Controls.LdapVirtualListControl.cs
26 // Author:
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
32 using System;
33 using Novell.Directory.Ldap;
34 using Novell.Directory.Ldap.Asn1;
36 namespace Novell.Directory.Ldap.Controls
39 /* The following is the ASN.1 of the VLV Request packet:
41 * VirtualListViewRequest ::= SEQUENCE {
42 * beforeCount INTEGER (0..maxInt),
43 * afterCount INTEGER (0..maxInt),
44 * CHOICE {
45 * byoffset [0] SEQUENCE {
46 * offset INTEGER (0 .. maxInt),
47 * contentCount INTEGER (0 .. maxInt) },
48 * greaterThanOrEqual [1] AssertionValue },
49 * contextID OCTET STRING OPTIONAL }
53 /// <summary> LdapVirtualListControl is a Server Control used to specify
54 /// that results from a search are to be returned in pages - which are
55 /// subsets of the entire virtual result set.
56 ///
57 /// On success, an updated LdapVirtualListResponse object is
58 /// returned as a response Control, containing information on the virtual
59 /// list size and the actual first index. This object can then be used
60 /// by the client with a new requested position or length and sent to the
61 /// server to obtain a different segment of the virtual list.
62 ///
63 /// </summary>
64 public class LdapVirtualListControl:LdapControl
66 /// <summary> Returns the number of entries after the top/center one to return per
67 /// page of results.
68 /// </summary>
69 virtual public int AfterCount
71 get
73 return m_afterCount;
77 /// <summary> Returns the number of entries before the top/center one to return per
78 /// page of results.
79 /// </summary>
80 virtual public int BeforeCount
82 get
84 return m_beforeCount;
88 /// <summary> Returns the size of the virtual search results list. For a newly
89 /// constructed control - one which is not the result of parseResponse on
90 /// a control returned by a server - the method returns -1.
91 /// </summary>
92 /// <summary> Sets the assumed size of the virtual search results list. This will
93 /// typically be a number returned on a previous virtual list request in
94 /// an LdapVirtualListResponse.
95 /// </summary>
96 virtual public int ListSize
98 get
100 return m_contentCount;
105 m_contentCount = value;
107 /* since we just changed a field we need to rebuild the ber
108 * encoded control
110 BuildIndexedVLVRequest();
112 /* Set the request data field in the in the parent LdapControl to
113 * the ASN.1 encoded value of this control. This encoding will be
114 * appended to the search request when the control is sent.
116 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
120 /// <summary> Returns the cookie used by some servers to optimize the processing of
121 /// virtual list requests.
122 /// </summary>
123 /// <summary> Sets the cookie used by some servers to optimize the processing of
124 /// virtual list requests. It should be the context field returned in a
125 /// virtual list response control for the same search.
126 /// </summary>
127 virtual public System.String Context
131 return m_context;
136 /* Index of the context field if one exists in the ber
138 int CONTEXTIDINDEX = 3;
140 /* Save off the new value in private variable
142 m_context = value;
144 /* Is there a context field that is already in the ber
146 if (m_vlvRequest.size() == 4)
148 /* If YES then replace it */
149 m_vlvRequest.set_Renamed(CONTEXTIDINDEX, new Asn1OctetString(m_context));
151 else if (m_vlvRequest.size() == 3)
153 /* If no then add a new one */
154 m_vlvRequest.add(new Asn1OctetString(m_context));
157 /* Set the request data field in the in the parent LdapControl to
158 * the ASN.1 encoded value of this control. This encoding will be
159 * appended to the search request when the control is sent.
161 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
166 /* The ASN.1 for the VLV Request has CHOICE field. These private
167 * variables represent differnt ids for these different options
169 private static int BYOFFSET = 0;
170 private static int GREATERTHANOREQUAL = 1;
173 /// <summary> The Request OID for a VLV Request</summary>
174 private static System.String requestOID = "2.16.840.1.113730.3.4.9";
177 * The Response stOID for a VLV Response
179 private static System.String responseOID = "2.16.840.1.113730.3.4.10";
182 * The encoded ASN.1 VLV Control is stored in this variable
184 private Asn1Sequence m_vlvRequest;
187 /* Private instance variables go here.
188 * These variables are used to store copies of various fields
189 * that can be set in a VLV control. One could have managed
190 * without really defining these private variables by reverse
191 * engineering each field from the ASN.1 encoded control.
192 * However that would have complicated and slowed down the code.
194 private int m_beforeCount;
195 private int m_afterCount;
196 private System.String m_jumpTo;
197 private System.String m_context = null;
198 private int m_startIndex = 0;
199 private int m_contentCount = - 1;
201 /// <summary> Constructs a virtual list control using the specified filter
202 /// expression.
203 ///
204 /// The expression specifies the first entry to be used for the
205 /// virtual search results. The other two paramers are the number of
206 /// entries before and after a located index to be returned.
207 ///
208 /// </summary>
209 /// <param name="jumpTo"> A search expression that defines the first
210 /// element to be returned in the virtual search results. The filter
211 /// expression in the search operation itself may be, for example,
212 /// "objectclass=person" and the jumpTo expression in the virtual
213 /// list control may be "cn=m*", to retrieve a subset of entries
214 /// starting at or centered around those with a common name beginning
215 /// with the letter "M".
216 ///
217 /// </param>
218 /// <param name="beforeCount"> The number of entries before startIndex (the
219 /// reference entry) to be returned.
220 ///
221 /// </param>
222 /// <param name="afterCount"> The number of entries after startIndex to be
223 /// returned.
224 /// </param>
225 public LdapVirtualListControl(System.String jumpTo, int beforeCount, int afterCount):this(jumpTo, beforeCount, afterCount, null)
227 return ;
232 /// <summary> Constructs a virtual list control using the specified filter
233 /// expression along with an optional server context.
234 ///
235 /// The expression specifies the first entry to be used for the
236 /// virtual search results. The other two paramers are the number of
237 /// entries before and after a located index to be returned.
238 ///
239 /// </summary>
240 /// <param name="jumpTo"> A search expression that defines the first
241 /// element to be returned in the virtual search results. The filter
242 /// expression in the search operation itself may be, for example,
243 /// "objectclass=person" and the jumpTo expression in the virtual
244 /// list control may be "cn=m*", to retrieve a subset of entries
245 /// starting at or centered around those with a common name beginning
246 /// with the letter "M".
247 ///
248 /// </param>
249 /// <param name="beforeCount">The number of entries before startIndex (the
250 /// reference entry) to be returned.
251 ///
252 /// </param>
253 /// <param name="afterCount">The number of entries after startIndex to be
254 /// returned.
255 ///
256 /// </param>
257 /// <param name="context">Used by some implementations to process requests
258 /// more efficiently. The context should be null on the first search,
259 /// and thereafter it should be whatever was returned by the server in the
260 /// virtual list response control.
261 /// </param>
262 public LdapVirtualListControl(System.String jumpTo, int beforeCount, int afterCount, System.String context):base(requestOID, true, null)
265 /* Save off the fields in local variables
267 m_beforeCount = beforeCount;
268 m_afterCount = afterCount;
269 m_jumpTo = jumpTo;
270 m_context = context;
272 /* Call private method to build the ASN.1 encoded request packet.
274 BuildTypedVLVRequest();
276 /* Set the request data field in the in the parent LdapControl to
277 * the ASN.1 encoded value of this control. This encoding will be
278 * appended to the search request when the control is sent.
280 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
281 return ;
284 /// <summary>Private method used to construct the ber encoded control
285 /// Used only when using the typed mode of VLV Control.
286 /// </summary>
287 private void BuildTypedVLVRequest()
289 /* Create a new Asn1Sequence object */
290 m_vlvRequest = new Asn1Sequence(4);
292 /* Add the beforeCount and afterCount fields to the sequence */
293 m_vlvRequest.add(new Asn1Integer(m_beforeCount));
294 m_vlvRequest.add(new Asn1Integer(m_afterCount));
296 /* The next field is dependent on the type of indexing being used.
297 * A "typed" VLV request uses a ASN.1 OCTET STRING to index to the
298 * correct object in the list. Encode the ASN.1 CHOICE corresponding
299 * to this option (as indicated by the greaterthanOrEqual field)
300 * in the ASN.1.
302 m_vlvRequest.add(new Asn1Tagged(new Asn1Identifier(Asn1Identifier.CONTEXT, false, GREATERTHANOREQUAL), new Asn1OctetString(m_jumpTo), false));
304 /* Add the optional context string if one is available.
306 if ((System.Object) m_context != null)
307 m_vlvRequest.add(new Asn1OctetString(m_context));
309 return ;
312 /// <summary> Use this constructor to fetch a subset when the size of the
313 /// virtual list is known,
314 ///
315 ///
316 /// </summary>
317 /// <param name="beforeCount">The number of entries before startIndex (the
318 /// reference entry) to be returned.
319 ///
320 /// </param>
321 /// <param name="afterCount"> The number of entries after startIndex to be
322 /// returned.
323 ///
324 /// </param>
325 /// <param name="startIndex">The index of the reference entry to be returned.
326 ///
327 /// </param>
328 /// <param name="contentCount">The total number of entries assumed to be in the
329 /// list. This is a number returned on a previous search, in the
330 /// LdapVirtualListResponse. The server may use this number to adjust
331 /// the returned subset offset.
332 /// </param>
333 public LdapVirtualListControl(int startIndex, int beforeCount, int afterCount, int contentCount):this(startIndex, beforeCount, afterCount, contentCount, null)
335 return ;
340 /// <summary> Use this constructor to fetch a subset when the size of the
341 /// virtual list is known,
342 ///
343 ///
344 /// </summary>
345 /// <param name="beforeCount"> The number of entries before startIndex (the
346 /// reference entry) to be returned.
347 ///
348 /// </param>
349 /// <param name="afterCount"> The number of entries after startIndex to be
350 /// returned.
351 ///
352 /// </param>
353 /// <param name="startIndex"> The index of the reference entry to be
354 /// returned.
355 ///
356 /// </param>
357 /// <param name="contentCount"> The total number of entries assumed to be in the
358 /// list. This is a number returned on a previous search, in the
359 /// LdapVirtualListResponse. The server may use this number to adjust
360 /// the returned subset offset.
361 ///
362 /// </param>
363 /// <param name="context"> Used by some implementations to process requests
364 /// more efficiently. The context should be null on the first search,
365 /// and thereafter it should be whatever was returned by the server in the
366 /// virtual list response control.
367 /// </param>
368 public LdapVirtualListControl(int startIndex, int beforeCount, int afterCount, int contentCount, System.String context):base(requestOID, true, null)
372 /* Save off the fields in local variables
374 m_beforeCount = beforeCount;
375 m_afterCount = afterCount;
376 m_startIndex = startIndex;
377 m_contentCount = contentCount;
378 m_context = context;
380 /* Call private method to build the ASN.1 encoded request packet.
382 BuildIndexedVLVRequest();
384 /* Set the request data field in the in the parent LdapControl to
385 * the ASN.1 encoded value of this control. This encoding will be
386 * appended to the search request when the control is sent.
388 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
389 return ;
392 /// <summary>Private method used to construct the ber encoded control
393 /// Used only when using the Indexed mode of VLV Control
394 /// </summary>
395 private void BuildIndexedVLVRequest()
397 /* Create a new Asn1Sequence object */
398 m_vlvRequest = new Asn1Sequence(4);
400 /* Add the beforeCount and afterCount fields to the sequence */
401 m_vlvRequest.add(new Asn1Integer(m_beforeCount));
402 m_vlvRequest.add(new Asn1Integer(m_afterCount));
404 /* The next field is dependent on the type of indexing being used.
405 * An "indexed" VLV request uses a ASN.1 SEQUENCE to index to the
406 * correct object in the list. Encode the ASN.1 CHOICE corresponding
407 * to this option (as indicated by the byoffset fieldin the ASN.1.
409 Asn1Sequence byoffset = new Asn1Sequence(2);
410 byoffset.add(new Asn1Integer(m_startIndex));
411 byoffset.add(new Asn1Integer(m_contentCount)); ;
413 /* Add the ASN.1 sequence to the encoded data
415 m_vlvRequest.add(new Asn1Tagged(new Asn1Identifier(Asn1Identifier.CONTEXT, true, BYOFFSET), byoffset, false));
417 /* Add the optional context string if one is available.
419 if ((System.Object) m_context != null)
420 m_vlvRequest.add(new Asn1OctetString(m_context));
422 return ;
427 /// <summary> Sets the center or starting list index to return, and the number of
428 /// results before and after.
429 ///
430 ///
431 /// </summary>
432 /// <param name="listIndex"> The center or starting list index to be
433 /// returned.
434 ///
435 /// </param>
436 /// <param name="beforeCount"> The number of entries before "listIndex" to be
437 /// returned.
438 ///
439 /// </param>
440 /// <param name="afterCount"> The number of entries after "listIndex" to be
441 /// returned.
442 /// </param>
443 public virtual void setRange(int listIndex, int beforeCount, int afterCount)
446 /* Save off the fields in local variables
448 m_beforeCount = beforeCount;
449 m_afterCount = afterCount;
450 m_startIndex = listIndex;
452 /* since we just changed a field we need to rebuild the ber
453 * encoded control
455 BuildIndexedVLVRequest();
457 /* Set the request data field in the in the parent LdapControl to
458 * the ASN.1 encoded value of this control. This encoding will be
459 * appended to the search request when the control is sent.
461 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
464 // PROPOSED ADDITION TO NEXT VERSION OF DRAFT (v7)
465 /// <summary> Sets the center or starting list index to return, and the number of
466 /// results before and after.
467 ///
468 ///
469 /// </summary>
470 /// <param name="jumpTo">A search expression that defines the first
471 /// element to be returned in the virtual search results. The filter
472 /// expression in the search operation itself may be, for example,
473 /// "objectclass=person" and the jumpTo expression in the virtual
474 /// list control may be "cn=m*", to retrieve a subset of entries
475 /// starting at or centered around those with a common name
476 /// beginning with the letter "M".
477 ///
478 /// </param>
479 /// <param name="beforeCount"> The number of entries before "listIndex" to be
480 /// returned.
481 ///
482 /// </param>
483 /// <param name="afterCount">The number of entries after "listIndex" to be
484 /// returned.
485 /// </param>
487 public virtual void setRange(System.String jumpTo, int beforeCount, int afterCount)
489 /* Save off the fields in local variables
491 m_beforeCount = beforeCount;
492 m_afterCount = afterCount;
493 m_jumpTo = jumpTo;
495 /* since we just changed a field we need to rebuild the ber
496 * encoded control
498 BuildTypedVLVRequest();
500 /* Set the request data field in the in the parent LdapControl to
501 * the ASN.1 encoded value of this control. This encoding will be
502 * appended to the search request when the control is sent.
504 setValue(m_vlvRequest.getEncoding(new LBEREncoder()));
506 static LdapVirtualListControl()
509 * This is where we register the control responses
512 /* Register the VLV Sort Control class which is returned by the server
513 * in response to a VLV Sort Request
517 LdapControl.register(responseOID, System.Type.GetType("Novell.Directory.Ldap.Controls.LdapVirtualListResponse"));
519 catch (System.Exception e)