1 32 package org.jruby.runtime.callback; 33 34 import java.lang.reflect.InvocationTargetException ; 35 import java.lang.reflect.Method ; 36 37 import org.jruby.exceptions.JumpException; 38 import org.jruby.exceptions.RaiseException; 39 import org.jruby.exceptions.MainExitException; 40 import org.jruby.exceptions.ThreadKill; 41 import org.jruby.runtime.Arity; 42 import org.jruby.runtime.Block; 43 import org.jruby.runtime.builtin.IRubyObject; 44 45 48 public class ReflectionCallback implements Callback { 49 private Method method; 50 private Class type; 51 private String methodName; 52 private Class [] argumentTypes; 53 private boolean isRestArgs; 54 private Arity arity; 55 private boolean isStaticMethod; 56 private boolean fast; 57 58 public ReflectionCallback(Class type, String methodName, Class [] argumentTypes, 59 boolean isRestArgs, boolean isStaticMethod, Arity arity, boolean fast) { 60 this.type = type; 61 this.methodName = methodName; 62 this.argumentTypes = argumentTypes; 63 this.isRestArgs = isRestArgs; 64 this.isStaticMethod = isStaticMethod; 65 this.arity = arity; 66 this.fast = fast; 67 68 assert type != null; 69 assert methodName != null; 70 assert arity != null; 71 72 loadMethod(fast); 73 } 74 75 private void loadMethod(boolean fast) { 76 Class [] args; 77 78 if (isStaticMethod) { 79 Class [] types = new Class [argumentTypes.length + 1]; 80 System.arraycopy(argumentTypes, 0, types, 1, argumentTypes.length); 81 types[0] = IRubyObject.class; 82 args = types; 83 } else { 84 args = argumentTypes; 85 } 86 87 if (!fast) { 89 Class [] types = new Class [args.length + 1]; 90 System.arraycopy(args, 0, types, 0, args.length); 91 types[args.length] = Block.class; 92 args = types; 93 } 94 95 try { 96 method = type.getMethod(methodName, args); 97 } catch (NoSuchMethodException e) { 98 throw new RuntimeException ("NoSuchMethodException: Cannot get method \"" + methodName 99 + "\" in class \"" + type.getName() + "\" by Reflection."); 100 } catch (SecurityException e) { 101 throw new RuntimeException ("SecurityException: Cannot get method \"" + methodName 102 + "\" in class \"" + type.getName() + "\" by Reflection."); 103 } 104 } 105 106 112 protected final Object [] packageRestArgumentsForReflection(final Object [] originalArgs) { 113 IRubyObject[] restArray = new IRubyObject[originalArgs.length - (argumentTypes.length - 1)]; 114 Object [] result = new Object [argumentTypes.length]; 115 try { 116 System.arraycopy(originalArgs, argumentTypes.length - 1, restArray, 0, originalArgs.length - (argumentTypes.length - 1)); 117 } catch (ArrayIndexOutOfBoundsException e) { 118 assert false : e; 119 return null; 120 } 121 System.arraycopy(originalArgs, 0, result, 0, argumentTypes.length - 1); 122 result[argumentTypes.length - 1] = restArray; 123 return result; 124 } 125 126 132 135 public IRubyObject execute(IRubyObject recv, IRubyObject[] oargs, Block block) { 136 arity.checkArity(recv.getRuntime(), oargs); 137 138 Object [] methodArgs = oargs; 139 140 if (isRestArgs) { 141 methodArgs = packageRestArgumentsForReflection(methodArgs); 142 } 143 try { 144 IRubyObject receiver = recv; 145 if (isStaticMethod) { 146 Object [] args = new Object [methodArgs.length + (fast ? 1 : 2)]; 147 System.arraycopy(methodArgs, 0, args, 1, methodArgs.length); 148 args[0] = recv; 149 if (!fast) args[methodArgs.length + 1] = block; 150 receiver = null; 151 methodArgs = args; 152 } else { 153 Object [] args = new Object [methodArgs.length + (fast ? 0 : 1)]; 154 System.arraycopy(methodArgs, 0, args, 0, methodArgs.length); 155 if (!fast) args[methodArgs.length] = block; 156 methodArgs = args; 157 } 158 return (IRubyObject) method.invoke(receiver, methodArgs); 159 } catch (InvocationTargetException e) { 160 if (e.getTargetException() instanceof RaiseException) { 161 throw (RaiseException) e.getTargetException(); 162 } else if (e.getTargetException() instanceof JumpException) { 163 throw (JumpException) e.getTargetException(); 164 } else if (e.getTargetException() instanceof ThreadKill) { 165 throw (ThreadKill) e.getTargetException(); 167 } else if (e.getTargetException() instanceof Exception ) { 168 if(e.getTargetException() instanceof MainExitException) { 169 throw (RuntimeException )e.getTargetException(); 170 } 171 recv.getRuntime().getJavaSupport().handleNativeException(e.getTargetException()); 172 return recv.getRuntime().getNil(); 173 } else { 174 throw (Error ) e.getTargetException(); 175 } 176 } catch (IllegalAccessException e) { 177 StringBuffer message = new StringBuffer (); 178 message.append(e.getMessage()); 179 message.append(':'); 180 message.append(" methodName=").append(methodName); 181 message.append(" recv=").append(recv.toString()); 182 message.append(" type=").append(type.getName()); 183 message.append(" methodArgs=["); 184 for (int i = 0; i < methodArgs.length; i++) { 185 message.append(methodArgs[i]); 186 message.append(' '); 187 } 188 message.append(']'); 189 assert false : message.toString(); 190 return null; 191 } catch (final IllegalArgumentException e) { 192 204 assert false : e; 205 return null; 206 } 207 } 208 209 212 public Arity getArity() { 213 return arity; 214 } 215 } 216 | Popular Tags |