KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb3 > service > ServiceContainer


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.ejb3.service;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.util.Hashtable JavaDoc;
26
27 import javax.ejb.EJBException JavaDoc;
28 import javax.ejb.Handle JavaDoc;
29 import javax.ejb.Timer JavaDoc;
30 import javax.ejb.TimerService JavaDoc;
31 import javax.management.Attribute JavaDoc;
32 import javax.management.AttributeList JavaDoc;
33 import javax.management.AttributeNotFoundException JavaDoc;
34 import javax.management.InstanceNotFoundException JavaDoc;
35 import javax.management.InvalidAttributeValueException JavaDoc;
36 import javax.management.MBeanException JavaDoc;
37 import javax.management.MBeanInfo JavaDoc;
38 import javax.management.MBeanRegistrationException JavaDoc;
39 import javax.management.MBeanServer JavaDoc;
40 import javax.management.ObjectName JavaDoc;
41 import javax.management.ReflectionException JavaDoc;
42
43 import org.jboss.annotation.ejb.Management;
44 import org.jboss.annotation.ejb.Service;
45 import org.jboss.aop.AspectManager;
46 import org.jboss.aop.MethodInfo;
47 import org.jboss.aop.advice.Interceptor;
48 import org.jboss.aop.joinpoint.Invocation;
49 import org.jboss.aop.joinpoint.InvocationResponse;
50 import org.jboss.aop.joinpoint.MethodInvocation;
51 import org.jboss.aop.util.MethodHashing;
52 import org.jboss.aop.util.PayloadKey;
53 import org.jboss.aspects.asynch.FutureHolder;
54 import org.jboss.ejb.AllowedOperationsAssociation;
55 import org.jboss.ejb.AllowedOperationsFlags;
56 import org.jboss.ejb3.BeanContext;
57 import org.jboss.ejb3.EJBContainerInvocation;
58 import org.jboss.ejb3.Ejb3Deployment;
59 import org.jboss.ejb3.ProxyFactory;
60 import org.jboss.ejb3.SessionContainer;
61 import org.jboss.ejb3.ThreadLocalENCFactory;
62 import org.jboss.ejb3.asynchronous.AsynchronousInterceptor;
63 import org.jboss.ejb3.interceptor.InterceptorInfoRepository;
64 import org.jboss.ejb3.timerservice.TimedObjectInvoker;
65 import org.jboss.ejb3.timerservice.TimerServiceFactory;
66 import org.jboss.logging.Logger;
67 import org.jboss.injection.Injector;
68
69 /**
70  * @author <a HREF="mailto:kabir.khan@jboss.org">Kabir Khan</a>
71  * @version $Revision: 57901 $
72  */

73 public class ServiceContainer extends SessionContainer implements TimedObjectInvoker
74 {
75    ServiceMBeanDelegate delegate;
76    Object JavaDoc singleton;
77    boolean injected;
78    BeanContext beanContext;
79    MBeanServer JavaDoc mbeanServer;
80    ObjectName JavaDoc delegateObjectName;
81    private TimerService JavaDoc timerService;
82
83    @SuppressWarnings JavaDoc("unused")
84    private static final Logger log = Logger.getLogger(ServiceContainer.class);
85
86    public ServiceContainer(MBeanServer JavaDoc server, ClassLoader JavaDoc cl, String JavaDoc beanClassName, String JavaDoc ejbName,
87                            AspectManager manager, Hashtable JavaDoc ctxProperties, InterceptorInfoRepository interceptorRepository,
88                            Ejb3Deployment deployment)
89    {
90       super(cl, beanClassName, ejbName, manager, ctxProperties, interceptorRepository, deployment);
91       beanContextClass = ServiceBeanContext.class;
92       this.mbeanServer = server;
93    }
94
95    public void callTimeout(Timer JavaDoc timer) throws Exception JavaDoc
96    {
97       Method JavaDoc timeout = callbackHandler.getTimeoutCallback();
98       if (timeout == null) throw new EJBException JavaDoc("No method has been annotated with @Timeout");
99       Object JavaDoc[] args = {timer};
100       AllowedOperationsAssociation.pushInMethodFlag(AllowedOperationsFlags.IN_EJB_TIMEOUT);
101       try
102       {
103          localInvoke(timeout, args);
104       }
105       catch(Throwable JavaDoc throwable)
106       {
107          if (throwable instanceof Exception JavaDoc) throw (Exception JavaDoc) throwable;
108          if(throwable instanceof Error JavaDoc) throw (Error JavaDoc) throwable;
109          throw new RuntimeException JavaDoc(throwable);
110       }
111       finally
112       {
113          AllowedOperationsAssociation.popInMethodFlag();
114       }
115    }
116
117    protected Object JavaDoc createSession(Class JavaDoc initTypes[], Object JavaDoc initArgs[])
118    {
119 // if((initTypes != null && initTypes.length > 0) || (initArgs != null && initArgs.length > 0))
120
// throw new IllegalArgumentException("service bean create method must take no arguments");
121
throw new RuntimeException JavaDoc("NYI");
122    }
123
124    public Object JavaDoc getSingleton()
125    {
126       return singleton;
127    }
128
129    public void create() throws Exception JavaDoc
130    {
131       super.create();
132       
133       // EJBTHREE-655: fire up an instance for use as MBean delegate
134
singleton = super.construct();
135
136       // won't work, before starting the management interface MBean injection must have been done.
137
//registerManagementInterface();
138

139       invokeOptionalMethod("create");
140    }
141
142
143    public void start() throws Exception JavaDoc
144    {
145       super.start();
146
147       try
148       {
149          initBeanContext();
150
151          // make sure the timer service is there before injection takes place
152
timerService = TimerServiceFactory.getInstance().createTimerService(this.getObjectName(), this);
153
154          injectDependencies(beanContext);
155
156          // TODO: EJBTHREE-655: shouldn't happen here, but in create
157
registerManagementInterface();
158          
159          TimerServiceFactory.getInstance().restoreTimerService(timerService);
160          
161          invokeOptionalMethod("start");
162       }
163       catch (Exception JavaDoc e)
164       {
165          e.printStackTrace();
166          stop();
167       }
168    }
169
170    public void stop() throws Exception JavaDoc
171    {
172       invokeOptionalMethod("stop");
173       
174       if (timerService != null) TimerServiceFactory.getInstance().removeTimerService(timerService);
175
176       // TODO: EJBTHREE-655: shouldn't happen here, but in destroy
177
unregisterManagementInterface();
178       
179       super.stop();
180
181       injected = false;
182    }
183
184    public void destroy() throws Exception JavaDoc
185    {
186       invokeOptionalMethod("destroy");
187       
188       //unregisterManagementInterface();
189

190       super.destroy();
191    }
192
193    public void initializePool() throws Exception JavaDoc
194    {
195       resolveInjectors();
196    }
197
198    public TimerService JavaDoc getTimerService()
199    {
200       return timerService;
201    }
202
203    public TimerService JavaDoc getTimerService(Object JavaDoc pKey)
204    {
205       assert timerService != null : "Timer Service not yet initialized";
206       return timerService;
207    }
208    
209    /**
210     * Invoke a method on the singleton without a specific security or transaction context.
211     *
212     * @param methodName
213     */

214    private void invokeOptionalMethod(String JavaDoc methodName)
215    {
216       /* EJBTHREE-655 has been postponed
217       ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
218       try
219       {
220          Thread.currentThread().setContextClassLoader(classloader);
221          Class parameterTypes[] = { };
222          Method method = clazz.getMethod(methodName, parameterTypes);
223          Object args[] = { };
224          method.invoke(singleton, args);
225       }
226       catch(NoSuchMethodException e)
227       {
228          // ignore
229       }
230       catch (IllegalArgumentException e)
231       {
232          throw new RuntimeException(e);
233       }
234       catch (IllegalAccessException e)
235       {
236          throw new RuntimeException(e);
237       }
238       catch (InvocationTargetException e)
239       {
240          throw new RuntimeException(e.getCause());
241       }
242       finally
243       {
244          Thread.currentThread().setContextClassLoader(oldLoader);
245       }
246       */

247    }
248    
249    public void invokePostConstruct(BeanContext beanContext)
250    {
251       //Ignore
252
}
253
254    public void invokePreDestroy(BeanContext beanContext)
255    {
256       //Ignore
257
}
258
259    public void invokeInit(Object JavaDoc bean)
260    {
261       //Ignore
262
}
263
264    /**
265     * Performs a synchronous local invocation
266     */

267    public Object JavaDoc localInvoke(Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc
268    {
269       return localInvoke(method, args, null);
270    }
271
272    /**
273     * Performs a synchronous or asynchronous local invocation
274     *
275     * @param provider If null a synchronous invocation, otherwise an asynchronous
276     */

277    public Object JavaDoc localInvoke(Method JavaDoc method, Object JavaDoc[] args, FutureHolder provider) throws Throwable JavaDoc
278    {
279       long start = System.currentTimeMillis();
280       
281       ClassLoader JavaDoc oldLoader = Thread.currentThread().getContextClassLoader();
282       try
283       {
284          invokeStats.callIn();
285          
286          Thread.currentThread().setContextClassLoader(classloader);
287          long hash = MethodHashing.calculateHash(method);
288          MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
289          if (info == null)
290          {
291             throw new RuntimeException JavaDoc("Could not resolve beanClass method from proxy call: " + method.toString());
292          }
293          Interceptor[] aspects = info.getInterceptors();
294          EJBContainerInvocation nextInvocation = new EJBContainerInvocation(info, aspects);
295          nextInvocation.setAdvisor(this);
296          nextInvocation.setArguments(args);
297
298          nextInvocation = populateInvocation(nextInvocation);
299
300          if (provider != null)
301          {
302             nextInvocation.getMetaData().addMetaData(AsynchronousInterceptor.ASYNCH, AsynchronousInterceptor.INVOKE_ASYNCH, "YES", PayloadKey.AS_IS);
303             nextInvocation.getMetaData().addMetaData(AsynchronousInterceptor.ASYNCH, AsynchronousInterceptor.FUTURE_HOLDER, provider, PayloadKey.AS_IS);
304          }
305          return nextInvocation.invokeNext();
306       }
307       finally
308       {
309          if (method != null)
310          {
311             long end = System.currentTimeMillis();
312             long elapsed = end - start;
313             invokeStats.updateStats(method, elapsed);
314          }
315          
316          invokeStats.callOut();
317          
318          Thread.currentThread().setContextClassLoader(oldLoader);
319       }
320    }
321
322    public InvocationResponse dynamicInvoke(Object JavaDoc target, Invocation invocation) throws Throwable JavaDoc
323    {
324       long start = System.currentTimeMillis();
325       
326       ClassLoader JavaDoc oldLoader = Thread.currentThread().getContextClassLoader();
327       EJBContainerInvocation newSi = null;
328       
329       MethodInvocation si = (MethodInvocation) invocation;
330       MethodInfo info = (MethodInfo) methodInterceptors.get(si.getMethodHash());
331       Method JavaDoc method = info.getUnadvisedMethod();
332       try
333       {
334          invokeStats.callIn();
335          
336          Thread.currentThread().setContextClassLoader(classloader);
337          
338          if (info == null)
339          {
340             throw new RuntimeException JavaDoc("Could not resolve beanClass method from proxy call");
341          }
342          Interceptor[] aspects = info.getInterceptors();
343          newSi = new EJBContainerInvocation(info, aspects);
344          newSi.setArguments(si.getArguments());
345          newSi.setMetaData(si.getMetaData());
346          newSi.setAdvisor(this);
347
348          newSi = populateInvocation(newSi);
349
350          Object JavaDoc rtn = null;
351          try
352          {
353             rtn = newSi.invokeNext();
354          }
355          catch (Throwable JavaDoc throwable)
356          {
357             return marshallException(invocation, throwable, newSi.getResponseContextInfo());
358          }
359          InvocationResponse response = SessionContainer.marshallResponse(invocation, rtn, newSi.getResponseContextInfo());
360
361          return response;
362       }
363       finally
364       {
365          if (method != null)
366          {
367             long end = System.currentTimeMillis();
368             long elapsed = end - start;
369             invokeStats.updateStats(method, elapsed);
370          }
371          
372          invokeStats.callOut();
373          
374          Thread.currentThread().setContextClassLoader(oldLoader);
375       }
376    }
377
378    protected void initBeanContext() throws RuntimeException JavaDoc
379    {
380       if (beanContext == null)
381       {
382          synchronized(singleton)
383          {
384             if (beanContext == null)
385             {
386                try
387                {
388                   beanContext = (BeanContext) beanContextClass.newInstance();
389                   beanContext.setContainer(this);
390                   beanContext.initialiseInterceptorInstances();
391                   beanContext.setInstance(singleton);
392                }
393                catch (InstantiationException JavaDoc e)
394                {
395                   throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
396
}
397                catch (IllegalAccessException JavaDoc e)
398                {
399                   throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
400
}
401             }
402          }
403       }
404    }
405
406    @Override JavaDoc
407    protected EJBContainerInvocation populateInvocation(EJBContainerInvocation invocation)
408    {
409       invocation.setTargetObject(singleton);
410       invocation.setBeanContext(beanContext);
411       return invocation;
412    }
413
414    protected synchronized void injectDependencies(BeanContext ctx)
415    {
416       if (injectors != null)
417       {
418          try
419          {
420             ThreadLocalENCFactory.push(enc);
421             for (Injector injector : injectors)
422             {
423                injector.inject(ctx);
424             }
425          }
426          finally
427          {
428             ThreadLocalENCFactory.pop();
429          }
430       }
431       injected = true;
432    }
433
434    // Dynamic MBean implementation --------------------------------------------------
435

436    public Object JavaDoc getAttribute(String JavaDoc attribute) throws AttributeNotFoundException JavaDoc,
437                                                        MBeanException JavaDoc, ReflectionException JavaDoc
438    {
439       return delegate.getAttribute(attribute);
440    }
441
442    public void setAttribute(Attribute JavaDoc attribute) throws AttributeNotFoundException JavaDoc,
443                                                         InvalidAttributeValueException JavaDoc, MBeanException JavaDoc, ReflectionException JavaDoc
444    {
445       delegate.setAttribute(attribute);
446    }
447
448    public AttributeList JavaDoc getAttributes(String JavaDoc[] attributes)
449    {
450       return delegate.getAttributes(attributes);
451    }
452
453    public AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes)
454    {
455       return delegate.setAttributes(attributes);
456    }
457
458    public Object JavaDoc invoke(String JavaDoc actionName, Object JavaDoc params[], String JavaDoc signature[])
459            throws MBeanException JavaDoc, ReflectionException JavaDoc
460    {
461       return delegate.invoke(actionName, params, signature);
462    }
463
464    @Override JavaDoc
465    protected Object JavaDoc invokeEJBObjectMethod(ProxyFactory factory, Object JavaDoc id, MethodInfo info, Object JavaDoc[] args) throws Exception JavaDoc
466    {
467       throw new RuntimeException JavaDoc("NYI");
468    }
469
470    public MBeanInfo JavaDoc getMBeanInfo()
471    {
472       return delegate.getMBeanInfo();
473    }
474
475
476    private void registerManagementInterface()
477    {
478       try
479       {
480          Management annotation = (Management)resolveAnnotation(Management.class);
481
482          Class JavaDoc intf = null;
483          if (annotation != null)
484             intf = annotation.value();
485
486          if (intf ==null)
487          {
488             Class JavaDoc[] interfaces = this.getBeanClass().getInterfaces();
489             int interfaceIndex = 0;
490             while (intf == null && interfaceIndex < interfaces.length)
491             {
492                if (interfaces[interfaceIndex].getAnnotation(Management.class) != null)
493                   intf = interfaces[interfaceIndex];
494                else
495                   ++interfaceIndex;
496             }
497          }
498
499          if (intf != null)
500          {
501             if (mbeanServer == null)
502                mbeanServer = org.jboss.mx.util.MBeanServerLocator.locateJBoss();
503
504             if (mbeanServer == null)
505                throw new RuntimeException JavaDoc("There is a @Management interface on " + ejbName + " but the MBeanServer has not been initialized for it");
506
507             Service JavaDoc service = (Service JavaDoc)resolveAnnotation(Service JavaDoc.class);
508
509             String JavaDoc objname = service.objectName();
510             delegateObjectName = (objname == null || objname.equals("")) ?
511                             new ObjectName JavaDoc(getObjectName().getCanonicalName() + ",type=ManagementInterface") : new ObjectName JavaDoc(service.objectName());
512
513             delegate = new ServiceMBeanDelegate(mbeanServer, this, intf, delegateObjectName);
514
515             Object JavaDoc securityDomainAnnotation = resolveAnnotation(org.jboss.annotation.security.SecurityDomain.class);
516
517             getDeployment().getKernelAbstraction().installMBean(delegateObjectName, getDependencyPolicy(), delegate);
518          }
519       }
520       catch (Exception JavaDoc e)
521       {
522          throw new RuntimeException JavaDoc("Problem registering @Management interface for @Service " + getBeanClass(), e);
523       }
524    }
525
526    private void unregisterManagementInterface() throws InstanceNotFoundException JavaDoc, MBeanRegistrationException JavaDoc
527    {
528       if (delegate != null)
529       {
530          getDeployment().getKernelAbstraction().uninstallMBean(delegateObjectName);
531       }
532    }
533    
534    protected void removeHandle(Handle JavaDoc handle)
535    {
536       throw new RuntimeException JavaDoc("Don't do this");
537    }
538 }
539
Popular Tags