1 23 24 30 package com.sun.ejb.containers.interceptors; 31 32 import com.sun.ejb.EJBUtils; 33 import com.sun.ejb.Invocation; 34 import com.sun.ejb.Invocation.InterceptorChain; 35 import com.sun.ejb.containers.BaseContainer; 36 import com.sun.ejb.containers.EJBContextImpl; 37 38 import com.sun.enterprise.deployment.EjbDescriptor; 39 import com.sun.enterprise.deployment.EjbInterceptor; 40 import com.sun.enterprise.deployment.MethodDescriptor; 41 import com.sun.enterprise.deployment.LifecycleCallbackDescriptor; 42 import static com.sun.enterprise.deployment.LifecycleCallbackDescriptor.CallbackType; 43 import com.sun.enterprise.deployment.EjbSessionDescriptor; 44 45 import java.io.Serializable ; 46 import java.lang.reflect.Method ; 47 48 import java.util.*; 49 import java.util.logging.Level ; 50 import java.util.logging.Logger ; 51 52 import javax.interceptor.InvocationContext; 53 54 55 61 public class InterceptorManager { 62 63 private BaseContainer container; 64 65 private EjbDescriptor ejbDesc; 66 67 private ClassLoader loader; 68 69 private Class beanClass; 70 71 private String beanClassName; 72 73 private Logger _logger; 74 75 private Class [] interceptorClasses; 76 77 private Class [] serializableInterceptorClasses; 78 79 private Map<String , Integer > instanceIndexMap 80 = new HashMap<String , Integer >(); 81 82 private boolean methodInterceptorsExists; 83 84 private String [] pre30LCMethodNames; 85 86 private Class [] lcAnnotationClasses; 87 88 private CallbackChainImpl[] callbackChain; 89 90 91 public InterceptorManager(Logger _logger, BaseContainer container, 92 Class [] lcAnnotationClasses, String [] pre30LCMethodNames) 93 throws Exception { 94 this._logger = _logger; 95 this.container = container; 96 this.lcAnnotationClasses = lcAnnotationClasses; 97 this.pre30LCMethodNames = pre30LCMethodNames; 98 99 ejbDesc = container.getEjbDescriptor(); 100 loader = container.getClassLoader(); 101 beanClassName = ejbDesc.getEjbImplClassName(); 102 103 this.beanClass = loader.loadClass(beanClassName); 104 buildInterceptorChain(); 105 if (_logger.isLoggable(Level.FINE)) { 106 _logger.log(Level.FINE, "InterceptorManager: " + toString()); 107 } 108 } 109 110 public Object [] createInterceptorInstances() { 111 int size = serializableInterceptorClasses.length; 112 Object [] interceptors = new Object [size]; 113 for (int index = 0; index < size; index++) { 114 Class clazz = serializableInterceptorClasses[index]; 115 try { 116 interceptors[index] = clazz.newInstance(); 117 } catch (IllegalAccessException illEx) { 118 throw new RuntimeException (illEx); 119 } catch (InstantiationException instEx) { 120 throw new RuntimeException (instEx); 121 } 122 } 123 124 return interceptors; 125 } 126 127 public InterceptorChain getAroundInvokeChain(MethodDescriptor mDesc, Method beanMethod) { 128 List<EjbInterceptor> list = ejbDesc.getAroundInvokeInterceptors(mDesc); 129 ArrayList<AroundInvokeInterceptor> interceptors = 130 new ArrayList<AroundInvokeInterceptor>(); 131 for (EjbInterceptor interceptor : list) { 132 String className = interceptor.getInterceptorClassName(); 133 Set<LifecycleCallbackDescriptor> aroundInvokeDescs = 134 interceptor.getAroundInvokeDescriptors(); 135 if(aroundInvokeDescs.isEmpty() ) { 136 continue; 137 } 138 139 List<LifecycleCallbackDescriptor> orderedAIInterceptors = 140 new ArrayList<LifecycleCallbackDescriptor>(); 141 try { 142 orderedAIInterceptors = interceptor.getOrderedAroundInvokeDescriptors(loader); 143 } catch (Exception e) { 144 throw new IllegalStateException ("No AroundInvokeIntercetpors found " 145 + " on class " + className, e); 146 } 147 148 Iterator<LifecycleCallbackDescriptor> aiIterator = orderedAIInterceptors.iterator(); 149 while (aiIterator.hasNext()) { 150 LifecycleCallbackDescriptor aroundInvokeDesc = aiIterator.next(); 151 152 Method method = null; 153 try { 154 method = aroundInvokeDesc.getLifecycleCallbackMethodObject(loader); 155 } catch(Exception e) { 156 throw new IllegalStateException ("No callback method of name " + 157 aroundInvokeDesc.getLifecycleCallbackMethod() 158 + " found on class " + className, e); 159 } 160 161 if (interceptor.getFromBeanClass()) { 162 interceptors.add(new BeanAroundInvokeInterceptor(method)); 163 } else { 164 Integer bigInt = instanceIndexMap.get(className); 165 int index = (bigInt == null) ? -1 : bigInt; 166 if (index == -1) { 167 throw new IllegalStateException (getInternalErrorString(className)); 168 } 169 Class clazz = interceptorClasses[index]; 170 _logger.log(Level.FINE, "*[md.getDeclaredMethod() => " 171 + method + " FOR CLAZZ: " + clazz); 172 interceptors.add(new AroundInvokeInterceptor(index, method)); 173 } 174 } 175 } 176 177 AroundInvokeInterceptor[] inter = interceptors.toArray( 178 new AroundInvokeInterceptor[interceptors.size()]); 179 return new AroundInvokeChainImpl(container, inter); 180 } 181 182 public boolean hasInterceptors() { 183 return this.methodInterceptorsExists; 184 } 185 186 public Object intercept(Invocation inv) 187 throws Throwable { 188 return inv.getInterceptorChain().invokeNext(0, inv); 189 } 190 191 public boolean intercept(CallbackType eventType, EJBContextImpl ctx) 192 throws Throwable { 193 194 CallbackChainImpl chain = null; 195 switch (eventType) { 196 case POST_CONSTRUCT: 197 case PRE_PASSIVATE: 198 case POST_ACTIVATE: 199 case PRE_DESTROY: 200 chain = callbackChain[eventType.ordinal()]; 201 CallbackInvocationContext invContext = new 202 CallbackInvocationContext(ctx, chain); 203 if (chain != null) { 204 chain.invokeNext(0, invContext); 205 } 206 break; 207 default: 208 throw new IllegalStateException ("Invalid event type"); 209 } 210 211 return true; 212 } 213 214 private void buildInterceptorChain() 215 throws ClassNotFoundException , Exception { 216 initInterceptorClassNames(); 217 initCallbackIndices(); 218 } 219 220 private void initInterceptorClassNames() 221 throws ClassNotFoundException , Exception { 222 Set<String > interceptorClassNames = ejbDesc.getInterceptorClassNames(); 223 int size = interceptorClassNames.size(); 224 interceptorClasses = new Class [size]; 225 serializableInterceptorClasses = new Class [size]; 226 int index = 0; 227 for (String className : interceptorClassNames) { 228 Class interClass = loader.loadClass(className); 229 interceptorClasses[index] = interClass; 230 serializableInterceptorClasses[index] = interClass; 231 instanceIndexMap.put(className, index); 232 if (!Serializable .class.isAssignableFrom(interClass)) { 233 serializableInterceptorClasses[index] = 234 EJBUtils.loadGeneratedSerializableClass(loader, className); 235 } 236 index++; 237 } 238 methodInterceptorsExists = interceptorClassNames.size() > 0; 239 240 if (ejbDesc.hasAroundInvokeMethod()) { 241 methodInterceptorsExists = true; 242 } 243 instanceIndexMap.put(beanClassName, index++); 244 } 245 246 private void initCallbackIndices() 247 throws ClassNotFoundException , Exception { 248 249 int size = CallbackType.values().length; 250 ArrayList[] callbacks = new ArrayList[size]; 251 boolean scanFor2xLifecycleMethods = true; 252 253 for (CallbackType eventType : CallbackType.values()) { 254 int index = eventType.ordinal(); 255 callbacks[index] = new ArrayList<CallbackInterceptor>(); 256 boolean scanForCallbacks = true; 257 if (! (ejbDesc instanceof EjbSessionDescriptor)) { 258 if ((eventType == CallbackType.PRE_PASSIVATE) || 259 (eventType == CallbackType.POST_ACTIVATE)) { 260 scanForCallbacks = false; 261 } 262 } 263 264 if (scanForCallbacks) { 265 List<EjbInterceptor> callbackList = ejbDesc.getCallbackInterceptors(eventType); 266 for (EjbInterceptor callback : callbackList) { 267 List<CallbackInterceptor> inters = createCallbackInterceptors(eventType, callback); 268 for (CallbackInterceptor inter : inters) { 269 callbacks[index].add(inter); 270 } 271 } 272 } 273 274 if (callbacks[index].size() > 0) { 275 scanFor2xLifecycleMethods = false; 276 } 277 } 278 279 if (scanFor2xLifecycleMethods) { 280 load2xLifecycleMethods(callbacks); 281 } 282 283 callbackChain = new CallbackChainImpl[size]; 284 for (CallbackType eventType : CallbackType.values()) { 285 int index = eventType.ordinal(); 286 CallbackInterceptor[] interceptors = (CallbackInterceptor[]) 287 callbacks[index].toArray(new CallbackInterceptor[callbacks[index].size()]); 288 callbackChain[index] = new CallbackChainImpl(container, interceptors); 289 } 290 291 } 292 293 private List<CallbackInterceptor> createCallbackInterceptors(CallbackType eventType, 294 EjbInterceptor inter) throws Exception { 295 List<CallbackInterceptor> callbackList = new ArrayList<CallbackInterceptor>(); 296 297 List<LifecycleCallbackDescriptor> orderedCallbackMethods = 298 inter.getOrderedCallbackDescriptors(eventType, loader); 299 300 String className = inter.getInterceptorClassName(); 301 302 303 for (LifecycleCallbackDescriptor callbackDesc : orderedCallbackMethods) { 304 Method method = null; 305 try { 306 method = callbackDesc.getLifecycleCallbackMethodObject(loader); 307 } catch(Exception e) { 308 throw new IllegalStateException ("No callback method of name " + 309 callbackDesc.getLifecycleCallbackMethod() 310 + " found on class " + className, e); 311 } 312 313 314 CallbackInterceptor interceptor = null; 315 if (inter.getFromBeanClass()) { 316 interceptor = new BeanCallbackInterceptor(method); 317 } else { 318 Integer bigInt = instanceIndexMap.get(className); 319 int index = (bigInt == null) ? -1 : bigInt; 320 if (index == -1) { 321 throw new IllegalStateException (getInternalErrorString(className)); 322 } 323 interceptor = new CallbackInterceptor(index, method); 324 } 325 callbackList.add(interceptor); 326 } 327 return callbackList; 328 } 329 330 331 private void load2xLifecycleMethods(ArrayList<CallbackInterceptor>[] metaArray) { 332 333 if (javax.ejb.EnterpriseBean .class.isAssignableFrom(beanClass)) { 334 int sz = lcAnnotationClasses.length; 335 for (int i = 0; i < sz; i++) { 336 if (pre30LCMethodNames[i] == null) { 337 continue; 338 } 339 try { 340 Method method = beanClass.getMethod( 341 pre30LCMethodNames[i], (Class []) null); 342 if (method != null) { 343 CallbackInterceptor meta = 344 new BeanCallbackInterceptor(method); 345 metaArray[i].add(meta); 346 _logger.log(Level.FINE, "**## bean has 2.x LM: " + meta); 347 } 348 } catch (NoSuchMethodException nsmEx) { 349 } 352 } 353 } 354 } 355 356 public String toString() { 357 StringBuilder sbldr = new StringBuilder (); 358 sbldr.append("##########################################################\n"); 359 sbldr.append("InterceptorManager<").append(beanClassName).append("> has ") 360 .append(interceptorClasses.length).append(" interceptors"); 361 sbldr.append("\n\tbeanClassName: ").append(beanClassName); 362 sbldr.append("\n\tInterceptors: "); 363 for (Class clazz : interceptorClasses) { 364 sbldr.append("\n\t\t").append(clazz.getName()); 365 } 366 sbldr.append("\n\tCallback Interceptors: "); 367 for (int i = 0; i < lcAnnotationClasses.length; i++) { 368 CallbackChainImpl chain = callbackChain[i]; 369 sbldr.append("\n\t").append(i) 370 .append(": ").append(lcAnnotationClasses[i]); 371 sbldr.append("\n\t\t").append(chain.toString()); 372 } 373 sbldr.append("\n"); 374 sbldr.append("##########################################################\n"); 375 return sbldr.toString(); 376 } 377 378 private String getInternalErrorString(String className) { 379 StringBuilder sbldr = new StringBuilder ("Internal error: "); 380 sbldr.append(" className: ").append(className) 381 .append(" is neither a bean class (") 382 .append(beanClassName).append(") nor an ") 383 .append("interceptor class ("); 384 for (Class cn : interceptorClasses) { 385 sbldr.append(cn.getName()).append("; "); 386 } 387 sbldr.append(")"); 388 _logger.log(Level.INFO, "++ : " + sbldr.toString()); 389 return sbldr.toString(); 390 } 391 392 } 393 394 class AroundInvokeChainImpl 395 implements InterceptorChain { 396 enum ChainType { 397 METHOD, CALLBACK} 398 399 ; 400 401 protected BaseContainer container; 402 protected AroundInvokeInterceptor[] interceptors; 403 protected int size; 404 405 protected AroundInvokeChainImpl(BaseContainer container, 406 AroundInvokeInterceptor[] interceptors) { 407 this.container = container; 408 this.interceptors = interceptors; 409 this.size = (interceptors == null) ? 0 : interceptors.length; 410 } 411 412 public Object invokeNext(int index, Invocation inv) 413 throws Throwable { 414 return (index < size) 415 ? interceptors[index].intercept(inv) 416 : container.invokeBeanMethod(inv); 417 } 418 419 public String toString() { 420 StringBuilder bldr = new StringBuilder (); 421 for (AroundInvokeInterceptor inter : interceptors) { 422 bldr.append("\n\t").append(inter); 423 } 424 425 return bldr.toString(); 426 } 427 } 428 429 class CallbackChainImpl { 430 431 protected BaseContainer container; 432 protected CallbackInterceptor[] interceptors; 433 protected int size; 434 435 CallbackChainImpl(BaseContainer container, 436 CallbackInterceptor[] interceptors) { 437 this.container = container; 438 this.interceptors = interceptors; 439 this.size = (interceptors == null) ? 0 : interceptors.length; 440 } 441 442 public Object invokeNext(int index, CallbackInvocationContext invContext) 443 throws Throwable { 444 445 Object result = null; 446 447 if (index < size) { 448 result = interceptors[index].intercept(invContext); 449 } 450 451 return result; 452 } 453 454 public String toString() { 455 StringBuilder bldr = new StringBuilder ("CallbackInterceptorChainImpl"); 456 for (CallbackInterceptor inter : interceptors) { 457 bldr.append("\n\t\t").append(inter); 458 } 459 460 return bldr.toString(); 461 } 462 } 463 464 class AroundInvokeInterceptor { 465 protected int index; 466 protected Method method; 467 468 AroundInvokeInterceptor(int index, Method method) { 469 this.index = index; 470 this.method = method; 471 } 472 473 Object intercept(final Invocation invCtx) throws Throwable { 474 try { 475 final Object [] interceptors = ((EJBContextImpl) invCtx.context) 476 .getInterceptorInstances(); 477 return java.security.AccessController 480 .doPrivileged(new java.security.PrivilegedExceptionAction () { 481 public java.lang.Object run() throws Exception { 482 if (!method.isAccessible()) { 483 method.setAccessible(true); 484 } 485 return method.invoke(interceptors[index], invCtx); 486 } 487 }); 488 } catch (java.lang.reflect.InvocationTargetException invEx) { 489 throw invEx.getCause(); 490 } catch (java.security.PrivilegedActionException paEx) { 491 Throwable th = paEx.getCause(); 492 if (th.getCause() != null) { 493 throw th.getCause(); 494 } 495 throw th; 496 } 497 } 498 499 public String toString() { 500 return "[" + index + "]: " + method; 501 } 502 503 } 504 505 class BeanAroundInvokeInterceptor 506 extends AroundInvokeInterceptor { 507 private static final Object [] NULL_ARGS = null; 508 509 BeanAroundInvokeInterceptor(Method method) { 510 super(-1, method); 511 } 512 513 Object intercept(final Invocation invCtx) throws Throwable { 514 try { 515 return java.security.AccessController 518 .doPrivileged(new java.security.PrivilegedExceptionAction () { 519 public java.lang.Object run() throws Exception { 520 if (!method.isAccessible()) { 521 method.setAccessible(true); 522 } 523 return method.invoke(invCtx.getTarget(), invCtx); 524 } 525 }); 526 } catch (java.lang.reflect.InvocationTargetException invEx) { 527 throw invEx.getCause(); 528 } catch (java.security.PrivilegedActionException paEx) { 529 Throwable th = paEx.getCause(); 530 if (th.getCause() != null) { 531 throw th.getCause(); 532 } 533 throw th; 534 } 535 } 536 } 537 538 class CallbackInterceptor { 539 protected int index; 540 protected Method method; 541 542 CallbackInterceptor(int index, Method method) { 543 this.index = index; 544 this.method = method; 545 } 546 547 Object intercept(final CallbackInvocationContext invContext) 548 throws Throwable { 549 try { 550 EJBContextImpl ejbContextImpl = (EJBContextImpl) 551 invContext.getEJBContext(); 552 final Object [] interceptors = ejbContextImpl 553 .getInterceptorInstances(); 554 return java.security.AccessController 557 .doPrivileged(new java.security.PrivilegedExceptionAction () { 558 public java.lang.Object run() throws Exception { 559 if (!method.isAccessible()) { 560 method.setAccessible(true); 561 } 562 return method.invoke(interceptors[index], 563 invContext); 564 } 565 }); 566 } catch (java.lang.reflect.InvocationTargetException invEx) { 567 throw invEx.getCause(); 568 } catch (java.security.PrivilegedActionException paEx) { 569 Throwable th = paEx.getCause(); 570 if (th.getCause() != null) { 571 throw th.getCause(); 572 } 573 throw th; 574 } 575 } 576 577 public String toString() { 578 return "callback[" + index + "]: " + method; 579 } 580 } 581 582 class BeanCallbackInterceptor 583 extends CallbackInterceptor { 584 private static final Object [] NULL_ARGS = null; 585 586 BeanCallbackInterceptor(Method method) { 587 super(-1, method); 588 } 589 590 Object intercept(final CallbackInvocationContext invContext) 591 throws Throwable { 592 try { 593 return java.security.AccessController 596 .doPrivileged(new java.security.PrivilegedExceptionAction () { 597 public java.lang.Object run() throws Exception { 598 if (!method.isAccessible()) { 599 method.setAccessible(true); 600 } 601 method.invoke(invContext.getTarget(), 602 NULL_ARGS); 603 return invContext.proceed(); 604 } 605 }); 606 } catch (java.lang.reflect.InvocationTargetException invEx) { 607 throw invEx.getCause(); 608 } catch (java.security.PrivilegedActionException paEx) { 609 Throwable th = paEx.getCause(); 610 if (th.getCause() != null) { 611 throw th.getCause(); 612 } 613 throw th; 614 } 615 } 616 617 public String toString() { 618 return "beancallback[" + index + "]: " + method; 619 } 620 } 621 622 | Popular Tags |