KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > local > BaseLocalProxyFactory


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.local;
23
24 import java.lang.reflect.InvocationHandler JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Proxy JavaDoc;
27 import java.lang.reflect.Constructor JavaDoc;
28 import java.rmi.AccessException JavaDoc;
29 import java.rmi.NoSuchObjectException JavaDoc;
30 import java.security.Principal JavaDoc;
31 import java.security.PrivilegedAction JavaDoc;
32 import java.security.AccessController JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collection JavaDoc;
35 import java.util.Collections JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Map JavaDoc;
39 import javax.ejb.AccessLocalException JavaDoc;
40 import javax.ejb.EJBLocalHome JavaDoc;
41 import javax.ejb.EJBLocalObject JavaDoc;
42 import javax.ejb.NoSuchObjectLocalException JavaDoc;
43 import javax.ejb.TransactionRequiredLocalException JavaDoc;
44 import javax.ejb.TransactionRolledbackLocalException JavaDoc;
45 import javax.naming.Context JavaDoc;
46 import javax.naming.InitialContext JavaDoc;
47 import javax.transaction.Transaction JavaDoc;
48 import javax.transaction.TransactionManager JavaDoc;
49 import javax.transaction.TransactionRequiredException JavaDoc;
50 import javax.transaction.TransactionRolledbackException JavaDoc;
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 /**
67  * The LocalProxyFactory implementation that handles local ejb interface
68  * proxies.
69  *
70  * @author <a HREF="mailto:docodan@mvcsoft.com">Daniel OConnor</a>
71  * @author <a HREF="mailto:scott.stark@jboss.org">Scott Stark</a>
72  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
73  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
74  * $Revision: 37459 $
75  */

76 public class BaseLocalProxyFactory implements LocalProxyFactory
77 {
78    // Attributes ----------------------------------------------------
79
protected static Logger log = Logger.getLogger(BaseLocalProxyFactory.class);
80
81    /**
82     * A map of the BaseLocalProxyFactory instances keyed by localJndiName
83     */

84    protected static Map JavaDoc invokerMap = Collections.synchronizedMap(new HashMap JavaDoc());
85
86    protected Container container;
87
88    /**
89     * The JNDI name of the local home interface binding
90     */

91    protected String JavaDoc localJndiName;
92
93    protected TransactionManager JavaDoc transactionManager;
94
95    // The home can be one.
96
protected EJBLocalHome JavaDoc home;
97
98    // The Stateless Object can be one.
99
protected EJBLocalObject JavaDoc statelessObject;
100
101    protected Map JavaDoc beanMethodInvokerMap;
102    protected Map JavaDoc homeMethodInvokerMap;
103    protected Class JavaDoc localHomeClass;
104    protected Class JavaDoc localClass;
105
106    protected Constructor JavaDoc proxyClassConstructor;
107
108    private final TransactionLocal cache = new TransactionLocal()
109    {
110       protected Object JavaDoc initialValue()
111       {
112          return new HashMap JavaDoc();
113       }
114    };
115
116    // Static --------------------------------------------------------
117

118    // Constructors --------------------------------------------------
119

120    // Public --------------------------------------------------------
121

122    // ContainerService implementation -------------------------------
123

124    public void setContainer(Container con)
125    {
126       this.container = con;
127    }
128
129    public void create() throws Exception JavaDoc
130    {
131       BeanMetaData metaData = container.getBeanMetaData();
132       localJndiName = metaData.getLocalJndiName();
133    }
134
135    public void start()
136       throws Exception JavaDoc
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       // this is faster than newProxyInstance
153
Class JavaDoc[] intfs = {localClass};
154       Class JavaDoc proxyClass = Proxy.getProxyClass(ClassLoaderAction.UTIL.get(localClass), intfs);
155       final Class JavaDoc[] constructorParams =
156          {InvocationHandler JavaDoc.class};
157
158       proxyClassConstructor = proxyClass.getConstructor(constructorParams);
159
160       Context JavaDoc iniCtx = new InitialContext JavaDoc();
161       String JavaDoc beanName = metaData.getEjbName();
162
163       // Set the transaction manager and transaction propagation
164
// context factory of the GenericProxy class
165
transactionManager =
166          (TransactionManager JavaDoc) iniCtx.lookup("java:/TransactionManager");
167
168       // Create method mappings for container invoker
169
Method JavaDoc[] methods = localClass.getMethods();
170       beanMethodInvokerMap = new HashMap JavaDoc();
171       for(int i = 0; i < methods.length; i++)
172       {
173          long hash = MarshalledInvocation.calculateHash(methods[i]);
174          beanMethodInvokerMap.put(new Long JavaDoc(hash), methods[i]);
175       }
176
177       methods = localHomeClass.getMethods();
178       homeMethodInvokerMap = new HashMap JavaDoc();
179       for(int i = 0; i < methods.length; i++)
180       {
181          long hash = MarshalledInvocation.calculateHash(methods[i]);
182          homeMethodInvokerMap.put(new Long JavaDoc(hash), methods[i]);
183       }
184
185       // bind that referance to my name
186
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       // Clean up the home proxy binding
194
try
195       {
196          if(invokerMap.remove(localJndiName) == this)
197          {
198             log.info("Unbind EJB LocalHome '" + container.getBeanMetaData().getEjbName() + "' from jndi '" + localJndiName + "'");
199
200             InitialContext JavaDoc ctx = new InitialContext JavaDoc();
201             ctx.unbind(localJndiName);
202          }
203       }
204       catch(Exception JavaDoc 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 JavaDoc getProxyClassConstructor()
226    {
227       if(proxyClassConstructor == null)
228       {
229       }
230       return proxyClassConstructor;
231    }
232
233    // EJBProxyFactory implementation -------------------------------
234
public EJBLocalHome JavaDoc getEJBLocalHome()
235    {
236       if(home == null)
237       {
238          EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container;
239          InvocationHandler JavaDoc handler = new LocalHomeProxy(localJndiName, this);
240          ClassLoader JavaDoc loader = ClassLoaderAction.UTIL.get(cic.getLocalHomeClass());
241          Class JavaDoc[] interfaces = {cic.getLocalHomeClass()};
242
243          home = (EJBLocalHome JavaDoc) Proxy.newProxyInstance(loader,
244             interfaces,
245             handler);
246       }
247       return home;
248    }
249
250    public EJBLocalObject JavaDoc getStatelessSessionEJBLocalObject()
251    {
252       if(statelessObject == null)
253       {
254          EJBProxyFactoryContainer cic = (EJBProxyFactoryContainer) container;
255          InvocationHandler JavaDoc handler =
256             new StatelessSessionProxy(localJndiName, this);
257          ClassLoader JavaDoc loader = ClassLoaderAction.UTIL.get(cic.getLocalClass());
258          Class JavaDoc[] interfaces = {cic.getLocalClass()};
259
260          statelessObject = (EJBLocalObject JavaDoc) Proxy.newProxyInstance(loader,
261             interfaces,
262             handler);
263       }
264       return statelessObject;
265    }
266
267    public EJBLocalObject JavaDoc getStatefulSessionEJBLocalObject(Object JavaDoc id)
268    {
269       InvocationHandler JavaDoc handler =
270          new StatefulSessionProxy(localJndiName, id, this);
271       try
272       {
273          return (EJBLocalObject JavaDoc) proxyClassConstructor.newInstance(new Object JavaDoc[]{handler});
274       }
275       catch(Exception JavaDoc ex)
276       {
277          throw new NestedRuntimeException(ex);
278       }
279    }
280
281    public Object JavaDoc getEntityEJBObject(Object JavaDoc id)
282    {
283       return getEntityEJBLocalObject(id);
284    }
285
286    public EJBLocalObject JavaDoc getEntityEJBLocalObject(Object JavaDoc id, boolean create)
287    {
288       EJBLocalObject JavaDoc result = null;
289       if(id != null)
290       {
291          final Transaction JavaDoc tx = cache.getTransaction();
292          if(tx == null)
293          {
294             result = createEJBLocalObject(id);
295          }
296          else
297          {
298             Map JavaDoc map = (Map JavaDoc) cache.get(tx);
299             if(create)
300             {
301                result = createEJBLocalObject(id);
302                map.put(id, result);
303             }
304             else
305             {
306                result = (EJBLocalObject JavaDoc) 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 JavaDoc getEntityEJBLocalObject(Object JavaDoc id)
319    {
320       return getEntityEJBLocalObject(id, false);
321    }
322
323    public Collection JavaDoc getEntityLocalCollection(Collection JavaDoc ids)
324    {
325       ArrayList JavaDoc list = new ArrayList JavaDoc(ids.size());
326       Iterator JavaDoc iter = ids.iterator();
327       while(iter.hasNext())
328       {
329          final Object JavaDoc nextId = iter.next();
330          list.add(getEntityEJBLocalObject(nextId));
331       }
332       return list;
333    }
334
335    /**
336     * Invoke a Home interface method.
337     */

338    public Object JavaDoc invokeHome(Method JavaDoc m, Object JavaDoc[] args) throws Exception JavaDoc
339    {
340       // Set the right context classloader
341
ClassLoader JavaDoc 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 JavaDoc ae)
362       {
363          throw new AccessLocalException JavaDoc(ae.getMessage(), ae);
364       }
365       catch(NoSuchObjectException JavaDoc nsoe)
366       {
367          throw new NoSuchObjectLocalException JavaDoc(nsoe.getMessage(), nsoe);
368       }
369       catch(TransactionRequiredException JavaDoc tre)
370       {
371          throw new TransactionRequiredLocalException JavaDoc(tre.getMessage());
372       }
373       catch(TransactionRolledbackException JavaDoc trbe)
374       {
375          throw new TransactionRolledbackLocalException JavaDoc(trbe.getMessage(), trbe);
376       }
377       finally
378       {
379          if(setCl)
380          {
381             TCLAction.UTIL.setContextClassLoader(oldCl);
382          }
383       }
384    }
385
386    public String JavaDoc getJndiName()
387    {
388       return localJndiName;
389    }
390
391    /**
392     * Return the transaction associated with the current thread.
393     * Returns <code>null</code> if the transaction manager was never
394     * set, or if no transaction is associated with the current thread.
395     */

396    Transaction JavaDoc getTransaction() throws javax.transaction.SystemException JavaDoc
397    {
398       if(transactionManager == null)
399       {
400          return null;
401       }
402       return transactionManager.getTransaction();
403    }
404
405    /**
406     * Invoke a local interface method.
407     */

408    public Object JavaDoc invoke(Object JavaDoc id, Method JavaDoc m, Object JavaDoc[] args)
409       throws Exception JavaDoc
410    {
411       // Set the right context classloader
412
ClassLoader JavaDoc 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 JavaDoc ae)
433       {
434          throw new AccessLocalException JavaDoc(ae.getMessage(), ae);
435       }
436       catch(NoSuchObjectException JavaDoc nsoe)
437       {
438          throw new NoSuchObjectLocalException JavaDoc(nsoe.getMessage(), nsoe);
439       }
440       catch(TransactionRequiredException JavaDoc tre)
441       {
442          throw new TransactionRequiredLocalException JavaDoc(tre.getMessage());
443       }
444       catch(TransactionRolledbackException JavaDoc trbe)
445       {
446          throw new TransactionRolledbackLocalException JavaDoc(trbe.getMessage(), trbe);
447       }
448       finally
449       {
450          if(setCl)
451          {
452             TCLAction.UTIL.setContextClassLoader(oldCl);
453          }
454       }
455    }
456
457    private EJBLocalObject JavaDoc createEJBLocalObject(Object JavaDoc id)
458    {
459       InvocationHandler JavaDoc handler = new EntityProxy(localJndiName, id, this);
460       try
461       {
462          return (EJBLocalObject JavaDoc) proxyClassConstructor.newInstance(new Object JavaDoc[]{handler});
463       }
464       catch(Exception JavaDoc 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 JavaDoc get(Class JavaDoc clazz)
480          {
481             return getClassLoaderAction().get(clazz);
482          }
483       }
484
485       ClassLoaderAction PRIVILEGED = new ClassLoaderAction()
486       {
487          public ClassLoader JavaDoc get(final Class JavaDoc clazz)
488          {
489             return (ClassLoader JavaDoc)AccessController.doPrivileged(
490                new PrivilegedAction JavaDoc()
491                {
492                   public Object JavaDoc run()
493                   {
494                      return clazz.getClassLoader();
495                   }
496                }
497             );
498          }
499       };
500
501       ClassLoaderAction NON_PRIVILEGED = new ClassLoaderAction()
502       {
503          public ClassLoader JavaDoc get(Class JavaDoc clazz)
504          {
505             return clazz.getClassLoader();
506          }
507       };
508
509       ClassLoader JavaDoc get(Class JavaDoc 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 JavaDoc getPrincipal()
525          {
526             return SecurityAssociation.getPrincipal();
527          }
528
529          public Object JavaDoc getCredential()
530          {
531             return SecurityAssociation.getCredential();
532          }
533       };
534
535       SecurityActions PRIVILEGED = new SecurityActions()
536       {
537          private final PrivilegedAction JavaDoc getPrincipalAction = new PrivilegedAction JavaDoc()
538          {
539             public Object JavaDoc run()
540             {
541                return SecurityAssociation.getPrincipal();
542             }
543          };
544
545          private final PrivilegedAction JavaDoc getCredentialAction = new PrivilegedAction JavaDoc()
546          {
547             public Object JavaDoc run()
548             {
549                return SecurityAssociation.getCredential();
550             }
551          };
552
553          public Principal JavaDoc getPrincipal()
554          {
555             return (Principal JavaDoc)AccessController.doPrivileged(getPrincipalAction);
556          }
557
558          public Object JavaDoc getCredential()
559          {
560             return AccessController.doPrivileged(getCredentialAction);
561          }
562       };
563
564       Principal JavaDoc getPrincipal();
565
566       Object JavaDoc 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 JavaDoc getContextClassLoader()
579          {
580             return getTCLAction().getContextClassLoader();
581          }
582
583          static ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread)
584          {
585             return getTCLAction().getContextClassLoader(thread);
586          }
587
588          static void setContextClassLoader(ClassLoader JavaDoc cl)
589          {
590             getTCLAction().setContextClassLoader(cl);
591          }
592
593          static void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl)
594          {
595             getTCLAction().setContextClassLoader(thread, cl);
596          }
597       }
598
599       TCLAction NON_PRIVILEGED = new TCLAction()
600       {
601          public ClassLoader JavaDoc getContextClassLoader()
602          {
603             return Thread.currentThread().getContextClassLoader();
604          }
605
606          public ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread)
607          {
608             return thread.getContextClassLoader();
609          }
610
611          public void setContextClassLoader(ClassLoader JavaDoc cl)
612          {
613             Thread.currentThread().setContextClassLoader(cl);
614          }
615
616          public void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl)
617          {
618             thread.setContextClassLoader(cl);
619          }
620       };
621
622       TCLAction PRIVILEGED = new TCLAction()
623       {
624          private final PrivilegedAction JavaDoc getTCLPrivilegedAction = new PrivilegedAction JavaDoc()
625          {
626             public Object JavaDoc run()
627             {
628                return Thread.currentThread().getContextClassLoader();
629             }
630          };
631
632          public ClassLoader JavaDoc getContextClassLoader()
633          {
634             return (ClassLoader JavaDoc)AccessController.doPrivileged(getTCLPrivilegedAction);
635          }
636
637          public ClassLoader JavaDoc getContextClassLoader(final Thread JavaDoc thread)
638          {
639             return (ClassLoader JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc()
640             {
641                public Object JavaDoc run()
642                {
643                   return thread.getContextClassLoader();
644                }
645             });
646          }
647
648          public void setContextClassLoader(final ClassLoader JavaDoc cl)
649          {
650             AccessController.doPrivileged(
651                new PrivilegedAction JavaDoc()
652                {
653                   public Object JavaDoc run()
654                   {
655                      Thread.currentThread().setContextClassLoader(cl);
656                      return null;
657                   }
658                }
659             );
660          }
661
662          public void setContextClassLoader(final Thread JavaDoc thread, final ClassLoader JavaDoc cl)
663          {
664             AccessController.doPrivileged(
665                new PrivilegedAction JavaDoc()
666                {
667                   public Object JavaDoc run()
668                   {
669                      thread.setContextClassLoader(cl);
670                      return null;
671                   }
672                }
673             );
674          }
675       };
676
677       ClassLoader JavaDoc getContextClassLoader();
678
679       ClassLoader JavaDoc getContextClassLoader(Thread JavaDoc thread);
680
681       void setContextClassLoader(ClassLoader JavaDoc cl);
682
683       void setContextClassLoader(Thread JavaDoc thread, ClassLoader JavaDoc cl);
684    }
685 }
686
Popular Tags