001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.cli;
017:
018: import org.apache.xbean.finder.ResourceFinder;
019: import org.apache.openejb.loader.SystemInstance;
020: import org.apache.openejb.util.OpenEjbVersion;
021: import org.apache.commons.cli.PosixParser;
022: import org.apache.commons.cli.CommandLineParser;
023: import org.apache.commons.cli.Options;
024: import org.apache.commons.cli.HelpFormatter;
025: import org.apache.commons.cli.CommandLine;
026: import org.apache.commons.cli.ParseException;
027:
028: import java.util.ArrayList;
029: import java.util.Locale;
030: import java.util.Properties;
031: import java.util.Enumeration;
032: import java.util.Map;
033: import java.util.List;
034: import java.io.IOException;
035: import java.io.File;
036: import java.io.FileInputStream;
037: import java.io.BufferedInputStream;
038: import java.io.InputStream;
039: import java.io.PrintWriter;
040: import java.io.StringWriter;
041: import java.lang.reflect.Method;
042: import java.net.URL;
043:
044: /**
045: * Entry point for ALL things OpenEJB. This will use the new service
046: * architecture explained here:
047: *
048: * @link http://docs.codehaus.org/display/OPENEJB/Executables
049: *
050: * @version $Rev: 636945 $ $Date: 2008-03-13 18:21:27 -0700 $
051: */
052: public class MainImpl implements Main {
053:
054: private static final String BASE_PATH = "META-INF/org.apache.openejb.cli/";
055: private static final String MAIN_CLASS_PROPERTY_NAME = "main.class";
056:
057: private static ResourceFinder finder = null;
058: private static String locale = "";
059: private static String descriptionBase = "description";
060: private static String descriptionI18n;
061:
062: public void main(String[] args) {
063: args = processSystemProperties(args);
064:
065: finder = new ResourceFinder(BASE_PATH);
066: locale = Locale.getDefault().getLanguage();
067: descriptionI18n = descriptionBase + "." + locale;
068:
069: CommandLineParser parser = new PosixParser();
070:
071: // create the Options
072: Options options = new Options();
073: options.addOption(null, "version", false, "");
074: options.addOption("h", "help", false, "");
075: options.addOption("e", "errors", false,
076: "Produce execution error messages");
077:
078: CommandLine line = null;
079: String commandName = null;
080: try {
081: // parse the arguments up until the first
082: // command, then let the rest fall into
083: // the arguments array.
084: line = parser.parse(options, args, true);
085:
086: // Get and remove the commandName (first arg)
087: List<String> list = line.getArgList();
088: if (list.size() > 0) {
089: commandName = list.get(0);
090: list.remove(0);
091: }
092:
093: // The rest of the args will be passed to the command
094: args = line.getArgs();
095: } catch (ParseException exp) {
096: exp.printStackTrace();
097: System.exit(-1);
098: }
099:
100: if (line.hasOption("version")) {
101: OpenEjbVersion.get().print(System.out);
102: System.exit(0);
103: } else if (line.hasOption("help") || commandName == null
104: || commandName.equals("help")) {
105: help();
106: System.exit(0);
107: }
108:
109: Properties props = null;
110: try {
111: props = finder.findProperties(commandName);
112: } catch (IOException e1) {
113: System.out.println("Unavailable command: " + commandName);
114:
115: help(false);
116:
117: System.exit(1);
118: }
119:
120: if (props == null) {
121: System.out.println("Unavailable command: " + commandName);
122: help(false);
123:
124: System.exit(1);
125: }
126:
127: // Shift the command name itself off the args list
128:
129: String mainClass = props.getProperty(MAIN_CLASS_PROPERTY_NAME);
130: if (mainClass == null) {
131: throw new NullPointerException("Command " + commandName
132: + " did not specify a " + MAIN_CLASS_PROPERTY_NAME
133: + " property");
134: }
135:
136: Class<?> clazz = null;
137: try {
138: clazz = Thread.currentThread().getContextClassLoader()
139: .loadClass(mainClass);
140: } catch (ClassNotFoundException cnfe) {
141: throw new IllegalStateException("Main class of command "
142: + commandName + " does not exist: " + mainClass,
143: cnfe);
144: }
145:
146: Method mainMethod = null;
147: try {
148: mainMethod = clazz.getMethod("main", String[].class);
149: } catch (Exception e) {
150: throw new IllegalStateException("Main class of command "
151: + commandName
152: + " does not have a static main method: "
153: + mainClass, e);
154: }
155:
156: try {
157: // WARNING, Definitely do *not* unwrap 'new Object[]{args}' to 'args'
158: mainMethod.invoke(clazz, new Object[] { args });
159: } catch (Throwable e) {
160: if (line.hasOption("errors")) {
161: e.printStackTrace();
162: }
163: System.exit(-10);
164: }
165: }
166:
167: private String[] processSystemProperties(String[] args) {
168: ArrayList<String> argsList = new ArrayList<String>();
169:
170: // We have to pre-screen for openejb.base as it has a direct affect
171: // on where we look for the conf/system.properties file which we
172: // need to read in and apply before we apply the command line -D
173: // properties. Once SystemInstance.init() is called in the next
174: // section of code, the openejb.base value is cemented and cannot
175: // be changed.
176: for (String arg : args) {
177: if (arg.indexOf("-Dopenejb.base") != -1) {
178: String prop = arg.substring(arg.indexOf("-D") + 2, arg
179: .indexOf("="));
180: String val = arg.substring(arg.indexOf("=") + 1);
181:
182: System.setProperty(prop, val);
183: }
184: }
185:
186: // get SystemInstance (the only static class in the system)
187: // so we'll set up all the props in it
188: SystemInstance systemInstance = null;
189: try {
190: SystemInstance.init(System.getProperties());
191: systemInstance = SystemInstance.get();
192: } catch (Exception e) {
193: e.printStackTrace();
194: System.exit(2);
195: }
196:
197: // Read in and apply the conf/system.properties
198: try {
199: File conf = systemInstance.getBase().getDirectory("conf");
200: File file = new File(conf, "system.properties");
201: if (file.exists()) {
202: Properties systemProperties = new Properties();
203: FileInputStream fin = new FileInputStream(file);
204: InputStream in = new BufferedInputStream(fin);
205: systemProperties.load(in);
206: System.getProperties().putAll(systemProperties);
207: systemInstance.getProperties().putAll(systemProperties);
208: }
209: } catch (IOException e) {
210: System.out
211: .println("Processing conf/system.properties failed: "
212: + e.getMessage());
213: }
214:
215: // Now read in and apply the properties specified on the command line
216: for (int i = 0; i < args.length; i++) {
217: String arg = args[i];
218: if (arg.indexOf("-D") != -1) {
219: String prop = arg.substring(arg.indexOf("-D") + 2, arg
220: .indexOf("="));
221: String val = arg.substring(arg.indexOf("=") + 1);
222:
223: System.setProperty(prop, val);
224: systemInstance.setProperty(prop, val);
225: } else {
226: argsList.add(arg);
227: }
228: }
229:
230: args = (String[]) argsList.toArray(new String[argsList.size()]);
231: return args;
232: }
233:
234: //DMB: TODO: Delete me
235: public static Enumeration<URL> doFindCommands() throws IOException {
236: return Thread.currentThread().getContextClassLoader()
237: .getResources(BASE_PATH);
238: }
239:
240: private static void help() {
241: help(true);
242: }
243:
244: private static void help(boolean printHeader) {
245:
246: // Here we are using commons-cli to create the list of available commands
247: // We actually use a different Options object to parse the 'openejb' command
248: try {
249: Options options = new Options();
250:
251: ResourceFinder commandFinder = new ResourceFinder(
252: "META-INF");
253: Map<String, Properties> commands = commandFinder
254: .mapAvailableProperties("org.apache.openejb.cli");
255: for (Map.Entry<String, Properties> command : commands
256: .entrySet()) {
257: if (command.getKey().contains("."))
258: continue;
259: Properties p = command.getValue();
260: String description = p.getProperty(descriptionI18n, p
261: .getProperty(descriptionBase));
262: options.addOption(command.getKey(), false, description);
263: }
264:
265: HelpFormatter formatter = new HelpFormatter();
266: StringWriter sw = new StringWriter();
267: PrintWriter pw = new PrintWriter(sw);
268:
269: String syntax = "openejb <command> [options] [args]";
270:
271: String header = "\nAvailable commands:";
272:
273: String footer = "\n"
274: + "Try 'openejb <command> --help' for help on a specific command.\n"
275: + "For example 'openejb deploy --help'.\n"
276: + "\n"
277: + "Apache OpenEJB -- EJB Container System and Server.\n"
278: + "For additional information, see http://openejb.apache.org\n"
279: + "Bug Reports to <users@openejb.apache.org>";
280:
281: if (!printHeader) {
282: pw.append(header).append("\n\n");
283: formatter.printOptions(pw, 74, options, 1, 3);
284: } else {
285: formatter.printHelp(pw, 74, syntax, header, options, 1,
286: 3, footer, false);
287: }
288:
289: pw.flush();
290:
291: // Fix up the commons-cli output to our liking.
292: String text = sw.toString().replaceAll("\n -", "\n ");
293: text = text.replace("\nApache OpenEJB",
294: "\n\nApache OpenEJB");
295: System.out.print(text);
296: } catch (IOException e) {
297: e.printStackTrace();
298: }
299: }
300: }
|