/*******************************************************************************
* Copyright (c) 2004, 2006
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*******************************************************************************/
package org.eclipse.buckminster.cmdline;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.regex.Matcher;
import org.eclipse.buckminster.cmdline.parser.ParseResult;
import org.eclipse.buckminster.runtime.IOUtils;
import org.eclipse.buckminster.runtime.URLUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.ProgressProvider;
import org.eclipse.osgi.util.NLS;
abstract public class AbstractCommand {
static private final OptionDescriptor helpDescriptor = new OptionDescriptor('?', "help", OptionValueType.NONE); //$NON-NLS-1$
private String calledUsingName;
private CommandInfo cmdInfo;
private boolean addHelpFlags;
private boolean helpRequested = false;
private Map<String, String> properties;
public void addProperties(Map<String, String> props) {
if (properties == null)
properties = new HashMap<String, String>(props);
else
properties.putAll(props);
}
public void addProperty(String key, String value) {
if (properties == null)
properties = new HashMap<String, String>();
properties.put(key, value);
}
public ProgressProvider getProgressProvider() {
return new ProgressProvider() {
@Override
public IProgressMonitor createMonitor(Job job) {
return getDefaultMonitor();
}
};
}
public void init(boolean helpFlags) {
addHelpFlags = helpFlags;
}
/**
* Internal run command. Assumes that all options has been set.
*
* @param cmdName
* The name of the command.
* @return the exit code.
*/
public int run(String cmdName) throws Exception {
calledUsingName = cmdName;
cmdInfo = CommandInfo.getCommand(cmdName);
return run(getProgressProvider().getDefaultMonitor());
}
protected void beginOptionProcessing() throws Exception {
// noop
}
protected void endOptionProcessing() throws Exception {
// noop
}
protected String getCalledUsingName() throws Exception {
return calledUsingName;
}
protected CommandInfo getCommandInfo() throws Exception {
return cmdInfo;
}
protected String getFullName() throws Exception {
return cmdInfo.getFullName();
}
protected InputStream getHelpStream() throws Exception {
Class<? extends AbstractCommand> myClass = getClass();
String helpResource = "/" + myClass.getName().replace('.', '/') + ".help"; //$NON-NLS-1$ //$NON-NLS-2$
return myClass.getResourceAsStream(helpResource);
}
protected void getOptionDescriptors(List<OptionDescriptor> appendHere) throws Exception {
appendHere.add(Headless.DEFINE_DESCRIPTOR);
appendHere.add(Headless.PROPERTIES_DESCRIPTOR);
}
protected void handleOption(Option option) throws Exception {
if (option.is(Headless.DEFINE_DESCRIPTOR)) {
String v = option.getValue();
Matcher m = Headless.DEFINE_PATTERN.matcher(v);
if (!m.matches())
throw new IllegalArgumentException(NLS.bind(Messages.Not_a_key_value_string_0, v));
String key = m.group(1);
String value = m.group(2) == null ? "" //$NON-NLS-1$
: m.group(2);
addProperty(key, value);
}
if (option.is(Headless.PROPERTIES_DESCRIPTOR)) {
String v = option.getValue();
InputStream input = null;
try {
URL propsURL = URLUtils.normalizeToURL(v);
input = new BufferedInputStream(propsURL.openStream());
Properties props = new Properties();
props.load(input);
Enumeration<?> names = props.propertyNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
addProperty(name, props.getProperty(name));
}
} catch (MalformedURLException e) {
throw new IllegalArgumentException(NLS.bind(Messages.Invalid_URL_or_Path_0, v));
} finally {
IOUtils.close(input);
}
}
}
protected void handleUnparsed(String[] unparsed) throws Exception {
// noop
}
protected void help() throws Exception {
help(getHelpStream());
}
protected void help(InputStream helpStream) throws Exception {
if (helpStream == null)
System.err.println(NLS.bind(Messages.AbstractCommand_Help_missing_for_0, getFullName()));
else {
try {
System.out.print(NLS.bind(Messages.AbstractCommand_Help_text_for_0, getFullName()));
IOUtils.copy(helpStream, System.out, null);
} finally {
IOUtils.close(helpStream);
}
System.out.flush();
}
}
protected boolean isHelpRequested() {
return helpRequested;
}
protected abstract int run(IProgressMonitor monitor) throws Exception;
final int basicRun(String calledAs, CommandInfo commandInfo, String[] commandArgs) throws Exception {
calledUsingName = calledAs;
cmdInfo = commandInfo;
ArrayList<OptionDescriptor> optionDescriptors = new ArrayList<OptionDescriptor>();
getOptionDescriptors(optionDescriptors);
if (addHelpFlags)
optionDescriptors.add(helpDescriptor);
Properties sysProps = null;
try {
parseOptions(commandArgs, optionDescriptors);
if (isHelpRequested()) {
help();
return Headless.EXIT_OK;
}
if (properties != null && !properties.isEmpty()) {
sysProps = System.getProperties();
Properties cmdProps = new Properties(sysProps);
for (Entry<String, String> entry : properties.entrySet())
cmdProps.setProperty(entry.getKey(), entry.getValue());
System.setProperties(cmdProps);
}
return run(getProgressProvider().getDefaultMonitor());
} catch (UsageException e) {
System.err.println(e.getMessage());
if (e.isEmitHelp())
help();
return Headless.EXIT_FAIL;
} finally {
if (sysProps != null)
System.setProperties(sysProps);
}
}
private void parseOptions(String[] args, List<OptionDescriptor> optionDescriptors) throws Exception {
ParseResult pr = ParseResult.parse(args, optionDescriptors);
Option[] options = pr.getOptions();
helpRequested = false;
beginOptionProcessing();
int top = options.length;
for (int idx = 0; idx < top; ++idx) {
Option option = options[idx];
if (option.is(helpDescriptor))
helpRequested = true;
else
handleOption(option);
}
endOptionProcessing();
if (!helpRequested)
handleUnparsed(pr.getUnparsed());
}
}