001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020 package org.granite.cdi;
021
022 import java.lang.reflect.Method;
023
024 import javax.enterprise.context.Conversation;
025 import javax.enterprise.inject.spi.Bean;
026 import javax.enterprise.inject.spi.BeanManager;
027 import javax.servlet.http.HttpSession;
028
029 import org.granite.context.GraniteContext;
030 import org.granite.logging.Logger;
031 import org.granite.messaging.webapp.HttpGraniteContext;
032 import org.granite.util.TypeUtil;
033 import org.jboss.weld.bootstrap.api.Service;
034 import org.jboss.weld.manager.api.WeldManager;
035
036
037 public class Weld10ConversationManager implements CDIConversationManager {
038
039 private static final Logger log = Logger.getLogger(Weld10ConversationManager.class);
040
041 private Class<?> conversationManagerClass;
042 private Class<Service> contextLifecycleClass;
043
044 @SuppressWarnings("unchecked")
045 public Weld10ConversationManager() {
046 try {
047 conversationManagerClass = TypeUtil.forName("org.jboss.weld.conversation.ConversationManager");
048 contextLifecycleClass = (Class<Service>)TypeUtil.forName("org.jboss.weld.context.ContextLifecycle");
049 }
050 catch (Exception e) {
051 log.error(e, "Could not load ConversationManager class");
052 }
053 }
054
055 public Conversation initConversation(BeanManager beanManager, String conversationId) {
056 try {
057 Bean<?> conversationManagerBean = beanManager.getBeans(conversationManagerClass).iterator().next();
058 Object conversationManager = beanManager.getReference(conversationManagerBean, conversationManagerClass, beanManager.createCreationalContext(conversationManagerBean));
059 conversationManagerClass.getMethod("beginOrRestoreConversation", String.class).invoke(conversationManager, conversationId);
060
061 @SuppressWarnings("unchecked")
062 Bean<Conversation> conversationBean = (Bean<Conversation>)beanManager.getBeans(Conversation.class).iterator().next();
063 Conversation conversation = (Conversation)beanManager.getReference(conversationBean, Conversation.class, beanManager.createCreationalContext(conversationBean));
064
065 HttpGraniteContext context = (HttpGraniteContext)GraniteContext.getCurrentInstance();
066 String cid = (String)conversation.getClass().getMethod("getUnderlyingId").invoke(conversation);
067 Object conversationContext = lookupConversationContext((WeldManager)beanManager);
068 Object beanStore = TypeUtil.newInstance("org.jboss.weld.servlet.ConversationBeanStore", new Class<?>[] { HttpSession.class, boolean.class, String.class },
069 new Object[] { context.getSession(true), false, cid });
070 for (Method m : conversationContext.getClass().getMethods()) {
071 if ("setBeanStore".equals(m.getName())) {
072 m.invoke(conversationContext, beanStore);
073 break;
074 }
075 }
076 conversationContext.getClass().getMethod("setActive", boolean.class).invoke(conversationContext, true);
077 return conversation;
078 }
079 catch (Exception e) {
080 throw new RuntimeException("Could not init conversation", e);
081 }
082 }
083
084 public void destroyConversation(BeanManager beanManager) {
085 try {
086 Object conversationContext = lookupConversationContext((WeldManager)beanManager);
087 if ((Boolean)conversationContext.getClass().getMethod("isActive").invoke(conversationContext)) {
088 Bean<?> conversationManagerBean = beanManager.getBeans(conversationManagerClass).iterator().next();
089 Object conversationManager = beanManager.getReference(conversationManagerBean, conversationManagerClass, beanManager.createCreationalContext(conversationManagerBean));
090 conversationManagerClass.getMethod("cleanupConversation").invoke(conversationManager);
091 }
092 }
093 catch (Exception e) {
094 throw new RuntimeException("Could not destroy conversation", e);
095 }
096 }
097
098 private Object lookupConversationContext(WeldManager beanManager) throws Exception {
099 Object contextLifecycle = beanManager.getServices().get(contextLifecycleClass);
100 return contextLifecycle.getClass().getMethod("getConversationContext").invoke(contextLifecycle);
101 }
102 }