/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.ejb.session; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.Decorator; import javax.enterprise.inject.spi.Interceptor; import javax.enterprise.inject.spi.SessionBeanType; import com.caucho.config.ConfigException; import com.caucho.config.gen.BeanGenerator; import com.caucho.config.gen.CandiEnhancedBean; import com.caucho.config.gen.CandiUtil; import com.caucho.config.inject.CreationalContextImpl; import com.caucho.config.inject.InjectManager; import com.caucho.config.inject.ManagedBeanImpl; import com.caucho.config.reflect.BaseType; import com.caucho.config.reflect.ReflectionAnnotatedType; import com.caucho.ejb.SessionPool; import com.caucho.ejb.cfg.EjbLazyGenerator; import com.caucho.ejb.gen.StatefulGenerator; import com.caucho.ejb.gen.StatelessGenerator; import com.caucho.ejb.inject.StatelessBeanImpl; import com.caucho.ejb.manager.EjbManager; import com.caucho.ejb.server.AbstractContext; import com.caucho.ejb.server.EjbInjectionTarget; import com.caucho.ejb.server.SingletonInjectionTarget; import com.caucho.ejb.server.StatelessInjectionTarget; import com.caucho.util.L10N; /** * Server home container for a stateless session bean */ public class StatelessManager<X> extends AbstractSessionManager<X> { private static final L10N L = new L10N(StatelessManager.class); private static Logger log = Logger.getLogger(StatelessManager.class.getName()); private int _sessionIdleMax = 16; private int _sessionConcurrentMax = -1; private long _sessionConcurrentTimeout = -1; private ThreadLocal<StatelessPool<X,?>> _localSessionPool = new ThreadLocal<StatelessPool<X,?>>(); private Object _decoratorClass; private List<Decorator<?>> _decoratorBeans; /** * Creates a new stateless server. * * @param urlPrefix * the url prefix for any request to the server * @param allowJVMCall * allows fast calls to the same JVM (with serialization) * @param config * the session configuration from the ejb.xml */ public StatelessManager(EjbManager ejbContainer, String ejbName, String moduleName, AnnotatedType<X> rawAnnType, AnnotatedType<X> annotatedType, EjbLazyGenerator<X> ejbGenerator) { super(ejbContainer, ejbName, moduleName, rawAnnType, annotatedType, ejbGenerator); introspect(); } @Override protected String getType() { return "stateless:"; } @Override protected SessionBeanType getSessionBeanType() { return SessionBeanType.STATELESS; } public int getSessionIdleMax() { return _sessionIdleMax; } public int getSessionConcurrentMax() { return _sessionConcurrentMax; } public long getSessionConcurrentTimeout() { return _sessionConcurrentTimeout; } @Override protected <T> StatelessContext<X,T> getSessionContext(Class<T> api) { return (StatelessContext<X,T>) super.getSessionContext(api); } /** * Returns the JNDI proxy object to create instances of the local interface. */ @Override public <T> Object getLocalJndiProxy(Class<T> api) { StatelessContext<X,T> context = getSessionContext(api); return new StatelessProviderProxy<X,T>(context.createProxy(null)); } /** * Returns the object implementation */ @Override public <T> T getLocalProxy(Class<T> api) { return getSessionContext(api).createProxy(null); } public void setLocalStatelessPool(StatelessPool<X,?> pool) { _localSessionPool.set(pool); } public StatelessPool<X,?> getLocalStatelessPool() { return _localSessionPool.get(); } @Override protected <T> Bean<T> createBean(ManagedBeanImpl<X> mBean, Class<T> api, Set<Type> apiList, AnnotatedType<X> extAnnType) { StatelessContext<X,T> context = getSessionContext(api); if (context == null) throw new NullPointerException(L.l("'{0}' is an unknown api for {1}", api, this)); StatelessBeanImpl<X,T> statelessBean = new StatelessBeanImpl<X,T>(this, mBean, api, apiList, context, extAnnType); return statelessBean; } @Override protected Class<?> getContextClass() { return StatelessContext.class; } /** * Creates the bean generator for the session bean. */ @Override protected BeanGenerator<X> createBeanGenerator() { EjbLazyGenerator<X> lazyGen = getLazyGenerator(); return new StatelessGenerator<X>(getEJBName(), getAnnotatedType(), lazyGen.getLocalApi(), lazyGen.getLocalBean(), lazyGen.getRemoteApi()); } /** * Called by the StatelessProxy on initialization. */ public <T> StatelessPool<X,T> createStatelessPool(StatelessProxyFactory proxy, StatelessContext<X,T> context, List<Interceptor<?>> interceptorBeans) { return new StatelessPool<X,T>(this, proxy, context, interceptorBeans); } @Override protected EjbInjectionTarget<X> createInjectionTarget() { return new StatelessInjectionTarget<X>(this, getAnnotatedType()); } /** * Returns the remote stub for the container */ @Override public <T> T getRemoteObject(Class<T> api, String protocol) { if (api == null) return null; StatelessContext<X,T> context = getSessionContext(api); if (context != null) { T result = context.createProxy(null); return result; } else { log.fine(this + " unknown api " + api.getName()); return null; } } @Override public void init() throws Exception { super.init(); } private void introspect() { AnnotatedType<?> annType = getAnnotatedType(); SessionPool sessionPool = annType.getAnnotation(SessionPool.class); if (sessionPool != null) { if (sessionPool.maxIdle() >= 0) _sessionIdleMax = sessionPool.maxIdle(); if (sessionPool.maxConcurrent() >= 0) _sessionConcurrentMax = sessionPool.maxConcurrent(); if (sessionPool.maxConcurrentTimeout() >= 0) _sessionConcurrentTimeout = sessionPool.maxConcurrentTimeout(); } } @Override protected <T> StatelessContext<X,T> createSessionContext(Class<T> api) { return new StatelessContext<X,T>(this, api); } @Override protected void postStart() { } @Override public AbstractContext getContext(Object key, boolean forceLoad) { return getContext(); } // XXX public Object[] getInterceptorBindings(List<Interceptor<?>> interceptorBeans, CreationalContextImpl<?> parentEnv) { int size = interceptorBeans.size(); if (size == 0) return null; Object []interceptors = new Object[size]; for (int i = 0; i < size; i++) { Interceptor<?> bean = interceptorBeans.get(i); interceptors[i] = getInjectManager().getReference(bean, parentEnv); } return interceptors; } @Override public void bind() { super.bind(); Class<?> instanceClass = getProxyImplClass(); if (instanceClass != null) { try { Method method = instanceClass.getMethod("__caucho_decorator_init"); _decoratorClass = method.invoke(null); Annotation []qualifiers = new Annotation[getBean().getQualifiers().size()]; getBean().getQualifiers().toArray(qualifiers); InjectManager moduleBeanManager = InjectManager.create(); Class<?> ejbClass = getAnnotatedType().getJavaClass(); BaseType type = BaseType.createGenericClass(ejbClass); Set<Type> types = type.getTypeClosure(moduleBeanManager); _decoratorBeans = moduleBeanManager.resolveDecorators(types); method = instanceClass.getMethod("__caucho_init_decorators", List.class); method.invoke(null, _decoratorBeans); } catch (InvocationTargetException e) { throw ConfigException.create(e.getCause()); } catch (Exception e) { log.log(Level.FINEST, e.toString(), e); } } } Object []createDelegates(CreationalContextImpl<?> env) { if (_decoratorBeans != null) { // if (env != null) // env.setInjectionPoint(oldPoint); return CandiUtil.generateProxyDelegate(getInjectManager(), _decoratorBeans, _decoratorClass, env); } else return null; } }