Extendable command line processor
6
Extendable command line processor for console applications.
import java.util.Map;
import java.util.HashMap;
import java.io.File;
public class CommandLineProcessor {
public static final String ARG_PREFIX1 = "--";
public static final String ARG_PREFIX2 = "//";
protected Map m_optionExtractors = new HashMap();
protected FileOption m_fileSetter = null;
protected int m_fileIndex = 0;
public void registerOption (String optionName, Option handler) {
addExtractor(optionName, new OptionExtractor(handler));
}
public void registerOption (String optionName, StringOption handler) {
addExtractor(optionName, new StringOptionExtractor(handler));
}
public void registerFiles (FileOption handler) {
m_fileSetter = handler;
}
public void registerOption (String optionName, IntOption handler) {
addExtractor(optionName, new IntOptionExtractor(handler));
}
public void execute (String[] args) {
boolean optionsAllowed = true;
int argIndex = 0;
while (argIndex < args.length) {
String arg = args[argIndex++];
if (optionsAllowed) {
if (ARG_PREFIX1.equals(arg) || ARG_PREFIX2.equals(arg)) {
optionsAllowed = false;
continue;
}
String optionName;
if (arg.startsWith(ARG_PREFIX1)) {
optionName = arg.substring(ARG_PREFIX1.length());
} else if (arg.startsWith(ARG_PREFIX2)) {
optionName = arg.substring(ARG_PREFIX2.length());
} else {
optionName = null;
}
if (optionName == null) {
setFile(arg);
} else {
Extractor extractor = (Extractor) m_optionExtractors.get(optionName);
if (extractor == null) {
throw new Exception("Unexpected option '" + optionName + "'");
}
argIndex = extractor.execute(optionName, args, argIndex);
}
} else {
setFile(arg);
}
}
}
protected void setFile (String value) {
if (m_fileSetter == null) {
throw new Exception("Unexpected file name: '" + value + "'");
}
m_fileSetter.execute(++m_fileIndex, new File(value));
}
protected void addExtractor (String optionName, Extractor extractor) {
if (m_optionExtractors.containsKey(optionName)) {
throw new Exception("Duplicated option name: '" + optionName + "'");
}
m_optionExtractors.put(optionName, extractor);
}
public static class Exception extends java.lang.RuntimeException {
public Exception (String message) {
super(message);
}
public Exception (String message, Throwable nested) {
super(message,nested);
}
}
public interface Option {
void execute (String option) throws Exception;
}
public interface StringOption {
void execute (String option, String value) throws Exception;
}
public interface IntOption {
void execute (String option, int value) throws Exception;
}
public interface FileOption {
void execute (int fileNo, File value) throws Exception;
}
protected abstract class Extractor {
public abstract int execute (String optionName, String[] args, int argIndex) throws Exception;
protected String getArg (String optionName, String[] args, int argIndex, String errorMessage) {
if (argIndex >= args.length) {
throw newException(optionName, errorMessage);
}
return args[argIndex];
}
protected Exception newException (String optionName, String errorMessage) {
return new Exception("Invalid option '" + optionName + "': " + errorMessage);
}
}
protected class OptionExtractor extends Extractor {
protected Option m_handler;
public OptionExtractor (Option handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
m_handler.execute(optionName);
return argIndex;
}
}
protected class StringOptionExtractor extends Extractor {
protected StringOption m_handler;
public StringOptionExtractor (StringOption handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
m_handler.execute(optionName, getArg(optionName, args, argIndex, "string value expected"));
return argIndex + 1;
}
}
protected class IntOptionExtractor extends Extractor {
protected IntOption m_handler;
public IntOptionExtractor (IntOption handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
String textValue = getArg(optionName, args, argIndex, "integer value expected");
int value;
try {
value = Integer.parseInt(textValue);
} catch (Throwable t) {
throw newException(optionName, "Invalid int argument");
}
m_handler.execute(optionName, value);
return argIndex + 1;
}
}
}
import java.util.HashMap;
import java.io.File;
public class CommandLineProcessor {
public static final String ARG_PREFIX1 = "--";
public static final String ARG_PREFIX2 = "//";
protected Map m_optionExtractors = new HashMap();
protected FileOption m_fileSetter = null;
protected int m_fileIndex = 0;
public void registerOption (String optionName, Option handler) {
addExtractor(optionName, new OptionExtractor(handler));
}
public void registerOption (String optionName, StringOption handler) {
addExtractor(optionName, new StringOptionExtractor(handler));
}
public void registerFiles (FileOption handler) {
m_fileSetter = handler;
}
public void registerOption (String optionName, IntOption handler) {
addExtractor(optionName, new IntOptionExtractor(handler));
}
public void execute (String[] args) {
boolean optionsAllowed = true;
int argIndex = 0;
while (argIndex < args.length) {
String arg = args[argIndex++];
if (optionsAllowed) {
if (ARG_PREFIX1.equals(arg) || ARG_PREFIX2.equals(arg)) {
optionsAllowed = false;
continue;
}
String optionName;
if (arg.startsWith(ARG_PREFIX1)) {
optionName = arg.substring(ARG_PREFIX1.length());
} else if (arg.startsWith(ARG_PREFIX2)) {
optionName = arg.substring(ARG_PREFIX2.length());
} else {
optionName = null;
}
if (optionName == null) {
setFile(arg);
} else {
Extractor extractor = (Extractor) m_optionExtractors.get(optionName);
if (extractor == null) {
throw new Exception("Unexpected option '" + optionName + "'");
}
argIndex = extractor.execute(optionName, args, argIndex);
}
} else {
setFile(arg);
}
}
}
protected void setFile (String value) {
if (m_fileSetter == null) {
throw new Exception("Unexpected file name: '" + value + "'");
}
m_fileSetter.execute(++m_fileIndex, new File(value));
}
protected void addExtractor (String optionName, Extractor extractor) {
if (m_optionExtractors.containsKey(optionName)) {
throw new Exception("Duplicated option name: '" + optionName + "'");
}
m_optionExtractors.put(optionName, extractor);
}
public static class Exception extends java.lang.RuntimeException {
public Exception (String message) {
super(message);
}
public Exception (String message, Throwable nested) {
super(message,nested);
}
}
public interface Option {
void execute (String option) throws Exception;
}
public interface StringOption {
void execute (String option, String value) throws Exception;
}
public interface IntOption {
void execute (String option, int value) throws Exception;
}
public interface FileOption {
void execute (int fileNo, File value) throws Exception;
}
protected abstract class Extractor {
public abstract int execute (String optionName, String[] args, int argIndex) throws Exception;
protected String getArg (String optionName, String[] args, int argIndex, String errorMessage) {
if (argIndex >= args.length) {
throw newException(optionName, errorMessage);
}
return args[argIndex];
}
protected Exception newException (String optionName, String errorMessage) {
return new Exception("Invalid option '" + optionName + "': " + errorMessage);
}
}
protected class OptionExtractor extends Extractor {
protected Option m_handler;
public OptionExtractor (Option handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
m_handler.execute(optionName);
return argIndex;
}
}
protected class StringOptionExtractor extends Extractor {
protected StringOption m_handler;
public StringOptionExtractor (StringOption handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
m_handler.execute(optionName, getArg(optionName, args, argIndex, "string value expected"));
return argIndex + 1;
}
}
protected class IntOptionExtractor extends Extractor {
protected IntOption m_handler;
public IntOptionExtractor (IntOption handler) {
m_handler = handler;
}
public int execute (String optionName, String[] args, int argIndex) {
String textValue = getArg(optionName, args, argIndex, "integer value expected");
int value;
try {
value = Integer.parseInt(textValue);
} catch (Throwable t) {
throw newException(optionName, "Invalid int argument");
}
m_handler.execute(optionName, value);
return argIndex + 1;
}
}
}
import java.io.File;
public class Test {
public static void main (String[] args) throws Exception {
final DummyFtpCopyUtility ftpCopy = new DummyFtpCopyUtility();
CommandLineProcessor clp = new CommandLineProcessor();
clp.registerOption("append", new CommandLineProcessor.Option() {
public void execute (String option) {
ftpCopy.appendMode = true;
}
});
clp.registerOption("host", new CommandLineProcessor.StringOption() {
public void execute (String option, String value) {
ftpCopy.host = value;
}
});
clp.registerOption("maxSize", new CommandLineProcessor.IntOption() {
public void execute (String option, int value) {
ftpCopy.maxFileSize = value;
}
});
clp.registerFiles(new CommandLineProcessor.FileOption() {
public void execute (int fileNo, File value) {
if (fileNo > 1) {
throw new CommandLineProcessor.Exception("Too many files specified. Extra file: '" + value + "'");
}
ftpCopy.sourceFile = value;
}
});
clp.execute(args);
ftpCopy.copy();
}
public static class DummyFtpCopyUtility {
protected boolean appendMode;
protected String host;
protected int maxFileSize = 0;
protected File sourceFile;
public void copy() {
if (sourceFile == null || host == null) {
System.out.println("Host and source file must be specified");
} else {
System.out.println("About to copy " + sourceFile + " to " + host);
if (appendMode) {
System.out.println("Append mode enabled");
}
if (maxFileSize > 0) {
System.out.println("Max file size: " + maxFileSize);
}
}
}
}
}
public class Test {
public static void main (String[] args) throws Exception {
final DummyFtpCopyUtility ftpCopy = new DummyFtpCopyUtility();
CommandLineProcessor clp = new CommandLineProcessor();
clp.registerOption("append", new CommandLineProcessor.Option() {
public void execute (String option) {
ftpCopy.appendMode = true;
}
});
clp.registerOption("host", new CommandLineProcessor.StringOption() {
public void execute (String option, String value) {
ftpCopy.host = value;
}
});
clp.registerOption("maxSize", new CommandLineProcessor.IntOption() {
public void execute (String option, int value) {
ftpCopy.maxFileSize = value;
}
});
clp.registerFiles(new CommandLineProcessor.FileOption() {
public void execute (int fileNo, File value) {
if (fileNo > 1) {
throw new CommandLineProcessor.Exception("Too many files specified. Extra file: '" + value + "'");
}
ftpCopy.sourceFile = value;
}
});
clp.execute(args);
ftpCopy.copy();
}
public static class DummyFtpCopyUtility {
protected boolean appendMode;
protected String host;
protected int maxFileSize = 0;
protected File sourceFile;
public void copy() {
if (sourceFile == null || host == null) {
System.out.println("Host and source file must be specified");
} else {
System.out.println("About to copy " + sourceFile + " to " + host);
if (appendMode) {
System.out.println("Append mode enabled");
}
if (maxFileSize > 0) {
System.out.println("Max file size: " + maxFileSize);
}
}
}
}
}
java -cp . Test --host localhost Foobar.txt
java -cp . Test --host localhost Foobar.txt --append
java -cp . Test --host localhost Foobar.txt --append --maxSize 1024
java -cp . Test --host localhost --append --maxSize 1024 -- --Foo--
java -cp . Test --host localhost Foobar.txt --append
java -cp . Test --host localhost Foobar.txt --append --maxSize 1024
java -cp . Test --host localhost --append --maxSize 1024 -- --Foo--
Comments
Sun. Nov. 5th, 2006 9:57 AM
bertheymans
bertheymans





