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}