blob: 2764d34cf87d87ac4549c2f949e4cdbe65d75893 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openejb.cli;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.OpenEjbVersion;
import org.apache.openejb.util.OptionsLog;
import org.apache.xbean.finder.ResourceFinder;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
/**
* Entry point for ALL things OpenEJB. This will use the new service
* architecture explained here:
*
* @version $Rev$ $Date$
* @link http://docs.codehaus.org/display/OPENEJB/Executables
*/
public class MainImpl implements Main {
private static final String BASE_PATH = "META-INF/org.apache.openejb.cli/";
private static final String MAIN_CLASS_PROPERTY_NAME = "main.class";
private static ResourceFinder finder;
private static String locale = "";
private static final String descriptionBase = "description";
private static String descriptionI18n;
public void main(String[] args) {
args = processSystemProperties(args);
finder = new ResourceFinder(BASE_PATH);
locale = Locale.getDefault().getLanguage();
descriptionI18n = descriptionBase + "." + locale;
final CommandLineParser parser = new PosixParser();
// create the Options
final Options options = new Options();
options.addOption(null, "version", false, "Display version");
options.addOption("h", "help", false, "Display help");
options.addOption("e", "errors", false, "Produce execution error messages");
CommandLine line = null;
String commandName = null;
try {
// parse the arguments up until the first
// command, then let the rest fall into
// the arguments array.
line = parser.parse(options, args, true);
// Get and remove the commandName (first arg)
final List<String> list = line.getArgList();
if (list.size() > 0) {
commandName = list.get(0);
list.remove(0);
}
// The rest of the args will be passed to the command
args = line.getArgs();
} catch (final ParseException exp) {
exp.printStackTrace();
System.exit(-1);
}
if (line.hasOption("version")) {
OpenEjbVersion.get().print(System.out);
System.exit(0);
} else if (line.hasOption("help") || commandName == null || commandName.equals("help")) {
help();
System.exit(0);
}
Properties props = null;
try {
props = finder.findProperties(commandName);
} catch (final IOException e1) {
System.out.println("Unavailable command: " + commandName);
help(false);
System.exit(1);
}
if (props == null) {
System.out.println("Unavailable command: " + commandName);
help(false);
System.exit(1);
}
// Shift the command name itself off the args list
final String mainClass = props.getProperty(MAIN_CLASS_PROPERTY_NAME);
if (mainClass == null) {
throw new NullPointerException("Command " + commandName + " did not specify a " + MAIN_CLASS_PROPERTY_NAME + " property");
}
Class<?> clazz = null;
try {
clazz = Thread.currentThread().getContextClassLoader().loadClass(mainClass);
} catch (final ClassNotFoundException cnfe) {
throw new IllegalStateException("Main class of command " + commandName + " does not exist: " + mainClass, cnfe);
}
Method mainMethod = null;
try {
mainMethod = clazz.getMethod("main", String[].class);
} catch (final Exception e) {
throw new IllegalStateException("Main class of command " + commandName + " does not have a static main method: " + mainClass, e);
}
try {
// WARNING, Definitely do *not* unwrap 'new Object[]{args}' to 'args'
mainMethod.invoke(clazz, new Object[]{args});
} catch (final Throwable e) {
if (line.hasOption("errors")) {
e.printStackTrace();
}
System.exit(-10);
}
}
private String[] processSystemProperties(String[] args) {
final ArrayList<String> argsList = new ArrayList<String>();
// We have to pre-screen for openejb.base as it has a direct affect
// on where we look for the conf/system.properties file which we
// need to read in and apply before we apply the command line -D
// properties. Once SystemInstance.init() is called in the next
// section of code, the openejb.base value is cemented and cannot
// be changed.
for (final String arg : args) {
if (arg.indexOf("-Dopenejb.base") != -1) {
final String prop = arg.substring(arg.indexOf("-D") + 2, arg.indexOf("="));
final String val = arg.substring(arg.indexOf("=") + 1);
System.setProperty(prop, val);
}
}
// get SystemInstance (the only static class in the system)
// so we'll set up all the props in it
SystemInstance systemInstance = null;
try {
SystemInstance.init(new Properties());
OptionsLog.install();
systemInstance = SystemInstance.get();
} catch (final Exception e) {
e.printStackTrace();
System.exit(2);
}
// Now read in and apply the properties specified on the command line
for (final String arg : args) {
final int idx = arg.indexOf("-D");
final int eq = arg.indexOf("=");
if (idx >= 0 && eq > idx) {
final String prop = arg.substring(idx + 2, eq);
final String val = arg.substring(eq + 1);
System.setProperty(prop, val);
systemInstance.setProperty(prop, val);
} else {
argsList.add(arg);
}
}
args = (String[]) argsList.toArray(new String[argsList.size()]);
return args;
}
//DMB: TODO: Delete me
public static Enumeration<URL> doFindCommands() throws IOException {
return Thread.currentThread().getContextClassLoader().getResources(BASE_PATH);
}
private static void help() {
help(true);
}
private static void help(final boolean printHeader) {
// Here we are using commons-cli to create the list of available commands
// We actually use a different Options object to parse the 'openejb' command
try {
final Options options = new Options();
final ResourceFinder commandFinder = new ResourceFinder("META-INF");
final Map<String, Properties> commands = commandFinder.mapAvailableProperties("org.apache.openejb.cli");
for (final Map.Entry<String, Properties> command : commands.entrySet()) {
if (command.getKey().contains(".")) {
continue;
}
final Properties p = command.getValue();
final String description = p.getProperty(descriptionI18n, p.getProperty(descriptionBase));
options.addOption(command.getKey(), false, description);
}
final HelpFormatter formatter = new HelpFormatter();
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
final String syntax = "openejb <command> [options] [args]";
final String header = "\nAvailable commands:";
final String footer = "\n" +
"Try 'openejb <command> --help' for help on a specific command.\n" +
"For example 'openejb deploy --help'.\n" +
"Important: to display exceptions while running commands, add -e option.\n" +
"\n" +
"Apache OpenEJB -- EJB Container System and Server.\n" +
"For additional information, see http://tomee.apache.org\n" +
"Bug Reports to <users@tomee.apache.org>";
if (!printHeader) {
pw.append(header).append("\n\n");
formatter.printOptions(pw, 74, options, 1, 3);
} else {
formatter.printHelp(pw, 74, syntax, header, options, 1, 3, footer, false);
}
pw.flush();
// Fix up the commons-cli output to our liking.
String text = sw.toString().replaceAll("\n -", "\n ");
text = text.replace("\nApache OpenEJB", "\n\nApache OpenEJB");
System.out.print(text);
} catch (final IOException e) {
e.printStackTrace();
}
}
}