You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CommandLineParser.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. * Copyright (c) 2006-2010 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. package com.dmdirc.commandline;
  23. import com.dmdirc.Main;
  24. import com.dmdirc.ServerManager;
  25. import com.dmdirc.commandparser.commands.global.NewServer;
  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.resourcemanager.DMDircResourceManager;
  31. import java.io.File;
  32. import java.net.URI;
  33. import java.net.URISyntaxException;
  34. import java.rmi.RemoteException;
  35. import java.util.ArrayList;
  36. import java.util.List;
  37. /**
  38. * Parses command line arguments for the client.
  39. *
  40. * @author Chris
  41. */
  42. public class CommandLineParser {
  43. /**
  44. * The arguments that the client supports, in groups of four, in the
  45. * following order: short option, long option, description, whether or not
  46. * the option takes an argument.
  47. */
  48. private static final Object[][] ARGUMENTS = new Object[][]{
  49. {'c', "connect", "Connect to the specified server", Boolean.TRUE},
  50. {'d', "directory", "Use the specified configuration directory", Boolean.TRUE},
  51. {'e', "existing", "Try to use an existing instance of DMDirc (use with -c)", Boolean.FALSE},
  52. {'h', "help", "Show command line options and exit", Boolean.FALSE},
  53. {'l', "launcher", "Specifies the version of DMDirc's launcher", Boolean.TRUE},
  54. {'p', "portable", "Enable portable mode", Boolean.FALSE},
  55. {'r', "disable-reporting", "Disable automatic error reporting", Boolean.FALSE},
  56. {'v', "version", "Display client version and exit", Boolean.FALSE},
  57. {'k', "check", "Check if an existing instance of DMDirc exists.", Boolean.FALSE},
  58. };
  59. /** A list of addresses to autoconnect to. */
  60. private final List<URI> addresses = new ArrayList<URI>();
  61. /** Whether to disable error reporting or not. */
  62. private boolean disablereporting;
  63. /** The version string passed for the launcher. */
  64. private String launcherVersion = "";
  65. /** The RMI server we're using. */
  66. private RemoteInterface server;
  67. /**
  68. * Creates a new instance of CommandLineParser.
  69. *
  70. * @param arguments The arguments to be parsed
  71. */
  72. public CommandLineParser(final String ... arguments) {
  73. boolean inArg = false;
  74. char previousArg = '.';
  75. for (String arg : arguments) {
  76. if (inArg) {
  77. processArgument(previousArg, arg);
  78. inArg = false;
  79. } else {
  80. if (arg.startsWith("--")) {
  81. previousArg = processLongArg(arg.substring(2));
  82. inArg = checkArgument(previousArg);
  83. } else if (arg.charAt(0) == '-') {
  84. previousArg = processShortArg(arg.substring(1));
  85. inArg = checkArgument(previousArg);
  86. } else {
  87. doUnknownArg("Unknown argument: " + arg);
  88. }
  89. }
  90. }
  91. if (inArg) {
  92. doUnknownArg("Missing parameter for argument: " + previousArg);
  93. }
  94. if (server != null) {
  95. try {
  96. server.connect(addresses);
  97. System.exit(0);
  98. } catch (RemoteException ex) {
  99. Logger.appError(ErrorLevel.MEDIUM,
  100. "Unable to execute remote connection", ex);
  101. }
  102. }
  103. RemoteServer.bind();
  104. }
  105. /**
  106. * Checks whether the specified arg type takes an argument. If it does,
  107. * this method returns true. If it doesn't, the method processes the
  108. * argument and returns false.
  109. *
  110. * @param argument The short code of the argument
  111. * @return True if the arg requires an argument, false otherwise
  112. */
  113. private boolean checkArgument(final char argument) {
  114. boolean needsArg = false;
  115. for (Object[] target : ARGUMENTS) {
  116. if ((Character) argument == target[0]) {
  117. needsArg = (Boolean) target[3];
  118. break;
  119. }
  120. }
  121. if (needsArg) {
  122. return true;
  123. } else {
  124. processArgument(argument, null);
  125. return false;
  126. }
  127. }
  128. /**
  129. * Processes the specified string as a single long argument.
  130. *
  131. * @param arg The string entered
  132. * @return The short form of the corresponding argument
  133. */
  134. private char processLongArg(final String arg) {
  135. for (Object[] target : ARGUMENTS) {
  136. if (arg.equalsIgnoreCase((String) target[1])) {
  137. return (Character) target[0];
  138. }
  139. }
  140. doUnknownArg("Unknown argument: " + arg);
  141. exit();
  142. return '.';
  143. }
  144. /**
  145. * Processes the specified string as a single short argument.
  146. *
  147. * @param arg The string entered
  148. * @return The short form of the corresponding argument
  149. */
  150. private char processShortArg(final String arg) {
  151. for (Object[] target : ARGUMENTS) {
  152. if (arg.equals(String.valueOf(target[0]))) {
  153. return (Character) target[0];
  154. }
  155. }
  156. doUnknownArg("Unknown argument: " + arg);
  157. exit();
  158. return '.';
  159. }
  160. /**
  161. * Processes the specified command-line argument.
  162. *
  163. * @param arg The short form of the argument used
  164. * @param param The (optional) string parameter for the option
  165. */
  166. private void processArgument(final char arg, final String param) {
  167. switch (arg) {
  168. case 'c':
  169. doConnect(param);
  170. break;
  171. case 'd':
  172. doDirectory(param);
  173. break;
  174. case 'e':
  175. doExisting();
  176. break;
  177. case 'k':
  178. doExistingCheck();
  179. break;
  180. case 'h':
  181. doHelp();
  182. break;
  183. case 'l':
  184. launcherVersion = param;
  185. break;
  186. case 'p':
  187. doDirectory(DMDircResourceManager.getCurrentWorkingDirectory());
  188. break;
  189. case 'r':
  190. disablereporting = true;
  191. break;
  192. case 'v':
  193. doVersion();
  194. break;
  195. default:
  196. // This really shouldn't ever happen, but we'll handle it nicely
  197. // anyway.
  198. doUnknownArg("Unknown argument: " + arg);
  199. break;
  200. }
  201. }
  202. /**
  203. * Informs the user that they entered an unknown argument, prints the
  204. * client help, and exits.
  205. *
  206. * @param message The message about the unknown argument to be displayed
  207. */
  208. private static void doUnknownArg(final String message) {
  209. System.out.println(message);
  210. System.out.println();
  211. doHelp();
  212. }
  213. /**
  214. * Exits DMDirc.
  215. */
  216. private static void exit() {
  217. System.exit(0);
  218. }
  219. /**
  220. * Handles the --connect argument.
  221. *
  222. * @param address The address the user told us to connect to
  223. */
  224. private void doConnect(final String address) {
  225. URI myAddress = null;
  226. try {
  227. myAddress = NewServer.getURI(address);
  228. addresses.add(myAddress);
  229. } catch (URISyntaxException ex) {
  230. doUnknownArg("Invalid address specified: " + ex.getMessage());
  231. }
  232. }
  233. /**
  234. * Handles the --existing argument.
  235. */
  236. private void doExisting() {
  237. server = RemoteServer.getServer();
  238. if (server == null) {
  239. System.err.println("Unable to connect to existing instance");
  240. }
  241. }
  242. /**
  243. * Handles the --check argument.
  244. */
  245. private static void doExistingCheck() {
  246. if (RemoteServer.getServer() == null) {
  247. System.out.println("Existing instance not found.");
  248. System.exit(1);
  249. } else {
  250. System.out.println("Existing instance found.");
  251. System.exit(0);
  252. }
  253. }
  254. /**
  255. * Sets the config directory to the one specified.
  256. *
  257. * @param dir The new config directory
  258. */
  259. private static void doDirectory(final String dir) {
  260. if (dir.endsWith(File.separator)) {
  261. Main.setConfigDir(dir);
  262. } else {
  263. Main.setConfigDir(dir + File.separator);
  264. }
  265. }
  266. /**
  267. * Prints out the client version and exits.
  268. */
  269. private static void doVersion() {
  270. System.out.println("DMDirc - a cross-platform, open-source IRC client.");
  271. System.out.println();
  272. System.out.println(" Version: "
  273. + IdentityManager.getGlobalConfig().getOption("version", "version"));
  274. System.out.println(" Update channel: "
  275. + IdentityManager.getGlobalConfig().getOption("updater", "channel"));
  276. exit();
  277. }
  278. /**
  279. * Prints out client help and exits.
  280. */
  281. private static void doHelp() {
  282. System.out.println("Usage: java -jar DMDirc.jar [options]");
  283. System.out.println();
  284. System.out.println("Valid options:");
  285. System.out.println();
  286. int maxLength = 0;
  287. for (Object[] arg : ARGUMENTS) {
  288. final String needsArg = ((Boolean) arg[3]) ? " <argument>" : "";
  289. if ((arg[1] + needsArg).length() > maxLength) {
  290. maxLength = (arg[1] + needsArg).length();
  291. }
  292. }
  293. for (Object[] arg : ARGUMENTS) {
  294. final String needsArg = ((Boolean) arg[3]) ? " <argument>" : "";
  295. final StringBuilder desc = new StringBuilder(maxLength + 1);
  296. desc.append(arg[1]);
  297. while (desc.length() < maxLength + 1) {
  298. desc.append(' ');
  299. }
  300. System.out.print(" -" + arg[0] + needsArg);
  301. System.out.println(" --" + desc + needsArg + " " + arg[2]);
  302. System.out.println();
  303. }
  304. exit();
  305. }
  306. /**
  307. * Applies any applicable settings to the config identity.
  308. */
  309. public void applySettings() {
  310. if (disablereporting) {
  311. IdentityManager.getConfigIdentity().setOption("temp", "noerrorreporting", true);
  312. }
  313. if (!launcherVersion.isEmpty()) {
  314. LauncherComponent.setLauncherInfo(launcherVersion);
  315. }
  316. }
  317. /**
  318. * Processes arguments once the client has been loaded properly.
  319. * This allows us to auto-connect to servers, etc.
  320. */
  321. public void processArguments() {
  322. for (URI address : addresses) {
  323. ServerManager.getServerManager().connectToAddress(address);
  324. }
  325. }
  326. }