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.io.IOException; 025import java.io.InputStream; 026import java.util.ArrayList; 027import java.util.List; 028import java.util.Map; 029 030import javax.servlet.ServletContext; 031import javax.servlet.ServletException; 032 033import org.granite.config.api.Configuration; 034import org.granite.jmx.MBeanUtil; 035import org.granite.logging.Logger; 036import org.granite.messaging.amf.io.convert.Converter; 037import org.granite.messaging.amf.io.util.ActionScriptClassDescriptor; 038import org.granite.messaging.amf.io.util.JavaClassDescriptor; 039import org.granite.messaging.amf.io.util.externalizer.Externalizer; 040import org.granite.util.ServletParams; 041import org.granite.util.StreamUtil; 042 043/** 044 * @author Franck WOLFF 045 */ 046public class ServletGraniteConfig implements ServletGraniteConfigMBean { 047 048 /////////////////////////////////////////////////////////////////////////// 049 // Static fields. 050 051 private static final Logger log = Logger.getLogger(ServletGraniteConfig.class); 052 053 private static final String GRANITE_CONFIG_DEFAULT = "/WEB-INF/granite/granite-config.xml"; 054 055 public static final String GRANITE_CONFIG_KEY = GraniteConfig.class.getName() + "_CACHE"; 056 public static final String GRANITE_CONFIG_DEFAULT_KEY = GraniteConfig.class.getName() + "_DEFAULT"; 057 public static final String GRANITE_CONFIG_CONFIGURATION_KEY = GraniteConfig.class.getName() + "_CONFIG"; 058 059 /////////////////////////////////////////////////////////////////////////// 060 // Instance fields. 061 062 private GraniteConfig config = null; 063 064 // Context where this GraniteConfig instance is registered (required for reload operation). 065 private ServletContext context = null; 066 067 // Should Granite MBeans be registered at startup. 068 private boolean registerMBeans = false; 069 070 // Reload listeners. 071 private final List<GraniteConfigReloadListener> reloadListeners = new ArrayList<GraniteConfigReloadListener>(); 072 073 /////////////////////////////////////////////////////////////////////////// 074 // Constructor. 075 076 private ServletGraniteConfig(ServletContext context, GraniteConfig config) { 077 this.context = context; 078 this.config = config; 079 } 080 081 /////////////////////////////////////////////////////////////////////////// 082 // Static GraniteConfig loaders. 083 084 public static synchronized GraniteConfig getConfig(ServletContext context) { 085 return ((ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY)).config; 086 } 087 088 public static synchronized ServletGraniteConfig getServletConfig(ServletContext context) { 089 return (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); 090 } 091 092 public static synchronized GraniteConfig loadConfig(ServletContext context) throws ServletException { 093 ServletGraniteConfig servletGraniteConfig = (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); 094 095 if (servletGraniteConfig == null) { 096 String path = getCustomConfigPath(context); 097 098 InputStream is = context.getResourceAsStream(path); 099 if (is == null) { 100 log.warn("Could not load custom granite-config.xml: %s (file does not exists)", path); 101 path = null; 102 } 103 104 Configuration configuration = (Configuration)context.getAttribute(GRANITE_CONFIG_CONFIGURATION_KEY); 105 106 String stdConfigPath = (String)context.getAttribute(GRANITE_CONFIG_DEFAULT_KEY); 107 108 boolean registerMBeans = ServletParams.get(context, GraniteConfigListener.GRANITE_MBEANS_ATTRIBUTE, Boolean.TYPE, false); 109 110 try { 111 String mbeanContextName = null; 112 // Use reflection for JDK 1.4 compatibility. 113 if (registerMBeans) 114 mbeanContextName = (String)ServletContext.class.getMethod("getContextPath").invoke(context); 115 116 GraniteConfig graniteConfig = new GraniteConfig(stdConfigPath, is, configuration, mbeanContextName); 117 118 servletGraniteConfig = loadConfig(context, graniteConfig); 119 } 120 catch (Exception e) { 121 log.error(e, "Could not load granite-config.xml"); 122 throw new ServletException("Could not load custom granite-config.xml", e); 123 } 124 finally { 125 if (is != null) try { 126 is.close(); 127 } catch (IOException e) { 128 // Ignore... 129 } 130 } 131 } 132 133 return servletGraniteConfig.config; 134 } 135 136 public static synchronized ServletGraniteConfig loadConfig(ServletContext context, GraniteConfig graniteConfig) { 137 ServletGraniteConfig servletGraniteConfig = new ServletGraniteConfig(context, graniteConfig); 138 139 context.setAttribute(GRANITE_CONFIG_KEY, servletGraniteConfig); 140 141 return servletGraniteConfig; 142 } 143 144 private static String getCustomConfigPath(ServletContext context) { 145 String path = null; 146 147 Configuration configuration = (Configuration)context.getAttribute(GRANITE_CONFIG_CONFIGURATION_KEY); 148 if (configuration != null) 149 path = configuration.getGraniteConfig(); 150 151 if (path == null) 152 path = ServletParams.get(context, "graniteConfigPath", String.class, GRANITE_CONFIG_DEFAULT); 153 154 return path; 155 } 156 157 public String getCustomConfigPath() { 158 return getCustomConfigPath(context); 159 } 160 161 162 /////////////////////////////////////////////////////////////////////////// 163 // GraniteConfigMBean implementation: attributes. 164 165 public boolean isRegisterMBeans() { 166 return registerMBeans; 167 } 168 public void setRegisterMBeans(boolean registerMBeans) { 169 this.registerMBeans = registerMBeans; 170 } 171 172 173 public synchronized void reload() { 174 175 if (context == null) 176 throw new IllegalStateException("GraniteConfig was not registered in ServletContext"); 177 178 ServletGraniteConfig oldConfig = (ServletGraniteConfig)context.getAttribute(GRANITE_CONFIG_KEY); 179 180 try { 181 context.removeAttribute(GRANITE_CONFIG_KEY); 182 GraniteConfig config = loadConfig(context); 183 for (GraniteConfigReloadListener listener : reloadListeners) { 184 try { 185 listener.onReload(context, config); 186 } 187 catch (Exception e) { 188 log.error(e, "Error while calling reload listener: %s", listener); 189 } 190 } 191 } 192 catch (Exception e) { 193 throw new RuntimeException(e.getMessage(), e); 194 } 195 finally { 196 if (context.getAttribute(GRANITE_CONFIG_KEY) == null) 197 context.setAttribute(GRANITE_CONFIG_KEY, oldConfig); 198 } 199 } 200 201 202 /////////////////////////////////////////////////////////////////////////// 203 // GraniteConfigMBean implementation 204 205 public void addReloadListener(GraniteConfigReloadListener listener) { 206 synchronized (reloadListeners) { 207 if (!reloadListeners.contains(listener)) 208 reloadListeners.add(listener); 209 } 210 } 211 212 public boolean removeReloadListener(GraniteConfigReloadListener listener) { 213 synchronized (reloadListeners) { 214 return reloadListeners.remove(listener); 215 } 216 } 217 218 public boolean getScan() { 219 return config.getScan(); 220 } 221 222 public String getAmf3DeserializerClass() { 223 return MBeanUtil.format( 224 config.getAmf3DeserializerConstructor() != null ? 225 config.getAmf3DeserializerConstructor().getDeclaringClass().getName(): 226 null 227 ); 228 } 229 230 public String getAmf3SerializerClass() { 231 return MBeanUtil.format( 232 config.getAmf3SerializerConstructor() != null ? 233 config.getAmf3SerializerConstructor().getDeclaringClass().getName(): 234 null 235 ); 236 } 237 238 public String getAmf3MessageInterceptorClass() { 239 return MBeanUtil.format( 240 config.getAmf3MessageInterceptor() != null ? 241 config.getAmf3MessageInterceptor().getClass().getName() : 242 null 243 ); 244 } 245 246 public String getClassGetterClass() { 247 return MBeanUtil.format( 248 config.getClassGetter() != null ? 249 config.getClassGetter().getClass().getName() : 250 null 251 ); 252 } 253 254 public String getMessageSelectorClass() { 255 return MBeanUtil.format( 256 config.getMessageSelectorConstructor() != null ? 257 config.getMessageSelectorConstructor().getDeclaringClass().getName() : 258 null 259 ); 260 } 261 262 public String getMethodMatcherClass() { 263 return MBeanUtil.format( 264 config.getMethodMatcher() != null ? 265 config.getMethodMatcher().getClass().getName() : 266 null 267 ); 268 } 269 270 public String getSecurityServiceClass() { 271 return MBeanUtil.format( 272 config.getSecurityService() != null ? 273 config.getSecurityService().getClass().getName() : 274 null 275 ); 276 } 277 278 public String getServiceInvocationListenerClass() { 279 return MBeanUtil.format( 280 config.getInvocationListener() != null ? 281 config.getInvocationListener().getClass().getName() : 282 null 283 ); 284 } 285 286 public String showStandardConfig() throws IOException { 287 String s = StreamUtil.getResourceAsString("org/granite/config/granite-config.xml", getClass().getClassLoader()); 288 return MBeanUtil.format(s); 289 } 290 291 public String showCustomConfig() throws IOException { 292 String path = getCustomConfigPath(); 293 294 InputStream is = context.getResourceAsStream(path); 295 try { 296 String s = StreamUtil.getStreamAsString(is); 297 return MBeanUtil.format(s); 298 } 299 finally { 300 if (is != null) 301 is.close(); 302 } 303 } 304 305 public String showConverters() { 306 Converter[] cs = config.getConverters().getConverters(); 307 String[] names = new String[cs.length]; 308 for (int i = 0; i < cs.length; i++) 309 names[i] = cs[i].getClass().getName(); 310 return MBeanUtil.format(names); 311 } 312 313 public String showExceptionConverters() { 314 String[] names = new String[config.getExceptionConverters().size()]; 315 for (int i = 0; i < config.getExceptionConverters().size(); i++) 316 names[i] = config.getExceptionConverters().get(i).getClass().getName(); 317 return MBeanUtil.format(names); 318 } 319 320 public String showInstantiators() { 321 String[] names = new String[config.getInstantiators().size()]; 322 int i = 0; 323 for (Map.Entry<String, String> e : config.getInstantiators().entrySet()) 324 names[i++] = e.getKey() + "=" + e.getValue(); 325 return MBeanUtil.format(names, true); 326 } 327 328 public String showAs3DescriptorsByInstanceOf() { 329 String[] names = new String[config.getAs3DescriptorsByInstanceOf().size()]; 330 int i = 0; 331 for (Map.Entry<String, String> e : config.getAs3DescriptorsByInstanceOf().entrySet()) 332 names[i++] = e.getKey() + "=" + e.getValue(); 333 return MBeanUtil.format(names, true); 334 } 335 336 public String showAs3DescriptorsByType() { 337 String[] names = new String[config.getAs3DescriptorsByType().size()]; 338 int i = 0; 339 for (Map.Entry<String, Class<? extends ActionScriptClassDescriptor>> e : config.getAs3DescriptorsByType().entrySet()) 340 names[i++] = e.getKey() + "=" + e.getValue().getName(); 341 return MBeanUtil.format(names, true); 342 } 343 344 public String showDisabledTideComponentsByName() { 345 String[] names = new String[config.getDisabledTideComponentsByName().size()]; 346 int i = 0; 347 for (Map.Entry<String, Object[]> e : config.getDisabledTideComponentsByName().entrySet()) 348 names[i++] = e.getKey() + "=" + e.getValue()[0]; 349 return MBeanUtil.format(names, true); 350 } 351 352 public String showEnabledTideComponentsByName() { 353 String[] names = new String[config.getEnabledTideComponentsByName().size()]; 354 int i = 0; 355 for (Map.Entry<String, Object[]> e : config.getEnabledTideComponentsByName().entrySet()) 356 names[i++] = e.getKey() + "=" + e.getValue()[0]; 357 return MBeanUtil.format(names, true); 358 } 359 360 public String showExternalizersByAnnotatedWith() { 361 String[] names = new String[config.getExternalizersByAnnotatedWith().size()]; 362 int i = 0; 363 for (Map.Entry<String, String> e : config.getExternalizersByAnnotatedWith().entrySet()) 364 names[i++] = e.getKey() + "=" + e.getValue(); 365 return MBeanUtil.format(names, true); 366 } 367 368 public String showExternalizersByInstanceOf() { 369 String[] names = new String[config.getExternalizersByInstanceOf().size()]; 370 int i = 0; 371 for (Map.Entry<String, String> e : config.getExternalizersByInstanceOf().entrySet()) 372 names[i++] = e.getKey() + "=" + e.getValue(); 373 return MBeanUtil.format(names, true); 374 } 375 376 public String showExternalizersByType() { 377 List<String> names = new ArrayList<String>(config.getExternalizersByType().size()); 378 for (Map.Entry<String, Externalizer> e : config.getExternalizersByType().entrySet()) { 379 if (config.EXTERNALIZER_FACTORY.getNullInstance() != e.getValue()) 380 names.add(e.getKey() + "=" + e.getValue().getClass().getName()); 381 } 382 return MBeanUtil.format(names.toArray(new String[names.size()]), true); 383 } 384 385 public String showJavaDescriptorsByInstanceOf() { 386 String[] names = new String[config.getJavaDescriptorsByInstanceOf().size()]; 387 int i = 0; 388 for (Map.Entry<String, String> e : config.getJavaDescriptorsByInstanceOf().entrySet()) 389 names[i++] = e.getKey() + "=" + e.getValue(); 390 return MBeanUtil.format(names, true); 391 } 392 393 public String showJavaDescriptorsByType() { 394 String[] names = new String[config.getJavaDescriptorsByType().size()]; 395 int i = 0; 396 for (Map.Entry<String, Class<? extends JavaClassDescriptor>> e : config.getJavaDescriptorsByType().entrySet()) 397 names[i++] = e.getKey() + "=" + e.getValue().getName(); 398 return MBeanUtil.format(names, true); 399 } 400 401 public String showScannedExternalizers() { 402 String[] names = new String[config.getScannedExternalizers().size()]; 403 for (int i = 0; i < config.getScannedExternalizers().size(); i++) 404 names[i] = config.getScannedExternalizers().get(i).getClass().getName(); 405 return MBeanUtil.format(names); 406 } 407 408 public String showTideComponentMatchers() { 409 String[] names = new String[config.getTideComponentMatchers().size()]; 410 for (int i = 0; i < config.getTideComponentMatchers().size(); i++) 411 names[i] = config.getTideComponentMatchers().get(i).toString(); 412 return MBeanUtil.format(names); 413 } 414}