001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2013 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 021package org.granite.messaging.jmf; 022 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.List; 026 027import javax.servlet.ServletContext; 028import javax.servlet.ServletContextEvent; 029import javax.servlet.ServletContextListener; 030import javax.servlet.ServletException; 031 032import org.granite.config.GraniteConfigListener; 033import org.granite.logging.Logger; 034import org.granite.messaging.jmf.codec.ExtendedObjectCodec; 035import org.granite.util.JMFAMFUtil; 036 037/** 038 * @author Franck WOLFF 039 */ 040public class JMFServletContextListener implements ServletContextListener { 041 042 private static final Logger log = Logger.getLogger(GraniteConfigListener.class); 043 044 private static final String[] CODEC_EXTENSION_FACTORY_NAMES = { 045 "org.granite.hibernate.jmf.Hibernate3CodecExtensionFactory" 046 }; 047 048 public static final String EXTENDED_OBJECT_CODECS_PARAM = "jmf-extended-object-codecs"; 049 public static final String DEFAULT_STORED_STRINGS_PARAM = "jmf-default-stored-strings"; 050 051 public static final String SHARED_CONTEXT_KEY = SharedContext.class.getName(); 052 public static final String DUMP_SHARED_CONTEXT_KEY = SharedContext.class.getName() + ":DUMP"; 053 054 public static SharedContext getSharedContext(ServletContext servletContext) { 055 return (SharedContext)servletContext.getAttribute(SHARED_CONTEXT_KEY); 056 } 057 058 public static SharedContext getDumpSharedContext(ServletContext servletContext) { 059 return (SharedContext)servletContext.getAttribute(DUMP_SHARED_CONTEXT_KEY); 060 } 061 062 public static ServletException newSharedContextNotInitializedException() { 063 return new ServletException( 064 "JMF shared context not initialized (configure " + JMFServletContextListener.class.getName() + " in your web.xml)" 065 ); 066 } 067 068 public void contextInitialized(ServletContextEvent event) { 069 log.info("Loading JMF shared context"); 070 071 ServletContext servletContext = event.getServletContext(); 072 073 List<ExtendedObjectCodec> extendedObjectCodecs = loadExtendedObjectCodecs(servletContext); 074 List<String> defaultStoredStrings = loadDefaultStoredStrings(servletContext); 075 076 SharedContext sharedContext = new DefaultSharedContext(new DefaultCodecRegistry(extendedObjectCodecs), null, defaultStoredStrings); 077 servletContext.setAttribute(SHARED_CONTEXT_KEY, sharedContext); 078 079 SharedContext dumpSharedContext = new DefaultSharedContext(new DefaultCodecRegistry(), null, defaultStoredStrings); 080 servletContext.setAttribute(DUMP_SHARED_CONTEXT_KEY, dumpSharedContext); 081 082 log.info("JMF shared context loaded"); 083 } 084 085 protected List<ExtendedObjectCodec> loadExtendedObjectCodecs(ServletContext servletContext) { 086 String extendedObjectCodecsParam = servletContext.getInitParameter(EXTENDED_OBJECT_CODECS_PARAM); 087 088 if (extendedObjectCodecsParam == null) 089 return detectExtendedObjectCodecs(); 090 091 ClassLoader classLoader = getClass().getClassLoader(); 092 093 List<ExtendedObjectCodec> extendedObjectCodecs = new ArrayList<ExtendedObjectCodec>(); 094 for (String className : extendedObjectCodecsParam.trim().split("\\s*\\,\\s*")) { 095 if (className.length() == 0) 096 continue; 097 098 log.info("Loading JMF extended object codec: %s", className); 099 try { 100 @SuppressWarnings("unchecked") 101 Class<? extends ExtendedObjectCodec> cls = (Class<? extends ExtendedObjectCodec>)classLoader.loadClass(className); 102 extendedObjectCodecs.add(cls.getDeclaredConstructor().newInstance()); 103 } 104 catch (Throwable t) { 105 log.warn(t, "Could not load JMF codec: %s", className); 106 } 107 } 108 return extendedObjectCodecs; 109 } 110 111 protected List<ExtendedObjectCodec> detectExtendedObjectCodecs() { 112 log.info("Auto detecting extended object codec..."); 113 114 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 115 for (String factoryName : CODEC_EXTENSION_FACTORY_NAMES) { 116 try { 117 CodecExtensionFactory factory = (CodecExtensionFactory)classLoader.loadClass(factoryName).newInstance(); 118 List<ExtendedObjectCodec> extendedObjectCodecs = factory.getCodecs(); 119 log.info("Using %s: %s", factoryName, extendedObjectCodecs); 120 return extendedObjectCodecs; 121 } 122 catch (Throwable t) { 123 log.debug(t, "Could not load factory: %s", factoryName); 124 } 125 } 126 127 log.info("No extended object codec detected"); 128 return Collections.emptyList(); 129 } 130 131 protected List<String> loadDefaultStoredStrings(ServletContext servletContext) { 132 List<String> defaultStoredStrings = new ArrayList<String>(JMFAMFUtil.AMF_DEFAULT_STORED_STRINGS); 133 134 String defaultStoredStringsParam = servletContext.getInitParameter(DEFAULT_STORED_STRINGS_PARAM); 135 136 if (defaultStoredStringsParam != null) { 137 for (String value : defaultStoredStringsParam.trim().split("\\s*\\,\\s*")) { 138 if (value.length() > 0) 139 defaultStoredStrings.add(value); 140 } 141 } 142 143 return defaultStoredStrings; 144 } 145 146 147 public void contextDestroyed(ServletContextEvent event) { 148 ServletContext servletContext = event.getServletContext(); 149 150 servletContext.removeAttribute(SHARED_CONTEXT_KEY); 151 } 152}