001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.admin.client.cli;
028    
029    import static org.opends.server.loggers.debug.DebugLogger.*;
030    import static org.opends.messages.AdminMessages.*;
031    import static org.opends.messages.DSConfigMessages.*;
032    import org.opends.messages.Message;
033    import static org.opends.server.tools.ToolConstants.*;
034    import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
035    import static org.opends.server.util.StaticUtils.wrapText;
036    
037    import java.io.IOException;
038    import java.io.OutputStream;
039    import java.util.Comparator;
040    import java.util.HashSet;
041    import java.util.Set;
042    import java.util.SortedSet;
043    import java.util.TreeSet;
044    import java.util.logging.Logger;
045    
046    import javax.naming.NamingException;
047    import javax.naming.ldap.InitialLdapContext;
048    
049    import org.opends.admin.ads.ADSContextException;
050    import org.opends.admin.ads.util.ConnectionUtils;
051    import org.opends.server.loggers.debug.DebugTracer;
052    import org.opends.server.util.args.ArgumentException;
053    import org.opends.server.util.args.BooleanArgument;
054    import org.opends.server.util.args.SubCommand;
055    
056    import static org.opends.server.admin.client.cli.DsFrameworkCliReturnCode.*;
057    
058    /**
059     * This class will parse CLI arguments for the dsframework command lines.
060     */
061    public class DsFrameworkCliParser extends SecureConnectionCliParser
062    {
063      /**
064       * The tracer object for the debug logger.
065       */
066      private static final DebugTracer TRACER = getTracer();
067    
068      /**
069       * The Logger.
070       */
071      static private final Logger LOG =
072        Logger.getLogger(DsFrameworkCliParser.class.getName());
073    
074      /**
075       * The different CLI group.
076       */
077      public HashSet<DsFrameworkCliSubCommandGroup> cliGroup;
078    
079    
080    
081      /**
082       * Creates a new instance of this subcommand argument parser with no
083       * arguments.
084       *
085       * @param mainClassName
086       *          The fully-qualified name of the Java class that should
087       *          be invoked to launch the program with which this
088       *          argument parser is associated.
089       * @param toolDescription
090       *          A human-readable description for the tool, which will be
091       *          included when displaying usage information.
092       * @param longArgumentsCaseSensitive
093       *          Indicates whether subcommand and long argument names
094       *          should be treated in a case-sensitive manner.
095       */
096      public DsFrameworkCliParser(String mainClassName, Message toolDescription,
097          boolean longArgumentsCaseSensitive)
098      {
099        super(mainClassName, toolDescription, longArgumentsCaseSensitive);
100        cliGroup = new HashSet<DsFrameworkCliSubCommandGroup>();
101      }
102    
103      /**
104       * Initialize the parser with the Global options and subcommands.
105       *
106       * @param outStream
107       *          The output stream to use for standard output, or <CODE>null</CODE>
108       *          if standard output is not needed.
109       * @throws ArgumentException
110       *           If there is a problem with any of the parameters used
111       *           to create this argument.
112       */
113      public void initializeParser(OutputStream outStream)
114          throws ArgumentException
115      {
116        // Global parameters
117        initializeGlobalArguments(createGlobalArguments(outStream));
118    
119        // ads  Group cli
120        cliGroup.add(new DsFrameworkCliAds());
121    
122        // Server-group Group cli
123        cliGroup.add(new DsFrameworkCliServerGroup());
124    
125        // Server Group cli
126        cliGroup.add(new DsFrameworkCliServer());
127    
128        // User Admin cli
129        cliGroup.add(new DsFrameworkCliGlobalAdmin());
130    
131        // Initialization
132        Comparator<SubCommand> c = new Comparator<SubCommand>() {
133    
134          public int compare(SubCommand o1, SubCommand o2) {
135            return o1.getName().compareTo(o2.getName());
136          }
137        };
138    
139        SortedSet<SubCommand> allSubCommands = new TreeSet<SubCommand>(c);
140    
141        for (DsFrameworkCliSubCommandGroup oneCli : cliGroup)
142        {
143          oneCli.initializeCliGroup(this, verboseArg);
144          Set<SubCommand> oneCliSubCmds = oneCli.getSubCommands() ;
145          allSubCommands.addAll(oneCliSubCmds);
146    
147          // register group help
148          String grpName = oneCli.getGroupName();
149          String option = OPTION_LONG_HELP + "-" + grpName;
150          BooleanArgument arg = new BooleanArgument(option, null, option,
151              INFO_DSCFG_DESCRIPTION_SHOW_GROUP_USAGE.get(grpName));
152          addGlobalArgument(arg);
153          arg.setHidden(oneCli.isHidden());
154          TreeSet<SubCommand> subCmds = new TreeSet<SubCommand>(c);
155          subCmds.addAll(oneCliSubCmds);
156          setUsageGroupArgument(arg, subCmds);
157        }
158    
159        // Register the --help-all argument.
160        String option = OPTION_LONG_HELP + "-all";
161        BooleanArgument arg = new BooleanArgument(option, null, option,
162            INFO_DSCFG_DESCRIPTION_SHOW_GROUP_USAGE_ALL.get());
163    
164        addGlobalArgument(arg);
165        setUsageGroupArgument(arg, allSubCommands);
166    
167      }
168    
169    
170    
171      /**
172       * Handle the subcommand.
173       * @param  outStream         The output stream to use for standard output.
174       * @param  errStream         The output stream to use for standard error.
175       *
176       * @return the return code
177       * @throws ADSContextException
178       *           If there is a problem with when trying to perform the
179       *           operation.
180       * @throws ArgumentException
181       *           If there is a problem with any of the parameters used
182       *           to execute this subcommand.
183       */
184      public DsFrameworkCliReturnCode performSubCommand(OutputStream outStream,
185          OutputStream errStream)
186        throws ADSContextException, ArgumentException
187      {
188        SubCommand subCmd = getSubCommand();
189    
190        for (DsFrameworkCliSubCommandGroup oneCli : cliGroup)
191        {
192          if (oneCli.isSubCommand(subCmd))
193          {
194            return oneCli.performSubCommand( subCmd, outStream, errStream);
195          }
196        }
197    
198        // Should never occurs: If we are here, it means that the code to
199        // handle to subcommand is not yet written.
200        return ERROR_UNEXPECTED;
201      }
202    
203    
204      /**
205       * Get the InitialLdapContext that has to be used for the ADS.
206       * @param  out         The output stream to use for standard output.
207       * @param  err         The output stream to use for standard error.
208       *
209       * @return The InitialLdapContext that has to be used for the ADS.
210       */
211      public InitialLdapContext getContext(OutputStream out, OutputStream err)
212      {
213        // Get connection parameters
214        String host = null ;
215        String port = null;
216        String dn   = null ;
217        String pwd  = null;
218        InitialLdapContext ctx = null;
219    
220        // Get connection parameters
221        host = ConnectionUtils.getHostNameForLdapUrl(getHostName());
222        port = getPort();
223        dn   = getBindDN();
224        pwd  = getBindPassword(dn, out, err);
225    
226        // Try to connect
227        if (useSSL())
228        {
229          String ldapsUrl = "ldaps://" + host + ":" + port;
230          try
231          {
232            ctx = ConnectionUtils.createLdapsContext(ldapsUrl, dn, pwd,
233                ConnectionUtils.getDefaultLDAPTimeout(), null,getTrustManager(),
234                getKeyManager());
235          }
236          catch (NamingException e)
237          {
238            Message message = ERR_ADMIN_CANNOT_CONNECT_TO_ADS.get(host);
239            try
240            {
241              err.write(wrapText(message, MAX_LINE_WIDTH).getBytes());
242              err.write(EOL.getBytes());
243            }
244            catch (IOException e1)
245            {
246            }
247            return null;
248          }
249        }
250        else if (useStartTLS())
251        {
252          String ldapUrl = "ldap://" + host + ":" + port;
253          try
254          {
255            ctx = ConnectionUtils.createStartTLSContext(ldapUrl, dn, pwd,
256                ConnectionUtils.getDefaultLDAPTimeout(), null, getTrustManager(),
257                getKeyManager(), null);
258          }
259          catch (NamingException e)
260          {
261            Message message = ERR_ADMIN_CANNOT_CONNECT_TO_ADS.get(host);
262            try
263            {
264              err.write(wrapText(message, MAX_LINE_WIDTH).getBytes());
265              err.write(EOL.getBytes());
266            }
267            catch (IOException e1)
268            {
269            }
270            return null;
271          }
272        }
273        else
274        {
275          String ldapUrl = "ldap://" + host + ":" + port;
276          try
277          {
278            ctx = ConnectionUtils.createLdapContext(ldapUrl, dn, pwd,
279                ConnectionUtils.getDefaultLDAPTimeout(), null);
280          }
281          catch (NamingException e)
282          {
283            Message message = ERR_ADMIN_CANNOT_CONNECT_TO_ADS.get(host);
284            try
285            {
286              err.write(wrapText(message, MAX_LINE_WIDTH).getBytes());
287              err.write(EOL.getBytes());
288            }
289            catch (IOException e1)
290            {
291            }
292            return null;
293          }
294        }
295        return ctx;
296      }
297    }