package php.runtime.reflection; import php.runtime.Memory; import php.runtime.env.Context; import php.runtime.env.Environment; import php.runtime.env.TraceInfo; import php.runtime.lang.Closure; import php.runtime.memory.ObjectMemory; import php.runtime.reflection.helper.ClosureEntity; import php.runtime.reflection.support.AbstractFunctionEntity; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class FunctionEntity extends AbstractFunctionEntity { protected boolean isInternal = false; protected ModuleEntity module; private Class<?> nativeClazz; private Method nativeMethod; private boolean isStatic = false; private Closure cachedClosure; public FunctionEntity(Context context) { super(context); } public boolean isStatic() { return isStatic; } public void setStatic(boolean aStatic) { isStatic = aStatic; } public boolean isInternal() { return isInternal; } public Class<?> getNativeClazz() { return nativeClazz; } public void setNativeClazz(Class<?> nativeClazz) { this.nativeClazz = nativeClazz; } public Method getNativeMethod() { return nativeMethod; } public void setNativeMethod(Method nativeMethod) { this.nativeMethod = nativeMethod; nativeMethod.setAccessible(true); } public boolean isDeprecated(){ return false; // TODO } public ModuleEntity getModule() { return module; } public void setModule(ModuleEntity module) { this.module = module; } public Memory invoke(Environment env, TraceInfo trace, Memory[] arguments) throws Throwable { try { return (Memory)nativeMethod.invoke(null, env, arguments); } catch (InvocationTargetException e){ return env.__throwException(e); } finally { unsetArguments(arguments); } } @Override public Closure getClosure(Environment env) { if (cachedClosure != null) return cachedClosure; final FunctionEntity bind = this; final ClosureEntity closureEntity1 = new ClosureEntity(this.getContext()); closureEntity1.setParent(env.scope.fetchUserClass(Closure.class)); closureEntity1.parameters = this.parameters; closureEntity1.setReturnReference(this.isReturnReference()); MethodEntity m = new MethodEntity(this); m.setClazz(closureEntity1); m.setName("__invoke"); closureEntity1.addMethod(m, null); closureEntity1.doneDeclare(); Closure tmp = new Closure(env, closureEntity1, new ObjectMemory(env.getLateObject()), null, new Memory[0]){ @Override public Memory __invoke(Environment e, Memory... args) { try { return bind.invoke(e, e.peekCall(0).trace, args); } catch (RuntimeException e1){ throw e1; } catch (Throwable throwable) { throw new RuntimeException(throwable); } } @Override public Memory getOrCreateStatic(String name) { return Memory.NULL; } @Override public ClassEntity getReflection() { return closureEntity1; } }; try { m.setNativeMethod(tmp.getClass().getDeclaredMethod("__invoke", Environment.class, Memory[].class)); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } return cachedClosure = tmp; } }