package org.dynjs.runtime.modules; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.dynjs.exception.InvalidModuleException; import org.dynjs.runtime.ExecutionContext; import org.dynjs.runtime.GlobalContext; import org.dynjs.runtime.JSFunction; import org.dynjs.runtime.JSObject; import org.dynjs.runtime.PropertyDescriptor; public class JavaClassModuleProvider extends ModuleProvider { public void addModule(Object module) throws InvalidModuleException { Module moduleAnno = module.getClass().getAnnotation(Module.class); if (moduleAnno == null) { throw new InvalidModuleException(module, "No @Module annotation"); } String moduleName = moduleAnno.name(); if (moduleName == null) { throw new InvalidModuleException(module, "Name not specified in @Module"); } modules.put(moduleName, module); } @Override public boolean load(ExecutionContext context, String moduleName) { Object javaModule = modules.get(moduleName); if (javaModule == null) { return false; } try { buildExports(context, moduleName, javaModule); return true; } catch (IllegalAccessException e) { return false; } } private JSObject buildExports(ExecutionContext context, String moduleName, Object javaModule) throws IllegalAccessException { Method[] methods = javaModule.getClass().getMethods(); JSObject module = (JSObject) context.getVariableEnvironment().getRecord().getBindingValue(context, "module", true); JSObject exports = (JSObject) module.get(context, "exports"); for (Method method : methods) { Export exportAnno = method.getAnnotation(Export.class); if (exportAnno == null) { continue; } String exportName = exportAnno.name(); if ("".equals(exportName)) { exportName = method.getName(); } final JSFunction function = buildFunction(context.getGlobalContext(), javaModule, method); PropertyDescriptor desc = new PropertyDescriptor(); desc.setValue(function); function.setDebugContext(moduleName + "." + exportName); exports.defineOwnProperty(context, exportName, desc, false); } return exports; } private JSFunction buildFunction(GlobalContext globalContext, Object module, Method method) throws IllegalAccessException { return new JavaFunction(globalContext, module, method); } private Map<String, Object> modules = new HashMap<>(); @Override public String generateModuleID(ExecutionContext context, String moduleName) { if (modules.get(moduleName) != null) return moduleName; return null; } }