001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2014 ForgeRock AS. 015 */ 016package org.forgerock.openig.ldap; 017 018import java.io.Closeable; 019import java.util.Collection; 020 021import org.forgerock.opendj.ldap.Connection; 022import org.forgerock.opendj.ldap.DN; 023import org.forgerock.opendj.ldap.Entry; 024import org.forgerock.opendj.ldap.ErrorResultException; 025import org.forgerock.opendj.ldap.SearchScope; 026import org.forgerock.opendj.ldap.requests.AddRequest; 027import org.forgerock.opendj.ldap.requests.BindRequest; 028import org.forgerock.opendj.ldap.requests.CompareRequest; 029import org.forgerock.opendj.ldap.requests.DeleteRequest; 030import org.forgerock.opendj.ldap.requests.ModifyDNRequest; 031import org.forgerock.opendj.ldap.requests.ModifyRequest; 032import org.forgerock.opendj.ldap.requests.SearchRequest; 033import org.forgerock.opendj.ldap.responses.BindResult; 034import org.forgerock.opendj.ldap.responses.CompareResult; 035import org.forgerock.opendj.ldap.responses.Result; 036import org.forgerock.opendj.ldap.responses.SearchResultEntry; 037import org.forgerock.opendj.ldap.responses.SearchResultReference; 038import org.forgerock.opendj.ldif.ConnectionEntryReader; 039 040/** 041 * Provides an adapted view of an OpenDJ LDAP connection exposing only the 042 * synchronous methods and protecting against future evolution of the 043 * {@link Connection} interface (e.g. migration to Promises). 044 */ 045public final class LdapConnection implements Closeable { 046 private final Connection connection; 047 048 LdapConnection(final Connection connection) { 049 this.connection = connection; 050 } 051 052 /** 053 * Adds an entry to the Directory Server using the provided add request. 054 * 055 * @param request The add request. 056 * @return The result of the operation. 057 * @throws ErrorResultException If the result code indicates that the request failed for some 058 * reason. 059 * @throws UnsupportedOperationException If this connection does not support add operations. 060 * @throws IllegalStateException If this connection has already been closed, i.e. if 061 * {@code isClosed() == true}. 062 * @throws NullPointerException If {@code request} was {@code null}. 063 */ 064 public Result add(AddRequest request) throws ErrorResultException { 065 return connection.add(request); 066 } 067 068 /** 069 * Adds the provided entry to the Directory Server. 070 * <p> 071 * This method is equivalent to the following code: 072 * 073 * <pre> 074 * AddRequest request = new AddRequest(entry); 075 * connection.add(request); 076 * </pre> 077 * 078 * @param entry 079 * The entry to be added. 080 * @return The result of the operation. 081 * @throws ErrorResultException 082 * If the result code indicates that the request failed for some 083 * reason. 084 * @throws UnsupportedOperationException 085 * If this connection does not support add operations. 086 * @throws IllegalStateException 087 * If this connection has already been closed, i.e. if 088 * {@code isClosed() == true}. 089 * @throws NullPointerException 090 * If {@code entry} was {@code null} . 091 */ 092 public Result add(Entry entry) throws ErrorResultException { 093 return connection.add(entry); 094 } 095 096 /** 097 * Adds an entry to the Directory Server using the provided lines of LDIF. 098 * <p> 099 * This method is equivalent to the following code: 100 * 101 * <pre> 102 * AddRequest request = new AddRequest(ldifLines); 103 * connection.add(request); 104 * </pre> 105 * 106 * @param ldifLines 107 * Lines of LDIF containing the an LDIF add change record or an 108 * LDIF entry record. 109 * @return The result of the operation. 110 * @throws ErrorResultException 111 * If the result code indicates that the request failed for some 112 * reason. 113 * @throws UnsupportedOperationException 114 * If this connection does not support add operations. 115 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 116 * If {@code ldifLines} was empty, or contained invalid LDIF, or 117 * could not be decoded using the default schema. 118 * @throws IllegalStateException 119 * If this connection has already been closed, i.e. if 120 * {@code isClosed() == true}. 121 * @throws NullPointerException 122 * If {@code ldifLines} was {@code null} . 123 */ 124 public Result add(String... ldifLines) throws ErrorResultException { 125 return connection.add(ldifLines); 126 } 127 128 /** 129 * Authenticates to the Directory Server using the provided bind request. 130 * 131 * @param request The bind request. 132 * @return The result of the operation. 133 * @throws ErrorResultException If the result code indicates that the request failed for some 134 * reason. 135 * @throws UnsupportedOperationException If this connection does not support bind operations. 136 * @throws IllegalStateException If this connection has already been closed, i.e. if 137 * {@code isClosed() == true}. 138 * @throws NullPointerException If {@code request} was {@code null}. 139 */ 140 public BindResult bind(BindRequest request) throws ErrorResultException { 141 return connection.bind(request); 142 } 143 144 /** 145 * Authenticates to the Directory Server using simple authentication and the 146 * provided user name and password. 147 * <p> 148 * This method is equivalent to the following code: 149 * 150 * <pre> 151 * BindRequest request = new SimpleBindRequest(name, password); 152 * connection.bind(request); 153 * </pre> 154 * 155 * @param name 156 * The distinguished name of the Directory object that the client 157 * wishes to bind as, which may be empty. 158 * @param password 159 * The password of the Directory object that the client wishes to 160 * bind as, which may be empty. 161 * @return The result of the operation. 162 * @throws ErrorResultException 163 * If the result code indicates that the request failed for some 164 * reason. 165 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 166 * If {@code name} could not be decoded using the default 167 * schema. 168 * @throws UnsupportedOperationException 169 * If this connection does not support bind operations. 170 * @throws IllegalStateException 171 * If this connection has already been closed, i.e. if 172 * {@code isClosed() == true}. 173 * @throws NullPointerException 174 * If {@code name} or {@code password} was {@code null}. 175 */ 176 public BindResult bind(String name, char[] password) throws ErrorResultException { 177 return connection.bind(name, password); 178 } 179 180 /** 181 * Releases any resources associated with this connection. For physical 182 * connections to a Directory Server this will mean that an unbind request 183 * is sent and the underlying socket is closed. 184 * <p> 185 * Other connection implementations may behave differently, and may choose 186 * not to send an unbind request if its use is inappropriate (for example a 187 * pooled connection will be released and returned to its connection pool 188 * without ever issuing an unbind request). 189 * <p> 190 * This method is equivalent to the following code: 191 * 192 * <pre> 193 * UnbindRequest request = new UnbindRequest(); 194 * connection.close(request); 195 * </pre> 196 * <p> 197 * Calling {@code close} on a connection that is already closed has no 198 * effect. 199 * 200 * @see org.forgerock.opendj.ldap.Connections#uncloseable(Connection) 201 */ 202 @Override 203 public void close() { 204 connection.close(); 205 } 206 207 /** 208 * Compares an entry in the Directory Server using the provided compare 209 * request. 210 * 211 * @param request The compare request. 212 * @return The result of the operation. 213 * @throws ErrorResultException If the result code indicates that the request failed for some 214 * reason. 215 * @throws UnsupportedOperationException If this connection does not support compare operations. 216 * @throws IllegalStateException If this connection has already been closed, i.e. if 217 * {@code isClosed() == true}. 218 * @throws NullPointerException If {@code request} was {@code null}. 219 */ 220 public CompareResult compare(CompareRequest request) throws ErrorResultException { 221 return connection.compare(request); 222 } 223 224 /** 225 * Compares the named entry in the Directory Server against the provided 226 * attribute value assertion. 227 * <p> 228 * This method is equivalent to the following code: 229 * 230 * <pre> 231 * CompareRequest request = new CompareRequest(name, attributeDescription, assertionValue); 232 * connection.compare(request); 233 * </pre> 234 * 235 * @param name 236 * The distinguished name of the entry to be compared. 237 * @param attributeDescription 238 * The name of the attribute to be compared. 239 * @param assertionValue 240 * The assertion value to be compared. 241 * @return The result of the operation. 242 * @throws ErrorResultException 243 * If the result code indicates that the request failed for some 244 * reason. 245 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 246 * If {@code name} or {@code AttributeDescription} could not be 247 * decoded using the default schema. 248 * @throws UnsupportedOperationException 249 * If this connection does not support compare operations. 250 * @throws IllegalStateException 251 * If this connection has already been closed, i.e. if 252 * {@code isClosed() == true}. 253 * @throws NullPointerException 254 * If {@code name}, {@code attributeDescription}, or 255 * {@code assertionValue} was {@code null}. 256 */ 257 public CompareResult compare(String name, String attributeDescription, String assertionValue) 258 throws ErrorResultException { 259 return connection.compare(name, attributeDescription, assertionValue); 260 } 261 262 /** 263 * Deletes an entry from the Directory Server using the provided delete 264 * request. 265 * 266 * @param request The delete request. 267 * @return The result of the operation. 268 * @throws ErrorResultException If the result code indicates that the request failed for some 269 * reason. 270 * @throws UnsupportedOperationException If this connection does not support delete operations. 271 * @throws IllegalStateException If this connection has already been closed, i.e. if 272 * {@code isClosed() == true}. 273 * @throws NullPointerException If {@code request} was {@code null}. 274 */ 275 public Result delete(DeleteRequest request) throws ErrorResultException { 276 return connection.delete(request); 277 } 278 279 /** 280 * Deletes the named entry from the Directory Server. 281 * <p> 282 * This method is equivalent to the following code: 283 * 284 * <pre> 285 * DeleteRequest request = new DeleteRequest(name); 286 * connection.delete(request); 287 * </pre> 288 * 289 * @param name 290 * The distinguished name of the entry to be deleted. 291 * @return The result of the operation. 292 * @throws ErrorResultException 293 * If the result code indicates that the request failed for some 294 * reason. 295 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 296 * If {@code name} could not be decoded using the default 297 * schema. 298 * @throws UnsupportedOperationException 299 * If this connection does not support delete operations. 300 * @throws IllegalStateException 301 * If this connection has already been closed, i.e. if 302 * {@code isClosed() == true}. 303 * @throws NullPointerException 304 * If {@code name} was {@code null}. 305 */ 306 public Result delete(String name) throws ErrorResultException { 307 return connection.delete(name); 308 } 309 310 /** 311 * Deletes the named entry and all of its subordinates from the Directory 312 * Server. 313 * <p> 314 * This method is equivalent to the following code: 315 * 316 * <pre> 317 * DeleteRequest request = new DeleteRequest(name).addControl( 318 * connection.delete(request); 319 * </pre> 320 * 321 * @param name 322 * The distinguished name of the subtree base entry to be 323 * deleted. 324 * @return The result of the operation. 325 * @throws ErrorResultException 326 * If the result code indicates that the request failed for some 327 * reason. 328 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 329 * If {@code name} could not be decoded using the default 330 * schema. 331 * @throws UnsupportedOperationException 332 * If this connection does not support delete operations. 333 * @throws IllegalStateException 334 * If this connection has already been closed, i.e. if 335 * {@code isClosed() == true}. 336 * @throws NullPointerException 337 * If {@code name} was {@code null}. 338 */ 339 public Result deleteSubtree(String name) throws ErrorResultException { 340 return connection.deleteSubtree(name); 341 } 342 343 /** 344 * Modifies an entry in the Directory Server using the provided modify 345 * request. 346 * 347 * @param request The modify request. 348 * @return The result of the operation. 349 * @throws ErrorResultException If the result code indicates that the request failed for some 350 * reason. 351 * @throws UnsupportedOperationException If this connection does not support modify operations. 352 * @throws IllegalStateException If this connection has already been closed, i.e. if 353 * {@code isClosed() == true}. 354 * @throws NullPointerException If {@code request} was {@code null}. 355 */ 356 public Result modify(ModifyRequest request) throws ErrorResultException { 357 return connection.modify(request); 358 } 359 360 /** 361 * Modifies an entry in the Directory Server using the provided lines of 362 * LDIF. 363 * <p> 364 * This method is equivalent to the following code: 365 * 366 * <pre> 367 * ModifyRequest request = new ModifyRequest(name, ldifChanges); 368 * connection.modify(request); 369 * </pre> 370 * 371 * @param ldifLines 372 * Lines of LDIF containing the a single LDIF modify change 373 * record. 374 * @return The result of the operation. 375 * @throws ErrorResultException 376 * If the result code indicates that the request failed for some 377 * reason. 378 * @throws UnsupportedOperationException 379 * If this connection does not support modify operations. 380 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 381 * If {@code ldifLines} was empty, or contained invalid LDIF, or 382 * could not be decoded using the default schema. 383 * @throws IllegalStateException 384 * If this connection has already been closed, i.e. if 385 * {@code isClosed() == true}. 386 * @throws NullPointerException 387 * If {@code ldifLines} was {@code null} . 388 */ 389 public Result modify(String... ldifLines) throws ErrorResultException { 390 return connection.modify(ldifLines); 391 } 392 393 /** 394 * Renames an entry in the Directory Server using the provided modify DN 395 * request. 396 * 397 * @param request The modify DN request. 398 * @return The result of the operation. 399 * @throws ErrorResultException If the result code indicates that the request failed for some 400 * reason. 401 * @throws UnsupportedOperationException If this connection does not support modify DN operations. 402 * @throws IllegalStateException If this connection has already been closed, i.e. if 403 * {@code isClosed() == true}. 404 * @throws NullPointerException If {@code request} was {@code null}. 405 */ 406 public Result modifyDN(ModifyDNRequest request) throws ErrorResultException { 407 return connection.modifyDN(request); 408 } 409 410 /** 411 * Renames the named entry in the Directory Server using the provided new 412 * RDN. 413 * <p> 414 * This method is equivalent to the following code: 415 * 416 * <pre> 417 * ModifyDNRequest request = new ModifyDNRequest(name, newRDN); 418 * connection.modifyDN(request); 419 * </pre> 420 * 421 * @param name 422 * The distinguished name of the entry to be renamed. 423 * @param newRDN 424 * The new RDN of the entry. 425 * @return The result of the operation. 426 * @throws ErrorResultException 427 * If the result code indicates that the request failed for some 428 * reason. 429 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 430 * If {@code name} or {@code newRDN} could not be decoded using 431 * the default schema. 432 * @throws UnsupportedOperationException 433 * If this connection does not support modify DN operations. 434 * @throws IllegalStateException 435 * If this connection has already been closed, i.e. if 436 * {@code isClosed() == true}. 437 * @throws NullPointerException 438 * If {@code name} or {@code newRDN} was {@code null}. 439 */ 440 public Result modifyDN(String name, String newRDN) throws ErrorResultException { 441 return connection.modifyDN(name, newRDN); 442 } 443 444 /** 445 * Reads the named entry from the Directory Server. 446 * <p> 447 * If the requested entry is not returned by the Directory Server then the 448 * request will fail with an {@link org.forgerock.opendj.ldap.EntryNotFoundException}. More 449 * specifically, this method will never return {@code null}. 450 * <p> 451 * This method is equivalent to the following code: 452 * 453 * <pre> 454 * SearchRequest request = 455 * new SearchRequest(name, SearchScope.BASE_OBJECT, "(objectClass=*)", attributeDescriptions); 456 * connection.searchSingleEntry(request); 457 * </pre> 458 * 459 * @param name 460 * The distinguished name of the entry to be read. 461 * @param attributeDescriptions 462 * The names of the attributes to be included with the entry, 463 * which may be {@code null} or empty indicating that all user 464 * attributes should be returned. 465 * @return The single search result entry returned from the search. 466 * @throws ErrorResultException 467 * If the result code indicates that the request failed for some 468 * reason. 469 * @throws UnsupportedOperationException 470 * If this connection does not support search operations. 471 * @throws IllegalStateException 472 * If this connection has already been closed, i.e. if 473 * {@code isClosed() == true}. 474 * @throws NullPointerException 475 * If the {@code name} was {@code null}. 476 */ 477 public SearchResultEntry readEntry(DN name, String... attributeDescriptions) 478 throws ErrorResultException { 479 return connection.readEntry(name, attributeDescriptions); 480 } 481 482 /** 483 * Reads the named entry from the Directory Server. 484 * <p> 485 * If the requested entry is not returned by the Directory Server then the 486 * request will fail with an {@link org.forgerock.opendj.ldap.EntryNotFoundException}. More 487 * specifically, this method will never return {@code null}. 488 * <p> 489 * This method is equivalent to the following code: 490 * 491 * <pre> 492 * SearchRequest request = 493 * new SearchRequest(name, SearchScope.BASE_OBJECT, "(objectClass=*)", attributeDescriptions); 494 * connection.searchSingleEntry(request); 495 * </pre> 496 * 497 * @param name 498 * The distinguished name of the entry to be read. 499 * @param attributeDescriptions 500 * The names of the attributes to be included with the entry. 501 * @return The single search result entry returned from the search. 502 * @throws ErrorResultException 503 * If the result code indicates that the request failed for some 504 * reason. 505 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 506 * If {@code baseObject} could not be decoded using the default 507 * schema. 508 * @throws UnsupportedOperationException 509 * If this connection does not support search operations. 510 * @throws IllegalStateException 511 * If this connection has already been closed, i.e. if 512 * {@code isClosed() == true}. 513 * @throws NullPointerException 514 * If the {@code name} was {@code null}. 515 */ 516 public SearchResultEntry readEntry(String name, String... attributeDescriptions) 517 throws ErrorResultException { 518 return connection.readEntry(name, attributeDescriptions); 519 } 520 521 /** 522 * Searches the Directory Server using the provided search parameters. Any 523 * matching entries returned by the search will be exposed through the 524 * returned {@code ConnectionEntryReader}. 525 * <p> 526 * Unless otherwise specified, calling this method is equivalent to: 527 * 528 * <pre> 529 * ConnectionEntryReader reader = new ConnectionEntryReader(this, request); 530 * </pre> 531 * 532 * @param request 533 * The search request. 534 * @return The result of the operation. 535 * @throws UnsupportedOperationException 536 * If this connection does not support search operations. 537 * @throws IllegalStateException 538 * If this connection has already been closed, i.e. if 539 * {@code isClosed() == true}. 540 * @throws NullPointerException 541 * If {@code request} or {@code entries} was {@code null}. 542 */ 543 public ConnectionEntryReader search(SearchRequest request) { 544 return connection.search(request); 545 } 546 547 /** 548 * Searches the Directory Server using the provided search request. Any 549 * matching entries returned by the search will be added to {@code entries}, 550 * even if the final search result indicates that the search failed. Search 551 * result references will be discarded. 552 * <p> 553 * <b>Warning:</b> Usage of this method is discouraged if the search request 554 * is expected to yield a large number of search results since the entire 555 * set of results will be stored in memory, potentially causing an 556 * {@code OutOfMemoryError}. 557 * <p> 558 * This method is equivalent to the following code: 559 * 560 * <pre> 561 * connection.search(request, entries, null); 562 * </pre> 563 * 564 * @param request 565 * The search request. 566 * @param entries 567 * The collection to which matching entries should be added. 568 * @return The result of the operation. 569 * @throws ErrorResultException 570 * If the result code indicates that the request failed for some 571 * reason. 572 * @throws UnsupportedOperationException 573 * If this connection does not support search operations. 574 * @throws IllegalStateException 575 * If this connection has already been closed, i.e. if 576 * {@code isClosed() == true}. 577 * @throws NullPointerException 578 * If {@code request} or {@code entries} was {@code null}. 579 */ 580 public Result search(SearchRequest request, Collection<? super SearchResultEntry> entries) 581 throws ErrorResultException { 582 return connection.search(request, entries); 583 } 584 585 /** 586 * Searches the Directory Server using the provided search request. Any 587 * matching entries returned by the search will be added to {@code entries}, 588 * even if the final search result indicates that the search failed. 589 * Similarly, search result references returned by the search will be added 590 * to {@code references}. 591 * <p> 592 * <b>Warning:</b> Usage of this method is discouraged if the search request 593 * is expected to yield a large number of search results since the entire 594 * set of results will be stored in memory, potentially causing an 595 * {@code OutOfMemoryError}. 596 * 597 * @param request 598 * The search request. 599 * @param entries 600 * The collection to which matching entries should be added. 601 * @param references 602 * The collection to which search result references should be 603 * added, or {@code null} if references are to be discarded. 604 * @return The result of the operation. 605 * @throws ErrorResultException 606 * If the result code indicates that the request failed for some 607 * reason. 608 * @throws UnsupportedOperationException 609 * If this connection does not support search operations. 610 * @throws IllegalStateException 611 * If this connection has already been closed, i.e. if 612 * {@code isClosed() == true}. 613 * @throws NullPointerException 614 * If {@code request} or {@code entries} was {@code null}. 615 */ 616 public Result search(SearchRequest request, Collection<? super SearchResultEntry> entries, 617 Collection<? super SearchResultReference> references) throws ErrorResultException { 618 return connection.search(request, entries, references); 619 } 620 621 /** 622 * Searches the Directory Server using the provided search parameters. Any 623 * matching entries returned by the search will be exposed through the 624 * {@code EntryReader} interface. 625 * <p> 626 * <b>Warning:</b> When using a queue with an optional capacity bound, the 627 * connection will stop reading responses and wait if necessary for space to 628 * become available. 629 * <p> 630 * This method is equivalent to the following code: 631 * 632 * <pre> 633 * SearchRequest request = new SearchRequest(baseDN, scope, filter, attributeDescriptions); 634 * connection.search(request, new LinkedBlockingQueue<Response>()); 635 * </pre> 636 * 637 * @param baseObject 638 * The distinguished name of the base entry relative to which the 639 * search is to be performed. 640 * @param scope 641 * The scope of the search. 642 * @param filter 643 * The filter that defines the conditions that must be fulfilled 644 * in order for an entry to be returned. 645 * @param attributeDescriptions 646 * The names of the attributes to be included with each entry. 647 * @return An entry reader exposing the returned entries. 648 * @throws UnsupportedOperationException 649 * If this connection does not support search operations. 650 * @throws IllegalStateException 651 * If this connection has already been closed, i.e. if 652 * {@code isClosed() == true}. 653 * @throws NullPointerException 654 * If the {@code baseObject}, {@code scope}, or {@code filter} 655 * were {@code null}. 656 */ 657 public ConnectionEntryReader search(String baseObject, SearchScope scope, String filter, 658 String... attributeDescriptions) { 659 return connection.search(baseObject, scope, filter, attributeDescriptions); 660 } 661 662 /** 663 * Searches the Directory Server for a single entry using the provided 664 * search request. 665 * <p> 666 * If the requested entry is not returned by the Directory Server then the 667 * request will fail with an {@link org.forgerock.opendj.ldap.EntryNotFoundException}. More 668 * specifically, this method will never return {@code null}. If multiple 669 * matching entries are returned by the Directory Server then the request 670 * will fail with an {@link org.forgerock.opendj.ldap.MultipleEntriesFoundException}. 671 * 672 * @param request 673 * The search request. 674 * @return The single search result entry returned from the search. 675 * @throws ErrorResultException 676 * If the result code indicates that the request failed for some 677 * reason. 678 * @throws UnsupportedOperationException 679 * If this connection does not support search operations. 680 * @throws IllegalStateException 681 * If this connection has already been closed, i.e. if 682 * {@code isClosed() == true}. 683 * @throws NullPointerException 684 * If the {@code request} was {@code null}. 685 */ 686 public SearchResultEntry searchSingleEntry(SearchRequest request) throws ErrorResultException { 687 return connection.searchSingleEntry(request); 688 } 689 690 /** 691 * Searches the Directory Server for a single entry using the provided 692 * search parameters. 693 * <p> 694 * If the requested entry is not returned by the Directory Server then the 695 * request will fail with an {@link org.forgerock.opendj.ldap.EntryNotFoundException}. More 696 * specifically, this method will never return {@code null}. If multiple 697 * matching entries are returned by the Directory Server then the request 698 * will fail with an {@link org.forgerock.opendj.ldap.MultipleEntriesFoundException}. 699 * <p> 700 * This method is equivalent to the following code: 701 * 702 * <pre> 703 * SearchRequest request = new SearchRequest(baseObject, scope, filter, attributeDescriptions); 704 * connection.searchSingleEntry(request); 705 * </pre> 706 * 707 * @param baseObject 708 * The distinguished name of the base entry relative to which the 709 * search is to be performed. 710 * @param scope 711 * The scope of the search. 712 * @param filter 713 * The filter that defines the conditions that must be fulfilled 714 * in order for an entry to be returned. 715 * @param attributeDescriptions 716 * The names of the attributes to be included with each entry. 717 * @return The single search result entry returned from the search. 718 * @throws ErrorResultException 719 * If the result code indicates that the request failed for some 720 * reason. 721 * @throws org.forgerock.i18n.LocalizedIllegalArgumentException 722 * If {@code baseObject} could not be decoded using the default 723 * schema or if {@code filter} is not a valid LDAP string 724 * representation of a filter. 725 * @throws UnsupportedOperationException 726 * If this connection does not support search operations. 727 * @throws IllegalStateException 728 * If this connection has already been closed, i.e. if 729 * {@code isClosed() == true}. 730 * @throws NullPointerException 731 * If the {@code baseObject}, {@code scope}, or {@code filter} 732 * were {@code null}. 733 */ 734 public SearchResultEntry searchSingleEntry(String baseObject, SearchScope scope, String filter, 735 String... attributeDescriptions) throws ErrorResultException { 736 return connection.searchSingleEntry(baseObject, scope, filter, attributeDescriptions); 737 } 738 739}