package nodebox.function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import nodebox.util.LoadException; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import static com.google.common.base.Preconditions.checkArgument; public final class JavaLibrary extends FunctionLibrary { public static JavaLibrary loadStaticClass(String identifier) { try { Class c = Class.forName(identifier); Field instanceField = c.getDeclaredField("LIBRARY"); return (JavaLibrary) instanceField.get(null); } catch (ClassNotFoundException e) { throw new LoadException(null, e); } catch (NoSuchFieldException e) { throw new LoadException(null, e); } catch (IllegalAccessException e) { throw new LoadException(null, e); } catch (ClassCastException e) { throw new LoadException(null, e); } catch (ExceptionInInitializerError e) { throw new LoadException(null, e); } } public static JavaLibrary ofClass(String namespace, Class c, String... methodNames) { ArrayList<Function> functions = new ArrayList<Function>(); for (String methodName : methodNames) { Function function = StaticMethodFunction.find(c, methodName); functions.add(function); } return new JavaLibrary(namespace, c, functions); } private final String namespace; private final Class clazz; private final ImmutableMap<String, Function> functionMap; private JavaLibrary(String namespace, Class clazz, Iterable<Function> functions) { this.namespace = namespace; this.clazz = clazz; ImmutableMap.Builder<String, Function> b = ImmutableMap.builder(); for (Function function : functions) { b.put(function.getName(), function); } functionMap = b.build(); } @Override public String getLink(File baseFile) { return "java:" + clazz.getName(); } public String getSimpleIdentifier() { return getNamespace(); } public String getNamespace() { return namespace; } public String getLanguage() { return "java"; } public Function getFunction(String name) { return functionMap.get(name); } public boolean hasFunction(String name) { return functionMap.containsKey(name); } private static class StaticMethodFunction implements Function { public static StaticMethodFunction find(Class c, String methodName) { Method m = Functions.findMethod(c, methodName, false); return new StaticMethodFunction(m); } private final Method method; private final ImmutableList<Argument> arguments; public StaticMethodFunction(Method method) { checkArgument(Modifier.isStatic(method.getModifiers()), "Method %s is not a static method.", method); this.method = method; this.arguments = Functions.introspect(method); } public String getName() { return method.getName(); } public Object invoke(Object... args) throws Exception { return method.invoke(null, args); } public ImmutableList<Argument> getArguments() { return arguments; } } }