001/* 002 * Copyright 2007-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2008-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk; 037 038 039 040import java.util.List; 041import java.util.Timer; 042import java.util.concurrent.LinkedBlockingQueue; 043import java.util.concurrent.TimeUnit; 044import java.util.logging.Level; 045 046import com.unboundid.asn1.ASN1Buffer; 047import com.unboundid.asn1.ASN1Element; 048import com.unboundid.asn1.ASN1OctetString; 049import com.unboundid.ldap.protocol.LDAPMessage; 050import com.unboundid.ldap.protocol.LDAPResponse; 051import com.unboundid.ldap.protocol.ProtocolOp; 052import com.unboundid.ldif.LDIFDeleteChangeRecord; 053import com.unboundid.util.Debug; 054import com.unboundid.util.InternalUseOnly; 055import com.unboundid.util.Mutable; 056import com.unboundid.util.StaticUtils; 057import com.unboundid.util.ThreadSafety; 058import com.unboundid.util.ThreadSafetyLevel; 059import com.unboundid.util.Validator; 060 061import static com.unboundid.ldap.sdk.LDAPMessages.*; 062 063 064 065/** 066 * This class implements the processing necessary to perform an LDAPv3 delete 067 * operation, which removes an entry from the directory. A delete request 068 * contains the DN of the entry to remove. It may also include a set of 069 * controls to send to the server. 070 * {@code DeleteRequest} objects are mutable and therefore can be altered and 071 * re-used for multiple requests. Note, however, that {@code DeleteRequest} 072 * objects are not threadsafe and therefore a single {@code DeleteRequest} 073 * object instance should not be used to process multiple requests at the same 074 * time. 075 * <BR><BR> 076 * <H2>Example</H2> 077 * The following example demonstrates the process for performing a delete 078 * operation: 079 * <PRE> 080 * DeleteRequest deleteRequest = 081 * new DeleteRequest("cn=entry to delete,dc=example,dc=com"); 082 * LDAPResult deleteResult; 083 * try 084 * { 085 * deleteResult = connection.delete(deleteRequest); 086 * // If we get here, the delete was successful. 087 * } 088 * catch (LDAPException le) 089 * { 090 * // The delete operation failed. 091 * deleteResult = le.toLDAPResult(); 092 * ResultCode resultCode = le.getResultCode(); 093 * String errorMessageFromServer = le.getDiagnosticMessage(); 094 * } 095 * </PRE> 096 */ 097@Mutable() 098@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 099public final class DeleteRequest 100 extends UpdatableLDAPRequest 101 implements ReadOnlyDeleteRequest, ResponseAcceptor, ProtocolOp 102{ 103 /** 104 * The serial version UID for this serializable class. 105 */ 106 private static final long serialVersionUID = -6126029442850884239L; 107 108 109 110 // The message ID from the last LDAP message sent from this request. 111 private int messageID = -1; 112 113 // The queue that will be used to receive response messages from the server. 114 private final LinkedBlockingQueue<LDAPResponse> responseQueue = 115 new LinkedBlockingQueue<>(); 116 117 // The DN of the entry to delete. 118 private String dn; 119 120 121 122 /** 123 * Creates a new delete request with the provided DN. 124 * 125 * @param dn The DN of the entry to delete. It must not be {@code null}. 126 */ 127 public DeleteRequest(final String dn) 128 { 129 super(null); 130 131 Validator.ensureNotNull(dn); 132 133 this.dn = dn; 134 } 135 136 137 138 /** 139 * Creates a new delete request with the provided DN. 140 * 141 * @param dn The DN of the entry to delete. It must not be 142 * {@code null}. 143 * @param controls The set of controls to include in the request. 144 */ 145 public DeleteRequest(final String dn, final Control[] controls) 146 { 147 super(controls); 148 149 Validator.ensureNotNull(dn); 150 151 this.dn = dn; 152 } 153 154 155 156 /** 157 * Creates a new delete request with the provided DN. 158 * 159 * @param dn The DN of the entry to delete. It must not be {@code null}. 160 */ 161 public DeleteRequest(final DN dn) 162 { 163 super(null); 164 165 Validator.ensureNotNull(dn); 166 167 this.dn = dn.toString(); 168 } 169 170 171 172 /** 173 * Creates a new delete request with the provided DN. 174 * 175 * @param dn The DN of the entry to delete. It must not be 176 * {@code null}. 177 * @param controls The set of controls to include in the request. 178 */ 179 public DeleteRequest(final DN dn, final Control[] controls) 180 { 181 super(controls); 182 183 Validator.ensureNotNull(dn); 184 185 this.dn = dn.toString(); 186 } 187 188 189 190 /** 191 * {@inheritDoc} 192 */ 193 @Override() 194 public String getDN() 195 { 196 return dn; 197 } 198 199 200 201 /** 202 * Specifies the DN of the entry to delete. 203 * 204 * @param dn The DN of the entry to delete. It must not be {@code null}. 205 */ 206 public void setDN(final String dn) 207 { 208 Validator.ensureNotNull(dn); 209 210 this.dn = dn; 211 } 212 213 214 215 /** 216 * Specifies the DN of the entry to delete. 217 * 218 * @param dn The DN of the entry to delete. It must not be {@code null}. 219 */ 220 public void setDN(final DN dn) 221 { 222 Validator.ensureNotNull(dn); 223 224 this.dn = dn.toString(); 225 } 226 227 228 229 /** 230 * {@inheritDoc} 231 */ 232 @Override() 233 public byte getProtocolOpType() 234 { 235 return LDAPMessage.PROTOCOL_OP_TYPE_DELETE_REQUEST; 236 } 237 238 239 240 /** 241 * {@inheritDoc} 242 */ 243 @Override() 244 public void writeTo(final ASN1Buffer buffer) 245 { 246 buffer.addOctetString(LDAPMessage.PROTOCOL_OP_TYPE_DELETE_REQUEST, dn); 247 } 248 249 250 251 /** 252 * Encodes the delete request protocol op to an ASN.1 element. 253 * 254 * @return The ASN.1 element with the encoded delete request protocol op. 255 */ 256 @Override() 257 public ASN1Element encodeProtocolOp() 258 { 259 return new ASN1OctetString(LDAPMessage.PROTOCOL_OP_TYPE_DELETE_REQUEST, dn); 260 } 261 262 263 264 /** 265 * Sends this delete request to the directory server over the provided 266 * connection and returns the associated response. 267 * 268 * @param connection The connection to use to communicate with the directory 269 * server. 270 * @param depth The current referral depth for this request. It should 271 * always be one for the initial request, and should only 272 * be incremented when following referrals. 273 * 274 * @return An LDAP result object that provides information about the result 275 * of the delete processing. 276 * 277 * @throws LDAPException If a problem occurs while sending the request or 278 * reading the response. 279 */ 280 @Override() 281 protected LDAPResult process(final LDAPConnection connection, final int depth) 282 throws LDAPException 283 { 284 if (connection.synchronousMode()) 285 { 286 @SuppressWarnings("deprecation") 287 final boolean autoReconnect = 288 connection.getConnectionOptions().autoReconnect(); 289 return processSync(connection, depth, autoReconnect); 290 } 291 292 final long requestTime = System.nanoTime(); 293 processAsync(connection, null); 294 295 try 296 { 297 // Wait for and process the response. 298 final LDAPResponse response; 299 try 300 { 301 final long responseTimeout = getResponseTimeoutMillis(connection); 302 if (responseTimeout > 0) 303 { 304 response = responseQueue.poll(responseTimeout, TimeUnit.MILLISECONDS); 305 } 306 else 307 { 308 response = responseQueue.take(); 309 } 310 } 311 catch (final InterruptedException ie) 312 { 313 Debug.debugException(ie); 314 Thread.currentThread().interrupt(); 315 throw new LDAPException(ResultCode.LOCAL_ERROR, 316 ERR_DELETE_INTERRUPTED.get(connection.getHostPort()), ie); 317 } 318 319 return handleResponse(connection, response, requestTime, depth, false); 320 } 321 finally 322 { 323 connection.deregisterResponseAcceptor(messageID); 324 } 325 } 326 327 328 329 /** 330 * Sends this delete request to the directory server over the provided 331 * connection and returns the message ID for the request. 332 * 333 * @param connection The connection to use to communicate with the 334 * directory server. 335 * @param resultListener The async result listener that is to be notified 336 * when the response is received. It may be 337 * {@code null} only if the result is to be processed 338 * by this class. 339 * 340 * @return The async request ID created for the operation, or {@code null} if 341 * the provided {@code resultListener} is {@code null} and the 342 * operation will not actually be processed asynchronously. 343 * 344 * @throws LDAPException If a problem occurs while sending the request. 345 */ 346 AsyncRequestID processAsync(final LDAPConnection connection, 347 final AsyncResultListener resultListener) 348 throws LDAPException 349 { 350 // Create the LDAP message. 351 messageID = connection.nextMessageID(); 352 final LDAPMessage message = new LDAPMessage(messageID, this, getControls()); 353 354 355 // If the provided async result listener is {@code null}, then we'll use 356 // this class as the message acceptor. Otherwise, create an async helper 357 // and use it as the message acceptor. 358 final AsyncRequestID asyncRequestID; 359 final long timeout = getResponseTimeoutMillis(connection); 360 if (resultListener == null) 361 { 362 asyncRequestID = null; 363 connection.registerResponseAcceptor(messageID, this); 364 } 365 else 366 { 367 final AsyncHelper helper = new AsyncHelper(connection, 368 OperationType.DELETE, messageID, resultListener, 369 getIntermediateResponseListener()); 370 connection.registerResponseAcceptor(messageID, helper); 371 asyncRequestID = helper.getAsyncRequestID(); 372 373 if (timeout > 0L) 374 { 375 final Timer timer = connection.getTimer(); 376 final AsyncTimeoutTimerTask timerTask = 377 new AsyncTimeoutTimerTask(helper); 378 timer.schedule(timerTask, timeout); 379 asyncRequestID.setTimerTask(timerTask); 380 } 381 } 382 383 384 // Send the request to the server. 385 try 386 { 387 Debug.debugLDAPRequest(Level.INFO, this, messageID, connection); 388 389 final LDAPConnectionLogger logger = 390 connection.getConnectionOptions().getConnectionLogger(); 391 if (logger != null) 392 { 393 logger.logDeleteRequest(connection, messageID, this); 394 } 395 396 connection.getConnectionStatistics().incrementNumDeleteRequests(); 397 connection.sendMessage(message, timeout); 398 return asyncRequestID; 399 } 400 catch (final LDAPException le) 401 { 402 Debug.debugException(le); 403 404 connection.deregisterResponseAcceptor(messageID); 405 throw le; 406 } 407 } 408 409 410 411 /** 412 * Processes this delete operation in synchronous mode, in which the same 413 * thread will send the request and read the response. 414 * 415 * @param connection The connection to use to communicate with the directory 416 * server. 417 * @param depth The current referral depth for this request. It should 418 * always be one for the initial request, and should only 419 * be incremented when following referrals. 420 * @param allowRetry Indicates whether the request may be re-tried on a 421 * re-established connection if the initial attempt fails 422 * in a way that indicates the connection is no longer 423 * valid and autoReconnect is true. 424 * 425 * @return An LDAP result object that provides information about the result 426 * of the delete processing. 427 * 428 * @throws LDAPException If a problem occurs while sending the request or 429 * reading the response. 430 */ 431 private LDAPResult processSync(final LDAPConnection connection, 432 final int depth, final boolean allowRetry) 433 throws LDAPException 434 { 435 // Create the LDAP message. 436 messageID = connection.nextMessageID(); 437 final LDAPMessage message = 438 new LDAPMessage(messageID, this, getControls()); 439 440 441 // Send the request to the server. 442 final long requestTime = System.nanoTime(); 443 Debug.debugLDAPRequest(Level.INFO, this, messageID, connection); 444 445 final LDAPConnectionLogger logger = 446 connection.getConnectionOptions().getConnectionLogger(); 447 if (logger != null) 448 { 449 logger.logDeleteRequest(connection, messageID, this); 450 } 451 452 connection.getConnectionStatistics().incrementNumDeleteRequests(); 453 try 454 { 455 connection.sendMessage(message, getResponseTimeoutMillis(connection)); 456 } 457 catch (final LDAPException le) 458 { 459 Debug.debugException(le); 460 461 if (allowRetry) 462 { 463 final LDAPResult retryResult = reconnectAndRetry(connection, depth, 464 le.getResultCode()); 465 if (retryResult != null) 466 { 467 return retryResult; 468 } 469 } 470 471 throw le; 472 } 473 474 while (true) 475 { 476 final LDAPResponse response; 477 try 478 { 479 response = connection.readResponse(messageID); 480 } 481 catch (final LDAPException le) 482 { 483 Debug.debugException(le); 484 485 if ((le.getResultCode() == ResultCode.TIMEOUT) && 486 connection.getConnectionOptions().abandonOnTimeout()) 487 { 488 connection.abandon(messageID); 489 } 490 491 if (allowRetry) 492 { 493 final LDAPResult retryResult = reconnectAndRetry(connection, depth, 494 le.getResultCode()); 495 if (retryResult != null) 496 { 497 return retryResult; 498 } 499 } 500 501 throw le; 502 } 503 504 if (response instanceof IntermediateResponse) 505 { 506 final IntermediateResponseListener listener = 507 getIntermediateResponseListener(); 508 if (listener != null) 509 { 510 listener.intermediateResponseReturned( 511 (IntermediateResponse) response); 512 } 513 } 514 else 515 { 516 return handleResponse(connection, response, requestTime, depth, 517 allowRetry); 518 } 519 } 520 } 521 522 523 524 /** 525 * Performs the necessary processing for handling a response. 526 * 527 * @param connection The connection used to read the response. 528 * @param response The response to be processed. 529 * @param requestTime The time the request was sent to the server. 530 * @param depth The current referral depth for this request. It 531 * should always be one for the initial request, and 532 * should only be incremented when following referrals. 533 * @param allowRetry Indicates whether the request may be re-tried on a 534 * re-established connection if the initial attempt fails 535 * in a way that indicates the connection is no longer 536 * valid and autoReconnect is true. 537 * 538 * @return The delete result. 539 * 540 * @throws LDAPException If a problem occurs. 541 */ 542 private LDAPResult handleResponse(final LDAPConnection connection, 543 final LDAPResponse response, 544 final long requestTime, final int depth, 545 final boolean allowRetry) 546 throws LDAPException 547 { 548 if (response == null) 549 { 550 final long waitTime = 551 StaticUtils.nanosToMillis(System.nanoTime() - requestTime); 552 if (connection.getConnectionOptions().abandonOnTimeout()) 553 { 554 connection.abandon(messageID); 555 } 556 557 throw new LDAPException(ResultCode.TIMEOUT, 558 ERR_DELETE_CLIENT_TIMEOUT.get(waitTime, messageID, dn, 559 connection.getHostPort())); 560 } 561 562 connection.getConnectionStatistics().incrementNumDeleteResponses( 563 System.nanoTime() - requestTime); 564 if (response instanceof ConnectionClosedResponse) 565 { 566 // The connection was closed while waiting for the response. 567 if (allowRetry) 568 { 569 final LDAPResult retryResult = reconnectAndRetry(connection, depth, 570 ResultCode.SERVER_DOWN); 571 if (retryResult != null) 572 { 573 return retryResult; 574 } 575 } 576 577 final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; 578 final String message = ccr.getMessage(); 579 if (message == null) 580 { 581 throw new LDAPException(ccr.getResultCode(), 582 ERR_CONN_CLOSED_WAITING_FOR_DELETE_RESPONSE.get( 583 connection.getHostPort(), toString())); 584 } 585 else 586 { 587 throw new LDAPException(ccr.getResultCode(), 588 ERR_CONN_CLOSED_WAITING_FOR_DELETE_RESPONSE_WITH_MESSAGE.get( 589 connection.getHostPort(), toString(), message)); 590 } 591 } 592 593 final LDAPResult result = (LDAPResult) response; 594 if ((result.getResultCode().equals(ResultCode.REFERRAL)) && 595 followReferrals(connection)) 596 { 597 if (depth >= connection.getConnectionOptions().getReferralHopLimit()) 598 { 599 return new LDAPResult(messageID, ResultCode.REFERRAL_LIMIT_EXCEEDED, 600 ERR_TOO_MANY_REFERRALS.get(), 601 result.getMatchedDN(), result.getReferralURLs(), 602 result.getResponseControls()); 603 } 604 605 return followReferral(result, connection, depth); 606 } 607 else 608 { 609 if (allowRetry) 610 { 611 final LDAPResult retryResult = reconnectAndRetry(connection, depth, 612 result.getResultCode()); 613 if (retryResult != null) 614 { 615 return retryResult; 616 } 617 } 618 619 return result; 620 } 621 } 622 623 624 625 /** 626 * Attempts to re-establish the connection and retry processing this request 627 * on it. 628 * 629 * @param connection The connection to be re-established. 630 * @param depth The current referral depth for this request. It should 631 * always be one for the initial request, and should only 632 * be incremented when following referrals. 633 * @param resultCode The result code for the previous operation attempt. 634 * 635 * @return The result from re-trying the add, or {@code null} if it could not 636 * be re-tried. 637 */ 638 private LDAPResult reconnectAndRetry(final LDAPConnection connection, 639 final int depth, 640 final ResultCode resultCode) 641 { 642 try 643 { 644 // We will only want to retry for certain result codes that indicate a 645 // connection problem. 646 switch (resultCode.intValue()) 647 { 648 case ResultCode.SERVER_DOWN_INT_VALUE: 649 case ResultCode.DECODING_ERROR_INT_VALUE: 650 case ResultCode.CONNECT_ERROR_INT_VALUE: 651 connection.reconnect(); 652 return processSync(connection, depth, false); 653 } 654 } 655 catch (final Exception e) 656 { 657 Debug.debugException(e); 658 } 659 660 return null; 661 } 662 663 664 665 /** 666 * Attempts to follow a referral to perform a delete operation in the target 667 * server. 668 * 669 * @param referralResult The LDAP result object containing information about 670 * the referral to follow. 671 * @param connection The connection on which the referral was received. 672 * @param depth The number of referrals followed in the course of 673 * processing this request. 674 * 675 * @return The result of attempting to process the delete operation by 676 * following the referral. 677 * 678 * @throws LDAPException If a problem occurs while attempting to establish 679 * the referral connection, sending the request, or 680 * reading the result. 681 */ 682 private LDAPResult followReferral(final LDAPResult referralResult, 683 final LDAPConnection connection, 684 final int depth) 685 throws LDAPException 686 { 687 for (final String urlString : referralResult.getReferralURLs()) 688 { 689 try 690 { 691 final LDAPURL referralURL = new LDAPURL(urlString); 692 final String host = referralURL.getHost(); 693 694 if (host == null) 695 { 696 // We can't handle a referral in which there is no host. 697 continue; 698 } 699 700 final DeleteRequest deleteRequest; 701 if (referralURL.baseDNProvided()) 702 { 703 deleteRequest = new DeleteRequest(referralURL.getBaseDN(), 704 getControls()); 705 } 706 else 707 { 708 deleteRequest = this; 709 } 710 711 final LDAPConnection referralConn = getReferralConnector(connection). 712 getReferralConnection(referralURL, connection); 713 try 714 { 715 return deleteRequest.process(referralConn, depth+1); 716 } 717 finally 718 { 719 referralConn.setDisconnectInfo(DisconnectType.REFERRAL, null, null); 720 referralConn.close(); 721 } 722 } 723 catch (final LDAPException le) 724 { 725 Debug.debugException(le); 726 } 727 } 728 729 // If we've gotten here, then we could not follow any of the referral URLs, 730 // so we'll just return the original referral result. 731 return referralResult; 732 } 733 734 735 736 /** 737 * {@inheritDoc} 738 */ 739 @InternalUseOnly() 740 @Override() 741 public void responseReceived(final LDAPResponse response) 742 throws LDAPException 743 { 744 try 745 { 746 responseQueue.put(response); 747 } 748 catch (final Exception e) 749 { 750 Debug.debugException(e); 751 752 if (e instanceof InterruptedException) 753 { 754 Thread.currentThread().interrupt(); 755 } 756 757 throw new LDAPException(ResultCode.LOCAL_ERROR, 758 ERR_EXCEPTION_HANDLING_RESPONSE.get( 759 StaticUtils.getExceptionMessage(e)), 760 e); 761 } 762 } 763 764 765 766 /** 767 * {@inheritDoc} 768 */ 769 @Override() 770 public int getLastMessageID() 771 { 772 return messageID; 773 } 774 775 776 777 /** 778 * {@inheritDoc} 779 */ 780 @Override() 781 public OperationType getOperationType() 782 { 783 return OperationType.DELETE; 784 } 785 786 787 788 /** 789 * {@inheritDoc} 790 */ 791 @Override() 792 public DeleteRequest duplicate() 793 { 794 return duplicate(getControls()); 795 } 796 797 798 799 /** 800 * {@inheritDoc} 801 */ 802 @Override() 803 public DeleteRequest duplicate(final Control[] controls) 804 { 805 final DeleteRequest r = new DeleteRequest(dn, controls); 806 807 if (followReferralsInternal() != null) 808 { 809 r.setFollowReferrals(followReferralsInternal()); 810 } 811 812 if (getReferralConnectorInternal() != null) 813 { 814 r.setReferralConnector(getReferralConnectorInternal()); 815 } 816 817 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 818 819 return r; 820 } 821 822 823 824 /** 825 * {@inheritDoc} 826 */ 827 @Override() 828 public LDIFDeleteChangeRecord toLDIFChangeRecord() 829 { 830 return new LDIFDeleteChangeRecord(this); 831 } 832 833 834 835 /** 836 * {@inheritDoc} 837 */ 838 @Override() 839 public String[] toLDIF() 840 { 841 return toLDIFChangeRecord().toLDIF(); 842 } 843 844 845 846 /** 847 * {@inheritDoc} 848 */ 849 @Override() 850 public String toLDIFString() 851 { 852 return toLDIFChangeRecord().toLDIFString(); 853 } 854 855 856 857 /** 858 * {@inheritDoc} 859 */ 860 @Override() 861 public void toString(final StringBuilder buffer) 862 { 863 buffer.append("DeleteRequest(dn='"); 864 buffer.append(dn); 865 buffer.append('\''); 866 867 final Control[] controls = getControls(); 868 if (controls.length > 0) 869 { 870 buffer.append(", controls={"); 871 for (int i=0; i < controls.length; i++) 872 { 873 if (i > 0) 874 { 875 buffer.append(", "); 876 } 877 878 buffer.append(controls[i]); 879 } 880 buffer.append('}'); 881 } 882 883 buffer.append(')'); 884 } 885 886 887 888 /** 889 * {@inheritDoc} 890 */ 891 @Override() 892 public void toCode(final List<String> lineList, final String requestID, 893 final int indentSpaces, final boolean includeProcessing) 894 { 895 // Create the request variable. 896 ToCodeHelper.generateMethodCall(lineList, indentSpaces, "DeleteRequest", 897 requestID + "Request", "new DeleteRequest", 898 ToCodeArgHelper.createString(dn, "Entry DN")); 899 900 // If there are any controls, then add them to the request. 901 for (final Control c : getControls()) 902 { 903 ToCodeHelper.generateMethodCall(lineList, indentSpaces, null, null, 904 requestID + "Request.addControl", 905 ToCodeArgHelper.createControl(c, null)); 906 } 907 908 909 // Add lines for processing the request and obtaining the result. 910 if (includeProcessing) 911 { 912 // Generate a string with the appropriate indent. 913 final StringBuilder buffer = new StringBuilder(); 914 for (int i=0; i < indentSpaces; i++) 915 { 916 buffer.append(' '); 917 } 918 final String indent = buffer.toString(); 919 920 lineList.add(""); 921 lineList.add(indent + "try"); 922 lineList.add(indent + '{'); 923 lineList.add(indent + " LDAPResult " + requestID + 924 "Result = connection.delete(" + requestID + "Request);"); 925 lineList.add(indent + " // The delete was processed successfully."); 926 lineList.add(indent + '}'); 927 lineList.add(indent + "catch (LDAPException e)"); 928 lineList.add(indent + '{'); 929 lineList.add(indent + " // The delete failed. Maybe the following " + 930 "will help explain why."); 931 lineList.add(indent + " ResultCode resultCode = e.getResultCode();"); 932 lineList.add(indent + " String message = e.getMessage();"); 933 lineList.add(indent + " String matchedDN = e.getMatchedDN();"); 934 lineList.add(indent + " String[] referralURLs = e.getReferralURLs();"); 935 lineList.add(indent + " Control[] responseControls = " + 936 "e.getResponseControls();"); 937 lineList.add(indent + '}'); 938 } 939 } 940}