1 22 package org.jboss.ejb.plugins.local; 23 24 import java.lang.reflect.InvocationHandler ; 25 import java.lang.reflect.Method ; 26 import java.lang.reflect.Proxy ; 27 import java.lang.reflect.Constructor ; 28 import java.rmi.AccessException ; 29 import java.rmi.NoSuchObjectException ; 30 import java.security.Principal ; 31 import java.security.PrivilegedAction ; 32 import java.security.AccessController ; 33 import java.util.ArrayList ; 34 import java.util.Collection ; 35 import java.util.Collections ; 36 import java.util.HashMap ; 37 import java.util.Iterator ; 38 import java.util.Map ; 39 import javax.ejb.AccessLocalException ; 40 import javax.ejb.EJBLocalHome ; 41 import javax.ejb.EJBLocalObject ; 42 import javax.ejb.NoSuchObjectLocalException ; 43 import javax.ejb.TransactionRequiredLocalException ; 44 import javax.ejb.TransactionRolledbackLocalException ; 45 import javax.naming.Context ; 46 import javax.naming.InitialContext ; 47 import javax.transaction.Transaction ; 48 import javax.transaction.TransactionManager ; 49 import javax.transaction.TransactionRequiredException ; 50 import javax.transaction.TransactionRolledbackException ; 51 52 import org.jboss.ejb.Container; 53 import org.jboss.ejb.EJBProxyFactoryContainer; 54 import org.jboss.ejb.LocalProxyFactory; 55 import org.jboss.invocation.InvocationType; 56 import org.jboss.invocation.MarshalledInvocation; 57 import org.jboss.invocation.LocalEJBInvocation; 58 import org.jboss.logging.Logger; 59 import org.jboss.metadata.BeanMetaData; 60 import org.jboss.naming.Util; 61 import org.jboss.security.SecurityAssociation; 62 import org.jboss.util.NestedRuntimeException; 63 import org.jboss.tm.TransactionLocal; 64 65 66 76 public class BaseLocalProxyFactory implements LocalProxyFactory 77 { 78 protected static Logger log = Logger.getLogger(BaseLocalProxyFactory.class); 80 81 84 protected static Map invokerMap = Collections.synchronizedMap(new HashMap ()); 85 86 protected Container container; 87 88 91 protected String localJndiName; 92 93 protected TransactionManager transactionManager; 94 95 protected EJBLocalHome home; 97 98 protected EJBLocalObject statelessObject; 100 101 protected Map beanMethodInvokerMap; 102 protected Map homeMethodInvokerMap; 103 protected Class localHomeClass; 104 protected Class localClass; 105 106 protected Constructor proxyClassConstructor; 107 108 private final TransactionLocal cache = new TransactionLocal() 109 { 110 protected Object initialValue() 111 { 112 return new HashMap (); 113 } 114 }; 115 116 118 120 122 124 public void setContainer(Container con) 125 { 126 this.container = con; 127 } 128 129 public void create() throws Exception 130 { 131 BeanMetaData metaData = container.getBeanMetaData(); 132 localJndiName = metaData.getLocalJndiName(); 133 } 134 135 public void start() 136 throws Exception 137 { 138 BeanMetaData metaData = container.getBeanMetaData(); 139 EJBProxyFactoryContainer invokerContainer = 140 (EJBProxyFactoryContainer) container; 141 localHomeClass = invokerContainer.getLocalHomeClass(); 142 localClass = invokerContainer.getLocalClass(); 143 if(localHomeClass == null || localClass == null) 144 { 145 log.debug(metaData.getEjbName() 146 + 147 " cannot be Bound, doesn't " + 148 "have local and local home interfaces"); 149 return; 150 } 151 152 Class [] intfs = {localClass}; 154 Class proxyClass = Proxy.getProxyClass(ClassLoaderAction.UTIL.get(localClass), intfs); 155 final Class [] constructorParams = 156 {InvocationHandler .class}; 157 158 proxyClassConstructor = proxyClass.getConstructor(constructorParams); 159 160 Context iniCtx = new InitialContext (); 161 String beanName = metaData.getEjbName(); 162 163 transactionManager = 166 (TransactionManager ) iniCtx.lookup("java:/TransactionManager"); 167 168 Method [] methods = localClass.getMethods(); 170 beanMethodInvokerMap = new HashMap (); 171 for(int i = 0; i < methods.length; i++) 172 { 173 long hash = MarshalledInvocation.calculateHash(methods[i]); 174 beanMethodInvokerMap.put(new Long (hash), methods[i]); 175 } 176 177 methods = localHomeClass.getMethods(); 178 homeMethodInvokerMap = new HashMap (); 179 for(int i = 0; i < methods.length; i++) 180 { 181 long hash = MarshalledInvocation.calculateHash(methods[i]); 182 homeMethodInvokerMap.put(new Long (hash), methods[i]); 183 } 184 185 Util.rebind(iniCtx, localJndiName, getEJBLocalHome()); 187 invokerMap.put(localJndiName, this); 188 log.info("Bound EJB LocalHome '" + beanName + "' to jndi '" + localJndiName + "'"); 189 } 190 191 public void stop() 192 { 193 try 195 { 196 if(invokerMap.remove(localJndiName) == this) 197 { 198 log.info("Unbind EJB LocalHome '" + container.getBeanMetaData().getEjbName() + "' from jndi '" + localJndiName + "'"); 199 200 InitialContext ctx = new InitialContext (); 201 ctx.unbind(localJndiName); 202 } 203 } 204 catch(Exception ignore) 205 { 206 } 207 } 208 209 public void destroy() 210 { 211 if(beanMethodInvokerMap != null) 212 { 213 beanMethodInvokerMap.clear(); 214 } 215 if(homeMethodInvokerMap != null) 216 { 217 homeMethodInvokerMap.clear(); 218 } 219 MarshalledInvocation.removeHashes(localHomeClass); 220 MarshalledInvocation.removeHashes(localClass); 221 222 container = null; 223 } 224 225 public Constructor getProxyClassConstructor() 226 { 227 if(proxyClassConstructor == null) 228 { 229 } 230 return proxyClassConstructor; 231 } 232 233 public EJBLocalHome getEJBLocalHome() 235 { 236 if(home == null) 237 { 238 EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container; 239 InvocationHandler handler = new LocalHomeProxy(localJndiName, this); 240 ClassLoader loader = ClassLoaderAction.UTIL.get(cic.getLocalHomeClass()); 241 Class [] interfaces = {cic.getLocalHomeClass()}; 242 243 home = (EJBLocalHome ) Proxy.newProxyInstance(loader, 244 interfaces, 245 handler); 246 } 247 return home; 248 } 249 250 public EJBLocalObject getStatelessSessionEJBLocalObject() 251 { 252 if(statelessObject == null) 253 { 254 EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container; 255 InvocationHandler handler = 256 new StatelessSessionProxy(localJndiName, this); 257 ClassLoader loader = ClassLoaderAction.UTIL.get(cic.getLocalClass()); 258 Class [] interfaces = {cic.getLocalClass()}; 259 260 statelessObject = (EJBLocalObject ) Proxy.newProxyInstance(loader, 261 interfaces, 262 handler); 263 } 264 return statelessObject; 265 } 266 267 public EJBLocalObject getStatefulSessionEJBLocalObject(Object id) 268 { 269 InvocationHandler handler = 270 new StatefulSessionProxy(localJndiName, id, this); 271 try 272 { 273 return (EJBLocalObject ) proxyClassConstructor.newInstance(new Object []{handler}); 274 } 275 catch(Exception ex) 276 { 277 throw new NestedRuntimeException(ex); 278 } 279 } 280 281 public Object getEntityEJBObject(Object id) 282 { 283 return getEntityEJBLocalObject(id); 284 } 285 286 public EJBLocalObject getEntityEJBLocalObject(Object id, boolean create) 287 { 288 EJBLocalObject result = null; 289 if(id != null) 290 { 291 final Transaction tx = cache.getTransaction(); 292 if(tx == null) 293 { 294 result = createEJBLocalObject(id); 295 } 296 else 297 { 298 Map map = (Map ) cache.get(tx); 299 if(create) 300 { 301 result = createEJBLocalObject(id); 302 map.put(id, result); 303 } 304 else 305 { 306 result = (EJBLocalObject ) map.get(id); 307 if(result == null) 308 { 309 result = createEJBLocalObject(id); 310 map.put(id, result); 311 } 312 } 313 } 314 } 315 return result; 316 } 317 318 public EJBLocalObject getEntityEJBLocalObject(Object id) 319 { 320 return getEntityEJBLocalObject(id, false); 321 } 322 323 public Collection getEntityLocalCollection(Collection ids) 324 { 325 ArrayList list = new ArrayList (ids.size()); 326 Iterator iter = ids.iterator(); 327 while(iter.hasNext()) 328 { 329 final Object nextId = iter.next(); 330 list.add(getEntityEJBLocalObject(nextId)); 331 } 332 return list; 333 } 334 335 338 public Object invokeHome(Method m, Object [] args) throws Exception 339 { 340 ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader(); 342 boolean setCl = !oldCl.equals(container.getClassLoader()); 343 if(setCl) 344 { 345 TCLAction.UTIL.setContextClassLoader(container.getClassLoader()); 346 } 347 348 SecurityActions sa = SecurityActions.UTIL.getSecurityActions(); 349 try 350 { 351 LocalEJBInvocation invocation = new LocalEJBInvocation(null, 352 m, 353 args, 354 getTransaction(), 355 sa.getPrincipal(), 356 sa.getCredential()); 357 invocation.setType(InvocationType.LOCALHOME); 358 359 return container.invoke(invocation); 360 } 361 catch(AccessException ae) 362 { 363 throw new AccessLocalException (ae.getMessage(), ae); 364 } 365 catch(NoSuchObjectException nsoe) 366 { 367 throw new NoSuchObjectLocalException (nsoe.getMessage(), nsoe); 368 } 369 catch(TransactionRequiredException tre) 370 { 371 throw new TransactionRequiredLocalException (tre.getMessage()); 372 } 373 catch(TransactionRolledbackException trbe) 374 { 375 throw new TransactionRolledbackLocalException (trbe.getMessage(), trbe); 376 } 377 finally 378 { 379 if(setCl) 380 { 381 TCLAction.UTIL.setContextClassLoader(oldCl); 382 } 383 } 384 } 385 386 public String getJndiName() 387 { 388 return localJndiName; 389 } 390 391 396 Transaction getTransaction() throws javax.transaction.SystemException 397 { 398 if(transactionManager == null) 399 { 400 return null; 401 } 402 return transactionManager.getTransaction(); 403 } 404 405 408 public Object invoke(Object id, Method m, Object [] args) 409 throws Exception 410 { 411 ClassLoader oldCl = TCLAction.UTIL.getContextClassLoader(); 413 boolean setCl = !oldCl.equals(container.getClassLoader()); 414 if(setCl) 415 { 416 TCLAction.UTIL.setContextClassLoader(container.getClassLoader()); 417 } 418 419 SecurityActions sa = SecurityActions.UTIL.getSecurityActions(); 420 try 421 { 422 LocalEJBInvocation invocation = new LocalEJBInvocation(id, 423 m, 424 args, 425 getTransaction(), 426 sa.getPrincipal(), 427 sa.getCredential()); 428 invocation.setType(InvocationType.LOCAL); 429 430 return container.invoke(invocation); 431 } 432 catch(AccessException ae) 433 { 434 throw new AccessLocalException (ae.getMessage(), ae); 435 } 436 catch(NoSuchObjectException nsoe) 437 { 438 throw new NoSuchObjectLocalException (nsoe.getMessage(), nsoe); 439 } 440 catch(TransactionRequiredException tre) 441 { 442 throw new TransactionRequiredLocalException (tre.getMessage()); 443 } 444 catch(TransactionRolledbackException trbe) 445 { 446 throw new TransactionRolledbackLocalException (trbe.getMessage(), trbe); 447 } 448 finally 449 { 450 if(setCl) 451 { 452 TCLAction.UTIL.setContextClassLoader(oldCl); 453 } 454 } 455 } 456 457 private EJBLocalObject createEJBLocalObject(Object id) 458 { 459 InvocationHandler handler = new EntityProxy(localJndiName, id, this); 460 try 461 { 462 return (EJBLocalObject ) proxyClassConstructor.newInstance(new Object []{handler}); 463 } 464 catch(Exception ex) 465 { 466 throw new NestedRuntimeException(ex); 467 } 468 } 469 470 interface ClassLoaderAction 471 { 472 class UTIL 473 { 474 static ClassLoaderAction getClassLoaderAction() 475 { 476 return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED; 477 } 478 479 static ClassLoader get(Class clazz) 480 { 481 return getClassLoaderAction().get(clazz); 482 } 483 } 484 485 ClassLoaderAction PRIVILEGED = new ClassLoaderAction() 486 { 487 public ClassLoader get(final Class clazz) 488 { 489 return (ClassLoader )AccessController.doPrivileged( 490 new PrivilegedAction () 491 { 492 public Object run() 493 { 494 return clazz.getClassLoader(); 495 } 496 } 497 ); 498 } 499 }; 500 501 ClassLoaderAction NON_PRIVILEGED = new ClassLoaderAction() 502 { 503 public ClassLoader get(Class clazz) 504 { 505 return clazz.getClassLoader(); 506 } 507 }; 508 509 ClassLoader get(Class clazz); 510 } 511 512 interface SecurityActions 513 { 514 class UTIL 515 { 516 static SecurityActions getSecurityActions() 517 { 518 return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED; 519 } 520 } 521 522 SecurityActions NON_PRIVILEGED = new SecurityActions() 523 { 524 public Principal getPrincipal() 525 { 526 return SecurityAssociation.getPrincipal(); 527 } 528 529 public Object getCredential() 530 { 531 return SecurityAssociation.getCredential(); 532 } 533 }; 534 535 SecurityActions PRIVILEGED = new SecurityActions() 536 { 537 private final PrivilegedAction getPrincipalAction = new PrivilegedAction () 538 { 539 public Object run() 540 { 541 return SecurityAssociation.getPrincipal(); 542 } 543 }; 544 545 private final PrivilegedAction getCredentialAction = new PrivilegedAction () 546 { 547 public Object run() 548 { 549 return SecurityAssociation.getCredential(); 550 } 551 }; 552 553 public Principal getPrincipal() 554 { 555 return (Principal )AccessController.doPrivileged(getPrincipalAction); 556 } 557 558 public Object getCredential() 559 { 560 return AccessController.doPrivileged(getCredentialAction); 561 } 562 }; 563 564 Principal getPrincipal(); 565 566 Object getCredential(); 567 } 568 569 interface TCLAction 570 { 571 class UTIL 572 { 573 static TCLAction getTCLAction() 574 { 575 return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED; 576 } 577 578 static ClassLoader getContextClassLoader() 579 { 580 return getTCLAction().getContextClassLoader(); 581 } 582 583 static ClassLoader getContextClassLoader(Thread thread) 584 { 585 return getTCLAction().getContextClassLoader(thread); 586 } 587 588 static void setContextClassLoader(ClassLoader cl) 589 { 590 getTCLAction().setContextClassLoader(cl); 591 } 592 593 static void setContextClassLoader(Thread thread, ClassLoader cl) 594 { 595 getTCLAction().setContextClassLoader(thread, cl); 596 } 597 } 598 599 TCLAction NON_PRIVILEGED = new TCLAction() 600 { 601 public ClassLoader getContextClassLoader() 602 { 603 return Thread.currentThread().getContextClassLoader(); 604 } 605 606 public ClassLoader getContextClassLoader(Thread thread) 607 { 608 return thread.getContextClassLoader(); 609 } 610 611 public void setContextClassLoader(ClassLoader cl) 612 { 613 Thread.currentThread().setContextClassLoader(cl); 614 } 615 616 public void setContextClassLoader(Thread thread, ClassLoader cl) 617 { 618 thread.setContextClassLoader(cl); 619 } 620 }; 621 622 TCLAction PRIVILEGED = new TCLAction() 623 { 624 private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction () 625 { 626 public Object run() 627 { 628 return Thread.currentThread().getContextClassLoader(); 629 } 630 }; 631 632 public ClassLoader getContextClassLoader() 633 { 634 return (ClassLoader )AccessController.doPrivileged(getTCLPrivilegedAction); 635 } 636 637 public ClassLoader getContextClassLoader(final Thread thread) 638 { 639 return (ClassLoader )AccessController.doPrivileged(new PrivilegedAction () 640 { 641 public Object run() 642 { 643 return thread.getContextClassLoader(); 644 } 645 }); 646 } 647 648 public void setContextClassLoader(final ClassLoader cl) 649 { 650 AccessController.doPrivileged( 651 new PrivilegedAction () 652 { 653 public Object run() 654 { 655 Thread.currentThread().setContextClassLoader(cl); 656 return null; 657 } 658 } 659 ); 660 } 661 662 public void setContextClassLoader(final Thread thread, final ClassLoader cl) 663 { 664 AccessController.doPrivileged( 665 new PrivilegedAction () 666 { 667 public Object run() 668 { 669 thread.setContextClassLoader(cl); 670 return null; 671 } 672 } 673 ); 674 } 675 }; 676 677 ClassLoader getContextClassLoader(); 678 679 ClassLoader getContextClassLoader(Thread thread); 680 681 void setContextClassLoader(ClassLoader cl); 682 683 void setContextClassLoader(Thread thread, ClassLoader cl); 684 } 685 } 686 | Popular Tags |