1 package hudson.remoting; 2 3 import java.io.IOException ; 4 import java.io.ObjectInputStream ; 5 import java.io.Serializable ; 6 import java.lang.reflect.InvocationHandler ; 7 import java.lang.reflect.InvocationTargetException ; 8 import java.lang.reflect.Method ; 9 import java.lang.reflect.Proxy ; 10 11 16 final class RemoteInvocationHandler implements InvocationHandler , Serializable { 17 21 private final int oid; 22 23 31 private transient Channel channel; 32 33 36 private final boolean userProxy; 37 38 RemoteInvocationHandler(int id, boolean userProxy) { 39 this.oid = id; 40 this.userProxy = userProxy; 41 } 42 43 46 RemoteInvocationHandler(Channel channel, int id, boolean userProxy) { 47 this.channel = channel; 48 this.oid = id; 49 this.userProxy = userProxy; 50 } 51 52 55 public static <T> T wrap(Channel channel, int id, Class <T> type, boolean userProxy) { 56 return type.cast(Proxy.newProxyInstance( type.getClassLoader(), new Class []{type}, 57 new RemoteInvocationHandler(channel,id,userProxy))); 58 } 59 60 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 61 if(channel==null) 62 throw new IllegalStateException ("proxy is not connected to a channel"); 63 64 if(args==null) args = EMPTY_ARRAY; 65 66 Class <?> dc = method.getDeclaringClass(); 67 if(dc ==Object .class) { 68 try { 70 return method.invoke(this,args); 71 } catch (InvocationTargetException e) { 72 throw e.getTargetException(); 73 } 74 } 75 76 if(userProxy) 78 return channel.call(new RPCRequest(oid,method,args,dc.getClassLoader())); 79 else 80 return new RPCRequest(oid,method,args).call(channel); 81 } 82 83 private void readObject(ObjectInputStream ois) throws IOException , ClassNotFoundException { 84 channel = Channel.current(); 85 ois.defaultReadObject(); 86 } 87 88 91 public boolean equals(Object o) { 92 if(Proxy.isProxyClass(o.getClass())) 93 o = Proxy.getInvocationHandler(o); 94 95 if (this == o) return true; 96 if (o == null || getClass() != o.getClass()) return false; 97 98 RemoteInvocationHandler that = (RemoteInvocationHandler) o; 99 100 return this.oid==that.oid && this.channel==that.channel; 101 102 } 103 104 public int hashCode() { 105 return oid; 106 } 107 108 109 protected void finalize() throws Throwable { 110 if(channel!=null) 112 channel.send(new UnexportCommand(oid)); 113 super.finalize(); 114 } 115 116 private static final long serialVersionUID = 1L; 117 118 130 private static final class RPCRequest extends Request<Serializable ,Throwable > implements DelegatingCallable<Serializable ,Throwable > { 131 134 private final int oid; 135 136 private final String methodName; 137 141 private final String [] types; 142 145 private final Object [] arguments; 146 147 151 private transient ClassLoader classLoader; 152 153 public RPCRequest(int oid, Method m, Object [] arguments) { 154 this(oid,m,arguments,null); 155 } 156 157 public RPCRequest(int oid, Method m, Object [] arguments, ClassLoader cl) { 158 this.oid = oid; 159 this.arguments = arguments; 160 this.methodName = m.getName(); 161 this.classLoader = cl; 162 163 this.types = new String [arguments.length]; 164 Class <?>[] params = m.getParameterTypes(); 165 for( int i=0; i<arguments.length; i++ ) 166 types[i] = params[i].getName(); 167 } 168 169 public Serializable call() throws Throwable { 170 return perform(Channel.current()); 171 } 172 173 public ClassLoader getClassLoader() { 174 if(classLoader!=null) 175 return classLoader; 176 else 177 return getClass().getClassLoader(); 178 } 179 180 protected Serializable perform(Channel channel) throws Throwable { 181 Object o = channel.getExportedObject(oid); 182 if(o==null) 183 throw new IllegalStateException ("Unable to call "+methodName+". Invalid object ID "+oid); 184 try { 185 Method m = choose(o); 186 m.setAccessible(true); return (Serializable ) m.invoke(o,arguments); 188 } catch (InvocationTargetException e) { 189 throw e.getTargetException(); 190 } 191 } 192 193 196 private Method choose(Object o) { 197 OUTER: 198 for(Method m : o.getClass().getMethods()) { 199 if(!m.getName().equals(methodName)) 200 continue; 201 Class <?>[] paramTypes = m.getParameterTypes(); 202 if(types.length!=arguments.length) 203 continue; 204 for( int i=0; i<types.length; i++ ) { 205 if(!types[i].equals(paramTypes[i].getName())) 206 continue OUTER; 207 } 208 return m; 209 } 210 return null; 211 } 212 213 public String toString() { 214 return "RPCRequest("+oid+","+methodName+")"; 215 } 216 217 private static final long serialVersionUID = 1L; 218 } 219 220 private static final Object [] EMPTY_ARRAY = new Object [0]; 221 } 222 | Popular Tags |