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.util.Set;
20  import java.util.TreeSet;
21  
22  import org.apache.commons.cli.BasicParser;
23  import org.apache.commons.cli.CommandLine;
24  import org.apache.commons.cli.CommandLineParser;
25  import org.apache.commons.cli.HelpFormatter;
26  import org.apache.commons.cli.Options;
27  import org.apache.commons.cli.ParseException;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
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  public abstract class AbstractHBaseTool implements Tool {
40  
41    protected static final int EXIT_SUCCESS = 0;
42    protected static final int EXIT_FAILURE = 1;
43  
44    private static final String HELP_OPTION = "help";
45  
46    private static final Log LOG = LogFactory.getLog(AbstractHBaseTool.class);
47  
48    private final Options options = new Options();
49  
50    protected Configuration conf = null;
51  
52    private static final Set<String> requiredOptions = new TreeSet<String>();
53    
54    protected String[] cmdLineArgs = null;
55  
56    /**
57     * Override this to add command-line options using {@link #addOptWithArg}
58     * and similar methods.
59     */
60    protected abstract void addOptions();
61  
62    /**
63     * This method is called to process the options after they have been parsed.
64     */
65    protected abstract void processOptions(CommandLine cmd);
66  
67    /** The "main function" of the tool */
68    protected abstract int doWork() throws Exception;
69  
70    @Override
71    public Configuration getConf() {
72      return conf;
73    }
74  
75    @Override
76    public void setConf(Configuration conf) {
77      this.conf = conf;
78    }
79  
80    @Override
81    public final int run(String[] args) throws Exception {
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        // parse the command line arguments
90        cmd = parseArgs(args);
91        cmdLineArgs = args;
92      } catch (ParseException e) {
93        LOG.error("Error when parsing command-line arguemnts", e);
94        printUsage();
95        return EXIT_FAILURE;
96      }
97  
98      if (cmd.hasOption(HELP_OPTION) || !sanityCheckOptions(cmd)) {
99        printUsage();
100       return EXIT_FAILURE;
101     }
102 
103     processOptions(cmd);
104 
105     int ret = EXIT_FAILURE;
106     try {
107       ret = doWork();
108     } catch (Exception e) {
109       LOG.error("Error running command-line tool", e);
110       return EXIT_FAILURE;
111     }
112     return ret;
113   }
114 
115   private boolean sanityCheckOptions(CommandLine cmd) {
116     boolean success = true;
117     for (String reqOpt : requiredOptions) {
118       if (!cmd.hasOption(reqOpt)) {
119         LOG.error("Required option -" + reqOpt + " is missing");
120         success = false;
121       }
122     }
123     return success;
124   }
125 
126   protected CommandLine parseArgs(String[] args) throws ParseException {
127     options.addOption(HELP_OPTION, false, "Show usage");
128     addOptions();
129     CommandLineParser parser = new BasicParser();
130     return parser.parse(options, args);
131   }
132 
133   protected void printUsage() {
134     HelpFormatter helpFormatter = new HelpFormatter();
135     helpFormatter.setWidth(80);
136     String usageHeader = "Options:";
137     String usageFooter = "";
138     String usageStr = "bin/hbase " + getClass().getName() + " <options>";
139 
140     helpFormatter.printHelp(usageStr, usageHeader, options,
141         usageFooter);
142   }
143 
144   protected void addRequiredOptWithArg(String opt, String description) {
145     requiredOptions.add(opt);
146     addOptWithArg(opt, description);
147   }
148 
149   protected void addOptNoArg(String opt, String description) {
150     options.addOption(opt, false, description);
151   }
152 
153   protected void addOptWithArg(String opt, String description) {
154     options.addOption(opt, true, description);
155   }
156 
157   /**
158    * Parse a number and enforce a range.
159    */
160   public static long parseLong(String s, long minValue, long maxValue) {
161     long l = Long.parseLong(s);
162     if (l < minValue || l > maxValue) {
163       throw new IllegalArgumentException("The value " + l
164           + " is out of range [" + minValue + ", " + maxValue + "]");
165     }
166     return l;
167   }
168 
169   public static int parseInt(String s, int minValue, int maxValue) {
170     return (int) parseLong(s, minValue, maxValue);
171   }
172 
173   /** Call this from the concrete tool class's main function. */
174   protected void doStaticMain(String args[]) {
175     int ret;
176     try {
177       ret = ToolRunner.run(HBaseConfiguration.create(), this, args);
178     } catch (Exception ex) {
179       LOG.error("Error running command-line tool", ex);
180       ret = EXIT_FAILURE;
181     }
182     System.exit(ret);
183   }
184 
185 }