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