1/*
2**
3** Copyright 2013, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** 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,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18package com.android.internal.os;
19
20import java.io.PrintStream;
21
22public abstract class BaseCommand {
23
24    protected String[] mArgs;
25    private int mNextArg;
26    private String mCurArgData;
27
28    // These are magic strings understood by the Eclipse plugin.
29    public static final String FATAL_ERROR_CODE = "Error type 1";
30    public static final String NO_SYSTEM_ERROR_CODE = "Error type 2";
31    public static final String NO_CLASS_ERROR_CODE = "Error type 3";
32
33    /**
34     * Call to run the command.
35     */
36    public void run(String[] args) {
37        if (args.length < 1) {
38            onShowUsage(System.out);
39            return;
40        }
41
42        mArgs = args;
43        mNextArg = 0;
44        mCurArgData = null;
45
46        try {
47            onRun();
48        } catch (IllegalArgumentException e) {
49            onShowUsage(System.err);
50            System.err.println();
51            System.err.println("Error: " + e.getMessage());
52        } catch (Exception e) {
53            e.printStackTrace(System.err);
54            System.exit(1);
55        }
56    }
57
58    /**
59     * Convenience to show usage information to error output.
60     */
61    public void showUsage() {
62        onShowUsage(System.err);
63    }
64
65    /**
66     * Convenience to show usage information to error output along
67     * with an error message.
68     */
69    public void showError(String message) {
70        onShowUsage(System.err);
71        System.err.println();
72        System.err.println(message);
73    }
74
75    /**
76     * Implement the command.
77     */
78    public abstract void onRun() throws Exception;
79
80    /**
81     * Print help text for the command.
82     */
83    public abstract void onShowUsage(PrintStream out);
84
85    /**
86     * Return the next option on the command line -- that is an argument that
87     * starts with '-'.  If the next argument is not an option, null is returned.
88     */
89    public String nextOption() {
90        if (mCurArgData != null) {
91            String prev = mArgs[mNextArg - 1];
92            throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
93        }
94        if (mNextArg >= mArgs.length) {
95            return null;
96        }
97        String arg = mArgs[mNextArg];
98        if (!arg.startsWith("-")) {
99            return null;
100        }
101        mNextArg++;
102        if (arg.equals("--")) {
103            return null;
104        }
105        if (arg.length() > 1 && arg.charAt(1) != '-') {
106            if (arg.length() > 2) {
107                mCurArgData = arg.substring(2);
108                return arg.substring(0, 2);
109            } else {
110                mCurArgData = null;
111                return arg;
112            }
113        }
114        mCurArgData = null;
115        return arg;
116    }
117
118    /**
119     * Return the next argument on the command line, whatever it is; if there are
120     * no arguments left, return null.
121     */
122    public String nextArg() {
123        if (mCurArgData != null) {
124            String arg = mCurArgData;
125            mCurArgData = null;
126            return arg;
127        } else if (mNextArg < mArgs.length) {
128            return mArgs[mNextArg++];
129        } else {
130            return null;
131        }
132    }
133
134    /**
135     * Return the next argument on the command line, whatever it is; if there are
136     * no arguments left, throws an IllegalArgumentException to report this to the user.
137     */
138    public String nextArgRequired() {
139        String arg = nextArg();
140        if (arg == null) {
141            String prev = mArgs[mNextArg - 1];
142            throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
143        }
144        return arg;
145    }
146}
147