idnits 2.17.1 draft-weltman-ldap-java-controls-02.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- ** Cannot find the required boilerplate sections (Copyright, IPR, etc.) in this document. Expected boilerplate is as follows today (2024-04-19) according to https://trustee.ietf.org/license-info : IETF Trust Legal Provisions of 28-dec-2009, Section 6.a: This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. IETF Trust Legal Provisions of 28-dec-2009, Section 6.b(i), paragraph 2: Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved. IETF Trust Legal Provisions of 28-dec-2009, Section 6.b(i), paragraph 3: This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- ** Missing expiration date. The document expiration date should appear on the first and last page. ** The document seems to lack a 1id_guidelines paragraph about Internet-Drafts being working documents. ** The document seems to lack a 1id_guidelines paragraph about 6 months document validity. ** The document seems to lack a 1id_guidelines paragraph about the list of current Internet-Drafts. ** The document seems to lack a 1id_guidelines paragraph about the list of Shadow Directories. == There are 2 instances of lines with non-ascii characters in the document. == No 'Intended status' indicated for this document; assuming Proposed Standard Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) == There are 3 instances of lines with non-RFC2606-compliant FQDNs in the document. Miscellaneous warnings: ---------------------------------------------------------------------------- == Line 381 has weird spacing: '...gesOnly tru...' == Line 421 has weird spacing: '...gesOnly tru...' -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (July 14, 1998) is 9411 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Missing reference section? '5' on line 470 looks like a reference -- Missing reference section? '6' on line 476 looks like a reference -- Missing reference section? '2' on line 661 looks like a reference -- Missing reference section? '1' on line 679 looks like a reference -- Missing reference section? '0' on line 716 looks like a reference -- Missing reference section? '9' on line 487 looks like a reference -- Missing reference section? '3' on line 534 looks like a reference -- Missing reference section? '4' on line 467 looks like a reference -- Missing reference section? '7' on line 480 looks like a reference -- Missing reference section? '8' on line 484 looks like a reference Summary: 7 errors (**), 0 flaws (~~), 5 warnings (==), 13 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group Rob Weltman 3 INTERNET-DRAFT Netscape Communications Corp. 4 Christine Ho 5 Netscape Communications Corp. 6 July 14, 1998 8 Java LDAP Controls 9 draft-weltman-ldap-java-controls-02.txt 11 Status of this Memo 13 This document is an Internet Draft. Internet Drafts are working 14 documents of the Internet Engineering Task Force (IETF), its Areas, 15 and its Working Groups. Note that other groups may also distribute 16 working documents as Internet Drafts. 18 Internet Drafts are draft documents valid for a maximum of six 19 months. Internet Drafts may be updated, replaced, or obsoleted by 20 other documents at any time. It is not appropriate to use Internet 21 Drafts as reference material or to cite them other than as a "working 22 draft" or "work in progress". 24 To learn the current status of any Internet-Draft, please check the 25 1id-abstracts.txt listing contained in the Internet-Drafts Shadow 26 Directories on ftp.ietf.org, nic.nordu.net, ftp.isi.edu, or 27 munnari.oz.au. 29 Abstract 31 This document defines support for the 32 Server Sorting Control, the Virtual List Control, and the Persistent 33 Search Control in the java LDAP API. Controls are an LDAP protocol 34 version 3 extension, to allow passing arbitrary control information 35 along with a standard request to a server, and to receive arbitrary 36 information back with a standard result. 38 JAVA LDAP CONTROLS July, 1998 40 1.Introduction........................................................3 41 2.Overview of the LDAP Control classes................................3 42 3.The java LDAP Control classes.......................................4 43 3.1 public class LDAPVirtualListControl..............................4 44 3.1.1Constructors..................................................4 45 3.1.2getAfterCount.................................................5 46 3.1.3getBeforeCount................................................6 47 3.1.4getListSize...................................................6 48 3.1.5setListSize...................................................6 49 3.1.6setRange......................................................6 50 3.2 public class LDAPVirtualListResponse.............................6 51 3.2.1getContentCount...............................................7 52 3.2.2getFirstPosition..............................................7 53 3.2.3getResultCode.................................................7 54 3.2.4parseResponse.................................................7 55 3.3 public class LDAPSortControl.....................................7 56 3.3.1Constructors..................................................7 57 3.3.2parseResponse.................................................8 58 3.4 public class LDAPPersistSearchControl............................8 59 3.4.1Constructors..................................................8 60 3.4.2getChangeTypes................................................9 61 3.4.3public boolean getReturnControls()............................9 62 3.4.4setChangeTypes................................................9 63 3.4.5setChangesOnly................................................9 64 3.4.6setReturnControls............................................10 65 3.4.7parseResponse................................................10 66 4.Security Considerations............................................10 67 5.Bibliography.......................................................10 68 6.Authors' Addresses.................................................11 69 7.Appendix A - Sample usage of the java LDAP controls................12 70 JAVA LDAP CONTROLS July, 1998 72 1. Introduction 74 Version 3 of the LDAP protocol provides a means of supplying 75 arbitrary additional information along with a request to an LDAP 76 server, and receiving arbitrary additional response information. A 77 few applications of the Control mechanism have been identified as 78 having general interest, and the protocol defined for their 79 transmission [5] and [6]. This document defines how support for the 80 Preferred Language Control, the Server Sorting Control, the Virtual 81 List Control, and the Persistent Search Control are supported 82 in the java LDAP API. The java LDAP API in general is described in 83 [2]. The Control protocol extension is described in [1], section 84 4.1.12, and applications of it in [5] and [6]. 86 2. Overview of the LDAP Control classes 88 LDAPControl is part of a basic LDAP class package. Specific 89 applications/implementations of Controls are in a subpackage called 90 "controls". 92 The base class LDAPControl is defined in [2] as: 94 public class LDAPControl implements Cloneable 96 An LDAPControl encapsulates optional additional parameters or 97 constraints to be applied to LDAP operations. If set as a Server 98 Control, it is sent to the server along with operation requests. 99 If set as a Client Control, it is not sent to the server, but 100 rather interpreted locally by the client. LDAPControl is an 101 LDAPv3 extension, and is not supported in an LDAPv2 environment. 103 Constructors 105 public LDAPControl(String id, 106 boolean critical, 107 byte vals[]) 109 Parameters are: 111 id The type of the Control, as a string. 113 critical True if the LDAP operation should be discarded if 114 the server does not support this Control. 116 vals Control-specific data. 118 getID 120 public String getID() 122 JAVA LDAP CONTROLS July, 1998 124 Returns the identifier of the control. 126 isCritical 128 public boolean isCritical() 130 Returns true if the control must be supported for an 131 associated operation to be executed. 133 getValue 135 public byte[] getValue() 137 Returns the control-specific data of the object. 139 The following Controls are defined for the controls subpackage: 141 LDAPVirtualListControl Encapsulates requests for a subset of a 142 virtual list of search results, and the 143 response of a server to such a request. 145 LDAPSortControl Encapsulates a requested sorting order for 146 search results returned by a server, and 147 the server's response to the request. 149 LDAPPersistSearchControl Used to start a persistent search, one 150 which runs continuously, returning results 151 as the Directory is modified. 153 3. The java LDAP Control classes 155 3.1 public class LDAPVirtualListControl 156 extends LDAPControl 158 LDAPVirtualListControl is a Server Control to specify that results 159 from a search are to be returned in pages, subsets of the entire 160 virtual result set. On success, an updated LDAPVirtualList object is 161 returned as a response Control, containing information on the virtual 162 list size and the actual first index. This object can then be updated 163 by the client with a new requested position or length and sent to the 164 server to obtain a different segment of the virtual list. The 165 protocol elements are defined in [6]. 167 3.1.1 Constructors 169 public LDAPVirtualListControl( String jumpTo, 171 JAVA LDAP CONTROLS July, 1998 173 int beforeCount, 174 int afterCount ) 176 Constructs a virtual list control using the specified filter 177 expression for the first entry, which defines the extent of the 178 virtual search results, and the number of entries before and after a 179 located index to be returned. 181 public LDAPVirtualListControl( int startIndex, 182 int beforeCount, 183 int afterCount, 184 int contentCount) 186 Use this constructor when the size of the virtual list is known, to 187 fetch a subset. 189 Parameters are: 191 jumpTo A search expression that defines the first 192 element to be returned in the virtual search 193 results. The filter expression in the search 194 operation itself may be, for example, 195 "objectclass=person" and the jumpTo expression in 196 the virtual list control may be "cn=m*", to 197 retrieve a subset of entries starting at or 198 centered around those with a common name 199 beginning with the letter "M". 201 beforeCount The number of entries before startIndex (the 202 reference entry) to be returned. 204 afterCount The number of entries after startIndex to be 205 returned. 207 startIndex The index of the reference entry to be returned. 209 contentCount The total number of entries assumed to be in the 210 list. This is a number returned on a previous 211 search, in the LDAPVirtualListResponse. The 212 server may use this number to adjust the returned 213 subset offset. 215 3.1.2 getAfterCount 217 public int getAfterCount() 219 Returns the number of entries after the top/center one to return per 220 page of results. 222 JAVA LDAP CONTROLS July, 1998 224 3.1.3 getBeforeCount 226 public int getBeforeCount() 228 Returns the number of entries before the top/center one to return per 229 page of results. 231 3.1.4 getListSize 233 public int getListSize() 235 Returns the size of the virtual search results list. For a newly 236 constructed control - one which is not the result of parseResponse on 237 a control returned by a server - the method returns -1. 239 3.1.5 setListSize 241 public void setListSize( int size ) 243 Sets the assumed size of the virtual search results list. This will 244 typically be a number returned on a previous virtual list request in 245 an LDAPVirtualListResponse. 247 3.1.6 setRange 249 public void setRange( int listIndex, 250 int beforeCount, 251 int afterCount ) 253 Sets the center or starting list index to return, and the number of 254 results before and after. 256 Parameters are: 258 listIndex The center or starting list index to be returned. 260 beforeCount The number of entries before "listIndex" to be 261 returned. 263 afterCount The number of entries after "listIndex" to be 264 returned. 266 3.2 public class LDAPVirtualListResponse 267 extends LDAPControl 269 LDAPVirtualListResponse is a Server Control returned by the server in 270 response to a virtual list search request. 272 JAVA LDAP CONTROLS July, 1998 274 3.2.1 getContentCount 276 public int getContentCount () 278 Returns the size of the virtual search results list 280 3.2.2 getFirstPosition 282 public int getFirstPosition () 284 Returns the index of the first entry returned 286 3.2.3 getResultCode 288 public int getResultCode () 290 Returns the result code for the virtual list request 292 3.2.4 parseResponse 294 public static LDAPVirtualListResponse parseResponse( 295 LDAPControl[] controls ) 297 When applied to an array of controls returned by a server, 298 parseResponse returns a virtual list response. The input is typically 299 provided with the LDAPConnection.getResponseControls method. 301 Parameters are: 303 controls An array of controls. It may be null. 305 3.3 public class LDAPSortControl 306 extends LDAPControl 308 LDAPSortControl is a Server Control to specify how search results are 309 to be sorted by the server (see [5]). If a server does not support 310 sorting in general or for a particular query, the results will be 311 returned unsorted, along with a control indicating why they were not 312 sorted (or that sort controls are not supported). If the control was 313 marked "critical", the whole search operation will fail if the sort 314 control is not supported. 316 3.3.1 Constructors 318 public LDAPSortControl( LDAPSortKey key, boolean critical) 320 JAVA LDAP CONTROLS July, 1998 322 Constructs a sort control with a single key. 324 public LDAPSortControl( LDAPSortKey[] keys, boolean critical) 326 Constructs a sort control with multiple sort keys. 328 Parameters are: 330 key A sort key object, which specifies attribute, 331 order, and optional matching rule. 333 keys An array of sort key objects, to be processed in 334 order. 336 critical True if the search operation is to fail if the 337 server does not support this control. 339 3.3.2 parseResponse 341 public static String parseResponse( LDAPControl[] controls, 342 int results[] ) 344 Processes an array of Server Controls to determine if sorting was 345 rejected, and if so, why. If sorting was rejected, the return value 346 is the attribute name which caused sorting to fail. results[0] 347 contains the result code on return. The result code is one defined in 348 [1], section 4.1.10. 350 Parameters are: 352 controls An array of Server Controls, typically obtained 353 with LDAPConnection.getResponseControls(). It may 354 be null, which is equivalent to no error. 356 3.4 public class LDAPPersistSearchControl 357 extends LDAPControl 359 The LDAPPersistSearchControl class is used to start a persistent 360 search, one that doesn't end after returning any initial results, but 361 continues to monitor changes in a designated part of a Directory, 362 reporting the results as changes are made. The protocol elements are 363 defined in [9]. 365 3.4.1 Constructors 367 public LDAPPersistSearchControl(int changeTypes, 368 boolean changesOnly, 369 boolean returnControls, 371 JAVA LDAP CONTROLS July, 1998 373 boolean isCritical) 375 Parameters are: 377 changeTypes The change types to be monitored as a logical OR 378 of any or all of these types: ADD, DELETE, 379 MODIFY, and/or MODDN. 381 changesOnly true if the initial search is to be skipped. 383 returnControls true if entry change controls are to be returned 384 with the search results. 386 isCritical true if the search is to be abandoned if the 387 server doesn't support this control. 389 3.4.2 getChangeTypes 391 public int getChangeTypes() 393 Returns the change types to be monitored as a logical OR of any or 394 all of these types: ADD, DELETE, MODIFY, and/or MODDN. 396 3.4.3 public boolean getReturnControls() 398 Returns true if entry change controls are to be returned with the 399 search results. 401 3.4.4 setChangeTypes 403 public void setChangeTypes(int types) 405 Sets change types to be monitored. 407 Parameters are: 409 types The change types to be monitored as a logical OR 410 of any or all of these types: ADD, DELETE, 411 MODIFY, and/or MODDN. 413 3.4.5 setChangesOnly 415 public void setChangesOnly(boolean changesOnly) 417 Requests that only changes be returned - skip the initial search. 419 Parameters are: 421 changesOnly true to skip the initial search. 423 JAVA LDAP CONTROLS July, 1998 425 3.4.6 setReturnControls 427 public void setReturnControls(boolean returnControls) 429 Requests that entry change controls are returned with the search 430 results. 432 Parameters are: 434 returnControls true to return entry change controls. 436 3.4.7 parseResponse 438 public static LDAPEntryChangeControl parseResponse( 439 LDAPControl[] controls) 441 Processes an array of Server Controls and returns an 442 LDAPEntryChangeControl if there is one. 444 Parameters are: 446 controls An array of Server Controls, typically obtained 447 with LDAPConnection.getResponseControls(). It may 448 be null. 450 4. Security Considerations 452 See [2] for security considerations in the java LDAP API. 454 5. Bibliography 456 [1] M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access 457 Protocol (v3)", Internet Draft draft-ietf-asid-ldapv3-protocol- 458 06.txt, July 1997. 460 [2] R. Weltman, T. Howes, M. Smith, "The Java LDAP Application 461 Program Interface", Internet Draft draft-ietf-asid-ldap-java- 462 api-01.txt, September 1997. 464 [3] H. Alvestrans, "Tags for the Identification of Languages", 465 Request for Comments 1766, March 1995. 467 [4] M. Wahl, T. Howes, "Use of Language Codes in LDAPv3", Internet 468 Draft draft-ietf-asid-ldapv3-lang-02.txt, June 1997. 470 [5] A. Herron, T. Howes, M. Wahl, "LDAP Control Extension for Server 471 Side Sorting of Search Results", Internet Draft draft-ietf-asid- 472 ldapv3-sorting-00.txt, April 1997. 474 JAVA LDAP CONTROLS July, 1998 476 [6] D. Boreham, "LDAP Control Extension for Virtual List View 477 Browsing of Search Results", Internet draft-ietf-ldapext- 478 ldapv3-vlv-01.txt, November 1997. 480 [7] C. Weider, A Herron, T. Howes, "LDAP Control Extension for 481 Simple Paged Results Manipulation", Internet Draft draft-ietf- 482 asid-ldapv3-simple-paged-01.txt, March 1997. 484 [8] R. Weltman, "Java LDAP Controls", draft-ietf-ldapext-ldap-java- 485 controls-01.txt, September 1997. 487 [9] M. Smith, G. Good, T. Howes, M. Smith, R. Weltman, �Persistent 488 Search: A Simple LDAP Change Notification Mechanism�, draft- 489 ietf-smith-ldap-psearch-00.txt, November 1997 491 6. Authors' Addresses 493 Rob Weltman 494 Netscape Communications Corp. 495 501 E. Middlefield Rd. 496 Mountain View, CA 94043 497 USA 498 +1 650 937-3301 499 rweltman@netscape.com 501 Christine Ho 502 Netscape Communications Corp. 503 501 E. Middlefield Rd. 504 Mountain View, CA 94043 505 USA 506 +1 650 937-5939 507 chrisho@netscape.com 509 JAVA LDAP CONTROLS July, 1998 511 7. Appendix A - Sample usage of the java LDAP controls 513 Doing a search with results sorted on the server 515 import netscape.ldap.*; 516 import netscape.ldap.controls.*; 517 import java.util.*; 519 public class SearchJensenSorted { 521 public static void main( String[] args ) { 522 try { 523 LDAPConnection ld = new LDAPConnection(); 524 /* Connect to server */ 525 String MY_HOST = "localhost"; 526 int MY_PORT = 389; 527 ld.connect( MY_HOST, MY_PORT ); 529 /* search for all entries with surname of Jensen */ 530 String MY_FILTER = "sn=Jensen"; 531 String MY_SEARCHBASE = "o=Ace Industry, c=US"; 533 /* Get the common name, uid, and telephone number */ 534 String[] attrs = new String[3]; 535 attrs[0] = "cn"; 536 attrs[1] = "telephonenumber"; 537 attrs[2] = "uid"; 539 /* Sort by lastname, firstname */ 540 LDAPSortKey[] keys = new LDAPSortKey[2]; 541 keys[0] = new LDAPSortKey( "sn" ); 542 keys[1] = new LDAPSortKey( "givenname" ); 543 LDAPSortControl sort = new LDAPSortControl( keys, true ); 544 LDAPSearchConstraints cons = ld.getSearchConstraints(); 545 cons.setServerControls( ld.SERVERCONTROLS, sort ); 547 LDAPSearchResults res = 548 ld.search( MY_SEARCHBASE, 549 LDAPConnection.SCOPE_ONE, 550 MY_FILTER, 551 attrs, 552 false, 553 cons ); 555 /* Loop on results until finished */ 556 while ( res.hasMoreElements() ) { 558 /* Next directory entry */ 559 LDAPEntry findEntry = (LDAPEntry)res.nextElement(); 560 System.out.println( findEntry.getDN() ); 562 /* Get the attributes of the entry */ 564 JAVA LDAP CONTROLS July, 1998 566 LDAPAttributeSet findAttrs = 567 findEntry.getAttributeSet(); 568 Enumeration enumAttrs = findAttrs.getAttributes(); 569 System.out.println( "Attributes: " ); 571 /* Loop on attributes */ 572 while ( enumAttrs.hasMoreElements() ) { 573 LDAPAttribute anAttr = 574 (LDAPAttribute)enumAttrs.nextElement(); 576 String attrName = anAttr.getName(); 577 System.out.println( "" + attrName ); 578 /* Loop on values for this attribute */ 579 Enumeration enumVals = anAttr.getStringValues(); 580 while ( enumVals.hasMoreElements() ) { 581 String aVal = 582 ( String )enumVals.nextElement(); 583 System.out.println( "" + aVal ); 584 } 585 } 586 } 588 /* Check if the server had something to say about the 589 sort request */ 590 LDAPControl[] controls = ld.getResponseControls(); 591 if ( controls != null ) { 592 int[] results = new int[1]; 593 String bad = 594 LDAPSortControl.parseResponse( controls, 595 results ); 596 if ( results[0] != 0 ) { 597 System.out.println( "Error code: " + results[0] ); 598 if ( bad != null ) 599 System.out.println( "Offending attribute: " + 600 bad ); 601 else 602 System.out.println( "No offending attribute + 603 "returned" ); 604 } 605 } 606 } 607 catch( LDAPException e ) { 608 System.out.println( "Error: " + e.toString() ); 609 } 610 /* Done, so disconnect */ 611 if ( ld.isConnected() ) 612 ld.disconnect(); 613 } 614 } 616 JAVA LDAP CONTROLS July, 1998 618 Using virtual list controls - an application using JFC 620 import netscape.ldap.*; 621 import netscape.ldap.controls.*; 623 // Call this to initialize the list box, whenever the search 624 // conditions change. 625 // "filter" may be "objectclass=person", for example 626 void initListBox( String host, int port, 627 String base, String filter ) { 628 // Create list box if not already done 629 if ( _dataList == null ) { 630 _dataList = new JList(); 631 JScrollPane scrollPane = new JScrollPane(_dataList); 632 add( scrollPane ); 633 } 634 // Create a virtual data model 635 vlistModel model = new vlistModel( host, port, base, filter ); 636 // Keep a buffer of one page before and one after 637 model.setPageSize( getScrollVisibleSize() ); 638 _dataList.setModel( model ); 639 } 641 // Data model to supply buffer list data 642 class vlistModel extends AbstractListModel { 643 vlistModel( String host, int port, String base, String filter ) { 644 _base = base; 645 _filter = filter; 646 // Connect to the server 647 try { 648 _ldc = new LDAPConnection(); 649 System.out.println( "Connecting to " + host + 650 ":" + port ); 651 _ldc.connect( host, port ); 652 } catch ( LDAPException e ) { 653 System.out.println( e ); 654 _ldc = null; 655 } 656 } 657 // Called by JList to get virtual list size 658 public int getSize() { 659 if ( !_initialized ) { 660 _initialized = true; 661 _pageControls = new LDAPControl[2]; 662 // Paged results also require a sort control 663 _pageControls[0] = 664 new LDAPSortControl( new LDAPSortKey("cn"), 665 true ); 666 // Do an initial search to get the virtual list size 667 // Keep one page before and one page after the start 669 JAVA LDAP CONTROLS July, 1998 671 _beforeCount = _pageSize; 672 _afterCount = _pageSize; 673 // Create the initial paged results control 674 LDAPVirtualListControl cont = 675 new LDAPVirtualListControl( "A", 676 _beforeCount, 677 _afterCount ); 678 _pageControls[1] = cont; 679 _vlc = (LDAPVirtualListControl)_pageControls[1]; 680 getPage( 0 ); 681 } 682 return _size; 683 } 684 // Get a page starting at first (although we may also fetch 685 // some preceding entries) 686 boolean getPage( int first ) { 687 _vlc.setRange( first, _beforeCount, _afterCount ); 688 return getPage(); 689 } 690 boolean getEntries() { 691 // Specify necessary controls for vlv 692 if ( _pageControls != null ) { 693 try { 694 LDAPSearchConstraints cons = 695 ldc.getSearchConstraints(); 696 cons.setServerControls( ldc.SERVERCONTROLS, 697 pageControls ); 698 } catch ( LDAPException e ) { 699 System.out.println( e + ", setting vlv control" ); 700 } 701 } 702 // Empty the buffer 703 _entries.removeAllElements(); 704 // Do a search 705 try { 706 String[] attrs = { "cn" }; 707 LDAPSearchResults result = 708 _ldc.search( base, 709 LDAPConnection.SCOPE_SUB, 710 filter, 711 attrs, 712 false, 713 cons ); 714 while ( result.hasMoreElements() ) { 715 LDAPEntry entry = (LDAPEntry)result.nextElement(); 716 LDAPAttribute attr = entry.getAttribute( attrs[0] ); 717 if ( attr != null ) { 718 Enumeration en = attr.getStringValues(); 719 while( en.hasMoreElements() ) { 720 String name = (String)en.nextElement(); 721 _entries.addElement( name ); 722 } 724 JAVA LDAP CONTROLS July, 1998 726 } 727 } 728 } catch ( LDAPException e ) { 729 System.out.println( e + ", searching" ); 730 return false; 731 } 732 return true; 733 } 734 // Fetch a buffer 735 boolean getPage() { 736 // Get the actual entries 737 if ( !getEntries() ) 738 return false; 739 // Check if we have a control returned 740 LDAPControl[] c = _ldc.getResponseControls(); 741 LDAPVirtualListResponse nextCont = 742 LDAPVirtualListResponse.parseResponse( c ); 743 if ( nextCont != null ) { 744 _selectedIndex = nextCont.getFirstPosition() - 1; 745 _top = Math.max( 0, _selectedIndex - _beforeCount ); 746 // Now we know the total size of the virtual list box 747 _size = nextCont.getContentCount(); 748 _vlc.setListSize( _size ); 749 } else { 750 System.out.println( "Null response control" ); 751 } 752 return true; 753 } 754 // Called by JList to fetch data to paint a single list item 755 public Object getElementAt(int index) { 756 if ( (index < _top) || (index >= _top + _entries.size()) ) { 757 getPage( index ); 758 } 759 int offset = index - _top; 760 if ( (offset < 0) || (offset >= _entries.size()) ) 761 return new String( "No entry at " + index ); 762 else 763 return _entries.elementAt( offset ); 764 } 765 // Called by application to find out the virutal selected index 766 public int getSelectedIndex() { 767 return _selectedIndex; 768 } 769 // Called by application to find out the top of the buffer 770 public int getFirstIndex() { 771 return _top; 772 } 773 public void setPageSize( int size ) { 774 _pageSize = size; 775 } 776 Vector _entries = new Vector(); 777 protected boolean _initialized = false; 779 JAVA LDAP CONTROLS July, 1998 781 private int _top = 0; 782 protected int _beforeCount; 783 protected int _afterCount; 784 private int _pageSize = 10; 785 private int _selectedIndex = 0; 786 protected LDAPControl[] _pageControls = null; 787 protected LDAPVirtualListControl _vlc = null; 788 protected int _size = -1; 789 private String _base; 790 private String _filter; 791 private LDAPConnection _ldc; 792 } 794 JAVA LDAP CONTROLS July, 1998 796 Starting a persistent search 798 import netscape.ldap.*; 799 import netscape.ldap.controls.*; 800 import java.util.*; 802 public class PersistSearch implements Runnable{ 804 public PersistSearch() { 805 } 807 public static void main(String[] argv) { 808 Thread th = new Thread(new PersistSearch(), "conn"); 809 th.start(); 810 System.out.println("Main thread, waiting for " + 811 "some action" ); 812 } 814 public static void printResults(String str, 815 LDAPSearchResults myResults) { 816 LDAPEntry myEntry = null; 818 /* hasMoreElements() will block until there is a change 819 on the server satisfying our search conditions. When 820 it returns, we can see what has changed. The loop is 821 then repeated, and hasMoreElements() will block again 822 until there are additional changes on the server. */ 823 while ( myResults.hasMoreElements() ) { 824 /* A new Richard has appeared, let's get his 825 attributes */ 826 System.out.println("**** " + str + "****"); 827 try { 828 myEntry = myResults.next(); 829 } catch (LDAPReferralException e) { 830 /* Or was it a referral? */ 831 LDAPUrl[] urls = e.getURLs(); 832 System.out.println("Referral received:" ); 833 for( int i = 0; i < urls.length; i++ ) 834 System.out.println(" " + urls[i].getUrl() ); 835 } 836 String nextDN = myEntry.getDN(); 837 System.out.println( nextDN ); 838 LDAPAttributeSet entryAttrs = myEntry.getAttributeSet(); 839 Enumeration attrsInSet = entryAttrs.getAttributes(); 840 while ( attrsInSet.hasMoreElements() ) { 841 LDAPAttribute nextAttr = 842 (LDAPAttribute)attrsInSet.nextElement(); 844 String attrName = nextAttr.getName(); 845 System.out.println( "\t" + attrName + ":" ); 846 Enumeration valsInAttr = nextAttr.getStringValues(); 847 while ( valsInAttr.hasMoreElements() ) { 849 JAVA LDAP CONTROLS July, 1998 851 String nextValue = 852 (String)valsInAttr.nextElement(); 853 System.out.println( "\t\t" + nextValue ); 854 } 855 } 856 System.out.println(""); 857 } 858 } 860 public void run() { 861 /* Connect to standard port on local host */ 862 String hostname = "localhost"; 863 int portnum = 389; 865 /* We want to be notified when any Richard is added to 866 any part of the directory under "o=Airius.com". 867 We're not interested in any Richards already there. 868 We also don't care for any return change controls. 869 We only want to do this search if the server 870 supports persistent search, so set isCritical to 871 true. 872 When a Richard is added, we want to know his email 873 address. */ 874 String filter = "givenname=Richard"; 875 String searchbase = "o=Airius.com"; 876 int scope = LDAPConnection.SCOPE_SUB; 877 String[] attrs = {"mail"}; 878 int op = LDAPPersistSearchControl.ADD; 879 boolean changesOnly = true; 880 boolean returnControls = false; 881 boolean isCritical = true; 883 try { 884 /* Connect */ 885 LDAPConnection ld = new LDAPConnection(); 886 ld.connect(hostname, portnum); 888 LDAPSearchConstraints cons = ld.getSearchConstraints(); 889 cons.setBatchSize(1); 890 LDAPPersistSearchControl control = 891 new LDAPPersistSearchControl( op, changesOnly, 892 returnControls, 893 isCritical ); 894 cons.setServerControls( control ); 896 /* The call to search will return almost immediately */ 897 LDAPSearchResults res = ld.search( searchbase, 898 scope, 899 filter, attrs, 900 false, cons ); 901 printResults("Persistent Search ", res); 902 } catch (Exception e) { 904 JAVA LDAP CONTROLS July, 1998 906 System.out.println(e.toString()); 907 } 908 } 909 }