001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2007-2010 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017
018package org.opends.server.admin.client.cli;
019
020import static com.forgerock.opendj.cli.CommonArguments.*;
021import static com.forgerock.opendj.cli.ReturnCode.*;
022import static com.forgerock.opendj.cli.Utils.*;
023
024import java.io.OutputStream;
025import java.io.PrintStream;
026import java.util.Collection;
027import java.util.Set;
028
029import org.forgerock.i18n.LocalizableMessage;
030import org.forgerock.i18n.LocalizableMessageBuilder;
031import org.forgerock.i18n.slf4j.LocalizedLogger;
032import org.opends.admin.ads.util.ApplicationTrustManager;
033
034import com.forgerock.opendj.cli.Argument;
035import com.forgerock.opendj.cli.ArgumentException;
036import com.forgerock.opendj.cli.ArgumentGroup;
037import com.forgerock.opendj.cli.BooleanArgument;
038import com.forgerock.opendj.cli.StringArgument;
039import com.forgerock.opendj.cli.SubCommandArgumentParser;
040
041/**
042 * This is a commodity class that can be used to check the arguments required to
043 * establish a secure connection in the command line. It can be used to generate
044 * an ApplicationTrustManager object based on the options provided by the user
045 * in the command line.
046 */
047public abstract class SecureConnectionCliParser extends SubCommandArgumentParser
048{
049  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
050
051  /** The 'verbose' global argument. */
052  protected BooleanArgument verboseArg;
053  /** The secure args list object. */
054  protected SecureConnectionCliArgs secureArgsList;
055  /** Argument indicating a properties file argument. */
056  protected StringArgument propertiesFileArg;
057  /** The argument which should be used to indicate that we will not look for properties file. */
058  protected BooleanArgument noPropertiesFileArg;
059
060  /**
061   * Creates a new instance of this argument parser with no arguments.
062   *
063   * @param mainClassName
064   *          The fully-qualified name of the Java class that should
065   *          be invoked to launch the program with which this
066   *          argument parser is associated.
067   * @param toolDescription
068   *          A human-readable description for the tool, which will be
069   *          included when displaying usage information.
070   * @param longArgumentsCaseSensitive
071   *          Indicates whether subcommand and long argument names
072   *          should be treated in a case-sensitive manner.
073   */
074  protected SecureConnectionCliParser(String mainClassName,
075      LocalizableMessage toolDescription, boolean longArgumentsCaseSensitive)
076  {
077    super(mainClassName, toolDescription, longArgumentsCaseSensitive);
078  }
079
080  /**
081   * Get the bindDN which has to be used for the command.
082   *
083   * @return The bindDN specified by the command line argument, or the
084   *         default value, if not specified.
085   */
086  public String getBindDN()
087  {
088    return secureArgsList.getBindDN();
089  }
090
091  /**
092   * Returns the Administrator UID provided in the command-line.
093   * @return the Administrator UID provided in the command-line.
094   */
095  public String getAdministratorUID()
096  {
097    return secureArgsList.getAdministratorUID();
098  }
099
100  /**
101   * Gets the password which has to be used for the command without prompting
102   * the user.  If no password was specified, return null.
103   *
104   * @return The password stored into the specified file on by the
105   *         command line argument, or null it if not specified.
106   */
107  public String getBindPassword()
108  {
109    return getBindPassword(secureArgsList.getBindPasswordArg(), secureArgsList.getBindPasswordFileArg());
110  }
111
112  /**
113   * Initialize Global option.
114   *
115   * @param outStream
116   *          The output stream used for the usage.
117   * @param alwaysSSL If true, always use the SSL connection type. In this case,
118   * the arguments useSSL and startTLS are not present.
119   *
120   * @throws ArgumentException
121   *           If there is a problem with any of the parameters used
122   *           to create this argument.
123   * @return a ArrayList with the options created.
124   */
125  protected Set<Argument> createGlobalArguments(OutputStream outStream, boolean alwaysSSL) throws ArgumentException
126  {
127    secureArgsList = new SecureConnectionCliArgs(alwaysSSL);
128    Set<Argument> set = secureArgsList.createGlobalArguments();
129
130    /* The 'showUsage' global argument. */
131    final BooleanArgument showUsageArg = showUsageArgument();
132    setUsageArgument(showUsageArg, outStream);
133    set.add(showUsageArg);
134
135    verboseArg = verboseArgument();
136    set.add(verboseArg);
137
138    propertiesFileArg = propertiesFileArgument();
139    setFilePropertiesArgument(propertiesFileArg);
140    set.add(propertiesFileArg);
141
142    noPropertiesFileArg = noPropertiesFileArgument();
143    setNoPropertiesFileArgument(noPropertiesFileArg);
144    set.add(noPropertiesFileArg);
145
146    return set;
147  }
148
149  /**
150   * Initialize the global options with the provided set of arguments.
151   *
152   * @param args the arguments to use to initialize the global options.
153   * @throws ArgumentException if there is a conflict with the provided
154   *                           arguments.
155   */
156  protected void initializeGlobalArguments(Collection<Argument> args) throws ArgumentException
157  {
158    initializeGlobalArguments(args, null);
159  }
160
161  /**
162   * Initialize the global options with the provided set of arguments.
163   *
164   * @param args     the arguments to use to initialize the global options.
165   * @param argGroup to which args will be added
166   * @throws ArgumentException if there is a conflict with the provided
167   *                           arguments.
168   */
169  protected void initializeGlobalArguments(
170          Collection<Argument> args,
171          ArgumentGroup argGroup)
172  throws ArgumentException
173  {
174    for (Argument arg : args)
175    {
176      addGlobalArgument(arg, argGroup);
177    }
178
179    // Set the propertiesFile argument
180    setFilePropertiesArgument(propertiesFileArg);
181  }
182
183  /**
184   * Get the host name which has to be used for the command.
185   *
186   * @return The host name specified by the command line argument, or
187   *         the default value, if not specified.
188   */
189  public String getHostName()
190  {
191    return secureArgsList.getHostName();
192  }
193
194  /**
195   * Get the port which has to be used for the command.
196   *
197   * @return The port specified by the command line argument, or the
198   *         default value, if not specified.
199   */
200  public String getPort()
201  {
202    return secureArgsList.getPort();
203  }
204
205  /**
206   * Indication if provided global options are validate.
207   *
208   * @param buf The {@link LocalizableMessageBuilder} to write the error message.
209   * @return return code.
210   */
211  public int validateGlobalOptions(final LocalizableMessageBuilder buf)
212  {
213    final int ret = secureArgsList.validateGlobalOptions(buf) ;
214    if (appendErrorMessageIfArgumentsConflict(buf, noPropertiesFileArg, propertiesFileArg))
215    {
216      return CONFLICTING_ARGS.get();
217    }
218    return ret;
219  }
220
221  /**
222   * Indication if provided global options are validate.
223   *
224   * @param err The stream to be used to print error message.
225   * @return return code.
226   */
227  public int validateGlobalOptions(PrintStream err)
228  {
229    LocalizableMessageBuilder buf = new LocalizableMessageBuilder();
230    int returnValue = validateGlobalOptions(buf);
231    printWrappedText(err, buf.toString());
232    return returnValue;
233  }
234
235  /**
236   * Indicate if the verbose mode is required.
237   *
238   * @return True if verbose mode is required
239   */
240  public boolean isVerbose()
241  {
242    return verboseArg.isPresent();
243  }
244
245  /**
246   * Handle TrustStore.
247   *
248   * @return The trustStore manager to be used for the command.
249   */
250  public ApplicationTrustManager getTrustManager()
251  {
252    return secureArgsList.getTrustManager();
253  }
254
255  /**
256   * Returns the timeout to be used to connect in milliseconds.
257   * The method must be called after parsing the arguments.
258   *
259   * @return the timeout to be used to connect in milliseconds or {@code 0} if there is no timeout.
260   * @throws IllegalStateException if the method is called before parsing the arguments.
261   */
262  public int getConnectTimeout()throws IllegalStateException
263  {
264    try
265    {
266      return secureArgsList.getConnectTimeoutArg().getIntValue();
267    }
268    catch (ArgumentException ae)
269    {
270      throw new IllegalStateException("Argument parser is not parsed: "+ae, ae);
271    }
272  }
273}