1 5 package com.tc.object.event; 6 7 import com.tc.asm.Type; 8 import com.tc.logging.TCLogger; 9 import com.tc.logging.TCLogging; 10 import com.tc.object.ClientObjectManager; 11 import com.tc.object.ObjectID; 12 import com.tc.object.dmi.DmiClassSpec; 13 import com.tc.object.dmi.DmiDescriptor; 14 import com.tc.object.loaders.ClassProvider; 15 import com.tc.object.lockmanager.api.LockLevel; 16 import com.tc.object.logging.RuntimeLogger; 17 import com.tc.util.Assert; 18 import com.tcclient.object.DistributedMethodCall; 19 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.util.HashSet ; 23 import java.util.Set ; 24 25 public class DmiManagerImpl implements DmiManager { 26 private static final TCLogger logger = TCLogging.getLogger(DmiManager.class); 27 private static final String lockName = "@DistributedMethodCall"; 28 private static final Object TRUE = new Object (); 29 30 private final ClassProvider classProvider; 31 private final ClientObjectManager objMgr; 32 private final RuntimeLogger runtimeLogger; 33 private final ThreadLocal feedBack; 34 private final ThreadLocal nesting; 35 36 public DmiManagerImpl(ClassProvider cp, ClientObjectManager om, RuntimeLogger rl) { 37 Assert.pre(cp != null); 38 Assert.pre(om != null); 39 Assert.pre(rl != null); 40 this.classProvider = cp; 41 this.objMgr = om; 42 this.runtimeLogger = rl; 43 this.feedBack = new ThreadLocal (); 44 this.nesting = new ThreadLocal (); 45 } 46 47 public boolean distributedInvoke(Object receiver, String method, Object [] params, boolean runOnAllNodes) { 48 if (feedBack.get() != null) { return false; } 49 if (nesting.get() != null) { return false; } 50 nesting.set(TRUE); 51 52 Assert.pre(receiver != null); 53 Assert.pre(method != null); 54 Assert.pre(params != null); 55 56 final String methodName = method.substring(0, method.indexOf('(')); 57 final String paramDesc = method.substring(method.indexOf('(')); 58 final DistributedMethodCall dmc = new DistributedMethodCall(receiver, params, methodName, paramDesc); 59 if (runtimeLogger.distributedMethodDebug()) runtimeLogger.distributedMethodCall(receiver.getClass().getName(), dmc 60 .getMethodName(), dmc.getParameterDesc()); 61 objMgr.getTransactionManager().begin(lockName, LockLevel.CONCURRENT); 62 try { 63 final ObjectID receiverId = objMgr.lookupOrCreate(receiver).getObjectID(); 64 final ObjectID dmiCallId = objMgr.lookupOrCreate(dmc).getObjectID(); 65 final DmiClassSpec[] classSpecs = getClassSpecs(classProvider, receiver, params); 66 final DmiDescriptor dd = new DmiDescriptor(receiverId, dmiCallId, classSpecs, runOnAllNodes); 67 objMgr.getTransactionManager().addDmiDescriptor(dd); 68 return true; 69 } finally { 70 objMgr.getTransactionManager().commit(lockName); 71 } 72 } 73 74 public void distributedInvokeCommit() { 75 if (feedBack.get() != null) { return; } 76 Assert.pre(nesting.get() != null); 77 nesting.set(null); 78 } 79 80 public void invoke(DmiDescriptor dd) { 81 Assert.pre(dd != null); 82 83 try { 84 checkClassAvailability(classProvider, dd.getClassSpecs()); 85 } catch (ClassNotFoundException e) { 86 if (logger.isDebugEnabled()) logger.debug("Ignoring distributed method call", e); 87 return; 88 } 89 DistributedMethodCall dmc; 90 try { 91 dmc = (DistributedMethodCall) objMgr.lookupObject(dd.getDmiCallId()); 92 } catch (Throwable e) { 93 if (logger.isDebugEnabled()) logger.debug("Ignoring distributed method call", e); 94 return; 95 } 96 try { 97 if (runtimeLogger.distributedMethodDebug()) runtimeLogger.distributedMethodCall(dmc.getReceiver().getClass() 98 .getName(), dmc.getMethodName(), dmc.getParameterDesc()); 99 feedBack.set(TRUE); 100 invoke(dmc); 101 } catch (Throwable e) { 102 runtimeLogger.distributedMethodCallError(dmc.getReceiver().getClass().getName(), dmc.getMethodName(), dmc 103 .getParameterDesc(), e); 104 if (logger.isDebugEnabled()) logger.debug("Ignoring distributed method call", e); 105 } finally { 106 feedBack.set(null); 107 } 108 } 109 110 private static void invoke(DistributedMethodCall dmc) throws IllegalArgumentException , IllegalAccessException , 111 InvocationTargetException { 112 final ClassLoader origContextLoader = Thread.currentThread().getContextClassLoader(); 113 Method m = getMethod(dmc); 114 m.setAccessible(true); 115 try { 116 Thread.currentThread().setContextClassLoader(dmc.getReceiver().getClass().getClassLoader()); 117 m.invoke(dmc.getReceiver(), dmc.getParameters()); 118 } finally { 119 Thread.currentThread().setContextClassLoader(origContextLoader); 120 } 121 } 122 123 private static Method getMethod(DistributedMethodCall dmc) { 124 String methodName = dmc.getMethodName(); 125 String paramDesc = dmc.getParameterDesc(); 126 127 Class c = dmc.getReceiver().getClass(); 128 129 while (c != null) { 130 Method [] methods = c.getDeclaredMethods(); 131 for (int i = 0; i < methods.length; i++) { 132 Method m = methods[i]; 133 if (!m.getName().equals(methodName)) { 134 continue; 135 } 136 Class [] argTypes = m.getParameterTypes(); 137 StringBuffer signature = new StringBuffer ("("); 138 for (int j = 0; j < argTypes.length; j++) { 139 signature.append(Type.getDescriptor(argTypes[j])); 140 } 141 signature.append(")"); 142 signature.append(Type.getDescriptor(m.getReturnType())); 143 if (signature.toString().equals(paramDesc)) { return m; } 144 } 145 146 c = c.getSuperclass(); 147 } 148 throw new RuntimeException ("Method " + methodName + paramDesc + " does not exist on this object: " 149 + dmc.getReceiver()); 150 } 151 152 private static void checkClassAvailability(ClassProvider classProvider, DmiClassSpec[] classSpecs) 153 throws ClassNotFoundException { 154 Assert.pre(classSpecs != null); 155 for (int i = 0; i < classSpecs.length; i++) { 156 DmiClassSpec s = classSpecs[i]; 157 classProvider.getClassFor(s.getClassName(), s.getClassLoaderDesc()); 158 } 159 } 160 161 private static DmiClassSpec[] getClassSpecs(ClassProvider classProvider, Object receiver, Object [] params) { 162 Assert.pre(classProvider != null); 163 Assert.pre(receiver != null); 164 Assert.pre(params != null); 165 166 Set set = new HashSet (); 167 set.add(getClassSpec(classProvider, receiver)); 168 for (int i = 0; i < params.length; i++) { 169 final Object p = params[i]; 170 if (p != null) set.add(getClassSpec(classProvider, p)); 171 } 172 DmiClassSpec[] rv = new DmiClassSpec[set.size()]; 173 set.toArray(rv); 174 return rv; 175 } 176 177 private static Object getClassSpec(ClassProvider classProvider, Object obj) { 178 Assert.pre(classProvider != null); 179 Assert.pre(obj != null); 180 final String classLoader = classProvider.getLoaderDescriptionFor(obj.getClass()); 181 final String className = obj.getClass().getName(); 182 return new DmiClassSpec(classLoader, className); 183 } 184 185 } 186 | Popular Tags |