blob: f72291143a7cd2b551bbbfb295181c78ca587ae1 [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.jackrabbit.vault.util.console;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import org.apache.commons.cli2.CommandLine;
import org.apache.commons.cli2.DisplaySetting;
import org.apache.commons.cli2.Group;
import org.apache.commons.cli2.Option;
import org.apache.commons.cli2.OptionException;
import org.apache.commons.cli2.builder.ArgumentBuilder;
import org.apache.commons.cli2.builder.DefaultOptionBuilder;
import org.apache.commons.cli2.builder.GroupBuilder;
import org.apache.commons.cli2.commandline.Parser;
import org.apache.commons.cli2.option.Command;
import org.apache.commons.cli2.util.HelpFormatter;
import org.apache.jackrabbit.vault.util.console.util.CliHelpFormatter;
import org.apache.jackrabbit.vault.util.console.util.Log4JConfig;
import org.apache.jackrabbit.vault.util.console.util.PomProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* {@code Console}...
*/
public abstract class AbstractApplication {
/**
* the default logger
*/
static final Logger log = LoggerFactory.getLogger(AbstractApplication.class);
private static final String LOG4J_PROPERTIES = "/org/apache/jackrabbit/vault/util/console/log4j.properties";
public static final String DEFAULT_CONF_FILENAME = "console.properties";
public static final String KEY_PROMPT = "prompt";
public static final String KEY_USER = "user";
public static final String KEY_PATH = "path";
public static final String KEY_HOST = "host";
public static final String KEY_LOGLEVEL = "loglevel";
/**
* The global env can be loaded and saved into the console properties.
*/
private Properties globalEnv = new Properties();
//private Option optPropertyFile;
private Option optLogLevel;
private Option optVersion;
private Option optHelp;
public String getVersion() {
return getPomProperties().getVersion();
}
public PomProperties getPomProperties() {
return new PomProperties("org.apache.jackrabbit.vault", "vault-cli");
}
public String getCopyrightLine() {
return "Copyright 2013 by Apache Software Foundation. See LICENSE.txt for more information.";
}
public String getVersionString() {
return getApplicationName() + " [version " + getVersion() + "] " + getCopyrightLine();
}
public void printVersion() {
System.out.println(getVersionString());
}
/**
* Returns the name of this application
*
* @return the name of this application
*/
public abstract String getApplicationName();
/**
* Returns the name of the shell command
*
* @return the name of the shell command
*/
public abstract String getShellCommand();
public void printHelp(String cmd) {
if (cmd == null) {
getAppHelpFormatter().print();
} else {
getDefaultContext().printHelp(cmd);
}
}
protected HelpFormatter getAppHelpFormatter() {
CliHelpFormatter hf = CliHelpFormatter.create();
StringBuffer sep = new StringBuffer(hf.getPageWidth());
while (sep.length() < hf.getPageWidth()) {
sep.append("-");
}
hf.setHeader(getVersionString());
hf.setDivider(sep.toString());
hf.setShellCommand(" " + getShellCommand() + " [options] <command> [arg1 [arg2 [arg3] ..]]");
hf.setGroup(getApplicationCLGroup());
hf.setSkipToplevel(true);
hf.getFullUsageSettings().removeAll(DisplaySetting.ALL);
hf.getDisplaySettings().remove(DisplaySetting.DISPLAY_GROUP_ARGUMENT);
hf.getDisplaySettings().remove(DisplaySetting.DISPLAY_PARENT_CHILDREN);
hf.getDisplaySettings().add(DisplaySetting.DISPLAY_OPTIONAL);
hf.getLineUsageSettings().add(DisplaySetting.DISPLAY_PROPERTY_OPTION);
hf.getLineUsageSettings().add(DisplaySetting.DISPLAY_PARENT_ARGUMENT);
hf.getLineUsageSettings().add(DisplaySetting.DISPLAY_ARGUMENT_BRACKETED);
return hf;
}
public Group getApplicationCLGroup() {
return new GroupBuilder()
.withName("")
.withOption(addApplicationOptions(new GroupBuilder()).create())
.withOption(getDefaultContext().getCommandsGroup())
.withMinimum(0)
.create();
}
public GroupBuilder addApplicationOptions(GroupBuilder gbuilder) {
final DefaultOptionBuilder obuilder = new DefaultOptionBuilder();
final ArgumentBuilder abuilder = new ArgumentBuilder();
/*
optPropertyFile =
obuilder
.withShortName("F")
.withLongName("console-settings")
.withDescription(
"The console settings property file. " +
"This is only required for interactive mode.")
.withArgument(abuilder
.withDescription("defaults to ...")
.withMinimum(1)
.withMaximum(1)
.create()
)
.create();
optInteractive =
obuilder
.withShortName("i")
.withLongName("interactive")
.withDescription("runs this application in an interactive mode.")
.create();
*/
optVersion =
obuilder
.withLongName("version")
.withDescription("print the version information and exit")
.create();
optHelp =
obuilder
.withShortName("h")
.withLongName("help")
.withDescription("print this help")
.withArgument(abuilder
.withName("command")
.withMaximum(1)
.create()
)
.create();
optLogLevel =
obuilder
.withLongName("log-level")
.withDescription("the log4j log level")
.withArgument(abuilder
.withName("level")
.withMaximum(1)
.create()
)
.create();
gbuilder
.withName("Global options:")
//.withOption(optPropertyFile)
.withOption(CliCommand.OPT_VERBOSE)
.withOption(CliCommand.OPT_QUIET)
.withOption(optVersion)
.withOption(optLogLevel)
.withOption(optHelp)
.withMinimum(0);
/*
if (getConsole() != null) {
gbuilder.withOption(optInteractive);
}
*/
return gbuilder;
}
protected void init() {
globalEnv.setProperty(KEY_PROMPT,
"[${" + KEY_USER + "}@${" + KEY_HOST + "} ${" + KEY_PATH +"}]$ ");
}
protected void initLogging() {
Log4JConfig.init(LOG4J_PROPERTIES);
}
protected void run(String[] args) {
// setup logging
try {
initLogging();
} catch (Throwable e) {
System.err.println("Error while initializing logging: " + e);
}
// setup and start
init();
Parser parser = new Parser();
parser.setGroup(getApplicationCLGroup());
parser.setHelpOption(optHelp);
try {
CommandLine cl = parser.parse(args);
String logLevel = getEnv().getProperty(KEY_LOGLEVEL);
if (cl.hasOption(optLogLevel)) {
logLevel = (String) cl.getValue(optLogLevel);
}
if (logLevel != null) {
Log4JConfig.setLevel(logLevel);
}
prepare(cl);
execute(cl);
} catch (OptionException e) {
log.error("{}. Type --help for more information.", e.getMessage());
} catch (ExecutionException e) {
log.error("Error while starting: {}", e.getMessage());
} finally {
close();
}
}
public void setLogLevel(String level) {
try {
Log4JConfig.setLevel(level);
getEnv().setProperty(KEY_LOGLEVEL, level);
System.out.println("Log level set to '" + Log4JConfig.getLevel() + "'");
} catch (Throwable e) {
System.err.println("Error while setting log level: " + e);
}
}
public void prepare(CommandLine cl) throws ExecutionException {
/*
try {
loadConfig((String) cl.getValue(optPropertyFile));
} catch (IOException e) {
throw new ExecutionException("Error while loading property file.", e);
}
*/
}
public void execute(CommandLine cl) throws ExecutionException {
if (cl.hasOption(optVersion)) {
printVersion();
//} else if (cl.hasOption(optInteractive)) {
// getConsole().run();
} else if (cl.hasOption(optHelp)) {
String cmd = (String) cl.getValue(optHelp);
if (cmd == null) {
// in this case, the --help is specified after the command
// eg: vlt checkout --help
Iterator iter = cl.getOptions().iterator();
while (iter.hasNext()) {
Object o = iter.next();
if (o instanceof Command) {
cmd = ((Command) o).getPreferredName();
break;
}
}
}
printHelp(cmd);
} else {
if (!getDefaultContext().execute(cl)) {
log.error("Unknown command. Type '--help' for more information.");
}
}
}
public void saveConfig(String path) throws IOException {
File file = new File(path == null ? DEFAULT_CONF_FILENAME : path);
/*
Properties props = new Properties();
Iterator iter = globalEnv.keySet().iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
if (key.startsWith("conf.") || key.startsWith("macro.")) {
props.put(key, globalEnv.getProperty(key));
}
}
props.store(out, "Console Configuration");
*/
FileOutputStream out = new FileOutputStream(file);
globalEnv.store(out, "Console Configuration");
out.close();
log.info("Configuration saved to {}", file.getCanonicalPath());
}
public void loadConfig(String path) throws IOException {
File file = new File(path == null ? DEFAULT_CONF_FILENAME : path);
if (!file.canRead() && path == null) {
// ignore errors for default config
return;
}
Properties props = new Properties();
try (FileInputStream in = new FileInputStream(file)) {
props.load(in);
}
Iterator iter = globalEnv.keySet().iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
if (!props.containsKey(key)) {
props.put(key, globalEnv.getProperty(key));
}
}
globalEnv = props;
log.info("Configuration loaded from {}", file.getCanonicalPath());
}
protected void close() {
}
public Properties getEnv() {
return globalEnv;
}
public void setProperty(String key, String value) {
if (value == null) {
globalEnv.remove(key);
} else {
if (key.equals(KEY_LOGLEVEL)) {
setLogLevel(value);
} else {
globalEnv.setProperty(key, value);
}
}
}
public String getProperty(String key) {
return globalEnv.getProperty(key);
}
protected abstract ExecutionContext getDefaultContext();
public abstract Console getConsole();
}