1 17 package org.apache.geronimo.kernel.basic; 18 19 import net.sf.cglib.asm.Type; 20 import net.sf.cglib.core.Signature; 21 import net.sf.cglib.proxy.MethodInterceptor; 22 import net.sf.cglib.proxy.MethodProxy; 23 import net.sf.cglib.reflect.FastClass; 24 import org.apache.geronimo.gbean.AbstractName; 25 import org.apache.geronimo.gbean.GAttributeInfo; 26 import org.apache.geronimo.gbean.GBeanData; 27 import org.apache.geronimo.gbean.GBeanInfo; 28 import org.apache.geronimo.gbean.GOperationInfo; 29 import org.apache.geronimo.gbean.GOperationSignature; 30 import org.apache.geronimo.gbean.runtime.GBeanInstance; 31 import org.apache.geronimo.gbean.runtime.RawInvoker; 32 import org.apache.geronimo.kernel.Kernel; 33 import org.apache.geronimo.kernel.management.State; 34 import org.apache.geronimo.kernel.proxy.DeadProxyException; 35 import org.apache.geronimo.kernel.proxy.GeronimoManagedBean; 36 37 import java.beans.Introspector ; 38 import java.lang.reflect.Method ; 39 import java.util.HashSet ; 40 import java.util.Iterator ; 41 import java.util.Map ; 42 import java.util.Set ; 43 44 47 public class ProxyMethodInterceptor implements MethodInterceptor { 48 51 private final Class proxyType; 52 53 56 private final AbstractName abstractName; 57 58 61 private ProxyInvoker[] gbeanInvokers; 62 63 public ProxyMethodInterceptor(Class proxyType, Kernel kernel, AbstractName abstractName) { 64 assert proxyType != null; 65 assert kernel != null; 66 assert abstractName != null; 67 68 this.proxyType = proxyType; 69 this.abstractName = abstractName; 70 gbeanInvokers = createGBeanInvokers(kernel, abstractName); 71 } 72 73 public synchronized void destroy() { 74 gbeanInvokers = null; 75 } 76 77 public AbstractName getAbstractName() { 78 return abstractName; 79 } 80 81 public final Object intercept(final Object object, final Method method, final Object [] args, final MethodProxy proxy) throws Throwable { 82 ProxyInvoker gbeanInvoker; 83 84 int interfaceIndex = proxy.getSuperIndex(); 85 synchronized (this) { 86 if (gbeanInvokers == null) { 87 throw new DeadProxyException("Proxy is no longer valid"); 88 } 89 gbeanInvoker = gbeanInvokers[interfaceIndex]; 90 } 91 92 if (gbeanInvoker == null) { 93 throw new UnsupportedOperationException ("No implementation method: objectName=" + abstractName + ", method=" + method); 94 } 95 96 return gbeanInvoker.invoke(abstractName, args); 97 } 98 99 private ProxyInvoker[] createGBeanInvokers(Kernel kernel, AbstractName abstractName) { 100 ProxyInvoker[] invokers; 101 try { 102 RawInvoker rawInvoker = (RawInvoker) kernel.getAttribute(abstractName, GBeanInstance.RAW_INVOKER); 103 invokers = createRawGBeanInvokers(rawInvoker, proxyType); 104 } catch (Exception e) { 105 invokers = createKernelGBeanInvokers(kernel, abstractName, proxyType); 106 } 107 108 try { 110 invokers[getSuperIndex(proxyType, proxyType.getMethod("equals", new Class []{Object .class}))] = new EqualsInvoke(kernel); 111 invokers[getSuperIndex(proxyType, proxyType.getMethod("hashCode", null))] = new HashCodeInvoke(); 112 invokers[getSuperIndex(proxyType, proxyType.getMethod("toString", null))] = new ToStringInvoke(proxyType.getName()); 113 if(GeronimoManagedBean.class.isAssignableFrom(proxyType)) { 114 invokers[getSuperIndex(proxyType, proxyType.getMethod("getState", null))] = new GetStateInvoke(kernel); 115 invokers[getSuperIndex(proxyType, proxyType.getMethod("getStateInstance", null))] = new GetStateInstanceInvoke(kernel); 116 invokers[getSuperIndex(proxyType, proxyType.getMethod("start", null))] = new StartInvoke(kernel); 117 invokers[getSuperIndex(proxyType, proxyType.getMethod("startRecursive", null))] = new StartRecursiveInvoke(kernel); 118 invokers[getSuperIndex(proxyType, proxyType.getMethod("stop", null))] = new StopInvoke(kernel); 119 invokers[getSuperIndex(proxyType, proxyType.getMethod("getStartTime", null))] = new GetStartTimeInvoke(kernel); 120 invokers[getSuperIndex(proxyType, proxyType.getMethod("getObjectName", null))] = new GetObjectNameInvoke(kernel); 121 } 122 } catch (Exception e) { 123 throw new AssertionError (new Exception ("Could not install invoker for proxyType " + proxyType + " for target " + abstractName, e)); 125 } 126 127 return invokers; 128 } 129 130 private ProxyInvoker[] createRawGBeanInvokers(RawInvoker rawInvoker, Class proxyType) { 131 Map operations = rawInvoker.getOperationIndex(); 132 Map attributes = rawInvoker.getAttributeIndex(); 133 134 FastClass fastClass = FastClass.create(proxyType); 136 ProxyInvoker[] invokers = new ProxyInvoker[fastClass.getMaxIndex() + 1]; 137 Method [] methods = proxyType.getMethods(); 138 for (int i = 0; i < methods.length; i++) { 139 Method method = methods[i]; 140 int interfaceIndex = getSuperIndex(proxyType, method); 141 if (interfaceIndex >= 0) { 142 invokers[interfaceIndex] = createRawGBeanInvoker(rawInvoker, method, operations, attributes); 143 } 144 } 145 146 return invokers; 147 } 148 149 private ProxyInvoker createRawGBeanInvoker(RawInvoker rawInvoker, Method method, Map operations, Map attributes) { 150 if (operations.containsKey(new GOperationSignature(method))) { 151 int methodIndex = ((Integer ) operations.get(new GOperationSignature(method))).intValue(); 152 return new RawOperationInvoker(rawInvoker, methodIndex); 153 } 154 155 if (method.getName().startsWith("get")) { 156 String attributeName = method.getName().substring(3); 157 Integer methodIndex = ((Integer ) attributes.get(attributeName)); 158 if (methodIndex != null) { 159 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue()); 160 } 161 methodIndex = getMethodIndex(attributes, attributeName); 162 if (methodIndex != null) { 163 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue()); 164 } 165 } 166 167 if (method.getName().startsWith("is")) { 168 String attributeName = method.getName().substring(2); 169 Integer methodIndex = ((Integer ) attributes.get(attributeName)); 170 if (methodIndex != null) { 171 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue()); 172 } 173 methodIndex = getMethodIndex(attributes, attributeName); 174 if (methodIndex != null) { 175 return new RawGetAttributeInvoker(rawInvoker, methodIndex.intValue()); 176 } 177 } 178 179 if (method.getName().startsWith("set")) { 180 String attributeName = method.getName().substring(3); 181 Integer methodIndex = ((Integer ) attributes.get(attributeName)); 182 if (methodIndex != null) { 183 return new RawSetAttributeInvoker(rawInvoker, methodIndex.intValue()); 184 } 185 methodIndex = getMethodIndex(attributes, attributeName); 186 if (methodIndex != null) { 187 return new RawSetAttributeInvoker(rawInvoker, methodIndex.intValue()); 188 } 189 } 190 return null; 191 } 192 193 private ProxyInvoker[] createKernelGBeanInvokers(Kernel kernel, AbstractName abstractName, Class proxyType) { 194 GBeanInfo info; 195 try { 196 info = kernel.getGBeanInfo(abstractName); 197 } catch (Exception e) { 198 throw new IllegalArgumentException ("Could not get GBeanInfo for target object: " + abstractName); 199 } 200 201 Set attributeInfos = info.getAttributes(); 203 Set attributeNames = new HashSet (attributeInfos.size()); 204 for (Iterator iterator = attributeInfos.iterator(); iterator.hasNext();) { 205 GAttributeInfo attributeInfo = (GAttributeInfo) iterator.next(); 206 attributeNames.add(attributeInfo.getName()); 207 } 208 209 Set operationInfos = info.getOperations(); 211 Set operationSignatures = new HashSet (operationInfos.size()); 212 for (Iterator iterator = operationInfos.iterator(); iterator.hasNext();) { 213 GOperationInfo operationInfo = (GOperationInfo) iterator.next(); 214 operationSignatures.add(new GOperationSignature(operationInfo.getName(), operationInfo.getParameterList())); 215 } 216 217 FastClass fastClass = FastClass.create(proxyType); 219 ProxyInvoker[] invokers = new ProxyInvoker[fastClass.getMaxIndex() + 1]; 220 Method [] methods = proxyType.getMethods(); 221 for (int i = 0; i < methods.length; i++) { 222 Method method = methods[i]; 223 int interfaceIndex = getSuperIndex(proxyType, method); 224 if (interfaceIndex >= 0) { 225 invokers[interfaceIndex] = createJMXGBeanInvoker(kernel, method, operationSignatures, attributeNames); 226 } 227 } 228 229 return invokers; 230 } 231 232 private ProxyInvoker createJMXGBeanInvoker(Kernel kernel, Method method, Set operationSignatures, Set attributeNames) { 233 if (operationSignatures.contains(new GOperationSignature(method))) { 234 return new KernelOperationInvoker(kernel, method); 235 } 236 237 String name = method.getName(); 238 if (name.startsWith("get")) { 239 String attributeName = method.getName().substring(3); 240 if (attributeNames.contains(attributeName)) { 241 return new KernelGetAttributeInvoker(kernel, attributeName); 242 } 243 attributeName = Introspector.decapitalize(attributeName); 244 if (attributeNames.contains(attributeName)) { 245 return new KernelGetAttributeInvoker(kernel, attributeName); 246 } 247 } else if (name.startsWith("is")) { 248 String attrName = method.getName().substring(2); 249 if (attributeNames.contains(attrName)) { 250 return new KernelGetAttributeInvoker(kernel, attrName); 251 } 252 attrName = Introspector.decapitalize(attrName); 253 if (attributeNames.contains(attrName)) { 254 return new KernelGetAttributeInvoker(kernel, attrName); 255 } 256 } else if (name.startsWith("set")) { 257 String attrName = method.getName().substring(3); 258 if (attributeNames.contains(attrName)) { 259 return new KernelSetAttributeInvoker(kernel, attrName); 260 } 261 attrName = Introspector.decapitalize(attrName); 262 if (attributeNames.contains(attrName)) { 263 return new KernelSetAttributeInvoker(kernel, attrName); 264 } 265 } 266 return null; 267 } 268 269 private static int getSuperIndex(Class proxyType, Method method) { 270 Signature signature = new Signature(method.getName(), Type.getReturnType(method), Type.getArgumentTypes(method)); 271 MethodProxy methodProxy = MethodProxy.find(proxyType, signature); 272 if (methodProxy != null) { 273 return methodProxy.getSuperIndex(); 274 } 275 return -1; 276 } 277 278 private static Integer getMethodIndex(Map attributes, String attributeName) { 279 Iterator iter = attributes.keySet().iterator(); 280 while (iter.hasNext()) { 281 String key = (String ) iter.next(); 282 if (key.equalsIgnoreCase(attributeName)) { 283 return (Integer ) attributes.get(key); 284 } 285 } 286 return null; 287 } 288 289 static final class HashCodeInvoke implements ProxyInvoker { 290 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 291 return new Integer (abstractName.hashCode()); 292 } 293 } 294 295 static final class EqualsInvoke implements ProxyInvoker { 296 private final Kernel kernel; 297 298 public EqualsInvoke(Kernel kernel) { 299 this.kernel = kernel; 300 } 301 302 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 303 AbstractName proxyTarget = kernel.getAbstractNameFor(arguments[0]); 304 return Boolean.valueOf(abstractName.equals(proxyTarget)); 305 } 306 } 307 308 static final class ToStringInvoke implements ProxyInvoker { 309 private final String interfaceName; 310 311 public ToStringInvoke(String interfaceName) { 312 this.interfaceName = "[" + interfaceName + ": "; 313 } 314 315 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 316 return interfaceName + abstractName + "]"; 317 } 318 } 319 320 static final class GetStateInvoke implements ProxyInvoker { 321 private Kernel kernel; 322 323 public GetStateInvoke(Kernel kernel) { 324 this.kernel = kernel; 325 } 326 327 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 328 return new Integer (kernel.getGBeanState(abstractName)); 329 } 330 } 331 332 static final class GetStateInstanceInvoke implements ProxyInvoker { 333 private Kernel kernel; 334 335 public GetStateInstanceInvoke(Kernel kernel) { 336 this.kernel = kernel; 337 } 338 339 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 340 return State.fromInt(kernel.getGBeanState(abstractName)); 341 } 342 } 343 344 static final class StartInvoke implements ProxyInvoker { 345 private Kernel kernel; 346 347 public StartInvoke(Kernel kernel) { 348 this.kernel = kernel; 349 } 350 351 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 352 kernel.startGBean(abstractName); 353 return null; 354 } 355 } 356 357 static final class StartRecursiveInvoke implements ProxyInvoker { 358 private Kernel kernel; 359 360 public StartRecursiveInvoke(Kernel kernel) { 361 this.kernel = kernel; 362 } 363 364 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 365 kernel.startRecursiveGBean(abstractName); 366 return null; 367 } 368 } 369 370 static final class GetStartTimeInvoke implements ProxyInvoker { 371 private Kernel kernel; 372 373 public GetStartTimeInvoke(Kernel kernel) { 374 this.kernel = kernel; 375 } 376 377 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 378 return new Long (kernel.getGBeanStartTime(abstractName)); 379 } 380 } 381 382 static final class StopInvoke implements ProxyInvoker { 383 private Kernel kernel; 384 385 public StopInvoke(Kernel kernel) { 386 this.kernel = kernel; 387 } 388 389 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 390 kernel.stopGBean(abstractName); 391 return null; 392 } 393 } 394 395 static final class GetObjectNameInvoke implements ProxyInvoker { 396 private Kernel kernel; 397 398 public GetObjectNameInvoke(Kernel kernel) { 399 this.kernel = kernel; 400 } 401 402 public Object invoke(AbstractName abstractName, Object [] arguments) throws Throwable { 403 GBeanData gBeanData = kernel.getGBeanData(abstractName); 404 return gBeanData.getAbstractName().getObjectName().getCanonicalName(); 405 } 406 } 407 } 408 | Popular Tags |