File Source: CommandLineParser.java
1 /*
2 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 package com.dmdirc.commandline;
24
25 import com.dmdirc.Main;
26 import com.dmdirc.config.IdentityManager;
27 import com.dmdirc.logger.ErrorLevel;
28 import com.dmdirc.logger.Logger;
29 import com.dmdirc.updater.components.LauncherComponent;
30 import com.dmdirc.util.InvalidAddressException;
31 import com.dmdirc.util.IrcAddress;
32 import com.dmdirc.util.resourcemanager.DMDircResourceManager;
33
34 import java.io.File;
35 import java.rmi.RemoteException;
36 import java.util.ArrayList;
37 import java.util.List;
38
39 /**
40 * Parses command line arguments for the client.
41 *
42 * @author Chris
43 */
44 public class CommandLineParser {
45
46 /**
47 * The arguments that the client supports, in groups of four, in the
48 * following order: short option, long option, description, whether or not
49 * the option takes an argument.
50 */
/*
P/P * Method: com.dmdirc.commandline.CommandLineParser__static_init
*
* Presumptions:
* init'ed(java.lang.Boolean.FALSE)
* init'ed(java.lang.Boolean.TRUE)
*
* Postconditions:
* ARGUMENTS == &new Object[][](CommandLineParser__static_init#1)
* new Object[](CommandLineParser__static_init#10) num objects == 1
* new Object[](CommandLineParser__static_init#2) num objects == 1
* new Object[](CommandLineParser__static_init#3) num objects == 1
* new Object[](CommandLineParser__static_init#4) num objects == 1
* new Object[](CommandLineParser__static_init#5) num objects == 1
* new Object[](CommandLineParser__static_init#6) num objects == 1
* new Object[](CommandLineParser__static_init#7) num objects == 1
* new Object[](CommandLineParser__static_init#8) num objects == 1
* new Object[](CommandLineParser__static_init#9) num objects == 1
* ...
*/
51 private static final Object[][] ARGUMENTS = new Object[][]{
52 {'c', "connect", "Connect to the specified server", Boolean.TRUE},
53 {'d', "directory", "Use the specified configuration directory", Boolean.TRUE},
54 {'e', "existing", "Try to use an existing instance of DMDirc (use with -c)", Boolean.FALSE},
55 {'h', "help", "Show command line options and exit", Boolean.FALSE},
56 {'l', "launcher", "Specifies the version of DMDirc's launcher", Boolean.TRUE},
57 {'p', "portable", "Enable portable mode", Boolean.FALSE},
58 {'r', "disable-reporting", "Disable automatic error reporting", Boolean.FALSE},
59 {'v', "version", "Display client version and exit", Boolean.FALSE},
60 {'k', "check", "Check if an existing instance of DMDirc exists.", Boolean.FALSE},
61 };
62
63 /** A list of addresses to autoconnect to. */
64 private final List<IrcAddress> addresses = new ArrayList<IrcAddress>();
65
66 /** Whether to disable error reporting or not. */
67 private boolean disablereporting;
68
69 /** The version string passed for the launcher. */
70 private String launcherVersion = "";
71
72 /** The RMI server we're using. */
73 private RemoteInterface server;
74
75 /**
76 * Creates a new instance of CommandLineParser.
77 *
78 * @param arguments The arguments to be parsed
79 */
/*
P/P * Method: void com.dmdirc.commandline.CommandLineParser(String[])
*
* Preconditions:
* arguments != null
* arguments.length <= 232-1
* (soft) arguments[...] != null
* (soft) init'ed(com.dmdirc.config.ConfigManager$1__static_init.new int[](ConfigManager$1__static_init#1)[...])
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) ARGUMENTS[...][0] != null
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
* ...
*
* Presumptions:
* init'ed(com.dmdirc.logger.ErrorLevel.MEDIUM)
*
* Postconditions:
* init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* java.lang.StringBuilder:toString(...)._tainted == 0
* this.addresses == &new ArrayList(CommandLineParser#1)
* possibly_updated(this.disablereporting)
* init'ed(this.launcherVersion)
* init'ed(this.server)
* new ArrayList(CommandLineParser#1) num objects == 1
* init'ed(new ArrayList(getSources#1) num objects)
* init'ed(new ConfigManager(getGlobalConfig#1) num objects)
* init'ed(new ConfigManager(getGlobalConfig#1).channel)
* ...
*
* Test Vectors:
* java.lang.String:charAt(...)@92: {0..44, 46..216-1}, {45}
* java.lang.String:startsWith(...)@89: {0}, {1}
*/
80 public CommandLineParser(final String ... arguments) {
81 boolean inArg = false;
82 char previousArg = '.';
83
84 for (String arg : arguments) {
85 if (inArg) {
86 processArgument(previousArg, arg);
87 inArg = false;
88 } else {
89 if (arg.startsWith("--")) {
90 previousArg = processLongArg(arg.substring(2));
91 inArg = checkArgument(previousArg);
92 } else if (arg.charAt(0) == '-') {
93 previousArg = processShortArg(arg.substring(1));
94 inArg = checkArgument(previousArg);
95 } else {
96 doUnknownArg("Unknown argument: " + arg);
97 }
98 }
99 }
100
101 if (inArg) {
102 doUnknownArg("Missing parameter for argument: " + previousArg);
103 }
104
105 if (server != null) {
106 try {
107 server.connect(addresses);
108 System.exit(0);
109 } catch (RemoteException ex) {
110 Logger.appError(ErrorLevel.MEDIUM,
111 "Unable to execute remote connection", ex);
112 }
113 }
114
115 RemoteServer.bind();
116 }
117
118 /**
119 * Checks whether the specified arg type takes an argument. If it does,
120 * this method returns true. If it doesn't, the method processes the
121 * argument and returns false.
122 *
123 * @param argument The short code of the argument
124 * @return True if the arg requires an argument, false otherwise
125 */
126 private boolean checkArgument(final char argument) {
/*
P/P * Method: bool checkArgument(char)
*
* Preconditions:
* (soft) init'ed(com.dmdirc.config.ConfigManager$1__static_init.new int[](ConfigManager$1__static_init#1)[...])
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) init'ed(ARGUMENTS[...][0])
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
* (soft) init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* (soft) this.addresses != null
*
* Postconditions:
* init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* java.lang.StringBuilder:toString(...)._tainted == 0
* init'ed(return_value)
* possibly_updated(this.disablereporting)
* possibly_updated(this.launcherVersion)
* possibly_updated(this.server)
* new ArrayList(getSources#1) num objects == 0
* new ConfigManager(getGlobalConfig#1) num objects == 0
* init'ed(new ConfigManager(getGlobalConfig#1).channel)
* init'ed(new ConfigManager(getGlobalConfig#1).ircd)
* ...
*/
127 boolean needsArg = false;
128
129 for (int i = 0; i < ARGUMENTS.length; i++) {
130 if (argument == ARGUMENTS[i][0]) {
131 needsArg = (Boolean) ARGUMENTS[i][3];
132 break;
133 }
134 }
135
136 if (needsArg) {
137 return true;
138 } else {
139 processArgument(argument, null);
140
141 return false;
142 }
143 }
144
145 /**
146 * Processes the specified string as a single long argument.
147 *
148 * @param arg The string entered
149 * @return The short form of the corresponding argument
150 */
151 private char processLongArg(final String arg) {
/*
P/P * Method: char processLongArg(String)
*
* Preconditions:
* (soft) arg != null
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) ARGUMENTS[...][0] != null
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.String:equalsIgnoreCase(...)@153: {0}, {1}
*/
152 for (int i = 0; i < ARGUMENTS.length; i++) {
153 if (arg.equalsIgnoreCase((String) ARGUMENTS[i][1])) {
154 return (Character) ARGUMENTS[i][0];
155 }
156 }
157
158 doUnknownArg("Unknown argument: " + arg);
159 exit();
160
161 return '.';
162 }
163
164 /**
165 * Processes the specified string as a single short argument.
166 *
167 * @param arg The string entered
168 * @return The short form of the corresponding argument
169 */
170 private char processShortArg(final String arg) {
/*
P/P * Method: char processShortArg(String)
*
* Preconditions:
* (soft) arg != null
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) ARGUMENTS[...][0] != null
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
*
* Postconditions:
* init'ed(return_value)
*
* Test Vectors:
* java.lang.String:equals(...)@172: {0}, {1}
*/
171 for (int i = 0; i < ARGUMENTS.length; i++) {
172 if (arg.equals(String.valueOf(ARGUMENTS[i][0]))) {
173 return (Character) ARGUMENTS[i][0];
174 }
175 }
176
177 doUnknownArg("Unknown argument: " + arg);
178 exit();
179
180 return '.';
181 }
182
183 /**
184 * Processes the sepcified command-line argument.
185 *
186 * @param arg The short form of the argument used
187 * @param param The (optional) string parameter for the option
188 */
189 private void processArgument(final char arg, final String param) {
/*
P/P * Method: void processArgument(char, String)
*
* Preconditions:
* (soft) init'ed(com.dmdirc.config.ConfigManager$1__static_init.new int[](ConfigManager$1__static_init#1)[...])
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) init'ed(ARGUMENTS[...][0])
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
* (soft) init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* (soft) param != null
* (soft) this.addresses != null
*
* Presumptions:
* com.dmdirc.util.resourcemanager.DMDircResourceManager:getCurrentWorkingDirectory(...)@210 != null
*
* Postconditions:
* init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* java.lang.StringBuilder:toString(...)._tainted == 0
* possibly_updated(this.disablereporting)
* possibly_updated(this.launcherVersion)
* possibly_updated(this.server)
* new ArrayList(getSources#1) num objects == 0
* new ConfigManager(getGlobalConfig#1) num objects == 0
* init'ed(new ConfigManager(getGlobalConfig#1).channel)
* init'ed(new ConfigManager(getGlobalConfig#1).ircd)
* init'ed(new ConfigManager(getGlobalConfig#1).listeners)
* ...
*
* Test Vectors:
* arg: {99}, {100}, {101}, {104}, {107}, {108}, {112}, {114}, {118}, {0..98, 102,103, 105,106, 109..111, 113, 115..117, 119..216-1}
*/
190 switch (arg) {
191 case 'c':
192 doConnect(param);
193 break;
194 case 'd':
195 doDirectory(param);
196 break;
197 case 'e':
198 doExisting();
199 break;
200 case 'k':
201 doExistingCheck();
202 break;
203 case 'h':
204 doHelp();
205 break;
206 case 'l':
207 launcherVersion = param;
208 break;
209 case 'p':
210 doDirectory(DMDircResourceManager.getCurrentWorkingDirectory());
211 break;
212 case 'r':
213 disablereporting = true;
214 break;
215 case 'v':
216 doVersion();
217 break;
218 default:
219 // This really shouldn't ever happen, but we'll handle it nicely
220 // anyway.
221
222 doUnknownArg("Unknown argument: " + arg);
223 break;
224 }
225 }
226
227 /**
228 * Informs the user that they entered an unknown argument, prints the
229 * client help, and exits.
230 *
231 * @param message The message about the unknown argument to be displayed
232 */
233 private void doUnknownArg(final String message) {
/*
P/P * Method: void doUnknownArg(String)
*
* Preconditions:
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) init'ed(ARGUMENTS[...][0])
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
*
* Presumptions:
* java.lang.System.out != null
*/
234 System.out.println(message);
235 System.out.println();
236 doHelp();
237 }
238
239 /**
240 * Exits DMDirc.
241 */
242 private void exit() {
/*
P/P * Method: void exit()
* exit does not return
*/
243 System.exit(0);
244 }
245
246 /**
247 * Handles the --connect argument.
248 *
249 * @param address The address the user told us to connect to
250 */
251 private void doConnect(final String address) {
/*
P/P * Method: void doConnect(String)
*
* Preconditions:
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) init'ed(ARGUMENTS[...][0])
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
* (soft) this.addresses != null
*/
252 IrcAddress myAddress = null;
253
254 try {
255 myAddress = new IrcAddress(address);
256 addresses.add(myAddress);
257 } catch (InvalidAddressException ex) {
258 doUnknownArg("Invalid address specified: " + ex.getMessage());
259 }
260 }
261
262 /**
263 * Handles the --existing argument.
264 */
265 private void doExisting() {
/*
P/P * Method: void doExisting()
*
* Presumptions:
* java.lang.System.err != null
*
* Postconditions:
* init'ed(this.server)
*/
266 server = RemoteServer.getServer();
267
268 if (server == null) {
269 System.err.println("Unable to connect to existing instance");
270 }
271 }
272
273 /**
274 * Handles the --check argument.
275 */
276 private void doExistingCheck() {
/*
P/P * Method: void doExistingCheck()
* doExistingCheck does not return
*
* Presumptions:
* java.lang.System.out != null
*/
277 if (RemoteServer.getServer() == null) {
278 System.out.println("Existing instance not found.");
279 System.exit(1);
280 } else {
281 System.out.println("Existing instance found.");
282 System.exit(0);
283 }
284 }
285
286 /**
287 * Sets the config directory to the one specified.
288 *
289 * @param dir The new config directory
290 */
291 private void doDirectory(final String dir) {
/*
P/P * Method: void doDirectory(String)
*
* Preconditions:
* dir != null
*
* Presumptions:
* init'ed(java.io.File.separator)
*
* Test Vectors:
* java.lang.String:endsWith(...)@292: {0}, {1}
*/
292 if (dir.endsWith(File.separator)) {
293 Main.setConfigDir(dir);
294 } else {
295 Main.setConfigDir(dir + File.separator);
296 }
297 }
298
299 /**
300 * Prints out the client version and exits.
301 */
302 private void doVersion() {
/*
P/P * Method: void doVersion()
*
* Preconditions:
* init'ed(com/dmdirc/config/IdentityManager.globalconfig)
* (soft) init'ed(com.dmdirc.config.ConfigManager$1__static_init.new int[](ConfigManager$1__static_init#1)[...])
*
* Presumptions:
* getGlobalConfig(...).sources != null
* java.lang.System.out != null
*
* Postconditions:
* com/dmdirc/config/IdentityManager.globalconfig != null
* java.lang.StringBuilder:toString(...)._tainted == 0
* new ArrayList(getSources#1) num objects == 0
* new ConfigManager(getGlobalConfig#1) num objects == 0
* new MapList(ConfigManager#1) num objects == 0
* new ArrayList(getSources#1) num objects <= 1
* new ConfigManager(getGlobalConfig#1) num objects == new ArrayList(getSources#1) num objects
* new MapList(ConfigManager#1) num objects == new ArrayList(getSources#1) num objects
* new ConfigManager(getGlobalConfig#1).channel == &java.lang.StringBuilder:toString(...)
* init'ed(new ConfigManager(getGlobalConfig#1).channel)
* ...
*/
303 System.out.println("DMDirc - a cross-platform, open-source IRC client.");
304 System.out.println();
305 System.out.println(" Version: "
306 + IdentityManager.getGlobalConfig().getOption("version", "version"));
307 System.out.println(" Update channel: "
308 + IdentityManager.getGlobalConfig().getOption("updater", "channel"));
309 exit();
310 }
311
312 /**
313 * Prints out client help and exits.
314 */
315 private void doHelp() {
/*
P/P * Method: void doHelp()
*
* Preconditions:
* (soft) ARGUMENTS[...] != null
* (soft) ARGUMENTS[...].length >= 4
* (soft) init'ed(ARGUMENTS[...][0])
* (soft) init'ed(ARGUMENTS[...][1])
* (soft) init'ed(ARGUMENTS[...][2])
* (soft) ARGUMENTS[...][3] != null
*
* Presumptions:
* java.lang.System.out != null
*/
316 System.out.println("Usage: java -jar DMDirc.jar [options]");
317 System.out.println();
318 System.out.println("Valid options:");
319 System.out.println();
320
321 int maxLength = 0;
322
323 for (Object[] arg : ARGUMENTS) {
324 final String needsArg = ((Boolean) arg[3]) ? " <argument>" : "";
325
326 if ((arg[1] + needsArg).length() > maxLength) {
327 maxLength = (arg[1] + needsArg).length();
328 }
329 }
330
331 for (Object[] arg : ARGUMENTS) {
332 final String needsArg = ((Boolean) arg[3]) ? " <argument>" : "";
333 final StringBuilder desc = new StringBuilder(maxLength + 1);
334
335 desc.append(arg[1]);
336
337 while (desc.length() < maxLength + 1) {
338 desc.append(' ');
339 }
340
341 System.out.print(" -" + arg[0] + needsArg);
342 System.out.println(" --" + desc + needsArg + " " + arg[2]);
343 System.out.println();
344 }
345
346 exit();
347 }
348
349 /**
350 * Applies any applicable settings to the config identity.
351 */
352 public void applySettings() {
/*
P/P * Method: void applySettings()
*
* Preconditions:
* init'ed(this.disablereporting)
* this.launcherVersion != null
* (soft) init'ed(com.dmdirc.config.ConfigManager$1__static_init.new int[](ConfigManager$1__static_init#1)[...])
* (soft) com/dmdirc/config/IdentityManager.config != null
* (soft) com/dmdirc/config/IdentityManager.config.file != null
* (soft) com/dmdirc/config/IdentityManager.config.listeners != null
* (soft) com/dmdirc/config/IdentityManager.config.myTarget != null
* (soft) init'ed(com/dmdirc/config/IdentityManager.config.myTarget.type)
* (soft) init'ed(com/dmdirc/config/IdentityManager.config.globalConfig)
*
* Postconditions:
* com/dmdirc/config/IdentityManager.config.globalConfig == One-of{old com/dmdirc/config/IdentityManager.config.globalConfig, &new ConfigManager(setOption#2*)}
* init'ed(com/dmdirc/config/IdentityManager.config.globalConfig)
* possibly_updated(com/dmdirc/config/IdentityManager.config.needSave)
* java.lang.StringBuilder:toString(...)._tainted == 0
* new ArrayList(getSources#1) num objects <= 1
* new ConfigManager(setOption#2*) num objects <= 1
* init'ed(new ConfigManager(setOption#2*).channel)
* init'ed(new ConfigManager(setOption#2*).ircd)
* init'ed(new ConfigManager(setOption#2*).listeners)
* init'ed(new ConfigManager(setOption#2*).network)
* ...
*
* Test Vectors:
* this.disablereporting: {0}, {1}
* java.lang.String:isEmpty(...)@357: {1}, {0}
*/
353 if (disablereporting) {
354 IdentityManager.getConfigIdentity().setOption("temp", "noerrorreporting", true);
355 }
356
357 if (!launcherVersion.isEmpty()) {
358 LauncherComponent.setLauncherInfo(launcherVersion);
359 }
360 }
361
362 /**
363 * Processes arguments once the client has been loaded properly.
364 * This allows us to auto-connect to servers, etc.
365 */
366 public void processArguments() {
/*
P/P * Method: void processArguments()
*
* Preconditions:
* this.addresses != null
*
* Presumptions:
* java.util.Iterator:next(...)@367 != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@367: {0}, {1}
*/
367 for (IrcAddress address : addresses) {
368 address.connect();
369 }
370 }
371
372 }
SofCheck Inspector Build Version : 2.17854
| CommandLineParser.java |
2009-Jun-25 01:54:24 |
| CommandLineParser.class |
2009-Sep-02 17:04:16 |