001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb3.stateful;
023:
024: import java.lang.reflect.Field;
025: import java.lang.reflect.Method;
026: import java.util.Hashtable;
027: import java.util.Map;
028:
029: import javax.annotation.PostConstruct;
030: import javax.annotation.PreDestroy;
031: import javax.ejb.EJBHome;
032: import javax.ejb.EJBObject;
033: import javax.ejb.Handle;
034: import javax.ejb.Init;
035: import javax.ejb.PostActivate;
036: import javax.ejb.PrePassivate;
037: import javax.ejb.Remote;
038: import javax.ejb.RemoteHome;
039: import javax.ejb.TimerService;
040:
041: import org.jboss.annotation.ejb.LocalBinding;
042: import org.jboss.annotation.ejb.RemoteBinding;
043: import org.jboss.annotation.ejb.RemoteBindings;
044: import org.jboss.annotation.ejb.cache.Cache;
045: import org.jboss.aop.AspectManager;
046: import org.jboss.aop.MethodInfo;
047: import org.jboss.aop.joinpoint.Invocation;
048: import org.jboss.aop.joinpoint.InvocationResponse;
049: import org.jboss.aop.util.MethodHashing;
050: import org.jboss.aspects.asynch.FutureHolder;
051: import org.jboss.ejb3.BeanContext;
052: import org.jboss.ejb3.EJBContainerInvocation;
053: import org.jboss.ejb3.Ejb3Deployment;
054: import org.jboss.ejb3.ProxyFactory;
055: import org.jboss.ejb3.ProxyFactoryHelper;
056: import org.jboss.ejb3.ProxyUtils;
057: import org.jboss.ejb3.SessionContainer;
058: import org.jboss.ejb3.cache.StatefulCache;
059: import org.jboss.ejb3.interceptor.InterceptorInfoRepository;
060: import org.jboss.ejb3.proxy.EJBMetaDataImpl;
061: import org.jboss.ejb3.proxy.handle.HomeHandleImpl;
062: import org.jboss.injection.Injector;
063: import org.jboss.injection.JndiFieldInjector;
064: import org.jboss.logging.Logger;
065:
066: /**
067: * Comment
068: *
069: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
070: * @version $Revision: 63485 $
071: */
072: public class StatefulContainer extends SessionContainer {
073: private static final Logger log = Logger
074: .getLogger(StatefulContainer.class);
075:
076: protected StatefulCache cache;
077:
078: public StatefulContainer(ClassLoader cl, String beanClassName,
079: String ejbName, AspectManager manager,
080: Hashtable ctxProperties,
081: InterceptorInfoRepository interceptorRepository,
082: Ejb3Deployment deployment) {
083: super (cl, beanClassName, ejbName, manager, ctxProperties,
084: interceptorRepository, deployment);
085: beanContextClass = StatefulBeanContext.class;
086: }
087:
088: public void start() throws Exception {
089: try {
090: super .start();
091: Cache cacheConfig = (Cache) resolveAnnotation(Cache.class);
092: cache = (StatefulCache) cacheConfig.value().newInstance();
093: cache.initialize(this );
094: cache.start();
095: } catch (Exception e) {
096: try {
097: stop();
098: } catch (Exception ignore) {
099: log.debug("Failed to cleanup after start() failure",
100: ignore);
101: }
102: throw e;
103: }
104:
105: }
106:
107: public void stop() throws Exception {
108: if (cache != null)
109: cache.stop();
110: super .stop();
111: }
112:
113: public StatefulCache getCache() {
114: return cache;
115: }
116:
117: /**
118: * Performs a synchronous local invocation
119: */
120: public Object localInvoke(Object id, Method method, Object[] args)
121: throws Throwable {
122: return localInvoke(id, method, args, null);
123: }
124:
125: /**
126: * Performs a synchronous or asynchronous local invocation
127: *
128: */
129: public Object localHomeInvoke(Method method, Object[] args)
130: throws Throwable {
131: ClassLoader oldLoader = Thread.currentThread()
132: .getContextClassLoader();
133: pushEnc();
134: try {
135: long hash = MethodHashing.calculateHash(method);
136: MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
137: if (info == null) {
138: throw new RuntimeException(
139: "Could not resolve beanClass method from proxy call: "
140: + method.toString());
141: }
142: return invokeLocalHomeMethod(info, args);
143: } finally {
144: Thread.currentThread().setContextClassLoader(oldLoader);
145: popEnc();
146: }
147: }
148:
149: /**
150: * Performs a synchronous or asynchronous local invocation
151: *
152: * @param provider If null a synchronous invocation, otherwise an asynchronous
153: */
154: public Object localInvoke(Object id, Method method, Object[] args,
155: FutureHolder provider) throws Throwable {
156: long start = System.currentTimeMillis();
157:
158: ClassLoader oldLoader = Thread.currentThread()
159: .getContextClassLoader();
160: pushEnc();
161: try {
162: long hash = MethodHashing.calculateHash(method);
163: MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
164: if (info == null) {
165: throw new RuntimeException(
166: "Could not resolve beanClass method from proxy call: "
167: + method.toString());
168: }
169:
170: Method unadvisedMethod = info.getUnadvisedMethod();
171:
172: try {
173: invokeStats.callIn();
174:
175: if (unadvisedMethod != null
176: && isHomeMethod(unadvisedMethod)) {
177: return invokeLocalHomeMethod(info, args);
178: } else if (unadvisedMethod != null
179: && isEJBObjectMethod(unadvisedMethod)) {
180: return invokeEJBLocalObjectMethod(id, info, args);
181: }
182:
183: StatefulContainerInvocation nextInvocation = new StatefulContainerInvocation(
184: info, id);
185: nextInvocation.setAdvisor(this );
186: nextInvocation.setArguments(args);
187:
188: ProxyUtils.addLocalAsynchronousInfo(nextInvocation,
189: provider);
190:
191: invokedMethod.push(new InvokedMethod(true, method));
192: return nextInvocation.invokeNext();
193: } finally {
194: if (unadvisedMethod != null) {
195: long end = System.currentTimeMillis();
196: long elapsed = end - start;
197: invokeStats.updateStats(unadvisedMethod, elapsed);
198: }
199:
200: invokeStats.callOut();
201:
202: invokedMethod.pop();
203: }
204: } finally {
205: Thread.currentThread().setContextClassLoader(oldLoader);
206: popEnc();
207: }
208: }
209:
210: /**
211: * Create a stateful bean and return its oid.
212: *
213: * @return
214: */
215: public Object createSession() {
216: ClassLoader oldLoader = Thread.currentThread()
217: .getContextClassLoader();
218: pushEnc();
219: try {
220: Thread.currentThread().setContextClassLoader(classloader);
221: return getCache().create().getId();
222: } finally {
223: Thread.currentThread().setContextClassLoader(oldLoader);
224: popEnc();
225: }
226: }
227:
228: /**
229: * Create a stateful bean and return its oid.
230: *
231: * @return
232: */
233: public Object createSession(Class[] initTypes, Object[] initValues) {
234: ClassLoader oldLoader = Thread.currentThread()
235: .getContextClassLoader();
236: pushEnc();
237: try {
238: Thread.currentThread().setContextClassLoader(classloader);
239: return getCache().create(initTypes, initValues).getId();
240: } finally {
241: Thread.currentThread().setContextClassLoader(oldLoader);
242: popEnc();
243: }
244: }
245:
246: protected void destroySession(Object id) {
247: getCache().remove(id);
248: }
249:
250: /**
251: * This should be a remote invocation call
252: *
253: * @param invocation
254: * @return
255: * @throws Throwable
256: */
257: public InvocationResponse dynamicInvoke(Object target,
258: Invocation invocation) throws Throwable {
259: long start = System.currentTimeMillis();
260:
261: ClassLoader oldLoader = Thread.currentThread()
262: .getContextClassLoader();
263: EJBContainerInvocation newSi = null;
264: pushEnc();
265: try {
266: Thread.currentThread().setContextClassLoader(classloader);
267: StatefulRemoteInvocation si = (StatefulRemoteInvocation) invocation;
268: MethodInfo info = (MethodInfo) methodInterceptors.get(si
269: .getMethodHash());
270: if (info == null) {
271: throw new RuntimeException(
272: "Could not resolve beanClass method from proxy call");
273: }
274:
275: InvocationResponse response = null;
276: Method unadvisedMethod = info.getUnadvisedMethod();
277: Object newId = null;
278:
279: try {
280: invokeStats.callIn();
281:
282: if (info != null && unadvisedMethod != null
283: && isHomeMethod(unadvisedMethod)) {
284: response = invokeHomeMethod(info, si);
285: } else if (info != null && unadvisedMethod != null
286: && isEJBObjectMethod(unadvisedMethod)) {
287: response = invokeEJBObjectMethod(info, si);
288: } else {
289: if (si.getId() == null) {
290: StatefulBeanContext ctx = getCache().create();
291: newId = ctx.getId();
292: } else {
293: newId = si.getId();
294: }
295: newSi = new StatefulContainerInvocation(info, newId);
296: newSi.setArguments(si.getArguments());
297: newSi.setMetaData(si.getMetaData());
298: newSi.setAdvisor(this );
299:
300: Object rtn = null;
301:
302: invokedMethod.push(new InvokedMethod(false,
303: unadvisedMethod));
304: rtn = newSi.invokeNext();
305:
306: response = marshallResponse(invocation, rtn, newSi
307: .getResponseContextInfo());
308: if (newId != null)
309: response.addAttachment(
310: StatefulConstants.NEW_ID, newId);
311: }
312: } catch (Throwable throwable) {
313: Throwable exception = throwable;
314: if (newId != null) {
315: exception = new ForwardId(throwable, newId);
316: }
317: Map responseContext = null;
318: if (newSi != null)
319: newSi.getResponseContextInfo();
320: response = marshallException(invocation, exception,
321: responseContext);
322: return response;
323: } finally {
324: if (unadvisedMethod != null) {
325: long end = System.currentTimeMillis();
326: long elapsed = end - start;
327: invokeStats.updateStats(unadvisedMethod, elapsed);
328: }
329:
330: invokeStats.callOut();
331:
332: invokedMethod.pop();
333: }
334:
335: return response;
336: } finally {
337: Thread.currentThread().setContextClassLoader(oldLoader);
338: popEnc();
339: }
340: }
341:
342: public TimerService getTimerService() {
343: throw new UnsupportedOperationException(
344: "stateful bean doesn't support TimerService (EJB3 18.2#2)");
345: }
346:
347: public TimerService getTimerService(Object pKey) {
348: return getTimerService();
349: }
350:
351: @Override
352: public void invokePostActivate(BeanContext beanContext) {
353: for (Injector injector : injectors) {
354: if (injector instanceof JndiFieldInjector) {
355: Field field = ((JndiFieldInjector) injector).getField();
356: if (field.isAnnotationPresent(javax.ejb.EJB.class)) {
357: continue; // skip nested EJB injection since the local proxy will be (de)serialized correctly
358: }
359: injector.inject(beanContext);
360: }
361: }
362: callbackHandler.postActivate(beanContext);
363: }
364:
365: @Override
366: public void invokePrePassivate(BeanContext beanContext) {
367: callbackHandler.prePassivate(beanContext);
368: }
369:
370: @Override
371: protected Class[] getHandledCallbacks() {
372: return new Class[] { PostConstruct.class, PreDestroy.class,
373: PostActivate.class, PrePassivate.class };
374: }
375:
376: public void invokeInit(Object bean) {
377: try {
378: Method[] methods = bean.getClass().getDeclaredMethods();
379:
380: for (int i = 0; i < methods.length; i++) {
381: if (methods[i].getParameterTypes().length == 0) {
382: if ((methods[i].getAnnotation(Init.class) != null)
383: || (resolveAnnotation(methods[i],
384: Init.class) != null)) {
385: methods[i].invoke(bean, new Object[0]);
386: }
387: }
388: }
389: } catch (Exception e) {
390: throw new RuntimeException(e);
391: }
392: }
393:
394: public void invokeInit(Object bean, Class[] initParameterTypes,
395: Object[] initParameterValues) {
396: try {
397: Method[] methods = bean.getClass().getDeclaredMethods();
398:
399: for (int i = 0; i < methods.length; i++) {
400: if ((methods[i].getAnnotation(Init.class) != null)
401: || (resolveAnnotation(methods[i], Init.class) != null)) {
402: Object[] parameters = getInitParameters(methods[i],
403: initParameterTypes, initParameterValues);
404:
405: if (parameters != null)
406: methods[i].invoke(bean, parameters);
407: }
408: }
409: } catch (Exception e) {
410: throw new RuntimeException(e);
411: }
412: }
413:
414: protected Object[] getInitParameters(Method method,
415: Class[] initParameterTypes, Object[] initParameterValues) {
416: if (method.getParameterTypes().length == initParameterTypes.length) {
417: for (int i = 0; i < initParameterTypes.length; ++i) {
418: Class formal = method.getParameterTypes()[i];
419: Class actual = initParameterTypes[i];
420: if (!isMethodInvocationConvertible(formal,
421: actual == null ? null : actual))
422: return null;
423: }
424: return initParameterValues;
425: }
426: return null;
427: }
428:
429: /**
430: * Determines whether a type represented by a class object is convertible to
431: * another type represented by a class object using a method invocation
432: * conversion, treating object types of primitive types as if they were
433: * primitive types (that is, a Boolean actual parameter type matches boolean
434: * primitive formal type). This behavior is because this method is used to
435: * determine applicable methods for an actual parameter list, and primitive
436: * types are represented by their object duals in reflective method calls.
437: *
438: * @param formal the formal parameter type to which the actual parameter type
439: * should be convertible
440: * @param actual the actual parameter type.
441: * @return true if either formal type is assignable from actual type, or
442: * formal is a primitive type and actual is its corresponding object
443: * type or an object type of a primitive type that can be converted
444: * to the formal type.
445: */
446: private static boolean isMethodInvocationConvertible(Class formal,
447: Class actual) {
448: /*
449: * if it's a null, it means the arg was null
450: */
451: if (actual == null && !formal.isPrimitive()) {
452: return true;
453: }
454: /*
455: * Check for identity or widening reference conversion
456: */
457: if (actual != null && formal.isAssignableFrom(actual)) {
458: return true;
459: }
460: /*
461: * Check for boxing with widening primitive conversion. Note that actual
462: * parameters are never primitives.
463: */
464: if (formal.isPrimitive()) {
465: if (formal == Boolean.TYPE && actual == Boolean.class)
466: return true;
467: if (formal == Character.TYPE && actual == Character.class)
468: return true;
469: if (formal == Byte.TYPE && actual == Byte.class)
470: return true;
471: if (formal == Short.TYPE
472: && (actual == Short.class || actual == Byte.class))
473: return true;
474: if (formal == Integer.TYPE
475: && (actual == Integer.class
476: || actual == Short.class || actual == Byte.class))
477: return true;
478: if (formal == Long.TYPE
479: && (actual == Long.class || actual == Integer.class
480: || actual == Short.class || actual == Byte.class))
481: return true;
482: if (formal == Float.TYPE
483: && (actual == Float.class || actual == Long.class
484: || actual == Integer.class
485: || actual == Short.class || actual == Byte.class))
486: return true;
487: if (formal == Double.TYPE
488: && (actual == Double.class || actual == Float.class
489: || actual == Long.class
490: || actual == Integer.class
491: || actual == Short.class || actual == Byte.class))
492: return true;
493: }
494: return false;
495: }
496:
497: private Object invokeEJBLocalObjectMethod(Object id,
498: MethodInfo info, Object[] args) throws Exception {
499: Method unadvisedMethod = info.getUnadvisedMethod();
500: if (unadvisedMethod.getName().equals("remove")) {
501: destroySession(id);
502:
503: return null;
504: } else if (unadvisedMethod.getName().equals("getEJBLocalHome")) {
505: Object bean = getCache().get(id).getInstance();
506:
507: return bean;
508: } else if (unadvisedMethod.getName().equals("getPrimaryKey")) {
509: return id;
510: } else if (unadvisedMethod.getName().equals("isIdentical")) {
511: EJBObject bean = (EJBObject) args[0];
512:
513: Object primaryKey = bean.getPrimaryKey();
514:
515: boolean isIdentical = id.equals(primaryKey);
516:
517: return isIdentical;
518: } else {
519: return null;
520: }
521: }
522:
523: private Object invokeLocalHomeMethod(MethodInfo info, Object[] args)
524: throws Exception {
525: Method unadvisedMethod = info.getUnadvisedMethod();
526: if (unadvisedMethod.getName().equals("create")) {
527: Class[] initParameterTypes = {};
528: Object[] initParameterValues = {};
529: if (unadvisedMethod.getParameterTypes().length > 0) {
530: initParameterTypes = unadvisedMethod
531: .getParameterTypes();
532: initParameterValues = args;
533: }
534:
535: LocalBinding binding = (LocalBinding) resolveAnnotation(LocalBinding.class);
536:
537: StatefulLocalProxyFactory factory = new StatefulLocalProxyFactory();
538: factory.setContainer(this );
539: factory.init();
540:
541: Object proxy = factory.createProxy(initParameterTypes,
542: initParameterValues);
543:
544: return proxy;
545: } else if (unadvisedMethod.getName().equals("remove")) {
546: StatefulHandleImpl handle = (StatefulHandleImpl) args[0];
547:
548: destroySession(handle.id);
549:
550: return null;
551: } else {
552: return null;
553: }
554: }
555:
556: public Object createLocalProxy(Object id) throws Exception {
557: StatefulLocalProxyFactory factory = new StatefulLocalProxyFactory();
558: factory.setContainer(this );
559: factory.init();
560:
561: return factory.createProxy(id);
562: }
563:
564: public Object createRemoteProxy(Object id) throws Exception {
565: RemoteBinding binding = null;
566: RemoteBindings bindings = (RemoteBindings) resolveAnnotation(RemoteBindings.class);
567: if (bindings != null)
568: binding = bindings.value()[0];
569: else
570: binding = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
571:
572: StatefulRemoteProxyFactory factory = new StatefulRemoteProxyFactory();
573: factory.setContainer(this );
574: factory.setRemoteBinding(binding);
575: factory.init();
576:
577: if (id != null)
578: return factory.createProxy(id);
579: else
580: return factory.createProxy();
581: }
582:
583: protected InvocationResponse invokeHomeMethod(MethodInfo info,
584: StatefulRemoteInvocation statefulInvocation)
585: throws Throwable {
586: Method unadvisedMethod = info.getUnadvisedMethod();
587: if (unadvisedMethod.getName().equals("create")) {
588: Class[] initParameterTypes = {};
589: Object[] initParameterValues = {};
590: if (unadvisedMethod.getParameterTypes().length > 0) {
591: initParameterTypes = unadvisedMethod
592: .getParameterTypes();
593: initParameterValues = statefulInvocation.getArguments();
594: }
595:
596: StatefulContainerInvocation newStatefulInvocation = buildNewInvocation(
597: info, statefulInvocation, initParameterTypes,
598: initParameterValues);
599:
600: Object proxy = createRemoteProxy(newStatefulInvocation
601: .getId());
602:
603: InvocationResponse response = marshallResponse(
604: statefulInvocation, proxy, newStatefulInvocation
605: .getResponseContextInfo());
606: if (newStatefulInvocation.getId() != null)
607: response.addAttachment(StatefulConstants.NEW_ID,
608: newStatefulInvocation.getId());
609: return response;
610: } else if (unadvisedMethod.getName().equals("remove")) {
611: StatefulHandleImpl handle = (StatefulHandleImpl) statefulInvocation
612: .getArguments()[0];
613:
614: destroySession(handle.id);
615:
616: InvocationResponse response = new InvocationResponse(null);
617: response.setContextInfo(statefulInvocation
618: .getResponseContextInfo());
619: return response;
620: } else if (unadvisedMethod.getName().equals("getEJBMetaData")) {
621: Class remote = null;
622: Class home = null;
623: Class pkClass = Object.class;
624: HomeHandleImpl homeHandle = null;
625:
626: Remote remoteAnnotation = (Remote) resolveAnnotation(Remote.class);
627: if (remoteAnnotation != null)
628: remote = remoteAnnotation.value()[0];
629: RemoteHome homeAnnotation = (RemoteHome) resolveAnnotation(RemoteHome.class);
630: if (homeAnnotation != null)
631: home = homeAnnotation.value();
632: RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
633: if (remoteBindingAnnotation != null)
634: homeHandle = new HomeHandleImpl(remoteBindingAnnotation
635: .jndiBinding());
636:
637: EJBMetaDataImpl metadata = new EJBMetaDataImpl(remote,
638: home, pkClass, true, false, homeHandle);
639:
640: InvocationResponse response = marshallResponse(
641: statefulInvocation, metadata, null);
642: return response;
643: } else if (unadvisedMethod.getName().equals("getHomeHandle")) {
644: HomeHandleImpl homeHandle = null;
645:
646: RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
647: if (remoteBindingAnnotation != null)
648: homeHandle = new HomeHandleImpl(remoteBindingAnnotation
649: .jndiBinding());
650:
651: InvocationResponse response = marshallResponse(
652: statefulInvocation, homeHandle, null);
653: return response;
654: } else {
655: return null;
656: }
657: }
658:
659: protected InvocationResponse invokeEJBObjectMethod(MethodInfo info,
660: StatefulRemoteInvocation statefulInvocation)
661: throws Throwable {
662: Method unadvisedMethod = info.getUnadvisedMethod();
663: if (unadvisedMethod.getName().equals("getHandle")) {
664: StatefulContainerInvocation newStatefulInvocation = buildInvocation(
665: info, statefulInvocation);
666:
667: StatefulHandleImpl handle = new StatefulHandleImpl();
668: handle.id = newStatefulInvocation.getId();
669: RemoteBinding remoteBinding = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
670: if (remoteBinding != null)
671: handle.jndiName = remoteBinding.jndiBinding();
672: InvocationResponse response = marshallResponse(
673: statefulInvocation, handle, null);
674: return response;
675: } else if (unadvisedMethod.getName().equals("remove")) {
676: destroySession(statefulInvocation.getId());
677:
678: InvocationResponse response = new InvocationResponse(null);
679: return response;
680: } else if (unadvisedMethod.getName().equals("getEJBHome")) {
681: HomeHandleImpl homeHandle = null;
682:
683: RemoteBinding remoteBindingAnnotation = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
684: if (remoteBindingAnnotation != null)
685: homeHandle = new HomeHandleImpl(ProxyFactoryHelper
686: .getHomeJndiName(this ));
687:
688: EJBHome ejbHome = homeHandle.getEJBHome();
689:
690: InvocationResponse response = marshallResponse(
691: statefulInvocation, ejbHome, null);
692: return response;
693: } else if (unadvisedMethod.getName().equals("getPrimaryKey")) {
694: Object id = statefulInvocation.getId();
695:
696: InvocationResponse response = marshallResponse(
697: statefulInvocation, id, null);
698: return response;
699: } else if (unadvisedMethod.getName().equals("isIdentical")) {
700: Object id = statefulInvocation.getId();
701: EJBObject bean = (EJBObject) statefulInvocation
702: .getArguments()[0];
703:
704: Object primaryKey = bean.getPrimaryKey();
705:
706: boolean isIdentical = id.equals(primaryKey);
707:
708: InvocationResponse response = marshallResponse(
709: statefulInvocation, isIdentical, null);
710: return response;
711: } else {
712: return null;
713: }
714: }
715:
716: private StatefulContainerInvocation buildNewInvocation(
717: MethodInfo info,
718: StatefulRemoteInvocation statefulInvocation,
719: Class[] initParameterTypes, Object[] initParameterValues) {
720: StatefulContainerInvocation newStatefulInvocation = null;
721:
722: StatefulBeanContext ctx = null;
723: if (initParameterTypes.length > 0)
724: ctx = getCache().create(initParameterTypes,
725: initParameterValues);
726: else
727: ctx = getCache().create();
728:
729: Object newId = ctx.getId();
730: newStatefulInvocation = new StatefulContainerInvocation(info,
731: newId);
732:
733: newStatefulInvocation.setArguments(statefulInvocation
734: .getArguments());
735: newStatefulInvocation.setMetaData(statefulInvocation
736: .getMetaData());
737: newStatefulInvocation.setAdvisor(this );
738:
739: return newStatefulInvocation;
740: }
741:
742: private StatefulContainerInvocation buildInvocation(
743: MethodInfo info, StatefulRemoteInvocation statefulInvocation) {
744: StatefulContainerInvocation newStatefulInvocation = null;
745: Object newId = null;
746: if (statefulInvocation.getId() == null) {
747: StatefulBeanContext ctx = getCache().create();
748: newId = ctx.getId();
749: newStatefulInvocation = new StatefulContainerInvocation(
750: info, newId);
751: } else {
752: newStatefulInvocation = new StatefulContainerInvocation(
753: info, statefulInvocation.getId());
754: }
755:
756: newStatefulInvocation.setArguments(statefulInvocation
757: .getArguments());
758: newStatefulInvocation.setMetaData(statefulInvocation
759: .getMetaData());
760: newStatefulInvocation.setAdvisor(this );
761:
762: return newStatefulInvocation;
763: }
764:
765: @Override
766: public Object getBusinessObject(BeanContext beanContext,
767: Class businessInterface) throws IllegalStateException {
768: StatefulBeanContext ctx = (StatefulBeanContext) beanContext;
769:
770: boolean isRemote = false;
771: boolean found = false;
772: Class[] remoteInterfaces = ProxyFactoryHelper
773: .getRemoteInterfaces(this );
774: if (remoteInterfaces != null) {
775: for (Class intf : remoteInterfaces) {
776: if (intf.getName().equals(businessInterface.getName())) {
777: isRemote = true;
778: found = true;
779: break;
780: }
781: }
782: }
783: if (found == false) {
784: Class[] localInterfaces = ProxyFactoryHelper
785: .getLocalInterfaces(this );
786: if (localInterfaces != null) {
787: for (Class intf : localInterfaces) {
788: if (intf.getName().equals(
789: businessInterface.getName())) {
790: found = true;
791: break;
792: }
793: }
794:
795: }
796: }
797: if (found == false)
798: throw new IllegalStateException(businessInterface.getName()
799: + " is not a business interface");
800:
801: for (ProxyFactory factory : proxyDeployer.getProxyFactories()) {
802: if (isRemote
803: && factory instanceof StatefulRemoteProxyFactory) {
804: return ((StatefulRemoteProxyFactory) factory)
805: .createProxy(ctx.getId());
806: } else if (!isRemote
807: && factory instanceof StatefulLocalProxyFactory) {
808: return ((StatefulLocalProxyFactory) factory)
809: .createProxy(ctx.getId());
810: }
811: }
812: throw new IllegalStateException(
813: "Unable to create proxy for getBusinessObject as a proxy factory was not found");
814: }
815:
816: protected void removeHandle(Handle arg) throws Exception {
817: /*
818: StatefulHandleImpl handle = (StatefulHandleImpl) arg;
819:
820: destroySession(handle.id);
821: */
822: arg.getEJBObject().remove();
823: }
824: }
|