import java.io.File; import java.lang.reflect.Method; public class CommandLineProcessor { public static final String METHOD_SET_FILE = "setFile"; public static final String ARG_PREFIX1 = "--"; public static final String ARG_PREFIX2 = "//"; protected int m_fileNo = 0; public void execute (String[] args, Object client) { 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(client, arg); } else { argIndex = setOption(client, optionName, args, argIndex); } } else { setFile(client, arg); } } } protected void setFile (Object client, String fileName) { Method method = getMethod(client, METHOD_SET_FILE, new Class[] { Integer.TYPE, File.class }); if (method == null) { throw new Exception("Client '" + client.getClass().getName() + "' has no method " + METHOD_SET_FILE); } try { method.invoke(client, new Object[] { new Integer(m_fileNo++), new File(fileName) }); } catch (Throwable t) { throw new Exception("Error updating file option", t); } } protected int setOption (Object client, String optionName, String[] args, int argIndex) { String methodName = "setOption" + optionName.substring(0,1).toUpperCase() + optionName.substring(1); Method method = getMethod(client, methodName, new Class[] { String.class }); if (method != null) { invokeOptionSetter(client, method, new Object[] { getArg(optionName, args, argIndex, "value expected") }, optionName); return argIndex+1; } method = getMethod(client, methodName, new Class[0]); if (method != null) { invokeOptionSetter(client, method, new Object[0], optionName); return argIndex; } throw new Exception("Unexpected option '" + optionName + "'"); } protected void invokeOptionSetter (Object client, Method method, Object[] args, String optionName) { try { method.invoke(client, args); } catch (Throwable t) { throw new Exception("Error updating option '" + optionName + "'", t); } } protected Method getMethod (Object client, String name, Class[] argTypes) { Class clazz = client.getClass(); try { return clazz.getMethod(name, argTypes); } catch (NoSuchMethodException nsme) { return null; } catch (Throwable t) { throw new Exception("Error accessing method " + name + " of class '" + clazz.getName() + "'", t); } } 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); } public static class Exception extends java.lang.RuntimeException { public Exception (String message) { super(message); } public Exception (String message, Throwable nested) { super(message,nested); } } } Usage sample: 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.execute(args, ftpCopy); ftpCopy.copy(); } public static class DummyFtpCopyUtility { protected boolean appendMode; protected String host; protected File sourceFile; public void setOptionAppend() { appendMode = true; } public void setOptionHost (String value) { host = value; } public void setFile (int fileNo, File value) { if (fileNo > 1) { throw new CommandLineProcessor.Exception("Too many files specified. Extra file: '" + value + "'"); } sourceFile = value; } 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"); } } } } }