001: /*
002: * Copyright (c) 2002-2006 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.xwork.config.impl;
006:
007: import com.opensymphony.xwork.config.*;
008: import com.opensymphony.xwork.config.entities.ActionConfig;
009: import com.opensymphony.xwork.config.entities.PackageConfig;
010: import com.opensymphony.xwork.config.entities.ResultTypeConfig;
011: import com.opensymphony.xwork.config.providers.InterceptorBuilder;
012:
013: import org.apache.commons.logging.Log;
014: import org.apache.commons.logging.LogFactory;
015:
016: import java.util.*;
017:
018: /**
019: * DefaultConfiguration
020: *
021: * @author Jason Carreira
022: * Created Feb 24, 2003 7:38:06 AM
023: */
024: public class DefaultConfiguration implements Configuration {
025:
026: protected static final Log LOG = LogFactory
027: .getLog(DefaultConfiguration.class);
028:
029: // Programmatic Action Conifigurations
030: private Map packageContexts = new LinkedHashMap();
031: protected RuntimeConfiguration runtimeConfiguration;
032:
033: public DefaultConfiguration() {
034: }
035:
036: public PackageConfig getPackageConfig(String name) {
037: return (PackageConfig) packageContexts.get(name);
038: }
039:
040: public Set getPackageConfigNames() {
041: return packageContexts.keySet();
042: }
043:
044: public Map getPackageConfigs() {
045: return packageContexts;
046: }
047:
048: public RuntimeConfiguration getRuntimeConfiguration() {
049: return runtimeConfiguration;
050: }
051:
052: public void addPackageConfig(String name,
053: PackageConfig packageContext) {
054: PackageConfig check = (PackageConfig) packageContexts.get(name);
055: if (check != null) {
056: LOG.error("The package name '" + name
057: + "' is already been used by another package: "
058: + check);
059: // would be better to throw ConfigurationException("name already used");
060: }
061: packageContexts.put(name, packageContext);
062: }
063:
064: /**
065: * Allows the configuration to clean up any resources used
066: */
067: public void destroy() {
068: }
069:
070: public void rebuildRuntimeConfiguration() {
071: runtimeConfiguration = buildRuntimeConfiguration();
072: }
073:
074: /**
075: * Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls
076: * buildRuntimeConfiguration().
077: *
078: * @throws ConfigurationException
079: */
080: public synchronized void reload() throws ConfigurationException {
081: packageContexts.clear();
082:
083: for (Iterator iterator = ConfigurationManager
084: .getConfigurationProviders().iterator(); iterator
085: .hasNext();) {
086: ConfigurationProvider provider = (ConfigurationProvider) iterator
087: .next();
088: provider.init(this );
089: }
090:
091: rebuildRuntimeConfiguration();
092: }
093:
094: public void removePackageConfig(String name) {
095: PackageConfig toBeRemoved = (PackageConfig) packageContexts
096: .get(name);
097:
098: if (toBeRemoved != null) {
099: for (Iterator iterator = packageContexts.values()
100: .iterator(); iterator.hasNext();) {
101: PackageConfig packageContext = (PackageConfig) iterator
102: .next();
103: packageContext.removeParent(toBeRemoved);
104: }
105: }
106: }
107:
108: /**
109: * This methodName builds the internal runtime configuration used by Xwork for finding and configuring Actions from the
110: * programmatic configuration data structures. All of the old runtime configuration will be discarded and rebuilt.
111: */
112: protected synchronized RuntimeConfiguration buildRuntimeConfiguration()
113: throws ConfigurationException {
114: Map namespaceActionConfigs = new LinkedHashMap();
115: Map namespaceConfigs = new LinkedHashMap();
116:
117: for (Iterator iterator = packageContexts.values().iterator(); iterator
118: .hasNext();) {
119: PackageConfig packageContext = (PackageConfig) iterator
120: .next();
121:
122: if (!packageContext.isAbstract()) {
123: String namespace = packageContext.getNamespace();
124: Map configs = (Map) namespaceActionConfigs
125: .get(namespace);
126:
127: if (configs == null) {
128: configs = new LinkedHashMap();
129: }
130:
131: Map actionConfigs = packageContext
132: .getAllActionConfigs();
133:
134: for (Iterator actionIterator = actionConfigs.keySet()
135: .iterator(); actionIterator.hasNext();) {
136: String actionName = (String) actionIterator.next();
137: ActionConfig baseConfig = (ActionConfig) actionConfigs
138: .get(actionName);
139: configs.put(actionName, buildFullActionConfig(
140: packageContext, baseConfig));
141: }
142:
143: namespaceActionConfigs.put(namespace, configs);
144: if (packageContext.getFullDefaultActionRef() != null) {
145: namespaceConfigs.put(namespace, packageContext
146: .getFullDefaultActionRef());
147: }
148: }
149: }
150:
151: return new RuntimeConfigurationImpl(namespaceActionConfigs,
152: namespaceConfigs);
153: }
154:
155: private void setDefaultResults(Map results,
156: PackageConfig packageContext) {
157: String defaultResult = packageContext
158: .getFullDefaultResultType();
159:
160: for (Iterator iterator = results.entrySet().iterator(); iterator
161: .hasNext();) {
162: Map.Entry entry = (Map.Entry) iterator.next();
163:
164: if (entry.getValue() == null) {
165: ResultTypeConfig resultTypeConfig = (ResultTypeConfig) packageContext
166: .getAllResultTypeConfigs().get(defaultResult);
167: entry.setValue(resultTypeConfig.getClazz());
168: }
169: }
170: }
171:
172: /**
173: * Builds the full runtime actionconfig with all of the defaults and inheritance
174: *
175: * @param packageContext the PackageConfig which holds the base config we're building from
176: * @param baseConfig the ActionConfig which holds only the configuration specific to itself, without the defaults
177: * and inheritance
178: * @return a full ActionConfig for runtime configuration with all of the inherited and default params
179: */
180: private ActionConfig buildFullActionConfig(
181: PackageConfig packageContext, ActionConfig baseConfig)
182: throws ConfigurationException {
183: Map params = new TreeMap(baseConfig.getParams());
184:
185: Map results = new TreeMap();
186: if (baseConfig.getPackageName()
187: .equals(packageContext.getName())) {
188: results.putAll(packageContext.getAllGlobalResults());
189: results.putAll(baseConfig.getResults());
190: } else {
191: PackageConfig baseConfigPackageConfig = (PackageConfig) packageContexts
192: .get(baseConfig.getPackageName());
193: if (baseConfigPackageConfig != null) {
194: results.putAll(baseConfigPackageConfig
195: .getAllGlobalResults());
196: }
197: results.putAll(baseConfig.getResults());
198: }
199:
200: setDefaultResults(results, packageContext);
201:
202: List interceptors = new ArrayList(baseConfig.getInterceptors());
203:
204: if (interceptors.size() <= 0) {
205: String defaultInterceptorRefName = packageContext
206: .getFullDefaultInterceptorRef();
207:
208: if (defaultInterceptorRefName != null) {
209: interceptors.addAll(InterceptorBuilder
210: .constructInterceptorReference(packageContext,
211: defaultInterceptorRefName,
212: new LinkedHashMap()));
213: }
214: }
215:
216: List externalRefs = baseConfig.getExternalRefs();
217:
218: List exceptionMappings = baseConfig.getExceptionMappings();
219: exceptionMappings.addAll(packageContext
220: .getAllExceptionMappingConfigs());
221:
222: ActionConfig config = new ActionConfig(baseConfig
223: .getMethodName(), baseConfig.getClassName(), params,
224: results, interceptors, externalRefs, exceptionMappings,
225: packageContext.getName());
226:
227: return config;
228: }
229:
230: private class RuntimeConfigurationImpl implements
231: RuntimeConfiguration {
232: private Map namespaceActionConfigs;
233: private Map namespaceConfigs;
234:
235: public RuntimeConfigurationImpl(Map namespaceActionConfigs,
236: Map namespaceConfigs) {
237: this .namespaceActionConfigs = namespaceActionConfigs;
238: this .namespaceConfigs = namespaceConfigs;
239: }
240:
241: /**
242: * Gets the configuration information for an action name, or returns null if the
243: * name is not recognized.
244: *
245: * @param name the name of the action
246: * @param namespace the namespace for the action or null for the empty namespace, ""
247: * @return the configuration information for action requested
248: */
249: public synchronized ActionConfig getActionConfig(
250: String namespace, String name) {
251: ActionConfig config = null;
252: Map actions = (Map) namespaceActionConfigs
253: .get((namespace == null) ? "" : namespace);
254:
255: if (actions != null) {
256: config = (ActionConfig) actions.get(name);
257: // fail over to default action
258: if (config == null) {
259: String defaultActionRef = (String) namespaceConfigs
260: .get((namespace == null) ? "" : namespace);
261: if (defaultActionRef != null) {
262: config = (ActionConfig) actions
263: .get(defaultActionRef);
264: }
265: }
266: }
267:
268: // fail over to empty namespace
269: if ((config == null) && (namespace != null)
270: && (!namespace.trim().equals(""))) {
271: actions = (Map) namespaceActionConfigs.get("");
272:
273: if (actions != null) {
274: config = (ActionConfig) actions.get(name);
275: // fail over to default action
276: if (config == null) {
277: String defaultActionRef = (String) namespaceConfigs
278: .get("");
279: if (defaultActionRef != null) {
280: config = (ActionConfig) actions
281: .get(defaultActionRef);
282: }
283: }
284: }
285: }
286:
287: return config;
288: }
289:
290: /**
291: * Gets the configuration settings for every action.
292: *
293: * @return a Map of namespace - > Map of ActionConfig objects, with the key being the action name
294: */
295: public synchronized Map getActionConfigs() {
296: return namespaceActionConfigs;
297: }
298:
299: public String toString() {
300: StringBuffer buff = new StringBuffer(
301: "RuntimeConfiguration - actions are\n");
302:
303: for (Iterator iterator = namespaceActionConfigs.keySet()
304: .iterator(); iterator.hasNext();) {
305: String namespace = (String) iterator.next();
306: Map actionConfigs = (Map) namespaceActionConfigs
307: .get(namespace);
308:
309: for (Iterator iterator2 = actionConfigs.keySet()
310: .iterator(); iterator2.hasNext();) {
311: buff.append(namespace + "/" + iterator2.next()
312: + "\n");
313: }
314: }
315:
316: return buff.toString();
317: }
318: }
319: }
|