/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Granite Data Services 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. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.granite.config.GraniteConfig.JMF_EXTENSIONS_MODE;
import org.granite.config.flex.ServletServicesConfig;
import org.granite.jmx.GraniteMBeanInitializer;
import org.granite.logging.Logger;
import org.granite.messaging.AliasRegistry;
import org.granite.messaging.DefaultAliasRegistry;
import org.granite.messaging.jmf.DefaultCodecRegistry;
import org.granite.messaging.jmf.DefaultSharedContext;
import org.granite.messaging.jmf.SharedContext;
import org.granite.messaging.jmf.codec.ExtendedObjectCodec;
import org.granite.messaging.jmf.codec.ExtendedObjectCodecService;
import org.granite.messaging.reflect.Reflection;
import org.granite.util.JMFAMFUtil;
import org.granite.util.ServiceLoader;
import org.granite.util.ServletParams;
/**
* @author William DRAI
*/
public class GraniteConfigListener implements ServletContextListener, HttpSessionListener {
private static final String GRANITE_CONFIG_SHUTDOWN_KEY = GraniteConfig.class.getName() + "_SHUTDOWN";
public static final String GRANITE_CONFIG_ATTRIBUTE = "org.granite.config.serverFilter";
public static final String GRANITE_CONFIG_PROVIDER_ATTRIBUTE = "org.granite.config.configProvider";
public static final String GRANITE_MBEANS_ATTRIBUTE = "registerGraniteMBeans";
public static final String GRANITE_SESSION_TRACKING = "org.granite.config.sessionTracking";
public static final String GRANITE_SESSION_MAP = "org.granite.config.sessionMap";
public static final String JMF_INITIALIZATION = "jmf-initialization";
public static final String SHARED_CONTEXT_KEY = SharedContext.class.getName();
public static final String DUMP_SHARED_CONTEXT_KEY = SharedContext.class.getName() + ":DUMP";
private static final Logger log = Logger.getLogger(GraniteConfigListener.class);
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
try {
log.info("Initializing GraniteDS...");
ServiceConfigurator serviceConfigurator = (ServiceConfigurator)context.getAttribute(GRANITE_CONFIG_ATTRIBUTE);
if (serviceConfigurator != null)
serviceConfigurator.initialize(context);
GraniteConfig gConfig = ServletGraniteConfig.loadConfig(context);
if (serviceConfigurator != null)
serviceConfigurator.configureServices(context);
else
ServletServicesConfig.loadConfig(context);
if ("true".equals(context.getInitParameter(GRANITE_SESSION_TRACKING))) {
Map<String, HttpSession> sessionMap = new ConcurrentHashMap<String, HttpSession>(200);
context.setAttribute(GRANITE_SESSION_MAP, sessionMap);
}
if (gConfig.isRegisterMBeans()) {
GraniteMBeanInitializer.registerMBeans(context,
ServletGraniteConfig.getServletConfig(context),
ServletServicesConfig.getServletConfig(context));
}
String jmfInitialization = context.getInitParameter(JMF_INITIALIZATION);
if (jmfInitialization == null || "true".equals(jmfInitialization))
loadJMFSharedContext(context, gConfig);
log.info("GraniteDS initialized");
}
catch (Exception e) {
throw new RuntimeException("Could not initialize Granite environment", e);
}
}
public void contextDestroyed(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
log.info("Stopping GraniteDS...");
@SuppressWarnings("unchecked")
List<ShutdownListener> listeners = (List<ShutdownListener>)sce.getServletContext().getAttribute(GRANITE_CONFIG_SHUTDOWN_KEY);
if (listeners != null) {
try {
for (ShutdownListener listener : listeners)
listener.stop();
}
catch (Exception e) {
throw new RuntimeException("Could not destroy Granite environment", e);
}
}
if (ServletParams.get(context, GRANITE_MBEANS_ATTRIBUTE, Boolean.TYPE, false))
GraniteMBeanInitializer.unregisterMBeans(context);
log.info("GraniteDS stopped");
}
public static synchronized void registerShutdownListener(ServletContext context, ShutdownListener listener) {
@SuppressWarnings("unchecked")
List<ShutdownListener> listeners = (List<ShutdownListener>)context.getAttribute(GRANITE_CONFIG_SHUTDOWN_KEY);
if (listeners == null) {
listeners = new ArrayList<ShutdownListener>();
context.setAttribute(GRANITE_CONFIG_SHUTDOWN_KEY, listeners);
}
listeners.add(listener);
}
public static interface ServiceConfigurator {
public void initialize(ServletContext context);
public void configureServices(ServletContext context) throws ServletException;
}
private static void loadJMFSharedContext(ServletContext servletContext, GraniteConfig graniteConfig) {
log.info("Loading JMF shared context");
List<ExtendedObjectCodec> extendedObjectCodecs = null;
if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.REPLACE)
extendedObjectCodecs = graniteConfig.getJmfExtendedCodecs();
else {
extendedObjectCodecs = new ArrayList<ExtendedObjectCodec>();
if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.PREPPEND)
extendedObjectCodecs.addAll(graniteConfig.getJmfExtendedCodecs());
for (ExtendedObjectCodecService service : ServiceLoader.load(ExtendedObjectCodecService.class))
extendedObjectCodecs.addAll(Arrays.asList(service.getExtensions()));
if (graniteConfig.getJmfExtendedCodecsMode() == JMF_EXTENSIONS_MODE.APPEND)
extendedObjectCodecs.addAll(graniteConfig.getJmfExtendedCodecs());
}
log.debug("Using JMF extended codecs: %s", extendedObjectCodecs);
List<String> defaultStoredStrings = null;
if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.REPLACE)
defaultStoredStrings = graniteConfig.getJmfDefaultStoredStrings();
else {
defaultStoredStrings = new ArrayList<String>();
if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.PREPPEND)
defaultStoredStrings.addAll(graniteConfig.getJmfDefaultStoredStrings());
defaultStoredStrings.addAll(JMFAMFUtil.AMF_DEFAULT_STORED_STRINGS);
if (graniteConfig.getJmfDefaultStoredStringsMode() == JMF_EXTENSIONS_MODE.APPEND)
defaultStoredStrings.addAll(graniteConfig.getJmfDefaultStoredStrings());
}
log.debug("Using JMF default stored strings: %s", defaultStoredStrings);
Reflection reflection = graniteConfig.getJmfReflection();
log.debug("Using JMF reflection: %s", reflection.getClass().getName());
AliasRegistry aliasRegistry = new DefaultAliasRegistry();
SharedContext sharedContext = new DefaultSharedContext(new DefaultCodecRegistry(extendedObjectCodecs), defaultStoredStrings, reflection, aliasRegistry);
servletContext.setAttribute(SHARED_CONTEXT_KEY, sharedContext);
SharedContext dumpSharedContext = new DefaultSharedContext(new DefaultCodecRegistry(), defaultStoredStrings, reflection, aliasRegistry);
servletContext.setAttribute(DUMP_SHARED_CONTEXT_KEY, dumpSharedContext);
log.info("JMF shared context loaded");
}
public static SharedContext getSharedContext(ServletContext servletContext) {
return (SharedContext)servletContext.getAttribute(SHARED_CONTEXT_KEY);
}
public static SharedContext getDumpSharedContext(ServletContext servletContext) {
return (SharedContext)servletContext.getAttribute(DUMP_SHARED_CONTEXT_KEY);
}
public static ServletException newSharedContextNotInitializedException() {
return new ServletException(
"JMF shared context not initialized (remove or set to true '" + JMF_INITIALIZATION + "' param in your web.xml)"
);
}
public void sessionCreated(HttpSessionEvent se) {
@SuppressWarnings("unchecked")
Map<String, HttpSession> sessionMap = (Map<String, HttpSession>)se.getSession().getServletContext().getAttribute(GRANITE_SESSION_MAP);
if (sessionMap != null)
sessionMap.put(se.getSession().getId(), se.getSession());
}
public void sessionDestroyed(HttpSessionEvent se) {
@SuppressWarnings("unchecked")
Map<String, HttpSession> sessionMap = (Map<String, HttpSession>)se.getSession().getServletContext().getAttribute(GRANITE_SESSION_MAP);
if (sessionMap != null)
sessionMap.remove(se.getSession().getId());
}
}