001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS. 026 */ 027package org.opends.server.tools; 028 029import static com.forgerock.opendj.cli.ArgumentConstants.*; 030import static com.forgerock.opendj.cli.Utils.*; 031 032import static org.opends.messages.ToolMessages.*; 033import static org.opends.server.protocols.ldap.LDAPResultCode.*; 034import static org.opends.server.util.args.LDAPConnectionArgumentParser.*; 035 036import java.io.BufferedReader; 037import java.io.FileReader; 038import java.io.IOException; 039import java.io.InputStreamReader; 040import java.io.OutputStream; 041import java.io.PrintStream; 042import java.io.Reader; 043import java.util.ArrayList; 044import java.util.concurrent.atomic.AtomicInteger; 045 046import org.forgerock.i18n.LocalizableMessage; 047import org.forgerock.i18n.slf4j.LocalizedLogger; 048import org.forgerock.opendj.ldap.ByteString; 049import org.forgerock.opendj.ldap.DecodeException; 050import org.opends.server.controls.SubtreeDeleteControl; 051import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler; 052import org.opends.server.protocols.ldap.DeleteRequestProtocolOp; 053import org.opends.server.protocols.ldap.DeleteResponseProtocolOp; 054import org.opends.server.protocols.ldap.LDAPMessage; 055import org.opends.server.protocols.ldap.ProtocolOp; 056import org.opends.server.types.Control; 057import org.opends.server.types.LDAPException; 058import org.opends.server.types.NullOutputStream; 059import org.opends.server.util.EmbeddedUtils; 060 061import com.forgerock.opendj.cli.ArgumentException; 062import com.forgerock.opendj.cli.ArgumentParser; 063import com.forgerock.opendj.cli.BooleanArgument; 064import com.forgerock.opendj.cli.CliConstants; 065import com.forgerock.opendj.cli.CommonArguments; 066import com.forgerock.opendj.cli.FileBasedArgument; 067import com.forgerock.opendj.cli.IntegerArgument; 068import com.forgerock.opendj.cli.StringArgument; 069 070/** 071 * This class provides a tool that can be used to issue delete requests to the 072 * Directory Server. 073 */ 074public class LDAPDelete 075{ 076 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 077 078 /** The fully-qualified name of this class. */ 079 private static final String CLASS_NAME = "org.opends.server.tools.LDAPDelete"; 080 081 082 /** The message ID counter to use for requests. */ 083 private final AtomicInteger nextMessageID; 084 085 /** The print stream to use for standard error. */ 086 private final PrintStream err; 087 /** The print stream to use for standard output. */ 088 private final PrintStream out; 089 090 091 092 /** 093 * Constructor for the LDAPDelete object. 094 * 095 * @param nextMessageID The next message ID to use for requests. 096 * @param out The print stream to use for standard output. 097 * @param err The print stream to use for standard error. 098 */ 099 public LDAPDelete(AtomicInteger nextMessageID, PrintStream out, 100 PrintStream err) 101 { 102 this.nextMessageID = nextMessageID; 103 this.out = out; 104 this.err = err; 105 } 106 107 /** 108 * Execute the delete request on the specified list of DNs. 109 * 110 * @param connection The connection to use to execute the request. 111 * @param lines The list of DNs to delete. 112 * @param deleteOptions The constraints to use for this request. 113 * 114 * @throws IOException If a problem occurs while attempting to communicate 115 * with the Directory Server. 116 * 117 * @throws LDAPException If the Directory Server returns an error response. 118 */ 119 public void readAndExecute(LDAPConnection connection, 120 ArrayList<String> lines, 121 LDAPDeleteOptions deleteOptions) 122 throws IOException, LDAPException 123 { 124 for(String line : lines) 125 { 126 executeDelete(connection, line, deleteOptions); 127 } 128 } 129 130 /** 131 * Read the specified DNs from the given reader 132 * (file or stdin) and execute the given delete request. 133 * 134 * @param connection The connection to use to execute the request. 135 * @param reader The reader to read the list of DNs from. 136 * @param deleteOptions The constraints to use for this request. 137 * 138 * @throws IOException If a problem occurs while attempting to communicate 139 * with the Directory Server. 140 * 141 * @throws LDAPException If the Directory Server returns an error response. 142 */ 143 public void readAndExecute(LDAPConnection connection, Reader reader, 144 LDAPDeleteOptions deleteOptions) 145 throws IOException, LDAPException 146 { 147 BufferedReader in = new BufferedReader(reader); 148 String line = null; 149 150 while ((line = in.readLine()) != null) 151 { 152 executeDelete(connection, line, deleteOptions); 153 } 154 in.close(); 155 } 156 157 158 /** 159 * Execute the delete request for the specified DN. 160 * 161 * @param connection The connection to use to execute the request. 162 * @param line The DN to delete. 163 * @param deleteOptions The list of constraints for this request. 164 * 165 * @throws IOException If a problem occurs while attempting to communicate 166 * with the Directory Server. 167 * 168 * @throws LDAPException If the Directory Server returns an error response. 169 */ 170 private void executeDelete(LDAPConnection connection, String line, 171 LDAPDeleteOptions deleteOptions) 172 throws IOException, LDAPException 173 { 174 ArrayList<Control> controls = deleteOptions.getControls(); 175 ProtocolOp protocolOp = null; 176 ByteString asn1OctetStr = ByteString.valueOfUtf8(line); 177 178 protocolOp = new DeleteRequestProtocolOp(asn1OctetStr); 179 180 out.println(INFO_PROCESSING_OPERATION.get("DELETE", asn1OctetStr)); 181 if(!deleteOptions.showOperations()) 182 { 183 LDAPMessage message = new LDAPMessage(nextMessageID.getAndIncrement(), 184 protocolOp, controls); 185 LDAPMessage responseMessage = null; 186 try 187 { 188 connection.getLDAPWriter().writeMessage(message); 189 responseMessage = connection.getLDAPReader().readMessage(); 190 } catch(DecodeException ae) 191 { 192 logger.traceException(ae); 193 if (!deleteOptions.continueOnError()) 194 { 195 String msg = LDAPToolUtils.getMessageForConnectionException(ae); 196 throw new IOException(msg, ae); 197 } 198 else 199 { 200 printWrappedText(err, INFO_OPERATION_FAILED.get("DELETE")); 201 printWrappedText(err, ae.getMessage()); 202 return; 203 } 204 } 205 206 DeleteResponseProtocolOp op = 207 responseMessage.getDeleteResponseProtocolOp(); 208 int resultCode = op.getResultCode(); 209 LocalizableMessage errorMessage = op.getErrorMessage(); 210 if(resultCode != SUCCESS && resultCode != REFERRAL && 211 !deleteOptions.continueOnError()) 212 { 213 LocalizableMessage msg = INFO_OPERATION_FAILED.get("DELETE"); 214 throw new LDAPException(resultCode, errorMessage, msg, 215 op.getMatchedDN(), null); 216 } else 217 { 218 if(resultCode != SUCCESS && resultCode != REFERRAL) 219 { 220 LocalizableMessage msg = INFO_OPERATION_FAILED.get("DELETE"); 221 LDAPToolUtils.printErrorMessage(err, msg, resultCode, errorMessage, 222 op.getMatchedDN()); 223 } else 224 { 225 LocalizableMessage msg = INFO_OPERATION_SUCCESSFUL.get("DELETE", line); 226 out.println(msg); 227 } 228 } 229 } 230 } 231 232 /** 233 * The main method for LDAPDelete tool. 234 * 235 * @param args The command-line arguments provided to this program. 236 */ 237 238 public static void main(String[] args) 239 { 240 int retCode = mainDelete(args, true, System.out, System.err); 241 242 if(retCode != 0) 243 { 244 System.exit(filterExitCode(retCode)); 245 } 246 } 247 248 /** 249 * Parses the provided command-line arguments and uses that information to 250 * run the ldapdelete tool. 251 * 252 * @param args The command-line arguments provided to this program. 253 * 254 * @return The error code. 255 */ 256 257 public static int mainDelete(String[] args) 258 { 259 return mainDelete(args, true, System.out, System.err); 260 } 261 262 /** 263 * Parses the provided command-line arguments and uses that information to 264 * run the ldapdelete tool. 265 * 266 * @param args The command-line arguments provided to this 267 * program. 268 * @param initializeServer Indicates whether to initialize the server. 269 * @param outStream The output stream to use for standard output, or 270 * <CODE>null</CODE> if standard output is not 271 * needed. 272 * @param errStream The output stream to use for standard error, or 273 * <CODE>null</CODE> if standard error is not 274 * needed. 275 * 276 * @return The error code. 277 */ 278 279 public static int mainDelete(String[] args, boolean initializeServer, 280 OutputStream outStream, OutputStream errStream) 281 { 282 PrintStream out = NullOutputStream.wrapOrNullStream(outStream); 283 PrintStream err = NullOutputStream.wrapOrNullStream(errStream); 284 285 LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); 286 LDAPDeleteOptions deleteOptions = new LDAPDeleteOptions(); 287 LDAPConnection connection = null; 288 289 BooleanArgument continueOnError = null; 290 BooleanArgument deleteSubtree = null; 291 BooleanArgument noop = null; 292 BooleanArgument saslExternal = null; 293 BooleanArgument showUsage = null; 294 BooleanArgument startTLS = null; 295 BooleanArgument trustAll = null; 296 BooleanArgument useSSL = null; 297 BooleanArgument verbose = null; 298 FileBasedArgument bindPasswordFile = null; 299 FileBasedArgument keyStorePasswordFile = null; 300 FileBasedArgument trustStorePasswordFile = null; 301 IntegerArgument port = null; 302 IntegerArgument version = null; 303 StringArgument bindDN = null; 304 StringArgument bindPassword = null; 305 StringArgument certNickname = null; 306 StringArgument controlStr = null; 307 StringArgument encodingStr = null; 308 StringArgument filename = null; 309 StringArgument hostName = null; 310 StringArgument keyStorePath = null; 311 StringArgument keyStorePassword = null; 312 StringArgument saslOptions = null; 313 StringArgument trustStorePath = null; 314 StringArgument trustStorePassword = null; 315 IntegerArgument connectTimeout = null; 316 StringArgument propertiesFileArgument = null; 317 BooleanArgument noPropertiesFileArgument = null; 318 319 Reader rdr = null; 320 ArrayList<String> dnStrings = new ArrayList<>(); 321 322 // Create the command-line argument parser for use with this program. 323 LocalizableMessage toolDescription = INFO_LDAPDELETE_TOOL_DESCRIPTION.get(); 324 ArgumentParser argParser = new ArgumentParser(CLASS_NAME, toolDescription, 325 false, true, 0, 1, "\"DN\""); 326 argParser.setShortToolDescription(REF_SHORT_DESC_LDAPDELETE.get()); 327 argParser.setVersionHandler(new DirectoryServerVersionHandler()); 328 try 329 { 330 propertiesFileArgument = new StringArgument("propertiesFilePath", 331 null, OPTION_LONG_PROP_FILE_PATH, 332 false, false, true, INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null, 333 INFO_DESCRIPTION_PROP_FILE_PATH.get()); 334 argParser.addArgument(propertiesFileArgument); 335 argParser.setFilePropertiesArgument(propertiesFileArgument); 336 337 noPropertiesFileArgument = new BooleanArgument( 338 "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE, 339 INFO_DESCRIPTION_NO_PROP_FILE.get()); 340 argParser.addArgument(noPropertiesFileArgument); 341 argParser.setNoPropertiesFileArgument(noPropertiesFileArgument); 342 343 hostName = new StringArgument("host", OPTION_SHORT_HOST, 344 OPTION_LONG_HOST, false, false, true, 345 INFO_HOST_PLACEHOLDER.get(), "localhost", 346 null, 347 INFO_DESCRIPTION_HOST.get()); 348 hostName.setPropertyName(OPTION_LONG_HOST); 349 argParser.addArgument(hostName); 350 351 port = new IntegerArgument("port", OPTION_SHORT_PORT, 352 OPTION_LONG_PORT, false, false, true, 353 INFO_PORT_PLACEHOLDER.get(), 389, null, 354 true, 1, true, 65535, 355 INFO_DESCRIPTION_PORT.get()); 356 port.setPropertyName(OPTION_LONG_PORT); 357 argParser.addArgument(port); 358 359 useSSL = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL, 360 OPTION_LONG_USE_SSL, 361 INFO_DESCRIPTION_USE_SSL.get()); 362 useSSL.setPropertyName(OPTION_LONG_USE_SSL); 363 argParser.addArgument(useSSL); 364 365 startTLS = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS, 366 OPTION_LONG_START_TLS, 367 INFO_DESCRIPTION_START_TLS.get()); 368 startTLS.setPropertyName(OPTION_LONG_START_TLS); 369 argParser.addArgument(startTLS); 370 371 bindDN = new StringArgument("bindDN", OPTION_SHORT_BINDDN, 372 OPTION_LONG_BINDDN, false, false, true, 373 INFO_BINDDN_PLACEHOLDER.get(), null, null, 374 INFO_DESCRIPTION_BINDDN.get()); 375 bindDN.setPropertyName(OPTION_LONG_BINDDN); 376 argParser.addArgument(bindDN); 377 378 bindPassword = new StringArgument("bindPassword", OPTION_SHORT_BINDPWD, 379 OPTION_LONG_BINDPWD, 380 false, false, true, 381 INFO_BINDPWD_PLACEHOLDER.get(), 382 null, null, 383 INFO_DESCRIPTION_BINDPASSWORD.get()); 384 bindPassword.setPropertyName(OPTION_LONG_BINDPWD); 385 argParser.addArgument(bindPassword); 386 387 bindPasswordFile = 388 new FileBasedArgument("bindPasswordFile", OPTION_SHORT_BINDPWD_FILE, 389 OPTION_LONG_BINDPWD_FILE, 390 false, false, 391 INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, 392 null, INFO_DESCRIPTION_BINDPASSWORDFILE.get()); 393 bindPasswordFile.setPropertyName(OPTION_LONG_BINDPWD_FILE); 394 argParser.addArgument(bindPasswordFile); 395 396 filename = new StringArgument("filename", OPTION_SHORT_FILENAME, 397 OPTION_LONG_FILENAME, false, false, 398 true, INFO_FILE_PLACEHOLDER.get(), null, 399 null, 400 INFO_DELETE_DESCRIPTION_FILENAME.get()); 401 filename.setPropertyName(OPTION_LONG_FILENAME); 402 argParser.addArgument(filename); 403 404 saslExternal = 405 new BooleanArgument("useSASLExternal", 'r', 406 "useSASLExternal", 407 INFO_DESCRIPTION_USE_SASL_EXTERNAL.get()); 408 saslExternal.setPropertyName("useSASLExternal"); 409 argParser.addArgument(saslExternal); 410 411 saslOptions = new StringArgument( 412 "saslOption", OPTION_SHORT_SASLOPTION, 413 OPTION_LONG_SASLOPTION, 414 false, true, true, 415 INFO_SASL_OPTION_PLACEHOLDER.get(), null, 416 null, INFO_DESCRIPTION_SASL_PROPERTIES.get()); 417 saslOptions.setPropertyName(OPTION_LONG_SASLOPTION); 418 argParser.addArgument(saslOptions); 419 420 trustAll = CommonArguments.getTrustAll(); 421 argParser.addArgument(trustAll); 422 423 keyStorePath = new StringArgument("keyStorePath", 424 OPTION_SHORT_KEYSTOREPATH, 425 OPTION_LONG_KEYSTOREPATH, 426 false, false, true, 427 INFO_KEYSTOREPATH_PLACEHOLDER.get(), 428 null, null, 429 INFO_DESCRIPTION_KEYSTOREPATH.get()); 430 keyStorePath.setPropertyName(OPTION_LONG_KEYSTOREPATH); 431 argParser.addArgument(keyStorePath); 432 433 keyStorePassword = 434 new StringArgument("keyStorePassword", 435 OPTION_SHORT_KEYSTORE_PWD, 436 OPTION_LONG_KEYSTORE_PWD, 437 false, false, 438 true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(), 439 null, null, 440 INFO_DESCRIPTION_KEYSTOREPASSWORD.get()); 441 keyStorePassword.setPropertyName(OPTION_LONG_KEYSTORE_PWD); 442 argParser.addArgument(keyStorePassword); 443 444 keyStorePasswordFile = 445 new FileBasedArgument("keyStorePasswordFile", 446 OPTION_SHORT_KEYSTORE_PWD_FILE, 447 OPTION_LONG_KEYSTORE_PWD_FILE, 448 false, false, 449 INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), 450 null, null, 451 INFO_DESCRIPTION_KEYSTOREPASSWORD_FILE.get()); 452 keyStorePasswordFile.setPropertyName(OPTION_LONG_KEYSTORE_PWD_FILE); 453 argParser.addArgument(keyStorePasswordFile); 454 455 certNickname = new StringArgument( 456 "certnickname", 'N', "certNickname", 457 false, false, true, INFO_NICKNAME_PLACEHOLDER.get(), null, 458 null, INFO_DESCRIPTION_CERT_NICKNAME.get()); 459 certNickname.setPropertyName("certNickname"); 460 argParser.addArgument(certNickname); 461 462 trustStorePath = new StringArgument( 463 "trustStorePath", 464 OPTION_SHORT_TRUSTSTOREPATH, 465 OPTION_LONG_TRUSTSTOREPATH, 466 false, false, true, 467 INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), 468 null, null, 469 INFO_DESCRIPTION_TRUSTSTOREPATH.get()); 470 trustStorePath.setPropertyName(OPTION_LONG_TRUSTSTOREPATH); 471 argParser.addArgument(trustStorePath); 472 473 trustStorePassword = 474 new StringArgument("trustStorePassword", null, 475 OPTION_LONG_TRUSTSTORE_PWD, 476 false, false, true, 477 INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, 478 null, INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get()); 479 trustStorePassword.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD); 480 argParser.addArgument(trustStorePassword); 481 482 trustStorePasswordFile = 483 new FileBasedArgument( 484 "trustStorePasswordFile", 485 OPTION_SHORT_TRUSTSTORE_PWD_FILE, 486 OPTION_LONG_TRUSTSTORE_PWD_FILE, false, false, 487 INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null, null, 488 INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get()); 489 trustStorePasswordFile.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD_FILE); 490 argParser.addArgument(trustStorePasswordFile); 491 492 deleteSubtree = 493 new BooleanArgument("deleteSubtree", 'x', "deleteSubtree", 494 INFO_DELETE_DESCRIPTION_DELETE_SUBTREE.get()); 495 deleteSubtree.setPropertyName("deleteSubtree"); 496 argParser.addArgument(deleteSubtree); 497 498 controlStr = 499 new StringArgument("control", 'J', "control", false, true, true, 500 INFO_LDAP_CONTROL_PLACEHOLDER.get(), 501 null, null, INFO_DESCRIPTION_CONTROLS.get()); 502 controlStr.setPropertyName("control"); 503 argParser.addArgument(controlStr); 504 505 version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION, 506 OPTION_LONG_PROTOCOL_VERSION, false, false, 507 true, 508 INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, 509 null, INFO_DESCRIPTION_VERSION.get()); 510 version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION); 511 argParser.addArgument(version); 512 513 int defaultTimeout = CliConstants.DEFAULT_LDAP_CONNECT_TIMEOUT; 514 connectTimeout = new IntegerArgument(OPTION_LONG_CONNECT_TIMEOUT, 515 null, OPTION_LONG_CONNECT_TIMEOUT, 516 false, false, true, INFO_TIMEOUT_PLACEHOLDER.get(), 517 defaultTimeout, null, 518 true, 0, false, Integer.MAX_VALUE, 519 INFO_DESCRIPTION_CONNECTION_TIMEOUT.get()); 520 connectTimeout.setPropertyName(OPTION_LONG_CONNECT_TIMEOUT); 521 argParser.addArgument(connectTimeout); 522 523 encodingStr = new StringArgument("encoding", 'i', 524 OPTION_LONG_ENCODING, false, 525 false, true, 526 INFO_ENCODING_PLACEHOLDER.get(), null, 527 null, 528 INFO_DESCRIPTION_ENCODING.get()); 529 encodingStr.setPropertyName(OPTION_LONG_ENCODING); 530 argParser.addArgument(encodingStr); 531 532 continueOnError = 533 new BooleanArgument("continueOnError", 'c', "continueOnError", 534 INFO_DESCRIPTION_CONTINUE_ON_ERROR.get()); 535 continueOnError.setPropertyName("continueOnError"); 536 argParser.addArgument(continueOnError); 537 538 noop = new BooleanArgument("no-op", OPTION_SHORT_DRYRUN, 539 OPTION_LONG_DRYRUN, INFO_DESCRIPTION_NOOP.get()); 540 noop.setPropertyName(OPTION_LONG_DRYRUN); 541 argParser.addArgument(noop); 542 543 verbose = CommonArguments.getVerbose(); 544 argParser.addArgument(verbose); 545 546 showUsage = CommonArguments.getShowUsage(); 547 argParser.addArgument(showUsage); 548 argParser.setUsageArgument(showUsage, out); 549 } catch (ArgumentException ae) 550 { 551 printWrappedText(err, ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage())); 552 return CLIENT_SIDE_PARAM_ERROR; 553 } 554 555 // Parse the command-line arguments provided to this program. 556 try 557 { 558 argParser.parseArguments(args); 559 } 560 catch (ArgumentException ae) 561 { 562 argParser.displayMessageAndUsageReference(err, ERR_ERROR_PARSING_ARGS.get(ae.getMessage())); 563 return CLIENT_SIDE_PARAM_ERROR; 564 } 565 566 // If we should just display usage or version information, 567 // then it has already been done so just exit. 568 if (argParser.usageOrVersionDisplayed()) 569 { 570 return 0; 571 } 572 573 if(bindPassword.isPresent() && bindPasswordFile.isPresent()) 574 { 575 printWrappedText( 576 err, ERR_TOOL_CONFLICTING_ARGS.get(bindPassword.getLongIdentifier(), bindPasswordFile.getLongIdentifier())); 577 return CLIENT_SIDE_PARAM_ERROR; 578 } 579 580 581 String hostNameValue = hostName.getValue(); 582 int portNumber = 389; 583 try 584 { 585 portNumber = port.getIntValue(); 586 } catch(ArgumentException ae) 587 { 588 logger.traceException(ae); 589 argParser.displayMessageAndUsageReference(err, ae.getMessageObject()); 590 return CLIENT_SIDE_PARAM_ERROR; 591 } 592 593 try 594 { 595 int versionNumber = version.getIntValue(); 596 if(versionNumber != 2 && versionNumber != 3) 597 { 598 printWrappedText(err, ERR_DESCRIPTION_INVALID_VERSION.get(versionNumber)); 599 return CLIENT_SIDE_PARAM_ERROR; 600 } 601 connectionOptions.setVersionNumber(versionNumber); 602 } catch(ArgumentException ae) 603 { 604 logger.traceException(ae); 605 argParser.displayMessageAndUsageReference(err, ae.getMessageObject()); 606 return CLIENT_SIDE_PARAM_ERROR; 607 } 608 609 String bindDNValue = bindDN.getValue(); 610 String fileNameValue = filename.getValue(); 611 String bindPasswordValue; 612 try 613 { 614 bindPasswordValue = getPasswordValue( 615 bindPassword, bindPasswordFile, bindDNValue, out, err); 616 } 617 catch (Exception ex) 618 { 619 logger.traceException(ex); 620 printWrappedText(err, ex.getMessage()); 621 return CLIENT_SIDE_PARAM_ERROR; 622 } 623 624 String keyStorePathValue = keyStorePath.getValue(); 625 String trustStorePathValue = trustStorePath.getValue(); 626 627 String keyStorePasswordValue = null; 628 if (keyStorePassword.isPresent()) 629 { 630 keyStorePasswordValue = keyStorePassword.getValue(); 631 } 632 else if (keyStorePasswordFile.isPresent()) 633 { 634 keyStorePasswordValue = keyStorePasswordFile.getValue(); 635 } 636 637 String trustStorePasswordValue = null; 638 if (trustStorePassword.isPresent()) 639 { 640 trustStorePasswordValue = trustStorePassword.getValue(); 641 } 642 else if (trustStorePasswordFile.isPresent()) 643 { 644 trustStorePasswordValue = trustStorePasswordFile.getValue(); 645 } 646 647 deleteOptions.setShowOperations(noop.isPresent()); 648 deleteOptions.setVerbose(verbose.isPresent()); 649 deleteOptions.setContinueOnError(continueOnError.isPresent()); 650 deleteOptions.setEncoding(encodingStr.getValue()); 651 deleteOptions.setDeleteSubtree(deleteSubtree.isPresent()); 652 653 if(controlStr.isPresent()) 654 { 655 for (String ctrlString : controlStr.getValues()) 656 { 657 Control ctrl = LDAPToolUtils.getControl(ctrlString, err); 658 if(ctrl == null) 659 { 660 printWrappedText(err, ERR_TOOL_INVALID_CONTROL_STRING.get(ctrlString)); 661 return CLIENT_SIDE_PARAM_ERROR; 662 } 663 deleteOptions.getControls().add(ctrl); 664 } 665 } 666 667 if(deleteOptions.getDeleteSubtree()) 668 { 669 Control control = new SubtreeDeleteControl(false); 670 deleteOptions.getControls().add(control); 671 } 672 673 ArrayList<String> trailingArgs = argParser.getTrailingArguments(); 674 dnStrings.addAll(trailingArgs); 675 676 // Set the connection options. 677 // Parse the SASL properties. 678 connectionOptions.setSASLExternal(saslExternal.isPresent()); 679 if(saslOptions.isPresent()) 680 { 681 for (String saslOption : saslOptions.getValues()) 682 { 683 boolean val = saslOption.startsWith("mech=") 684 ? connectionOptions.setSASLMechanism(saslOption) 685 : connectionOptions.addSASLProperty(saslOption); 686 if (!val) 687 { 688 return CLIENT_SIDE_PARAM_ERROR; 689 } 690 } 691 } 692 connectionOptions.setUseSSL(useSSL.isPresent()); 693 connectionOptions.setStartTLS(startTLS.isPresent()); 694 695 if(connectionOptions.useSASLExternal()) 696 { 697 if(!connectionOptions.useSSL() && !connectionOptions.useStartTLS()) 698 { 699 printWrappedText(err, ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS.get()); 700 return CLIENT_SIDE_PARAM_ERROR; 701 } 702 if(keyStorePathValue == null) 703 { 704 printWrappedText(err, ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE.get()); 705 return CLIENT_SIDE_PARAM_ERROR; 706 } 707 } 708 709 LDAPDelete ldapDelete = null; 710 try 711 { 712 if (initializeServer) 713 { 714 // Bootstrap and initialize directory data structures. 715 EmbeddedUtils.initializeForClientUse(); 716 } 717 718 // Connect to the specified host with the supplied userDN and password. 719 SSLConnectionFactory sslConnectionFactory = null; 720 if(connectionOptions.useSSL() || connectionOptions.useStartTLS()) 721 { 722 String clientAlias; 723 if (certNickname.isPresent()) 724 { 725 clientAlias = certNickname.getValue(); 726 } 727 else 728 { 729 clientAlias = null; 730 } 731 732 sslConnectionFactory = new SSLConnectionFactory(); 733 sslConnectionFactory.init(trustAll.isPresent(), keyStorePathValue, 734 keyStorePasswordValue, clientAlias, 735 trustStorePathValue, trustStorePasswordValue); 736 connectionOptions.setSSLConnectionFactory(sslConnectionFactory); 737 } 738 739 AtomicInteger nextMessageID = new AtomicInteger(1); 740 connection = new LDAPConnection(hostNameValue, portNumber, 741 connectionOptions, out, err); 742 int timeout = connectTimeout.getIntValue(); 743 connection.connectToHost(bindDNValue, bindPasswordValue, nextMessageID, 744 timeout); 745 746 ldapDelete = new LDAPDelete(nextMessageID, out, err); 747 if(fileNameValue == null && dnStrings.isEmpty()) 748 { 749 // Read from stdin. 750 rdr = new InputStreamReader(System.in); 751 } else if(fileNameValue != null) 752 { 753 rdr = new FileReader(fileNameValue); 754 } 755 756 if(rdr != null) 757 { 758 ldapDelete.readAndExecute(connection, rdr, deleteOptions); 759 } else 760 { 761 ldapDelete.readAndExecute(connection, dnStrings, deleteOptions); 762 } 763 } catch(LDAPException le) 764 { 765 logger.traceException(le); 766 LDAPToolUtils.printErrorMessage(err, le.getMessageObject(), 767 le.getResultCode(), 768 le.getErrorMessage(), 769 le.getMatchedDN()); 770 return le.getResultCode(); 771 } catch(LDAPConnectionException lce) 772 { 773 logger.traceException(lce); 774 LDAPToolUtils.printErrorMessage(err, lce.getMessageObject(), 775 lce.getResultCode(), 776 lce.getErrorMessage(), 777 lce.getMatchedDN()); 778 return lce.getResultCode(); 779 } 780 catch(ArgumentException e) 781 { 782 argParser.displayMessageAndUsageReference(err, e.getMessageObject()); 783 return 1; 784 } 785 catch (Exception e) 786 { 787 logger.traceException(e); 788 printWrappedText(err, e.getMessage()); 789 return 1; 790 } finally 791 { 792 if(connection != null) 793 { 794 if (ldapDelete == null) 795 { 796 connection.close(null); 797 } 798 else 799 { 800 connection.close(ldapDelete.nextMessageID); 801 } 802 } 803 } 804 return 0; 805 } 806 807} 808