/** * 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.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletException; import org.granite.config.api.Configuration; import org.granite.context.GraniteContext; import org.granite.jmx.MBeanUtil; import org.granite.logging.Logger; import org.granite.messaging.amf.io.convert.Converter; import org.granite.messaging.amf.io.util.ActionScriptClassDescriptor; import org.granite.messaging.amf.io.util.JavaClassDescriptor; import org.granite.messaging.amf.io.util.externalizer.Externalizer; import org.granite.messaging.webapp.ServletGraniteContext; import org.granite.util.ServletParams; import org.granite.util.StreamUtil; /** * @author Franck WOLFF */ public class ServletGraniteConfig implements ServletGraniteConfigMBean { /////////////////////////////////////////////////////////////////////////// // Static fields. private static final Logger log = Logger.getLogger(ServletGraniteConfig.class); private static final String GRANITE_CONFIG_DEFAULT = "/WEB-INF/granite/granite-config.xml"; public static final String GRANITE_CONFIG_KEY = GraniteConfig.class.getName() + "_CACHE"; public static final String GRANITE_CONFIG_DEFAULT_KEY = GraniteConfig.class.getName() + "_DEFAULT"; public static final String GRANITE_CONFIG_CONFIGURATION_KEY = GraniteConfig.class.getName() + "_CONFIG"; /////////////////////////////////////////////////////////////////////////// // Instance fields. private GraniteConfig config = null; // Context where this GraniteConfig instance is registered (required for reload operation). private ServletContext context = null; // Should Granite MBeans be registered at startup. private boolean registerMBeans = false; // Reload listeners. private final List<GraniteConfigReloadListener> reloadListeners = new ArrayList<GraniteConfigReloadListener>(); /////////////////////////////////////////////////////////////////////////// // Constructor. private ServletGraniteConfig(ServletContext context, GraniteConfig config) { this.context = context; this.config = config; } /////////////////////////////////////////////////////////////////////////// // Static GraniteConfig loaders. public static synchronized GraniteConfig getConfig(ServletContext context) { return ((ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY)).config; } public static synchronized ServletGraniteConfig getServletConfig(ServletContext context) { return (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); } public static synchronized GraniteConfig loadConfig(ServletContext context) throws ServletException { ServletGraniteConfig servletGraniteConfig = (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); if (servletGraniteConfig == null) { String path = getCustomConfigPath(context); InputStream is = context.getResourceAsStream(path); if (is == null) { log.warn("Could not load custom granite-config.xml: %s (file does not exists)", path); path = null; } Configuration configuration = (Configuration)context.getAttribute(GRANITE_CONFIG_CONFIGURATION_KEY); String stdConfigPath = (String)context.getAttribute(GRANITE_CONFIG_DEFAULT_KEY); boolean registerMBeans = ServletParams.get(context, GraniteConfigListener.GRANITE_MBEANS_ATTRIBUTE, Boolean.TYPE, false); try { String mbeanContextName = null; // Use reflection for JDK 1.4 compatibility. if (registerMBeans) mbeanContextName = (String)ServletContext.class.getMethod("getContextPath").invoke(context); ServletGraniteContext.createThreadInstance(null, null, context, (String)null, null); GraniteConfig graniteConfig = new GraniteConfig(stdConfigPath, is, configuration, mbeanContextName); servletGraniteConfig = loadConfig(context, graniteConfig); } catch (Exception e) { log.error(e, "Could not load granite-config.xml"); throw new ServletException("Could not load custom granite-config.xml", e); } finally { if (is != null) try { is.close(); } catch (IOException e) { // Ignore... } GraniteContext.release(); } } return servletGraniteConfig.config; } public static synchronized ServletGraniteConfig loadConfig(ServletContext context, GraniteConfig graniteConfig) { ServletGraniteConfig servletGraniteConfig = new ServletGraniteConfig(context, graniteConfig); context.setAttribute(GRANITE_CONFIG_KEY, servletGraniteConfig); return servletGraniteConfig; } private static String getCustomConfigPath(ServletContext context) { String path = null; Configuration configuration = (Configuration)context.getAttribute(GRANITE_CONFIG_CONFIGURATION_KEY); if (configuration != null) path = configuration.getGraniteConfig(); if (path == null) path = ServletParams.get(context, "graniteConfigPath", String.class, GRANITE_CONFIG_DEFAULT); return path; } public String getCustomConfigPath() { return getCustomConfigPath(context); } /////////////////////////////////////////////////////////////////////////// // GraniteConfigMBean implementation: attributes. public boolean isRegisterMBeans() { return registerMBeans; } public void setRegisterMBeans(boolean registerMBeans) { this.registerMBeans = registerMBeans; } public synchronized void reload() { if (context == null) throw new IllegalStateException("GraniteConfig was not registered in ServletContext"); ServletGraniteConfig oldConfig = (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); try { context.removeAttribute(GRANITE_CONFIG_KEY); ServletGraniteContext.createThreadInstance(null, null, context, (String)null, null); GraniteConfig config = loadConfig(context); for (GraniteConfigReloadListener listener : reloadListeners) { try { listener.onReload(context, config); } catch (Exception e) { log.error(e, "Error while calling reload listener: %s", listener); } } } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } finally { GraniteContext.release(); if (context.getAttribute(GRANITE_CONFIG_KEY) == null) context.setAttribute(GRANITE_CONFIG_KEY, oldConfig); } } /////////////////////////////////////////////////////////////////////////// // GraniteConfigMBean implementation public void addReloadListener(GraniteConfigReloadListener listener) { synchronized (reloadListeners) { if (!reloadListeners.contains(listener)) reloadListeners.add(listener); } } public boolean removeReloadListener(GraniteConfigReloadListener listener) { synchronized (reloadListeners) { return reloadListeners.remove(listener); } } public boolean getScan() { return config.getScan(); } public String getAmf3DeserializerClass() { return MBeanUtil.format( config.getAmf3DeserializerConstructor() != null ? config.getAmf3DeserializerConstructor().getDeclaringClass().getName(): null ); } public String getAmf3SerializerClass() { return MBeanUtil.format( config.getAmf3SerializerConstructor() != null ? config.getAmf3SerializerConstructor().getDeclaringClass().getName(): null ); } public String getAmf3MessageInterceptorClass() { return MBeanUtil.format( config.getAmf3MessageInterceptor() != null ? config.getAmf3MessageInterceptor().getClass().getName() : null ); } public String getClassGetterClass() { return MBeanUtil.format( config.getClassGetter() != null ? config.getClassGetter().getClass().getName() : null ); } public String getMessageSelectorClass() { return MBeanUtil.format( config.getMessageSelectorConstructor() != null ? config.getMessageSelectorConstructor().getDeclaringClass().getName() : null ); } public String getMethodMatcherClass() { return MBeanUtil.format( config.getMethodMatcher() != null ? config.getMethodMatcher().getClass().getName() : null ); } public String getSecurityServiceClass() { return MBeanUtil.format( config.getSecurityService() != null ? config.getSecurityService().getClass().getName() : null ); } public String getServiceInvocationListenerClass() { return MBeanUtil.format( config.getInvocationListener() != null ? config.getInvocationListener().getClass().getName() : null ); } public String showStandardConfig() throws IOException { String s = StreamUtil.getResourceAsString("org/granite/config/granite-config.xml", getClass().getClassLoader()); return MBeanUtil.format(s); } public String showCustomConfig() throws IOException { String path = getCustomConfigPath(); InputStream is = context.getResourceAsStream(path); try { String s = StreamUtil.getStreamAsString(is); return MBeanUtil.format(s); } finally { if (is != null) is.close(); } } public String showConverters() { Converter[] cs = config.getConverters().getConverters(); String[] names = new String[cs.length]; for (int i = 0; i < cs.length; i++) names[i] = cs[i].getClass().getName(); return MBeanUtil.format(names); } public String showExceptionConverters() { String[] names = new String[config.getExceptionConverters().size()]; for (int i = 0; i < config.getExceptionConverters().size(); i++) names[i] = config.getExceptionConverters().get(i).getClass().getName(); return MBeanUtil.format(names); } public String showInstantiators() { String[] names = new String[config.getInstantiators().size()]; int i = 0; for (Map.Entry<String, String> e : config.getInstantiators().entrySet()) names[i++] = e.getKey() + "=" + e.getValue(); return MBeanUtil.format(names, true); } public String showAs3DescriptorsByInstanceOf() { String[] names = new String[config.getAs3DescriptorsByInstanceOf().size()]; int i = 0; for (Map.Entry<String, String> e : config.getAs3DescriptorsByInstanceOf().entrySet()) names[i++] = e.getKey() + "=" + e.getValue(); return MBeanUtil.format(names, true); } public String showAs3DescriptorsByType() { String[] names = new String[config.getAs3DescriptorsByType().size()]; int i = 0; for (Map.Entry<String, Class<? extends ActionScriptClassDescriptor>> e : config.getAs3DescriptorsByType().entrySet()) names[i++] = e.getKey() + "=" + e.getValue().getName(); return MBeanUtil.format(names, true); } public String showDisabledTideComponentsByName() { String[] names = new String[config.getDisabledTideComponentsByName().size()]; int i = 0; for (Map.Entry<String, Object[]> e : config.getDisabledTideComponentsByName().entrySet()) names[i++] = e.getKey() + "=" + e.getValue()[0]; return MBeanUtil.format(names, true); } public String showEnabledTideComponentsByName() { String[] names = new String[config.getEnabledTideComponentsByName().size()]; int i = 0; for (Map.Entry<String, Object[]> e : config.getEnabledTideComponentsByName().entrySet()) names[i++] = e.getKey() + "=" + e.getValue()[0]; return MBeanUtil.format(names, true); } public String showExternalizersByAnnotatedWith() { String[] names = new String[config.getExternalizersByAnnotatedWith().size()]; int i = 0; for (Map.Entry<String, String> e : config.getExternalizersByAnnotatedWith().entrySet()) names[i++] = e.getKey() + "=" + e.getValue(); return MBeanUtil.format(names, true); } public String showExternalizersByInstanceOf() { String[] names = new String[config.getExternalizersByInstanceOf().size()]; int i = 0; for (Map.Entry<String, String> e : config.getExternalizersByInstanceOf().entrySet()) names[i++] = e.getKey() + "=" + e.getValue(); return MBeanUtil.format(names, true); } public String showExternalizersByType() { List<String> names = new ArrayList<String>(config.getExternalizersByType().size()); for (Map.Entry<String, Externalizer> e : config.getExternalizersByType().entrySet()) { if (config.EXTERNALIZER_FACTORY.getNullInstance() != e.getValue()) names.add(e.getKey() + "=" + e.getValue().getClass().getName()); } return MBeanUtil.format(names.toArray(new String[names.size()]), true); } public String showJavaDescriptorsByInstanceOf() { String[] names = new String[config.getJavaDescriptorsByInstanceOf().size()]; int i = 0; for (Map.Entry<String, String> e : config.getJavaDescriptorsByInstanceOf().entrySet()) names[i++] = e.getKey() + "=" + e.getValue(); return MBeanUtil.format(names, true); } public String showJavaDescriptorsByType() { String[] names = new String[config.getJavaDescriptorsByType().size()]; int i = 0; for (Map.Entry<String, Class<? extends JavaClassDescriptor>> e : config.getJavaDescriptorsByType().entrySet()) names[i++] = e.getKey() + "=" + e.getValue().getName(); return MBeanUtil.format(names, true); } public String showScannedExternalizers() { String[] names = new String[config.getScannedExternalizers().size()]; for (int i = 0; i < config.getScannedExternalizers().size(); i++) names[i] = config.getScannedExternalizers().get(i).getClass().getName(); return MBeanUtil.format(names); } public String showTideComponentMatchers() { String[] names = new String[config.getTideComponentMatchers().size()]; for (int i = 0; i < config.getTideComponentMatchers().size(); i++) names[i] = config.getTideComponentMatchers().get(i).toString(); return MBeanUtil.format(names); } }