/*
* Copyright 2008 Hippo.
*
* Licensed 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.hippoecm.tools.cli;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Helper class for commands to map command to it's class and map aliases.
* This class also handles the reflecion stuff for executing commands.
*/
public final class CommandHelper {
/**
* Hide constructor.
*/
private CommandHelper() {
super();
}
/**
* The map containing command->class sets.
*/
private static Map<String, String> commandMap = new TreeMap<String, String>();
/**
* The map containing alias->command sets.
*/
private static Map<String, String> aliasMap = new TreeMap<String, String>();
/**
* Check if the alias is a registered alias.
* @param alias the alias
* @return true if the alias if found
*/
public static boolean isAlias(final String alias) {
return aliasMap.containsKey(alias);
}
/**
* Get the command for the alias.
* @param alias the alias
* @return the command or null if the alias is not found
*/
public static String getCommandForAlias(final String alias) {
if (isAlias(alias)) {
return aliasMap.get(alias);
}
return null;
}
/**
* Check if the command is a registered command.
* @param command the command
* @return true if the command is found
*/
public static boolean isCommand(final String command) {
return commandMap.containsKey(command);
}
/**
* Get the class name for the command.
* @param command the command
* @return the class name or null if command is not found
*/
public static String getClassForCommand(final String command) {
if (isCommand(command)) {
return commandMap.get(command);
}
return null;
}
/**
* Register a new command class.
* @param clazz the class name
*/
public static void registerCommandClass(final String clazz) {
String[] aliases = (String[]) runMethod("getAliases", clazz);
String command = (String) runMethod("getCommand", clazz);
commandMap.put(command, clazz);
for (String alias : aliases) {
aliasMap.put(alias, command);
}
}
/**
* Get the registerd commands as array.
* @return a string array with the commands
*/
public static String[] getCommandsAsArray() {
Set<String> commandSet = commandMap.keySet();
String[] commands = new String[commandSet.size()];
commandSet.toArray(commands);
return commands;
}
/**
* Get the registered aliases as array.
* @return a string array with the aliases
*/
public static String[] getAliasesAsArray() {
Set<String> aliasSet = aliasMap.keySet();
String[] aliases = new String[aliasSet.size()];
aliasSet.toArray(aliases);
return aliases;
}
/**
* @see runMethod(String,String,String[])
* @param method The method to execute
* @param clazz The name of the class to execute.
* @return The return value of the method.
*/
public static Object runMethod(final String method, final String clazz) {
return runMethod(method, clazz, null);
}
/**
* This method hides the ugly details of reflection. In a nutshell it
* invokes the doIt() method of the java class associated with the command
* being executed.
*
* @param method The method to execute
* @param clazz The name of the class to execute.
* @param args The command line parses into tokens.
* @return The return value of the method.
*/
public static Object runMethod(final String method, final String clazz, final String[] args) {
// get the class object.
Class theClass = null;
try {
theClass = Class.forName(clazz);
if (theClass == null) {
throw new RuntimeException("theClass is null.");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Class Not Found: " + clazz);
}
// get the constructor object.
Constructor theConstructor = null;
try {
theConstructor = theClass.getConstructor(new Class[0]);
if (theConstructor == null) {
throw new RuntimeException("theConstructor is null.");
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
throw new RuntimeException("Unable to find constructor for " + clazz);
}
// get the instance object.
Command theInstance = null;
try {
theInstance = (Command) theConstructor.newInstance((Object[]) new Class[0]);
if (null == theInstance) {
throw new RuntimeException("theInstance is null.");
}
} catch (InvocationTargetException e) {
e.getCause().printStackTrace();
throw new RuntimeException("InvocationTargetException for " + clazz);
} catch (java.lang.NoClassDefFoundError e) {
throw new RuntimeException("NoClassDefFoundError for " + clazz);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unable to load constructor for " + clazz);
}
Class[] parameterTypes = new Class[1];
parameterTypes[0] = java.lang.String[].class;
// gets the method object.
Method theMethod = null;
try {
if (args == null) {
theMethod = theClass.getMethod(method);
} else {
theMethod = theClass.getMethod(method, parameterTypes);
}
if (null == theMethod) {
throw new RuntimeException("theMethod is null.");
}
} catch (Exception e) {
Method[] methlist = theClass.getDeclaredMethods();
for (int i = 0; i < methlist.length; i++) {
Method m = methlist[i];
System.out.println("name = " + m.getName());
System.out.println("decl class = " + m.getDeclaringClass());
Class[] pvec = m.getParameterTypes();
for (int j = 0; j < pvec.length; j++) {
System.out.println("param #" + j + " " + pvec[j]);
}
Class[] evec = m.getExceptionTypes();
for (int j = 0; j < evec.length; j++) {
System.out.println("exc #" + j + " " + evec[j]);
}
System.out.println("return type = " + m.getReturnType());
System.out.println("-----");
}
e.printStackTrace();
throw new RuntimeException("Unable to find test method for " + clazz);
}
Object[] params = new Object[1];
params[0] = args;
Object theReturnValue;
try {
if (args == null) {
theReturnValue = theMethod.invoke(theInstance);
} else {
theReturnValue = theMethod.invoke(theInstance, params);
}
} catch (IllegalAccessException e) {
throw new RuntimeException("IllegalAccessException for " + clazz);
} catch (InvocationTargetException e) {
// check for exit command
if (e.getCause() instanceof JcrShellShutdownException) {
throw new JcrShellShutdownException();
}
e.getCause().printStackTrace();
throw new RuntimeException("InvocationTargetException for " + clazz);
} catch (NoClassDefFoundError e) {
throw new RuntimeException("NoClassDefFoundError for " + clazz);
}
return theReturnValue;
}
}