/* * 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.message; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.MessageDrivenBean; import javax.ejb.MessageDrivenContext; import javax.enterprise.inject.spi.AnnotatedType; import javax.resource.spi.ActivationSpec; import javax.resource.spi.ResourceAdapter; import javax.resource.spi.UnavailableException; import javax.resource.spi.endpoint.MessageEndpoint; import javax.resource.spi.endpoint.MessageEndpointFactory; import javax.transaction.UserTransaction; import javax.transaction.xa.XAResource; import com.caucho.config.ConfigException; import com.caucho.config.gen.BeanGenerator; import com.caucho.config.inject.BeanBuilder; import com.caucho.config.inject.InjectManager; import com.caucho.config.inject.InjectionTargetBuilder; import com.caucho.config.inject.OwnerCreationalContext; import com.caucho.config.reflect.ReflectionAnnotatedFactory; import com.caucho.ejb.cfg.EjbLazyGenerator; import com.caucho.ejb.gen.MessageGenerator; import com.caucho.ejb.manager.EjbManager; import com.caucho.ejb.server.AbstractContext; import com.caucho.ejb.server.AbstractEjbBeanManager; import com.caucho.inject.Module; import com.caucho.java.gen.JavaClassGenerator; import com.caucho.util.L10N; /** * JCA activation-spec server container for a message bean. */ @Module public class MessageManager<X> extends AbstractEjbBeanManager<X> implements MessageEndpointFactory { private static final L10N L = new L10N(MessageManager.class); protected static final Logger log = Logger.getLogger(MessageManager.class.getName()); private ResourceAdapter _ra; private ActivationSpec _activationSpec; private MessageDrivenContext _context; private EjbLazyGenerator<X> _lazyGenerator; private Class<X> _proxyImplClass; private InjectionTargetBuilder<X> _builder; private Method _ejbCreate; public MessageManager(EjbManager ejbContainer, String ejbName, String moduleName, AnnotatedType<X> rawAnnType, AnnotatedType<X> annotatedType, EjbLazyGenerator<X> lazyGenerator) { super(ejbContainer, ejbName, moduleName, rawAnnType, annotatedType); InjectManager webBeans = InjectManager.create(); UserTransaction ut = webBeans.getReference(UserTransaction.class); _lazyGenerator = lazyGenerator; // ejb/0fbl _context = new MessageDrivenContextImpl(this, ut); } protected String getType() { return "message:"; } /** * Sets the activation spec */ public void setActivationSpec(ActivationSpec activationSpec) { _activationSpec = activationSpec; } /** * Sets the resource adapter */ public void setResourceAdapter(ResourceAdapter ra) { _ra = ra; } @Override public ArrayList<AnnotatedType<? super X>> getLocalApi() { return new ArrayList<AnnotatedType<? super X>>(); } /** * Initialize the server */ @Override public void init() throws Exception { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); super.init(); if (_activationSpec == null) throw error(L.l("ActivationSpec is missing from message-driven bean '{0}'.", getEJBName())); if (_ra == null) throw error(L.l("ResourceAdapter is missing from message-driven bean '{0}'.", getEJBName())); bindContext(); } finally { thread.setContextClassLoader(oldLoader); } } @Override public void bind() { try { boolean isAutoCompile = true; if (_proxyImplClass == null) { BeanGenerator<X> beanGen = createBeanGenerator(); String fullClassName = beanGen.getFullClassName(); JavaClassGenerator javaGen = _lazyGenerator.getJavaClassGenerator(); if (javaGen.preload(fullClassName) != null) { } else if (isAutoCompile) { beanGen.introspect(); javaGen.generate(beanGen); } javaGen.compilePendingJava(); _proxyImplClass = (Class<X>) javaGen.loadClass(fullClassName); InjectManager cdiManager = InjectManager.create(getClassLoader()); AnnotatedType annType = ReflectionAnnotatedFactory.introspectType(_proxyImplClass); _builder = new InjectionTargetBuilder(cdiManager, annType, null); try { Class<?> beanClass = _proxyImplClass;//getBeanSkelClass(); if (beanClass == null) beanClass = getAnnotatedType().getJavaClass(); if (beanClass != null) _ejbCreate = beanClass.getMethod("ejbCreate", new Class[0]); // getProducer().bindInjection(); } catch (Exception e) { log.log(Level.FINEST, e.toString(), e); } } } catch (Exception e) { throw ConfigException.create(e); } } /** * Creates the bean generator for the session bean. */ protected BeanGenerator<X> createBeanGenerator() { AnnotatedType<X> ejbClass = getAnnotatedType(); return new MessageGenerator<X>(getEJBName(), ejbClass); } @Override protected void bindContext() { super.bindContext(); InjectManager manager = InjectManager.create(); BeanBuilder<?> factory = manager.createBeanFactory(_context.getClass()); manager.addBean(factory.singleton(_context)); } /** * Starts the server. */ @Override public boolean start() throws Exception { if (! super.start()) return false; // _ra.start(ResourceManagerImpl.create()); _ra.endpointActivation(this, _activationSpec); return true; } /** * Returns the message driven context */ public MessageDrivenContext getMessageContext() { return _context; } void generate() throws Exception { } @Override public AbstractContext getContext(Object obj, boolean foo) { throw new UnsupportedOperationException(); } /** * Creates an endpoint with the associated XA resource. */ @Override public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException { return createEndpoint(xaResource, 0); } /** * Creates an endpoint with the associated XA resource. */ public MessageEndpoint createEndpoint(XAResource xaResource, long timeout) throws UnavailableException { try { Object listener = createMessageListener(); ((CauchoMessageEndpoint) listener).__caucho_setXAResource(xaResource); return (MessageEndpoint) listener; } catch (RuntimeException e) { throw e; } catch (InvocationTargetException e) { if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause(); if (e.getCause() != null) throw new UnavailableException(e.getCause()); else throw new UnavailableException(e); } catch (Exception e) { throw new RuntimeException(e); } } /** * Returns true to find out whether message deliveries to the * message endpoint will be transacted. This is only a hint. */ public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException { return false; } private X createMessageListener() throws Exception { Thread thread = Thread.currentThread(); ClassLoader oldLoader = thread.getContextClassLoader(); try { thread.setContextClassLoader(getClassLoader()); OwnerCreationalContext<X> env = new OwnerCreationalContext<X>(null); X listener = _builder.produce(env); _builder.inject(listener, env); if (listener instanceof MessageDrivenBean) { MessageDrivenBean bean = (MessageDrivenBean) listener; bean.setMessageDrivenContext(_context); } //initInstance(listener); if (_ejbCreate != null) _ejbCreate.invoke(listener); /* if (listener instanceof CandiEnhancedBean) { CandiEnhancedBean bean = (CandiEnhancedBean) listener; bean.__caucho_postConstruct(); } */ _builder.postConstruct(listener); return listener; } finally { thread.setContextClassLoader(oldLoader); } } /** * Cleans up the entity server nicely. */ @Override public void destroy() { _ra.endpointDeactivation(this, _activationSpec); } /* (non-Javadoc) * @see com.caucho.ejb.server.AbstractEjbBeanManager#getLocalJndiProxy(java.lang.Class) */ @Override public <T> Object getLocalJndiProxy(Class<T> api) { // TODO Auto-generated method stub return null; } /* (non-Javadoc) * @see com.caucho.ejb.server.AbstractEjbBeanManager#getLocalProxy(java.lang.Class) */ @Override public <T> T getLocalProxy(Class<T> api) { // TODO Auto-generated method stub return null; } /* (non-Javadoc) * @see com.caucho.ejb.server.AbstractEjbBeanManager#getRemoteObject(java.lang.Class, java.lang.String) */ @Override public <T> T getRemoteObject(Class<T> api, String protocol) { // TODO Auto-generated method stub return null; } }