001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * Granite Data Services is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * Granite Data Services 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 Lesser 015 * 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 library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 020 * USA, or see <http://www.gnu.org/licenses/>. 021 */ 022package org.granite.config; 023 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.List; 027import java.util.Map; 028import java.util.concurrent.ConcurrentHashMap; 029 030import javax.servlet.ServletContext; 031import javax.servlet.ServletContextEvent; 032import javax.servlet.ServletContextListener; 033import javax.servlet.ServletException; 034import javax.servlet.http.HttpSession; 035import javax.servlet.http.HttpSessionEvent; 036import javax.servlet.http.HttpSessionListener; 037 038import org.granite.config.GraniteConfig.JMF_EXTENSIONS_MODE; 039import org.granite.config.flex.ServletServicesConfig; 040import org.granite.jmx.GraniteMBeanInitializer; 041import org.granite.logging.Logger; 042import org.granite.messaging.AliasRegistry; 043import org.granite.messaging.DefaultAliasRegistry; 044import org.granite.messaging.jmf.DefaultCodecRegistry; 045import org.granite.messaging.jmf.DefaultSharedContext; 046import org.granite.messaging.jmf.SharedContext; 047import org.granite.messaging.jmf.codec.ExtendedObjectCodec; 048import org.granite.messaging.jmf.codec.ExtendedObjectCodecService; 049import org.granite.messaging.reflect.Reflection; 050import org.granite.scan.ServiceLoader; 051import org.granite.util.JMFAMFUtil; 052import org.granite.util.ServletParams; 053 054 055/** 056 * @author William DRAI 057 */ 058public class GraniteConfigListener implements ServletContextListener, HttpSessionListener { 059 060 private static final String GRANITE_CONFIG_SHUTDOWN_KEY = GraniteConfig.class.getName() + "_SHUTDOWN"; 061 public static final String GRANITE_CONFIG_ATTRIBUTE = "org.granite.config.serverFilter"; 062 public static final String GRANITE_CONFIG_PROVIDER_ATTRIBUTE = "org.granite.config.configProvider"; 063 public static final String GRANITE_MBEANS_ATTRIBUTE = "registerGraniteMBeans"; 064 065 public static final String GRANITE_SESSION_TRACKING = "org.granite.config.sessionTracking"; 066 public static final String GRANITE_SESSION_MAP = "org.granite.config.sessionMap"; 067 068 public static final String JMF_INITIALIZATION = "jmf-initialization"; 069 public static final String SHARED_CONTEXT_KEY = SharedContext.class.getName(); 070 public static final String DUMP_SHARED_CONTEXT_KEY = SharedContext.class.getName() + ":DUMP"; 071 072 private static final Logger log = Logger.getLogger(GraniteConfigListener.class); 073 074 public void contextInitialized(ServletContextEvent sce) { 075 ServletContext context = sce.getServletContext(); 076 try { 077 log.info("Initializing GraniteDS..."); 078 079 ServiceConfigurator serviceConfigurator = (ServiceConfigurator)context.getAttribute(GRANITE_CONFIG_ATTRIBUTE); 080 if (serviceConfigurator != null) 081 serviceConfigurator.initialize(context); 082 083 GraniteConfig gConfig = ServletGraniteConfig.loadConfig(context); 084 085 if (serviceConfigurator != null) 086 serviceConfigurator.configureServices(context); 087 else 088 ServletServicesConfig.loadConfig(context); 089 090 if ("true".equals(context.getInitParameter(GRANITE_SESSION_TRACKING))) { 091 Map<String, HttpSession> sessionMap = new ConcurrentHashMap<String, HttpSession>(200); 092 context.setAttribute(GRANITE_SESSION_MAP, sessionMap); 093 } 094 095 if (gConfig.isRegisterMBeans()) { 096 GraniteMBeanInitializer.registerMBeans(context, 097 ServletGraniteConfig.getServletConfig(context), 098 ServletServicesConfig.getServletConfig(context)); 099 } 100 101 String jmfInitialization = context.getInitParameter(JMF_INITIALIZATION); 102 if (jmfInitialization == null || "true".equals(jmfInitialization)) 103 loadJMFSharedContext(context, gConfig); 104 105 log.info("GraniteDS initialized"); 106 } 107 catch (Exception e) { 108 throw new RuntimeException("Could not initialize Granite environment", e); 109 } 110 } 111 112 public void contextDestroyed(ServletContextEvent sce) { 113 ServletContext context = sce.getServletContext(); 114 115 log.info("Stopping GraniteDS..."); 116 117 @SuppressWarnings("unchecked") 118 List<ShutdownListener> listeners = (List<ShutdownListener>)sce.getServletContext().getAttribute(GRANITE_CONFIG_SHUTDOWN_KEY); 119 if (listeners != null) { 120 try { 121 for (ShutdownListener listener : listeners) 122 listener.stop(); 123 } 124 catch (Exception e) { 125 throw new RuntimeException("Could not destroy Granite environment", e); 126 } 127 } 128 129 if (ServletParams.get(context, GRANITE_MBEANS_ATTRIBUTE, Boolean.TYPE, false)) 130 GraniteMBeanInitializer.unregisterMBeans(context); 131 132 log.info("GraniteDS stopped"); 133 } 134 135 public static synchronized void registerShutdownListener(ServletContext context, ShutdownListener listener) { 136 @SuppressWarnings("unchecked") 137 List<ShutdownListener> listeners = (List<ShutdownListener>)context.getAttribute(GRANITE_CONFIG_SHUTDOWN_KEY); 138 if (listeners == null) { 139 listeners = new ArrayList<ShutdownListener>(); 140 context.setAttribute(GRANITE_CONFIG_SHUTDOWN_KEY, listeners); 141 } 142 listeners.add(listener); 143 } 144 145 146 public static interface ServiceConfigurator { 147 148 public void initialize(ServletContext context); 149 150 public void configureServices(ServletContext context) throws ServletException; 151 } 152 153 154 private static void loadJMFSharedContext(ServletContext servletContext, GraniteConfig graniteConfig) { 155 log.info("Loading JMF shared context"); 156 157 List<ExtendedObjectCodec> extendedObjectCodecs = null; 158 159 if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.REPLACE) 160 extendedObjectCodecs = graniteConfig.getJmfExtendedCodecs(); 161 else { 162 extendedObjectCodecs = new ArrayList<ExtendedObjectCodec>(); 163 164 if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.PREPPEND) 165 extendedObjectCodecs.addAll(graniteConfig.getJmfExtendedCodecs()); 166 167 for (ExtendedObjectCodecService service : ServiceLoader.load(ExtendedObjectCodecService.class)) 168 extendedObjectCodecs.addAll(Arrays.asList(service.getExtensions())); 169 170 if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.APPEND) 171 extendedObjectCodecs.addAll(graniteConfig.getJmfExtendedCodecs()); 172 } 173 174 log.debug("Using JMF extended codecs: %s", extendedObjectCodecs); 175 176 List<String> defaultStoredStrings = null; 177 if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.REPLACE) 178 defaultStoredStrings = graniteConfig.getJmfDefaultStoredStrings(); 179 else { 180 defaultStoredStrings = new ArrayList<String>(); 181 182 if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.PREPPEND) 183 defaultStoredStrings.addAll(graniteConfig.getJmfDefaultStoredStrings()); 184 185 defaultStoredStrings.addAll(JMFAMFUtil.AMF_DEFAULT_STORED_STRINGS); 186 187 if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.APPEND) 188 defaultStoredStrings.addAll(graniteConfig.getJmfDefaultStoredStrings()); 189 } 190 191 log.debug("Using JMF default stored strings: %s", defaultStoredStrings); 192 193 Reflection reflection = graniteConfig.getJmfReflection(); 194 195 log.debug("Using JMF reflection: %s", reflection.getClass().getName()); 196 197 AliasRegistry aliasRegistry = new DefaultAliasRegistry(); 198 199 SharedContext sharedContext = new DefaultSharedContext(new DefaultCodecRegistry(extendedObjectCodecs), defaultStoredStrings, reflection, aliasRegistry); 200 servletContext.setAttribute(SHARED_CONTEXT_KEY, sharedContext); 201 202 SharedContext dumpSharedContext = new DefaultSharedContext(new DefaultCodecRegistry(), defaultStoredStrings, reflection, aliasRegistry); 203 servletContext.setAttribute(DUMP_SHARED_CONTEXT_KEY, dumpSharedContext); 204 205 log.info("JMF shared context loaded"); 206 } 207 208 public static SharedContext getSharedContext(ServletContext servletContext) { 209 return (SharedContext)servletContext.getAttribute(SHARED_CONTEXT_KEY); 210 } 211 212 public static SharedContext getDumpSharedContext(ServletContext servletContext) { 213 return (SharedContext)servletContext.getAttribute(DUMP_SHARED_CONTEXT_KEY); 214 } 215 216 public static ServletException newSharedContextNotInitializedException() { 217 return new ServletException( 218 "JMF shared context not initialized (remove or set to true '" + JMF_INITIALIZATION + "' param in your web.xml)" 219 ); 220 } 221 222 public void sessionCreated(HttpSessionEvent se) { 223 @SuppressWarnings("unchecked") 224 Map<String, HttpSession> sessionMap = (Map<String, HttpSession>)se.getSession().getServletContext().getAttribute(GRANITE_SESSION_MAP); 225 if (sessionMap != null) 226 sessionMap.put(se.getSession().getId(), se.getSession()); 227 } 228 229 public void sessionDestroyed(HttpSessionEvent se) { 230 @SuppressWarnings("unchecked") 231 Map<String, HttpSession> sessionMap = (Map<String, HttpSession>)se.getSession().getServletContext().getAttribute(GRANITE_SESSION_MAP); 232 if (sessionMap != null) 233 sessionMap.remove(se.getSession().getId()); 234 } 235}