001/* 002 * Copyright 2010-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds; 022 023 024 025import java.io.OutputStream; 026import java.io.PrintStream; 027import java.lang.reflect.Constructor; 028import java.util.Arrays; 029import java.util.List; 030 031import com.unboundid.ldap.listener.InMemoryDirectoryServerTool; 032import com.unboundid.ldap.sdk.LDAPException; 033import com.unboundid.ldap.sdk.ResultCode; 034import com.unboundid.ldap.sdk.Version; 035import com.unboundid.ldap.sdk.examples.AuthRate; 036import com.unboundid.ldap.sdk.examples.Base64Tool; 037import com.unboundid.ldap.sdk.examples.IdentifyReferencesToMissingEntries; 038import com.unboundid.ldap.sdk.examples.IdentifyUniqueAttributeConflicts; 039import com.unboundid.ldap.sdk.examples.IndentLDAPFilter; 040import com.unboundid.ldap.sdk.examples.LDAPCompare; 041import com.unboundid.ldap.sdk.examples.LDAPDebugger; 042import com.unboundid.ldap.sdk.examples.ModRate; 043import com.unboundid.ldap.sdk.examples.SearchRate; 044import com.unboundid.ldap.sdk.examples.SearchAndModRate; 045import com.unboundid.ldap.sdk.examples.ValidateLDIF; 046import com.unboundid.ldap.sdk.persist.GenerateSchemaFromSource; 047import com.unboundid.ldap.sdk.persist.GenerateSourceFromSchema; 048import com.unboundid.ldap.sdk.transformations.TransformLDIF; 049import com.unboundid.ldap.sdk.unboundidds.examples.DumpDNs; 050import com.unboundid.ldap.sdk.unboundidds.examples.SubtreeAccessibility; 051import com.unboundid.ldap.sdk.unboundidds.examples.SummarizeAccessLog; 052import com.unboundid.ldap.sdk.unboundidds.tools.GenerateTOTPSharedSecret; 053import com.unboundid.ldap.sdk.unboundidds.tools.LDAPDelete; 054import com.unboundid.ldap.sdk.unboundidds.tools.LDAPModify; 055import com.unboundid.ldap.sdk.unboundidds.tools.LDAPSearch; 056import com.unboundid.ldap.sdk.unboundidds.tools.ManageAccount; 057import com.unboundid.ldap.sdk.unboundidds.tools.SplitLDIF; 058import com.unboundid.util.CommandLineTool; 059import com.unboundid.util.Debug; 060import com.unboundid.util.StaticUtils; 061import com.unboundid.util.ThreadSafety; 062import com.unboundid.util.ThreadSafetyLevel; 063import com.unboundid.util.ssl.TLSCipherSuiteSelector; 064import com.unboundid.util.ssl.cert.ManageCertificates; 065 066import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*; 067 068 069 070/** 071 * This class provides an entry point that may be used to launch other tools 072 * provided as part of the LDAP SDK. This is primarily a convenience for 073 * someone who just has the jar file and none of the scripts, since you can run 074 * "<CODE>java -jar unboundid-ldapsdk.jar {tool-name} {tool-args}</CODE>" 075 * in order to invoke any of the example tools. Running just 076 * "<CODE>java -jar unboundid-ldapsdk.jar</CODE>" will display version 077 * information about the LDAP SDK. 078 * <BR> 079 * <BLOCKQUOTE> 080 * <B>NOTE:</B> This class, and other classes within the 081 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 082 * supported for use against Ping Identity, UnboundID, and 083 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 084 * for proprietary functionality or for external specifications that are not 085 * considered stable or mature enough to be guaranteed to work in an 086 * interoperable way with other types of LDAP servers. 087 * </BLOCKQUOTE> 088 * <BR> 089 * The tool names are case-insensitive. Supported tool names include: 090 * <UL> 091 * <LI>authrate -- Launch the {@link AuthRate} tool.</LI> 092 * <LI>base64 -- Launch the {@link Base64Tool} tool.</LI> 093 * <LI>deliver-one-time-password -- Launch the 094 * {@link DeliverOneTimePassword} tool.</LI> 095 * <LI>deliver-password-reset-token -- Launch the 096 * {@link DeliverPasswordResetToken} tool.</LI> 097 * <LI>dump-dns -- Launch the {@link DumpDNs} tool.</LI> 098 * <LI>generate-schema-from-source -- Launch the 099 * {@link GenerateSchemaFromSource} tool.</LI> 100 * <LI>generate-source-from-schema -- Launch the 101 * {@link GenerateSourceFromSchema} tool.</LI> 102 * <LI>generate-totp-shared-secret -- Launch the 103 * {@link GenerateTOTPSharedSecret} tool.</LI> 104 * <LI>identify-references-to-missing-entries -- Launch the 105 * {@link IdentifyReferencesToMissingEntries} tool.</LI> 106 * <LI>identify-unique-attribute-conflicts -- Launch the 107 * {@link IdentifyUniqueAttributeConflicts} tool.</LI> 108 * <LI>indent-ldap-filter -- Launch the {@link IndentLDAPFilter} tool.</LI> 109 * <LI>in-memory-directory-server -- Launch the 110 * {@link InMemoryDirectoryServerTool} tool.</LI> 111 * <LI>ldapcompare -- Launch the {@link LDAPCompare} tool.</LI> 112 * <LI>ldapdelete -- Launch the {@link LDAPDelete} tool.</LI> 113 * <LI>ldapmodify -- Launch the {@link LDAPModify} tool.</LI> 114 * <LI>ldapsearch -- Launch the {@link LDAPSearch} tool.</LI> 115 * <LI>ldap-debugger -- Launch the {@link LDAPDebugger} tool.</LI> 116 * <LI>manage-account -- Launch the {@link ManageAccount} tool.</LI> 117 * <LI>manage-certificates -- Launch the {@link ManageCertificates} tool.</LI> 118 * <LI>modrate -- Launch the {@link ModRate} tool.</LI> 119 * <LI>move-subtree -- Launch the {@link MoveSubtree} tool.</LI> 120 * <LI>register-yubikey-otp-device -- Launch the 121 * {@link RegisterYubiKeyOTPDevice} tool.</LI> 122 * <LI>searchrate -- Launch the {@link SearchRate} tool.</LI> 123 * <LI>search-and-mod-rate -- Launch the {@link SearchAndModRate} tool.</LI> 124 * <LI>split-ldif -- Launch the {@link SplitLDIF} tool.</LI> 125 * <LI>subtree-accessibility -- Launch the {@link SubtreeAccessibility} 126 * tool.</LI> 127 * <LI>summarize-access-log -- Launch the {@link SummarizeAccessLog} 128 * tool.</LI> 129 * <LI>tls-cipher-suite-selector -- Launch the {@link TLSCipherSuiteSelector} 130 * tool.</LI> 131 * <LI>transform-ldif -- Launch the {@link TransformLDIF} tool.</LI> 132 * <LI>validate-ldif -- Launch the {@link ValidateLDIF} tool.</LI> 133 * <LI>version -- Display version information for the LDAP SDK.</LI> 134 * </UL> 135 */ 136@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 137public final class Launcher 138{ 139 /** 140 * Prevent this utility class from being instantiated. 141 */ 142 private Launcher() 143 { 144 // No implementation required. 145 } 146 147 148 149 /** 150 * Parses the command-line arguments and performs any appropriate processing 151 * for this program. 152 * 153 * @param args The command-line arguments provided to this program. 154 */ 155 public static void main(final String... args) 156 { 157 main(System.out, System.err, args); 158 } 159 160 161 162 /** 163 * Parses the command-line arguments and performs any appropriate processing 164 * for this program. 165 * 166 * @param outStream The output stream to which standard out should be 167 * written. It may be {@code null} if output should be 168 * suppressed. 169 * @param errStream The output stream to which standard error should be 170 * written. It may be {@code null} if error messages 171 * should be suppressed. 172 * @param args The command-line arguments provided to this program. 173 * 174 * @return A result code with information about the status of processing. 175 */ 176 public static ResultCode main(final OutputStream outStream, 177 final OutputStream errStream, 178 final String... args) 179 { 180 if ((args == null) || (args.length == 0) || 181 args[0].equalsIgnoreCase("version")) 182 { 183 if (outStream != null) 184 { 185 final PrintStream out = new PrintStream(outStream); 186 for (final String line : Version.getVersionLines()) 187 { 188 out.println(line); 189 } 190 } 191 192 return ResultCode.SUCCESS; 193 } 194 195 final String firstArg = StaticUtils.toLowerCase(args[0]); 196 final String[] remainingArgs = new String[args.length - 1]; 197 System.arraycopy(args, 1, remainingArgs, 0, remainingArgs.length); 198 199 if (firstArg.equals("authrate")) 200 { 201 return AuthRate.main(remainingArgs, outStream, errStream); 202 } 203 else if (firstArg.equals("base64")) 204 { 205 return Base64Tool.main(System.in, outStream, errStream, remainingArgs); 206 } 207 else if (firstArg.equals("deliver-one-time-password")) 208 { 209 return DeliverOneTimePassword.main(remainingArgs, outStream, errStream); 210 } 211 else if (firstArg.equals("deliver-password-reset-token")) 212 { 213 return DeliverPasswordResetToken.main(remainingArgs, outStream, 214 errStream); 215 } 216 else if (firstArg.equals("dump-dns")) 217 { 218 return DumpDNs.main(remainingArgs, outStream, errStream); 219 } 220 else if (firstArg.equals("identify-references-to-missing-entries")) 221 { 222 return IdentifyReferencesToMissingEntries.main(remainingArgs, outStream, 223 errStream); 224 } 225 else if (firstArg.equals("identify-unique-attribute-conflicts")) 226 { 227 return IdentifyUniqueAttributeConflicts.main(remainingArgs, outStream, 228 errStream); 229 } 230 else if (firstArg.equals("in-memory-directory-server")) 231 { 232 return InMemoryDirectoryServerTool.main(remainingArgs, outStream, 233 errStream); 234 } 235 else if (firstArg.equals("indent-ldap-filter")) 236 { 237 return IndentLDAPFilter.main(outStream, errStream, remainingArgs); 238 } 239 else if (firstArg.equals("generate-schema-from-source")) 240 { 241 return GenerateSchemaFromSource.main(remainingArgs, outStream, errStream); 242 } 243 else if (firstArg.equals("generate-source-from-schema")) 244 { 245 return GenerateSourceFromSchema.main(remainingArgs, outStream, errStream); 246 } 247 else if (firstArg.equals("generate-totp-shared-secret")) 248 { 249 return GenerateTOTPSharedSecret.main(outStream, errStream, remainingArgs); 250 } 251 else if (firstArg.equals("ldapcompare")) 252 { 253 return LDAPCompare.main(remainingArgs, outStream, errStream); 254 } 255 else if (firstArg.equals("ldapdelete")) 256 { 257 return LDAPDelete.main(System.in, outStream, errStream, remainingArgs); 258 } 259 else if (firstArg.equals("ldapmodify")) 260 { 261 return LDAPModify.main(System.in, outStream, errStream, remainingArgs); 262 } 263 else if (firstArg.equals("ldapsearch")) 264 { 265 return LDAPSearch.main(outStream, errStream, remainingArgs); 266 } 267 else if (firstArg.equals("ldap-debugger")) 268 { 269 return LDAPDebugger.main(remainingArgs, outStream, errStream); 270 } 271 else if (firstArg.equals("manage-account")) 272 { 273 return ManageAccount.main(outStream, errStream, remainingArgs); 274 } 275 else if (firstArg.equals("manage-certificates")) 276 { 277 return ManageCertificates.main(System.in, outStream, errStream, 278 remainingArgs); 279 } 280 else if (firstArg.equals("modrate")) 281 { 282 return ModRate.main(remainingArgs, outStream, errStream); 283 } 284 else if (firstArg.equals("move-subtree")) 285 { 286 return MoveSubtree.main(remainingArgs, outStream, errStream); 287 } 288 else if (firstArg.equals("register-yubikey-otp-device")) 289 { 290 return RegisterYubiKeyOTPDevice.main(remainingArgs, outStream, errStream); 291 } 292 else if (firstArg.equals("searchrate")) 293 { 294 return SearchRate.main(remainingArgs, outStream, errStream); 295 } 296 else if (firstArg.equals("search-and-mod-rate")) 297 { 298 return SearchAndModRate.main(remainingArgs, outStream, errStream); 299 } 300 else if (firstArg.equals("split-ldif")) 301 { 302 return SplitLDIF.main(outStream, errStream, remainingArgs); 303 } 304 else if (firstArg.equals("subtree-accessibility")) 305 { 306 return SubtreeAccessibility.main(remainingArgs, outStream, errStream); 307 } 308 else if (firstArg.equals("summarize-access-log")) 309 { 310 return SummarizeAccessLog.main(remainingArgs, outStream, errStream); 311 } 312 else if (firstArg.equals("tls-cipher-suite-selector")) 313 { 314 return TLSCipherSuiteSelector.main(outStream, errStream, remainingArgs); 315 } 316 else if (firstArg.equals("transform-ldif")) 317 { 318 return TransformLDIF.main(outStream, errStream, remainingArgs); 319 } 320 else if (firstArg.equals("validate-ldif")) 321 { 322 return ValidateLDIF.main(remainingArgs, outStream, errStream); 323 } 324 else 325 { 326 if (errStream != null) 327 { 328 final PrintStream err = new PrintStream(errStream); 329 err.println("Unrecognized tool name '" + args[0] + '\''); 330 err.println("Supported tool names include:"); 331 err.println(" authrate"); 332 err.println(" base64"); 333 err.println(" deliver-one-time-password"); 334 err.println(" deliver-password-reset-token"); 335 err.println(" dump-dns"); 336 err.println(" generate-schema-from-source"); 337 err.println(" generate-source-from-schema"); 338 err.println(" generate-totp-shared-secret"); 339 err.println(" identify-references-to-missing-entries"); 340 err.println(" identify-unique-attribute-conflicts"); 341 err.println(" indent-ldap-filter"); 342 err.println(" in-memory-directory-server"); 343 err.println(" ldapcompare"); 344 err.println(" ldapdelete"); 345 err.println(" ldapmodify"); 346 err.println(" ldapsearch"); 347 err.println(" ldap-debugger"); 348 err.println(" manage-account"); 349 err.println(" manage-certificates"); 350 err.println(" modrate"); 351 err.println(" move-subtree"); 352 err.println(" register-yubikey-otp-device"); 353 err.println(" searchrate"); 354 err.println(" search-and-mod-rate"); 355 err.println(" split-ldif"); 356 err.println(" subtree-accessibility"); 357 err.println(" summarize-access-log"); 358 err.println(" tls-cipher-suite-selector"); 359 err.println(" transform-ldif"); 360 err.println(" validate-ldif"); 361 err.println(" version"); 362 } 363 364 return ResultCode.PARAM_ERROR; 365 } 366 } 367 368 369 370 /** 371 * Retrieves a list of all of the classes that provide the implementations for 372 * all of the command-line tools included with the LDAP SDK. 373 * 374 * @return A list of all of the classes that provide the implementations for 375 * all of the command-line tools included with the LDAP SDK. 376 */ 377 public static List<Class<? extends CommandLineTool>> getToolClasses() 378 { 379 return Arrays.asList( 380 AuthRate.class, 381 Base64Tool.class, 382 DeliverOneTimePassword.class, 383 DeliverPasswordResetToken.class, 384 DumpDNs.class, 385 GenerateSchemaFromSource.class, 386 GenerateSourceFromSchema.class, 387 GenerateTOTPSharedSecret.class, 388 IdentifyReferencesToMissingEntries.class, 389 IdentifyUniqueAttributeConflicts.class, 390 IndentLDAPFilter.class, 391 InMemoryDirectoryServerTool.class, 392 LDAPCompare.class, 393 LDAPDebugger.class, 394 LDAPDelete.class, 395 LDAPModify.class, 396 LDAPSearch.class, 397 ManageAccount.class, 398 ManageCertificates.class, 399 ModRate.class, 400 MoveSubtree.class, 401 RegisterYubiKeyOTPDevice.class, 402 SearchAndModRate.class, 403 SearchRate.class, 404 SplitLDIF.class, 405 SubtreeAccessibility.class, 406 SummarizeAccessLog.class, 407 TLSCipherSuiteSelector.class, 408 TransformLDIF.class, 409 ValidateLDIF.class); 410 } 411 412 413 414 /** 415 * Retrieves an instance of the specified type of command-line tool with the 416 * given output and error streams. The tool class must provide a two-argument 417 * constructor in which the first argument is a possibly-{@code null} 418 * {@code OutputStream} to use for standard output, and the second argument is 419 * a possibly-{@code null} {@code OutputStream} to use for standard error. 420 * 421 * @param toolClass The class that provides the implementation for the 422 * desired command-line tool. 423 * @param outStream The output stream to which standard out should be 424 * written. It may be {@code null} if output should be 425 * suppressed. 426 * @param errStream The output stream to which standard error should be 427 * written. It may be {@code null} if error messages 428 * should be suppressed. 429 * 430 * @return An instance of the specified command-line tool. 431 * 432 * @throws LDAPException If a problem occurs while attempting to create an 433 * instance of the requested tool. 434 */ 435 public static CommandLineTool getToolInstance(final Class<?> toolClass, 436 final OutputStream outStream, 437 final OutputStream errStream) 438 throws LDAPException 439 { 440 if (! CommandLineTool.class.isAssignableFrom(toolClass)) 441 { 442 throw new LDAPException(ResultCode.PARAM_ERROR, 443 ERR_LAUNCHER_CLASS_NOT_COMMAND_LINE_TOOL.get(toolClass.getName(), 444 CommandLineTool.class.getName())); 445 } 446 447 final Constructor<?> constructor; 448 try 449 { 450 constructor = toolClass.getConstructor(OutputStream.class, 451 OutputStream.class); 452 } 453 catch (final Exception e) 454 { 455 Debug.debugException(e); 456 throw new LDAPException(ResultCode.PARAM_ERROR, 457 ERR_LAUNCHER_TOOL_CLASS_MISSING_EXPECTED_CONSTRUCTOR.get( 458 toolClass.getName()), 459 e); 460 } 461 462 463 try 464 { 465 return (CommandLineTool) constructor.newInstance(outStream, errStream); 466 } 467 catch (final Exception e) 468 { 469 Debug.debugException(e); 470 throw new LDAPException(ResultCode.LOCAL_ERROR, 471 ERR_LAUNCHER_ERROR_INVOKING_CONSTRUCTOR.get(toolClass.getName(), 472 StaticUtils.getExceptionMessage(e)), 473 e); 474 } 475 } 476}