1 28 29 package org.jruby.javasupport.proxy; 30 31 import java.lang.reflect.Constructor ; 32 import java.lang.reflect.InvocationTargetException ; 33 34 import org.jruby.Ruby; 35 import org.jruby.RubyArray; 36 import org.jruby.RubyClass; 37 import org.jruby.RubyFixnum; 38 import org.jruby.RubyModule; 39 import org.jruby.RubyObject; 40 import org.jruby.RubyProc; 41 import org.jruby.exceptions.RaiseException; 42 import org.jruby.javasupport.Java; 43 import org.jruby.javasupport.JavaObject; 44 import org.jruby.javasupport.JavaUtil; 45 import org.jruby.runtime.Block; 46 import org.jruby.runtime.CallbackFactory; 47 import org.jruby.runtime.ObjectAllocator; 48 import org.jruby.runtime.builtin.IRubyObject; 49 50 public class JavaProxyConstructor extends JavaProxyReflectionObject { 51 52 private final Constructor proxyConstructor; 53 54 private final JavaProxyClass declaringProxyClass; 55 56 JavaProxyConstructor(Ruby runtime, JavaProxyClass pClass, 57 Constructor constructor) { 58 super(runtime, runtime.getModule("Java").getClass( 59 "JavaProxyConstructor")); 60 this.declaringProxyClass = pClass; 61 this.proxyConstructor = constructor; 62 } 63 64 public Class [] getParameterTypes() { 65 Class [] decl = proxyConstructor.getParameterTypes(); 66 Class [] result = new Class [decl.length - 1]; 67 System.arraycopy(decl, 0, result, 0, result.length); 68 return result; 69 } 70 71 public JavaProxyClass getDeclaringClass() { 72 return declaringProxyClass; 73 } 74 75 public Object newInstance(Object [] args, JavaProxyInvocationHandler handler) 76 throws IllegalArgumentException , InstantiationException , 77 IllegalAccessException , InvocationTargetException { 78 if (args.length + 1 != proxyConstructor.getParameterTypes().length) { 79 throw new IllegalArgumentException ("wrong number of parameters"); 80 } 81 82 Object [] realArgs = new Object [args.length + 1]; 83 System.arraycopy(args, 0, realArgs, 0, args.length); 84 realArgs[args.length] = handler; 85 86 return proxyConstructor.newInstance(realArgs); 87 } 88 89 public static RubyClass createJavaProxyConstructorClass(Ruby runtime, 90 RubyModule javaProxyModule) { 91 RubyClass result = javaProxyModule.defineClassUnder( 92 "JavaProxyConstructor", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); 93 94 CallbackFactory callbackFactory = runtime 95 .callbackFactory(JavaProxyConstructor.class); 96 97 JavaProxyReflectionObject.registerRubyMethods(runtime, result); 98 99 result.defineFastMethod("argument_types", callbackFactory 100 .getFastMethod("argument_types")); 101 102 result.defineFastMethod("declaring_class", callbackFactory 103 .getFastMethod("getDeclaringClass")); 104 105 result.defineMethod("new_instance", callbackFactory 106 .getOptMethod("new_instance")); 107 108 result.defineFastMethod("arity", callbackFactory.getFastMethod("arity")); 109 110 return result; 111 112 } 113 114 public RubyFixnum arity() { 115 return getRuntime().newFixnum(getParameterTypes().length); 116 } 117 118 protected String nameOnInspection() { 119 return getDeclaringClass().nameOnInspection(); 120 } 121 122 public IRubyObject inspect() { 123 StringBuffer result = new StringBuffer (); 124 result.append(nameOnInspection()); 125 Class [] parameterTypes = getParameterTypes(); 126 for (int i = 0; i < parameterTypes.length; i++) { 127 result.append(parameterTypes[i].getName()); 128 if (i < parameterTypes.length - 1) { 129 result.append(','); 130 } 131 } 132 result.append(")>"); 133 return getRuntime().newString(result.toString()); 134 } 135 136 public RubyArray argument_types() { 137 return buildRubyArray(getParameterTypes()); 138 } 139 140 public RubyObject new_instance(IRubyObject[] args, Block block) { 141 int size = this.checkArgumentCount(args, 1, 2) - 1; 142 final RubyProc proc; 143 144 if (args[size] instanceof RubyProc) { 147 proc = (RubyProc) args[size]; 148 } else { 149 proc = getRuntime().newProc(false,block); 150 size++; 151 } 152 153 RubyArray constructor_args = (RubyArray) args[0]; 154 Class [] parameterTypes = getParameterTypes(); 155 156 int count = (int) constructor_args.length().getLongValue(); 157 Object [] converted = new Object [count]; 158 for (int i = 0; i < count; i++) { 159 IRubyObject ith = constructor_args.aref(new IRubyObject[] { getRuntime().newFixnum(i) }); 161 converted[i] = JavaUtil.convertArgument(Java.ruby_to_java(this, ith, Block.NULL_BLOCK), parameterTypes[i]); 162 } 163 164 final IRubyObject recv = this; 165 166 JavaProxyInvocationHandler handler = new JavaProxyInvocationHandler() { 167 168 public Object invoke(Object proxy, JavaProxyMethod method, 169 Object [] nargs) throws Throwable { 170 int length = nargs == null ? 0 : nargs.length; 171 IRubyObject[] rubyArgs = new IRubyObject[length + 2]; 172 rubyArgs[0] = JavaObject.wrap(recv.getRuntime(), proxy); 173 rubyArgs[1] = method; 174 for (int i = 0; i < length; i++) { 175 rubyArgs[i + 2] = JavaUtil.convertJavaToRuby(getRuntime(), 176 nargs[i]); 177 } 178 IRubyObject call_result = proc.call(rubyArgs); 179 Object converted_result = JavaUtil.convertRubyToJava( 180 call_result, method.getReturnType()); 181 return converted_result; 182 } 183 184 }; 185 186 Object result; 187 try { 188 result = newInstance(converted, handler); 189 } catch (Exception e) { 190 RaiseException ex = getRuntime().newArgumentError( 191 "Constructor invocation failed: " + e.getMessage()); 192 ex.initCause(e); 193 throw ex; 194 } 195 196 return JavaObject.wrap(getRuntime(), result); 197 198 } 199 200 } 201 | Popular Tags |