001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.config;
006:
007: import com.opensymphony.util.FileManager;
008: import com.opensymphony.xwork.config.entities.ActionConfig;
009: import com.opensymphony.xwork.config.entities.InterceptorMapping;
010: import com.opensymphony.xwork.config.impl.DefaultConfiguration;
011: import com.opensymphony.xwork.config.providers.XmlConfigurationProvider;
012: import com.opensymphony.xwork.interceptor.Interceptor;
013:
014: import org.apache.commons.logging.Log;
015: import org.apache.commons.logging.LogFactory;
016:
017: import java.util.ArrayList;
018: import java.util.Iterator;
019: import java.util.List;
020: import java.util.Map;
021:
022: /**
023: * ConfigurationManager - central for XWork Configuration management, including
024: * its ConfigurationProvider.
025: *
026: * @author Jason Carreira
027: * @author tm_jee
028: * @version $Date: 2007-06-02 11:01:04 +0200 (Sat, 02 Jun 2007) $ $Id: ConfigurationManager.java 1533 2007-06-02 09:01:04Z tm_jee $
029: */
030: public class ConfigurationManager {
031:
032: protected static final Log LOG = LogFactory
033: .getLog(ConfigurationManager.class);
034: protected static Configuration configurationInstance;
035: private static List configurationProviders = new ArrayList();
036:
037: private ConfigurationManager() {
038: }
039:
040: public static synchronized void setConfiguration(
041: Configuration configuration) {
042: configurationInstance = configuration;
043: }
044:
045: /**
046: * Get the current XWork configuration object. By default an instance of DefaultConfiguration will be returned
047: *
048: * @see com.opensymphony.xwork.config.impl.DefaultConfiguration
049: */
050: public static synchronized Configuration getConfiguration() {
051: if (configurationInstance == null) {
052: configurationInstance = new DefaultConfiguration();
053: try {
054: configurationInstance.reload();
055: } catch (ConfigurationException e) {
056: configurationInstance = null;
057: throw e;
058: }
059: } else {
060: conditionalReload();
061: }
062:
063: return configurationInstance;
064: }
065:
066: /**
067: * <p/>
068: * get the current list of ConfigurationProviders.
069: * </p>
070: * <p/>
071: * if no custom ConfigurationProviders have been added, this method
072: * will return a list containing only the default ConfigurationProvider, XMLConfigurationProvider. if a custom
073: * ConfigurationProvider has been added, then the XmlConfigurationProvider must be added by hand.
074: * </p>
075: *
076: * TODO: the lazy instantiation of XmlConfigurationProvider should be refactored to be elsewhere. the behavior described above seems unintuitive.
077: *
078: * @return the list of registered ConfigurationProvider objects
079: * @see com.opensymphony.xwork.config.ConfigurationProvider
080: */
081: public static List getConfigurationProviders() {
082: synchronized (configurationProviders) {
083: if (configurationProviders.size() == 0) {
084: configurationProviders
085: .add(new XmlConfigurationProvider());
086: }
087:
088: return configurationProviders;
089: }
090: }
091:
092: /**
093: * adds a configuration provider to the List of ConfigurationProviders. a given ConfigurationProvider may be added
094: * more than once
095: *
096: * @param provider the ConfigurationProvider to register
097: */
098: public static void addConfigurationProvider(
099: ConfigurationProvider provider) {
100: synchronized (configurationProviders) {
101: if (!configurationProviders.contains(provider)) {
102: configurationProviders.add(provider);
103: }
104: }
105: }
106:
107: /**
108: * clears the registered ConfigurationProviders. this method will call destroy() on each of the registered
109: * ConfigurationProviders
110: *
111: * @see com.opensymphony.xwork.config.ConfigurationProvider#destroy
112: */
113: public static void clearConfigurationProviders() {
114: synchronized (configurationProviders) {
115: for (Iterator iterator = configurationProviders.iterator(); iterator
116: .hasNext();) {
117: ConfigurationProvider provider = (ConfigurationProvider) iterator
118: .next();
119: provider.destroy();
120: }
121:
122: configurationProviders.clear();
123: }
124: }
125:
126: public static synchronized void destroyConfiguration() {
127: synchronized (configurationProviders) {
128: clearConfigurationProviders(); // let's destroy the ConfigurationProvider first
129: configurationProviders = new ArrayList();
130:
131: if (configurationInstance != null) {
132: /* let's destroy the interceptors used. */
133:
134: // keeps a copy of the interceptor that we've destroyed before, so we don't destroy them twice
135: List destroyedInterceptors = new ArrayList();
136: Map namespacesMap = configurationInstance
137: .getRuntimeConfiguration().getActionConfigs();
138: if (namespacesMap != null) {
139: for (Iterator i = namespacesMap.entrySet()
140: .iterator(); i.hasNext();) {
141: Map.Entry namespaceMapEntry = (Map.Entry) i
142: .next();
143: String namespace = (String) namespaceMapEntry
144: .getKey();
145: Map actionConfigsMap = (Map) namespaceMapEntry
146: .getValue();
147:
148: for (Iterator ii = actionConfigsMap.entrySet()
149: .iterator(); ii.hasNext();) {
150: Map.Entry actionConfigMapEntry = (Map.Entry) ii
151: .next();
152: String actionName = (String) actionConfigMapEntry
153: .getKey();
154: ActionConfig actionConfig = (ActionConfig) actionConfigMapEntry
155: .getValue();
156:
157: List interceptorMappings = actionConfig
158: .getInterceptors();
159: for (Iterator iii = interceptorMappings
160: .iterator(); iii.hasNext();) {
161: InterceptorMapping interceptorMapping = (InterceptorMapping) iii
162: .next();
163: if (interceptorMapping != null
164: && interceptorMapping
165: .getInterceptor() != null) {
166: Interceptor interceptor = interceptorMapping
167: .getInterceptor();
168: if (!destroyedInterceptors
169: .contains(interceptor)) {
170: destroyedInterceptors
171: .add(interceptor); // keep a copy so we know we've destroy this interceptor before.
172: try {
173: if (LOG.isDebugEnabled())
174: LOG
175: .debug("destroying interceptor ["
176: + interceptor
177: + "] registered under name ["
178: + interceptorMapping
179: .getName()
180: + "] with namespace ["
181: + namespace
182: + "] in package ["
183: + actionConfig
184: .getPackageName()
185: + "]");
186: interceptor.destroy();
187: } catch (Exception e) {
188: // we don't want a bad interceptor to cause the whole destoy process to blow
189: // everything up, if this happens, just inform the user by logging the error
190: LOG
191: .error("an exception occurred while calling destroy() method on interceptor ["
192: + interceptor
193: + "] registered under name ["
194: + interceptorMapping
195: .getName()
196: + "] with namespace ["
197: + namespace
198: + "] in package ["
199: + actionConfig
200: .getPackageName()
201: + "]");
202: }
203: }
204: }
205: }
206: }
207: }
208: }
209:
210: configurationInstance.destroy(); // let's destroy it first, before nulling it.
211: }
212: configurationInstance = null;
213: }
214: }
215:
216: /**
217: * reloads the Configuration files if the configuration files indicate that they need to be reloaded.
218: *
219: * <B>NOTE:</b> FileManager could be configured through webwork.properties through
220: * webwork.configuration.xml.reload property.
221: */
222: private static synchronized void conditionalReload() {
223: if (FileManager.isReloadingConfigs()) {
224: boolean reload;
225:
226: synchronized (configurationProviders) {
227: if (LOG.isDebugEnabled()) {
228: LOG
229: .debug("Checking ConfigurationProviders for reload.");
230: }
231:
232: reload = false;
233:
234: for (Iterator iterator = getConfigurationProviders()
235: .iterator(); iterator.hasNext();) {
236: ConfigurationProvider provider = (ConfigurationProvider) iterator
237: .next();
238:
239: if (provider.needsReload()) {
240: reload = true;
241:
242: break;
243: }
244: }
245: }
246:
247: if (reload) {
248: configurationInstance.reload();
249: }
250: }
251: }
252: }
|