View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to you under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14   * License for the specific language governing permissions and limitations
15   * under the License.
16   */
17  package org.apache.hadoop.hbase.util;
18  
19  import java.io.IOException;
20
21  import org.apache.commons.cli.BasicParser;
22  import org.apache.commons.cli.CommandLine;
23  import org.apache.commons.cli.HelpFormatter;
24  import org.apache.commons.cli.Option;
25  import org.apache.commons.cli.Options;
26  import org.apache.commons.cli.ParseException;
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.conf.Configuration;
31  import org.apache.hadoop.hbase.HBaseConfiguration;
32  import org.apache.hadoop.util.Tool;
33  import org.apache.hadoop.util.ToolRunner;
34
35  /**
36   * Common base class used for HBase command-line tools. Simplifies workflow and
37   * command-line argument parsing.
38   */
39  @InterfaceAudience.Private
40  public abstract class AbstractHBaseTool implements Tool {
41    protected static final int EXIT_SUCCESS = 0;
42    protected static final int EXIT_FAILURE = 1;
43  
44    private static final Option HELP_OPTION = new Option("h", "help", false,
45        "Prints help for this tool.");
46  
47    private static final Log LOG = LogFactory.getLog(AbstractHBaseTool.class);
48
49    private final Options options = new Options();
50
51    protected Configuration conf = null;
52
53    protected String[] cmdLineArgs = null;
54
55    /**
56     * Override this to add command-line options using {@link #addOptWithArg}
57     * and similar methods.
58     */
59    protected abstract void addOptions();
60
61    /**
62     * This method is called to process the options after they have been parsed.
63     */
64    protected abstract void processOptions(CommandLine cmd);
65  
66    /** The "main function" of the tool */
67    protected abstract int doWork() throws Exception;
68
69    @Override
70    public Configuration getConf() {
71      return conf;
72    }
73  
74    @Override
75    public void setConf(Configuration conf) {
76      this.conf = conf;
77    }
78  
79    @Override
80    public final int run(String[] args) throws IOException {
81      cmdLineArgs = args;
82      if (conf == null) {
83        LOG.error("Tool configuration is not initialized");
84        throw new NullPointerException("conf");
85      }
86
87      CommandLine cmd;
88      try {
89        addOptions();
90        if (isHelpCommand(args)) {
91          printUsage();
92          return EXIT_SUCCESS;
93        }
94        // parse the command line arguments
95        cmd = new BasicParser().parse(options, args);
96      } catch (ParseException e) {
97        LOG.error("Error when parsing command-line arguments", e);
98        printUsage();
99        return EXIT_FAILURE;
100     }
101 
102     processOptions(cmd);
103
104     int ret;
105     try {
106       ret = doWork();
107     } catch (Exception e) {
108       LOG.error("Error running command-line tool", e);
109       return EXIT_FAILURE;
110     }
111     return ret;
112   }
113
114   private boolean isHelpCommand(String[] args) throws ParseException {
115     Options helpOption = new Options().addOption(HELP_OPTION);
116     // this parses the command line but doesn't throw an exception on unknown options
117     CommandLine cl = new BasicParser().parse(helpOption, args, true);
118     return cl.getOptions().length != 0;
119   }
120
121   protected void printUsage() {
122     printUsage("bin/hbase " + getClass().getName() + " <options>", "Options:", "");
123   }
124
125   protected void printUsage(final String usageStr, final String usageHeader,
126       final String usageFooter) {
127     HelpFormatter helpFormatter = new HelpFormatter();
128     helpFormatter.setWidth(120);
129     helpFormatter.printHelp(usageStr, usageHeader, options, usageFooter);
130   }
131
132   protected void addOption(Option option) {
133     options.addOption(option);
134   }
135
136   protected void addRequiredOptWithArg(String opt, String description) {
137     Option option = new Option(opt, true, description);
138     option.setRequired(true);
139     options.addOption(option);
140   }
141 
142   protected void addRequiredOptWithArg(String shortOpt, String longOpt, String description) {
143     Option option = new Option(shortOpt, longOpt, true, description);
144     option.setRequired(true);
145     options.addOption(option);
146   }
147
148   protected void addOptNoArg(String opt, String description) {
149     options.addOption(opt, false, description);
150   }
151
152   protected void addOptNoArg(String shortOpt, String longOpt, String description) {
153     options.addOption(shortOpt, longOpt, false, description);
154   }
155
156   protected void addOptWithArg(String opt, String description) {
157     options.addOption(opt, true, description);
158   }
159
160   protected void addOptWithArg(String shortOpt, String longOpt, String description) {
161     options.addOption(shortOpt, longOpt, true, description);
162   }
163
164   public int getOptionAsInt(CommandLine cmd, String opt, int defaultValue) {
165     if (cmd.hasOption(opt)) {
166       return Integer.parseInt(cmd.getOptionValue(opt));
167     } else {
168       return defaultValue;
169     }
170   }
171
172   public double getOptionAsDouble(CommandLine cmd, String opt, double defaultValue) {
173     if (cmd.hasOption(opt)) {
174       return Double.parseDouble(cmd.getOptionValue(opt));
175     } else {
176       return defaultValue;
177     }
178   }
179   /**
180    * Parse a number and enforce a range.
181    */
182   public static long parseLong(String s, long minValue, long maxValue) {
183     long l = Long.parseLong(s);
184     if (l < minValue || l > maxValue) {
185       throw new IllegalArgumentException("The value " + l
186           + " is out of range [" + minValue + ", " + maxValue + "]");
187     }
188     return l;
189   }
190 
191   public static int parseInt(String s, int minValue, int maxValue) {
192     return (int) parseLong(s, minValue, maxValue);
193   }
194
195   /** Call this from the concrete tool class's main function. */
196   protected void doStaticMain(String args[]) {
197     int ret;
198     try {
199       ret = ToolRunner.run(HBaseConfiguration.create(), this, args);
200     } catch (Exception ex) {
201       LOG.error("Error running command-line tool", ex);
202       ret = EXIT_FAILURE;
203     }
204     System.exit(ret);
205   }
206
207 }