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
021 package org.granite.messaging.jmf;
022
023 import java.util.ArrayList;
024 import java.util.Collections;
025 import java.util.List;
026
027 import javax.servlet.ServletContext;
028 import javax.servlet.ServletContextEvent;
029 import javax.servlet.ServletContextListener;
030 import javax.servlet.ServletException;
031
032 import org.granite.config.GraniteConfigListener;
033 import org.granite.logging.Logger;
034 import org.granite.messaging.jmf.codec.ExtendedObjectCodec;
035 import org.granite.util.JMFAMFUtil;
036
037 /**
038 * @author Franck WOLFF
039 */
040 public 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 }