1 28 package org.jruby.internal.runtime.methods; 29 30 import java.lang.reflect.InvocationTargetException ; 31 import java.lang.reflect.Method ; 32 import java.util.Arrays ; 33 34 import org.jruby.Ruby; 35 import org.jruby.RubyModule; 36 import org.jruby.exceptions.JumpException; 37 import org.jruby.exceptions.MainExitException; 38 import org.jruby.exceptions.RaiseException; 39 import org.jruby.exceptions.ThreadKill; 40 import org.jruby.runtime.Arity; 41 import org.jruby.runtime.Block; 42 import org.jruby.runtime.ThreadContext; 43 import org.jruby.runtime.Visibility; 44 import org.jruby.runtime.builtin.IRubyObject; 45 46 public class FullFunctionReflectedMethod extends DynamicMethod { 47 private Method method; 48 private Class type; 49 private String methodName; 50 private Arity arity; 51 52 public FullFunctionReflectedMethod(RubyModule implementationClass, Class type, String methodName, 53 Arity arity, Visibility visibility) { 54 super(implementationClass, visibility); 55 this.type = type; 56 this.methodName = methodName; 57 this.arity = arity; 58 59 assert type != null; 60 assert methodName != null; 61 assert arity != null; 62 63 Class [] parameterTypes; 64 if (arity.isFixed()) { 65 parameterTypes = new Class [arity.getValue()+1]; 66 Arrays.fill(parameterTypes, IRubyObject.class); 67 parameterTypes[arity.getValue()] = Block.class; 68 } else { 69 parameterTypes = new Class [2]; 70 parameterTypes[0] = IRubyObject[].class; 71 parameterTypes[1] = Block.class; 72 } 73 try { 74 method = type.getMethod(methodName, parameterTypes); 75 } catch (NoSuchMethodException e) { 76 assert false : e; 77 } catch (SecurityException e) { 78 assert false : e; 79 } 80 81 assert method != null; 82 } 83 84 public void preMethod(ThreadContext context, RubyModule klazz, IRubyObject self, String name, IRubyObject[] args, boolean noSuper, Block block) { 85 context.preReflectedMethodInternalCall(implementationClass, klazz, self, name, args, noSuper, block); 86 } 87 88 public void postMethod(ThreadContext context) { 89 context.postReflectedMethodInternalCall(); 90 } 91 92 public IRubyObject internalCall(ThreadContext context, RubyModule klazz, IRubyObject self, String name, IRubyObject[] args, boolean noSuper, Block block) { 93 Ruby runtime = context.getRuntime(); 94 arity.checkArity(runtime, args); 95 96 assert self != null; 97 assert args != null; 98 assert method != null; 99 100 Object [] methodArgs; 101 if (!arity.isFixed()) { 102 methodArgs = new Object []{args, block}; 103 } else { 104 methodArgs = new Object [args.length + 1]; 105 System.arraycopy(args, 0, methodArgs, 0, args.length); 106 methodArgs[args.length] = block; 107 } 108 109 try { 110 return (IRubyObject) method.invoke(self, methodArgs); 111 } catch (InvocationTargetException e) { 112 if (e.getTargetException() instanceof RaiseException) { 113 throw (RaiseException) e.getTargetException(); 114 } else if (e.getTargetException() instanceof JumpException) { 115 throw (JumpException) e.getTargetException(); 116 } else if (e.getTargetException() instanceof ThreadKill) { 117 throw (ThreadKill) e.getTargetException(); 119 } else if (e.getTargetException() instanceof Exception ) { 120 if(e.getTargetException() instanceof MainExitException) { 121 throw (RuntimeException )e.getTargetException(); 122 } 123 runtime.getJavaSupport().handleNativeException(e.getTargetException()); 124 return runtime.getNil(); 125 } else { 126 throw (Error ) e.getTargetException(); 127 } 128 } catch (IllegalAccessException e) { 129 StringBuffer message = new StringBuffer (); 130 message.append(e.getMessage()); 131 message.append(':'); 132 message.append(" methodName=").append(methodName); 133 message.append(" recv=").append(self.toString()); 134 message.append(" type=").append(type.getName()); 135 message.append(" methodArgs=["); 136 for (int i = 0; i < methodArgs.length; i++) { 137 message.append(methodArgs[i]); 138 message.append(' '); 139 } 140 message.append(']'); 141 assert false : message.toString(); 142 return null; 143 } catch (final IllegalArgumentException e) { 144 156 assert false : e; 157 return null; 158 } 159 } 160 161 public DynamicMethod dup() { 162 FullFunctionReflectedMethod newMethod = 163 new FullFunctionReflectedMethod(getImplementationClass(), type, methodName, arity, getVisibility()); 164 165 newMethod.method = method; 166 167 return newMethod; 168 } 169 170 public Arity getArity() { 172 return arity; 173 } 174 } 175 | Popular Tags |