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