/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2003 Christian Pesch. All Rights Reserved. */ package slash.metamusic.client; import org.apache.commons.cli.*; import slash.metamusic.util.Files; import slash.metamusic.util.LoggingWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.*; import java.util.logging.Logger; /** * Abstract base class for command line clients * * @author Christian Pesch * @version $Id: CommandLineClient.java 731 2006-02-24 08:44:04Z cpesch $ */ public abstract class CommandLineClient { /** * Logging output */ protected static Logger log = Logger.getLogger(CommandLineClient.class.getName()); protected static final String VERBOSE_PARAMETER = "v"; protected static final String VERBOSE_PARAMETER_LONG = "verbose"; /** * Indicates wether output should be done with more verbosity. * Will pass debug outputs to user. */ protected boolean verbose; public CommandLineClient() { log = Logger.getLogger(getClass().getName()); } public boolean isVerbose() { return verbose; } public void setVerbose(boolean verbose) { this.verbose = verbose; } protected Properties loadProperties(String name) { Properties properties = new Properties(); try { properties.load(new FileInputStream(Files.replaceSeparators("properties/" + name + ".properties"))); log.fine("Loading properties " + properties); } catch (IOException e) { log.severe("Cannot load properties from '" + name + "': " + e.getMessage()); } return properties; } /** * Parse the given command line arguments. * * @param args the command line arguments to parse */ @SuppressWarnings({"ACCESS_STATIC_VIA_INSTANCE"}) protected void parseCommandLine(String[] args) { Options options = new Options(); options.addOption(OptionBuilder.withArgName(VERBOSE_PARAMETER_LONG) .withDescription("enables verbose output") .withLongOpt(VERBOSE_PARAMETER_LONG) .create(VERBOSE_PARAMETER)); fillInOptions(options); List<String> argList = new ArrayList<String>(); Properties properties = loadProperties("client"); argList.addAll(parseProperties(properties, "client.")); argList.addAll(Arrays.asList(args)); CommandLineParser parser = new GnuParser(); CommandLine commandLine = null; try { commandLine = parser.parse(options, argList.toArray(new String[argList.size()])); } catch (ParseException e) { log.severe("Cannot parse command line: " + e.getMessage()); printUsage(options); System.exit(10); } setVerbose(commandLine.hasOption(VERBOSE_PARAMETER)); boolean success = parseCommandLine(commandLine); if (!success) { printUsage(options); System.exit(5); } } private List<String> parseProperties(Properties properties, String prefix) { List<String> argList = new ArrayList<String>(); //noinspection unchecked Enumeration<String> enumeration = (Enumeration<String>) properties.propertyNames(); while (enumeration.hasMoreElements()) { String propertyName = enumeration.nextElement(); if (propertyName.startsWith(prefix)) { String propertyValue = properties.getProperty(propertyName); propertyName = propertyName.substring(prefix.length()); argList.add("--" + propertyName); argList.add(propertyValue); } } return argList; } /** * Hook for subclasses to add additional command line options. * * @param options the options to add additional options to */ protected abstract void fillInOptions(Options options); /** * Hook for subclasses to parse additional command line options. * * @param commandLine the command line to use for parsing * @return true, if the parsing was successful */ protected abstract boolean parseCommandLine(CommandLine commandLine); /** * Print the given command line options * * @param options the command line options to print */ protected void printUsage(Options options) { new HelpFormatter().printHelp( new PrintWriter(new LoggingWriter(log)), HelpFormatter.DEFAULT_WIDTH, getUsage(), "available options:", options, HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD, ""); } /** * Hook for subclasses to print the usage of this client. * * @return the usage of this client */ protected abstract String getUsage(); /** * Run this client with the given command line arguments * * @param args the command line arguments to parse */ public void run(String[] args) throws Exception { long start = System.currentTimeMillis(); try { parseCommandLine(args); try { beforeRunning(); run(); } catch (Exception e) { log.severe("An exception occurred while running: " + e.getMessage()); } finally { afterRunning(); } } finally { long end = System.currentTimeMillis(); log.info("Overall run time was " + (end - start) / 1000 + " seconds."); } } /** * Hook for subclasses before running. */ public abstract void beforeRunning(); /** * Hook for subclasses to run. */ public abstract void run(); /** * Hook for subclasses after running. */ public abstract void afterRunning(); /** * A convenience method to implement the method main(String[]). * * @param client the client to run * @param args the command line arguments */ protected static void main(CommandLineClient client, String[] args) { try { client.run(args); System.exit(0); } catch (Throwable t) { t.printStackTrace(); System.exit(20); } } }