Source code: mucode/util/Launcher.java
1 /* mucode - A lightweight and flexible mobile code toolkit
2 * Copyright (C) 2000, Gian Pietro Picco
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 package mucode.util;
19
20 import mucode.*;
21 import java.util.*;
22 import java.io.*;
23
24 /**
25 * This class simplifies the task of passing command line parameteres from an
26 * application to a <i>µ</i>Server embedded in it. It also provides a
27 * facilities for starting a <i>µ</i>Server directly from the command
28 * line.
29 *
30 * The class is essentially a wrapper around a <i>µ</i>Server. The
31 * method {@link #parseArgs parseArgs} allows parsing of command line
32 * arguments. <br>
33 *
34 * Command line options start with a dash (<code>"-"</code>). The set of
35 * recognized options is the same as the set of <i>µ</i>Server
36 * properties, defined in {@link MuConstants} and explained in {@link
37 * mucode.MuServer#properties}. An additional option
38 * <code>-propertyfile</code> is recognized, that allows to load properties
39 * from a configuration file, formatted as explained in {@link
40 * MuServer#loadProperties loadProperties}. This option is mutually exclusive
41 * with standard options: e.g., it is <b>not</b> possible to specify: <br>
42 * <code>java mucode.util.Launcher -propertyfile prop.cfg -debug on</code><br>
43 *
44 * Options setting a value are followed by the value. Flags (e.g.,
45 * <code>"-debug"</code>) accept one of the values <code>on</code> and
46 * <code>off</code>. <br>
47 *
48 * The method {@link #launch launch} parses the command line arguments, and
49 * then starts the run-time support for the <i>µ</i>Server, by calling
50 * its {@link MuServer#boot boot} method.
51 *
52 * This class contains a <code>main()</code>, thus a <i>µ</i>Server
53 * listening on the specified port can be started directly from command
54 * line. <P>
55 *
56 * <B>Example.</B> <code>java mucode.util.Launcher -debug on -port 2000</code>
57 * creates a new Java VM containing a <i>µ</i>Server that will listen on
58 * port <code>2000</code>, and will output debug messages.
59 *
60 * @author <a href="mailto:picco@elet.polimi.it">Gian Pietro Picco</a>
61 * @version 1.0
62 *
63 * @see MuServer
64 * @see MuConstants
65 * */
66 public class Launcher implements MuConstants {
67 private MuServer server = null;
68
69 /**
70 * Create a new <code>Launcher</code>, operating on a new
71 * <i>µ</i>Server.
72 */
73 public Launcher() { server = new MuServer(); }
74
75 /**
76 * Create a new <code>Launcher</code> operating on the specified
77 * <i>µ</i>Server.
78 */
79 public Launcher(MuServer server) { this.server = server; }
80
81 /**
82 * Retrieve the <i>µ</i>Server this object is operating on.
83 *
84 * @return a <code>MuServer</code> value
85 */
86 public MuServer getServer() { return server; }
87
88
89 /**
90 * Parse a set of arguments (typically coming from the command line),
91 * starting at the specified <code>index</code>, and then start the
92 * <i>µ</i>Server associated with this object, by calling its {@link
93 * MuServer#boot} method.
94 *
95 * @param args the arguments
96 * @param index the index of the first element of <code>args</code> to be
97 * considered for parsing.
98 * */
99 public void launch(String[] args, int index) {
100 try {
101 parseArgs(args, index);
102 server.boot();
103 // if (server.isDebugOn()) server.properties.list(System.out);
104 server.properties.list(System.out);
105 } catch(IllegalArgumentException e) {
106 System.out.println(e.toString());
107 if (server.isMessagesOn()) printHelp();
108 System.exit(0);
109 }
110 }
111
112 /** Parse an array of <code>String</code> arguments, usually coming directly
113 * from the command line. Useful when the <i>µ</i>Server is embedded
114 * in an application that needs to specify its own arguments and still
115 * needs to provide access to the <i>µ</i>Server's options through
116 * the command line. The arguments for the <i>µ</i>Server must always
117 * be the last ones in the argument array. Thus, for instance, in
118 *
119 * <pre>java MyApplication myArg1 myArg2 -debug on -compression on</pre>
120 *
121 * if a variable <code>String[] args</code> contains the arguments passed to
122 * <code>MyApplication</code> on the command line (e.g., as retrieved from
123 * <code>MyApplication.main()</code>, the <i>µ</i>Server object can be
124 * configured with the options by invoking
125 *
126 * <pre>
127 * MuServer s = MuServer();
128 * new Launcher(s).parseArgs(args, 2);
129 * </pre>
130 *
131 * @param args the arguments
132 * @param index the index of the first element of <code>args</code> to be
133 * considered for parsing. */
134 public void parseArgs(String[] args, int index) {
135 if (args.length != 0) {
136 if (index < 0 || index > args.length || args == null)
137 throw new IllegalArgumentException();
138 if (args[0].equals("-propertyfile")) {
139 if (args.length != 2) {
140 printHelp();
141 System.exit(0);
142 } else {
143 try {
144 server.loadProperties(args[1]);
145 } catch(FileNotFoundException fe) {
146 System.out.println("Property file " + args[1] +
147 " not found. Halting...");
148 System.exit(0);
149 } catch(IOException e) {
150 System.out.println("I/O problems. Halting...");
151 e.printStackTrace();
152 System.exit(0);
153 }
154 } // end of else
155 } else {
156 int i = index;
157 while (i < args.length) {
158 // Parse single arguments
159 if (args[i].equals("-" + PORTkey) ||
160 args[i].equals("-" + TIMEOUTkey))
161 server.setProperty(args[i].substring(1), args[++i]);
162 // Parse flag arguments
163 else if (args[i].equals("-" + COMPRESSIONkey) ||
164 args[i].equals("-" + DEBUGkey) ||
165 args[i].equals("-" + MESSAGESkey) ||
166 args[i].equals("-" + ERRORSkey))
167 server.setProperty(args[i].substring(1), parseFlag(args[++i]));
168 else if (args[i].equals("-" + UBICLASSESkey)) {
169
170 String[] classnames = parseMultipleArgs(args, ++i);
171 i = i + classnames.length;
172 String propvalue = "";
173 for (int j = 0; j < classnames.length; j++) {
174 server.addUbiquitousClass(classnames[j]);
175 propvalue = propvalue + classnames[j] + " ";
176 }
177 server.setProperty(UBICLASSESkey, propvalue);
178 }
179 else if (args[i].equals("-" + UBIPACKAGESkey)) {
180 String[] packagenames = parseMultipleArgs(args, i++);
181 i = i + packagenames.length;
182 String propvalue = "";
183 for (int j = 0; j < packagenames.length; j++) {
184 server.addUbiquitousPackage(packagenames[j]);
185 propvalue = propvalue + packagenames[j] + " ";
186 }
187 server.setProperty(UBIPACKAGESkey, propvalue);
188 }
189 else throw new IllegalArgumentException(args[i]);
190 i++;
191 }
192 }
193 }
194 }
195
196 private String[] parseMultipleArgs(String[] args, int start) {
197 int i = start;
198 Vector vr = new Vector();
199
200 while (i < args.length && !isFlag(args[i])) {
201 vr.addElement(args[i]);
202 i++;
203 } // end of while ()
204
205 String[] res = new String[vr.size()];
206 vr.copyInto(res);
207 return res;
208 }
209
210 private boolean isFlag(String arg) { return arg.startsWith("-"); }
211
212 private String parseFlag(String flag) {
213 if (flag.equals("on")) return "true";
214 else if (flag.equals("off")) return "false";
215 else throw new IllegalArgumentException(flag);
216 }
217
218 private static void printHelp() {
219 System.out.println("Usage: java mucode.util.Launcher ");
220 System.out.println(" "+
221 "[-port <number>]");
222 System.out.println(" "+
223 "[-timeout <millisec>]");
224 System.out.println(" "+
225 "[-compression {on|off}]");
226 System.out.println(" "+
227 "[-debug {on|off}]");
228 System.out.println(" "+
229 "[-messages {on|off}]");
230 System.out.println(" "+
231 "[-errors {on|off}]");
232 System.out.println(" "+
233 "[-ubiclasses <classname1 classname2 ...>]");
234 System.out.println(" "+
235 "[-ubipackages <packagename1 packagename2 ...>]");
236 System.out.println(" "+
237 "[-propertyfile <filename>]");
238 System.out.println("The -propertyfile option is mutually exclusive with all the other options.");
239 }
240
241 /** Create and start a <i>µ</i>Server directly from the command
242 line, by specifying command line options. */
243 public static void main(String[] args){
244 new Launcher().launch(args, 0);
245 }
246 }