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