Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2002-2006 by OpenSymphony + * All rights reserved. + */ +package com.opensymphony.xwork2.config.impl; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.DefaultTextProvider; +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.config.*; +import com.opensymphony.xwork2.config.entities.*; +import com.opensymphony.xwork2.config.providers.InterceptorBuilder; +import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; +import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer; +import com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter; +import com.opensymphony.xwork2.conversion.impl.XWorkConverter; +import com.opensymphony.xwork2.inject.*; +import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; +import com.opensymphony.xwork2.ognl.OgnlUtil; +import com.opensymphony.xwork2.ognl.OgnlValueStackFactory; +import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; +import com.opensymphony.xwork2.util.CompoundRoot; +import com.opensymphony.xwork2.util.PatternMatcher; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.ValueStackFactory; +import com.opensymphony.xwork2.util.location.LocatableProperties; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; +import com.opensymphony.xwork2.util.reflection.ReflectionProvider; +import ognl.PropertyAccessor; + +import java.util.*; + + +/** + * DefaultConfiguration + * + * @author Jason Carreira + * Created Feb 24, 2003 7:38:06 AM + */ +public class DefaultConfiguration implements Configuration { + + protected static final Logger LOG = LoggerFactory.getLogger(DefaultConfiguration.class); + + + // Programmatic Action Configurations + protected Map<String, PackageConfig> packageContexts = new LinkedHashMap<String, PackageConfig>(); + protected RuntimeConfiguration runtimeConfiguration; + protected Container container; + protected String defaultFrameworkBeanName; + protected Set<String> loadedFileNames = new TreeSet<String>(); + protected List<UnknownHandlerConfig> unknownHandlerStack; + + + ObjectFactory objectFactory; + + public DefaultConfiguration() { + this("xwork"); + } + + public DefaultConfiguration(String defaultBeanName) { + this.defaultFrameworkBeanName = defaultBeanName; + } + + + public PackageConfig getPackageConfig(String name) { + return packageContexts.get(name); + } + + public List<UnknownHandlerConfig> getUnknownHandlerStack() { + return unknownHandlerStack; + } + + public void setUnknownHandlerStack(List<UnknownHandlerConfig> unknownHandlerStack) { + this.unknownHandlerStack = unknownHandlerStack; + } + + public Set<String> getPackageConfigNames() { + return packageContexts.keySet(); + } + + public Map<String, PackageConfig> getPackageConfigs() { + return packageContexts; + } + + public Set<String> getLoadedFileNames() { + return loadedFileNames; + } + + public RuntimeConfiguration getRuntimeConfiguration() { + return runtimeConfiguration; + } + + /** + * @return the container + */ + public Container getContainer() { + return container; + } + + public void addPackageConfig(String name, PackageConfig packageContext) { + PackageConfig check = packageContexts.get(name); + if (check != null) { + if (check.getLocation() != null && packageContext.getLocation() != null + && check.getLocation().equals(packageContext.getLocation())) { + if (LOG.isDebugEnabled()) { + LOG.debug("The package name '" + name + + "' is already been loaded by the same location and could be removed: " + + packageContext.getLocation()); + } + } else { + throw new ConfigurationException("The package name '" + name + + "' at location "+packageContext.getLocation() + + " is already been used by another package at location " + check.getLocation(), + packageContext); + } + } + packageContexts.put(name, packageContext); + } + + public PackageConfig removePackageConfig(String packageName) { + return packageContexts.remove(packageName); + } + + /** + * Allows the configuration to clean up any resources used + */ + public void destroy() { + packageContexts.clear(); + loadedFileNames.clear(); + } + + public void rebuildRuntimeConfiguration() { + runtimeConfiguration = buildRuntimeConfiguration(); + } + + /** + * Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls + * buildRuntimeConfiguration(). + * + * @throws ConfigurationException + */ + public synchronized void reload(List<ConfigurationProvider> providers) throws ConfigurationException { + + // Silly copy necessary due to lack of ability to cast generic lists + List<ContainerProvider> contProviders = new ArrayList<ContainerProvider>(); + contProviders.addAll(providers); + + reloadContainer(contProviders); + } + + /** + * Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls + * buildRuntimeConfiguration(). + * + * @throws ConfigurationException + */ + public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException { + packageContexts.clear(); + loadedFileNames.clear(); + List<PackageProvider> packageProviders = new ArrayList<PackageProvider>(); + + ContainerProperties props = new ContainerProperties(); + ContainerBuilder builder = new ContainerBuilder(); + for (final ContainerProvider containerProvider : providers) + { + containerProvider.init(this); + containerProvider.register(builder, props); + } + props.setConstants(builder); + + builder.factory(Configuration.class, new Factory<Configuration>() { + public Configuration create(Context context) throws Exception { + return DefaultConfiguration.this; + } + }); + + ActionContext oldContext = ActionContext.getContext(); + try { + // Set the bootstrap container for the purposes of factory creation + Container bootstrap = createBootstrapContainer(); + setContext(bootstrap); + container = builder.create(false); + setContext(container); + objectFactory = container.getInstance(ObjectFactory.class); + + // Process the configuration providers first + for (final ContainerProvider containerProvider : providers) + { + if (containerProvider instanceof PackageProvider) { + container.inject(containerProvider); + ((PackageProvider)containerProvider).loadPackages(); + packageProviders.add((PackageProvider)containerProvider); + } + } + + // Then process any package providers from the plugins + Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class); + if (packageProviderNames != null) { + for (String name : packageProviderNames) { + PackageProvider provider = container.getInstance(PackageProvider.class, name); + provider.init(this); + provider.loadPackages(); + packageProviders.add(provider); + } + } + + rebuildRuntimeConfiguration(); + } finally { + if (oldContext == null) { + ActionContext.setContext(null); + } + } + return packageProviders; + } + + protected ActionContext setContext(Container cont) { + ActionContext context = ActionContext.getContext(); + if (context == null) { + ValueStack vs = cont.getInstance(ValueStackFactory.class).createValueStack(); + context = new ActionContext(vs.getContext()); + ActionContext.setContext(context); + } + return context; + } + + protected Container createBootstrapContainer() { + ContainerBuilder builder = new ContainerBuilder(); + builder.factory(ObjectFactory.class, Scope.SINGLETON); + builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON); + builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON); + builder.factory(XWorkConverter.class, Scope.SINGLETON); + builder.factory(XWorkBasicConverter.class, Scope.SINGLETON); + builder.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON); + builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON); + builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON); + builder.factory(OgnlUtil.class, Scope.SINGLETON); + builder.constant("devMode", "false"); + builder.constant("logMissingProperties", "false"); + return builder.create(true); + } + + /** + * This builds the internal runtime configuration used by Xwork for finding and configuring Actions from the + * programmatic configuration data structures. All of the old runtime configuration will be discarded and rebuilt. + * + * <p> + * It basically flattens the data structures to make the information easier to access. It will take + * an {...@link ActionConfig} and combine its data with all inherited dast. For example, if the {...@link ActionConfig} + * is in a package that contains a global result and it also contains a result, the resulting {...@link ActionConfig} + * will have two results. + */ + protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws ConfigurationException { + Map<String, Map<String, ActionConfig>> namespaceActionConfigs = new LinkedHashMap<String, Map<String, ActionConfig>>(); + Map<String, String> namespaceConfigs = new LinkedHashMap<String, String>(); + + for (PackageConfig packageConfig : packageContexts.values()) { + + if (!packageConfig.isAbstract()) { + String namespace = packageConfig.getNamespace(); + Map<String, ActionConfig> configs = namespaceActionConfigs.get(namespace); + + if (configs == null) { + configs = new LinkedHashMap<String, ActionConfig>(); + } + + Map<String, ActionConfig> actionConfigs = packageConfig.getAllActionConfigs(); + + for (Object o : actionConfigs.keySet()) { + String actionName = (String) o; + ActionConfig baseConfig = actionConfigs.get(actionName); + configs.put(actionName, buildFullActionConfig(packageConfig, baseConfig)); + } + + + + namespaceActionConfigs.put(namespace, configs); + if (packageConfig.getFullDefaultActionRef() != null) { + namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef()); + } + } + } + + return new RuntimeConfigurationImpl(namespaceActionConfigs, namespaceConfigs); + } + + private void setDefaultResults(Map<String, ResultConfig> results, PackageConfig packageContext) { + String defaultResult = packageContext.getFullDefaultResultType(); + + for (Map.Entry<String, ResultConfig> entry : results.entrySet()) { + + if (entry.getValue() == null) { + ResultTypeConfig resultTypeConfig = packageContext.getAllResultTypeConfigs().get(defaultResult); + entry.setValue(new ResultConfig.Builder(null, resultTypeConfig.getClassName()).build()); + } + } + } + + /** + * Builds the full runtime actionconfig with all of the defaults and inheritance + * + * @param packageContext the PackageConfig which holds the base config we're building from + * @param baseConfig the ActionConfig which holds only the configuration specific to itself, without the defaults + * and inheritance + * @return a full ActionConfig for runtime configuration with all of the inherited and default params + * @throws com.opensymphony.xwork2.config.ConfigurationException + * + */ + private ActionConfig buildFullActionConfig(PackageConfig packageContext, ActionConfig baseConfig) throws ConfigurationException { + Map<String, String> params = new TreeMap<String, String>(baseConfig.getParams()); + Map<String, ResultConfig> results = new TreeMap<String, ResultConfig>(); + + if (!baseConfig.getPackageName().equals(packageContext.getName()) && packageContexts.containsKey(baseConfig.getPackageName())) { + results.putAll(packageContexts.get(baseConfig.getPackageName()).getAllGlobalResults()); + } else { + results.putAll(packageContext.getAllGlobalResults()); + } + + results.putAll(baseConfig.getResults()); + + setDefaultResults(results, packageContext); + + List<InterceptorMapping> interceptors = new ArrayList<InterceptorMapping>(baseConfig.getInterceptors()); + + if (interceptors.size() <= 0) { + String defaultInterceptorRefName = packageContext.getFullDefaultInterceptorRef(); + + if (defaultInterceptorRefName != null) { + interceptors.addAll(InterceptorBuilder.constructInterceptorReference(new PackageConfig.Builder(packageContext), defaultInterceptorRefName, + new LinkedHashMap<String, String>(), packageContext.getLocation(), objectFactory)); + } + } + + + + return new ActionConfig.Builder(baseConfig) + .addParams(params) + .addResultConfigs(results) + .defaultClassName(packageContext.getDefaultClassRef()) // fill in default if non class has been provided + .interceptors(interceptors) + .addExceptionMappings(packageContext.getAllExceptionMappingConfigs()) + .build(); + } + + + private class RuntimeConfigurationImpl implements RuntimeConfiguration { + private Map<String, Map<String, ActionConfig>> namespaceActionConfigs; + private Map<String, ActionConfigMatcher> namespaceActionConfigMatchers; + private NamespaceMatcher namespaceMatcher; + private Map<String, String> namespaceConfigs; + + public RuntimeConfigurationImpl(Map<String, Map<String, ActionConfig>> namespaceActionConfigs, Map<String, String> namespaceConfigs) { + this.namespaceActionConfigs = namespaceActionConfigs; + this.namespaceConfigs = namespaceConfigs; + + PatternMatcher<int[]> matcher = container.getInstance(PatternMatcher.class); + + this.namespaceActionConfigMatchers = new LinkedHashMap<String, ActionConfigMatcher>(); + this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet()); + + for (String ns : namespaceActionConfigs.keySet()) { + namespaceActionConfigMatchers.put(ns, + new ActionConfigMatcher(matcher, + namespaceActionConfigs.get(ns), true)); + } + } + + + /** + * Gets the configuration information for an action name, or returns null if the + * name is not recognized. + * + * @param name the name of the action + * @param namespace the namespace for the action or null for the empty namespace, "" + * @return the configuration information for action requested + */ + public synchronized ActionConfig getActionConfig(String namespace, String name) { + ActionConfig config = findActionConfigInNamespace(namespace, name); + + // try wildcarded namespaces + if (config == null) { + NamespaceMatch match = namespaceMatcher.match(namespace); + if (match != null) { + config = findActionConfigInNamespace(match.getPattern(), name); + + // If config found, place all the matches found in the namespace processing in the action's parameters + if (config != null) { + config = new ActionConfig.Builder(config) + .addParams(match.getVariables()) + .build(); + } + } + } + + // fail over to empty namespace + if ((config == null) && (namespace != null) && (!"".equals(namespace.trim()))) { + config = findActionConfigInNamespace("", name); + } + + + return config; + } + + ActionConfig findActionConfigInNamespace(String namespace, String name) { + ActionConfig config = null; + if (namespace == null) { + namespace = ""; + } + Map<String, ActionConfig> actions = namespaceActionConfigs.get(namespace); + if (actions != null) { + config = actions.get(name); + // Check wildcards + if (config == null) { + config = namespaceActionConfigMatchers.get(namespace).match(name); + // fail over to default action + if (config == null) { + String defaultActionRef = namespaceConfigs.get(namespace); + if (defaultActionRef != null) { + config = actions.get(defaultActionRef); + } + } + } + } + return config; + } + + /** + * Gets the configuration settings for every action. + * + * @return a Map of namespace - > Map of ActionConfig objects, with the key being the action name + */ + public synchronized Map<String, Map<String, ActionConfig>> getActionConfigs() { + return namespaceActionConfigs; + } + + @Override + public String toString() { + StringBuilder buff = new StringBuilder("RuntimeConfiguration - actions are\n"); + + for (String namespace : namespaceActionConfigs.keySet()) { + Map<String, ActionConfig> actionConfigs = namespaceActionConfigs.get(namespace); + + for (String s : actionConfigs.keySet()) { + buff.append(namespace).append("/").append(s).append("\n"); + } + } + + return buff.toString(); + } + } + + class ContainerProperties extends LocatableProperties { + private static final long serialVersionUID = -7320625750836896089L; + + @Override + public Object setProperty(String key, String value) { + String oldValue = getProperty(key); + if (oldValue != null && !oldValue.equals(value) && !defaultFrameworkBeanName.equals(oldValue)) { + LOG.info("Overriding property "+key+" - old value: "+oldValue+" new value: "+value); + } + return super.setProperty(key, value); + } + + public void setConstants(ContainerBuilder builder) { + for (Object keyobj : keySet()) { + String key = (String)keyobj; + builder.factory(String.class, key, + new LocatableConstantFactory<String>(getProperty(key), getPropertyLocation(key))); + } + } + } +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,34 @@ +/** + * + */ +package com.opensymphony.xwork2.config.impl; + +import com.opensymphony.xwork2.inject.Context; +import com.opensymphony.xwork2.inject.Factory; +import com.opensymphony.xwork2.util.location.Located; +import com.opensymphony.xwork2.util.location.LocationUtils; + +/** + * Factory that remembers where a constant came from + */ +public class LocatableConstantFactory<T> extends Located implements Factory { + T constant; + public LocatableConstantFactory(T constant, Object location) { + this.constant = constant; + setLocation(LocationUtils.getLocation(location)); + } + + public T create(Context ignored) { + return constant; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(super.toString()); + sb.append(" defined at "); + sb.append(getLocation().toString()); + return sb.toString(); + } + +} \ No newline at end of file Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,52 @@ +package com.opensymphony.xwork2.config.impl; + +import com.opensymphony.xwork2.inject.Context; +import com.opensymphony.xwork2.inject.Factory; +import com.opensymphony.xwork2.inject.Scope; +import com.opensymphony.xwork2.util.location.Located; +import com.opensymphony.xwork2.util.location.LocationUtils; + +import java.util.LinkedHashMap; + +/** + * Attaches location information to the factory. + */ +public class LocatableFactory<T> extends Located implements Factory<T> { + + + private Class implementation; + private Class type; + private String name; + private Scope scope; + + public LocatableFactory(String name, Class type, Class implementation, Scope scope, Object location) { + this.implementation = implementation; + this.type = type; + this.name = name; + this.scope = scope; + setLocation(LocationUtils.getLocation(location)); + } + + @SuppressWarnings("unchecked") + public T create(Context context) { + Object obj = context.getContainer().inject(implementation); + return (T) obj; + } + + @Override + public String toString() { + String fields = new LinkedHashMap<String, Object>() { + { + put("type", type); + put("name", name); + put("implementation", implementation); + put("scope", scope); + } + }.toString(); + StringBuilder sb = new StringBuilder(fields); + sb.append(super.toString()); + sb.append(" defined at "); + sb.append(getLocation().toString()); + return sb.toString(); + } +} \ No newline at end of file Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2003 by OpenSymphony + * All rights reserved. + */ +package com.opensymphony.xwork2.config.impl; + +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.ConfigurationProvider; +import com.opensymphony.xwork2.config.ContainerProvider; +import com.opensymphony.xwork2.config.PackageProvider; +import com.opensymphony.xwork2.config.RuntimeConfiguration; +import com.opensymphony.xwork2.config.entities.PackageConfig; +import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig; +import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.inject.Scope; +import com.opensymphony.xwork2.util.location.LocatableProperties; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +/** + * Simple configuration used for unit testing + */ +public class MockConfiguration implements Configuration { + + private Map<String, PackageConfig> packages = new HashMap<String, PackageConfig>(); + private Set<String> loadedFiles = new HashSet<String>(); + private Container container; + protected List<UnknownHandlerConfig> unknownHandlerStack; + private ContainerBuilder builder; + + public MockConfiguration() { + builder = new ContainerBuilder(); + } + + public void selfRegister() { + //this cannot be done in the constructor, as it causes an infinite loop + builder.factory(Configuration.class, MockConfiguration.class, Scope.SINGLETON); + LocatableProperties props = new LocatableProperties(); + new XWorkConfigurationProvider().register(builder, props); + builder.constant("devMode", "false"); + container = builder.create(true); + } + + public PackageConfig getPackageConfig(String name) { + return packages.get(name); + } + + public Set<String> getPackageConfigNames() { + return packages.keySet(); + } + + public Map<String, PackageConfig> getPackageConfigs() { + return packages; + } + + public RuntimeConfiguration getRuntimeConfiguration() { + throw new UnsupportedOperationException(); + } + + public void addPackageConfig(String name, PackageConfig packageContext) { + packages.put(name, packageContext); + } + + public void buildRuntimeConfiguration() { + throw new UnsupportedOperationException(); + } + + public void destroy() { + throw new UnsupportedOperationException(); + } + + public void rebuildRuntimeConfiguration() { + throw new UnsupportedOperationException(); + } + + public void reload(List<ConfigurationProvider> providers) throws ConfigurationException { + throw new UnsupportedOperationException(); + } + + public PackageConfig removePackageConfig(String name) { + return packages.remove(name); + } + + public Container getContainer() { + return container; + } + + public Set<String> getLoadedFileNames() { + return loadedFiles; + } + + public List<PackageProvider> reloadContainer( + List<ContainerProvider> containerProviders) + throws ConfigurationException { + throw new UnsupportedOperationException(); + } + + public List<UnknownHandlerConfig> getUnknownHandlerStack() { + return unknownHandlerStack; + } + + public void setUnknownHandlerStack(List<UnknownHandlerConfig> unknownHandlerStack) { + this.unknownHandlerStack = unknownHandlerStack; + } + +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2006 by OpenSymphony + * All rights reserved. + */ +package com.opensymphony.xwork2.config.impl; + +import java.util.Map; + +/** + * Represents a match from a namespace pattern matching. + * + * @Since 2.1 + */ +public class NamespaceMatch { + private String pattern; + private Map<String,String> variables; + + public NamespaceMatch(String pattern, Map<String, String> variables) { + this.pattern = pattern; + this.variables = variables; + } + + /** + * @return The pattern that was matched + */ + public String getPattern() { + return pattern; + } + + /** + * @return The variables containing the matched values + */ + public Map<String, String> getVariables() { + return variables; + } +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2006 by OpenSymphony + * All rights reserved. + */ +package com.opensymphony.xwork2.config.impl; + +import com.opensymphony.xwork2.util.PatternMatcher; + +import java.util.Map; +import java.util.Set; + +/** + * Matches namespace strings against a wildcard pattern matcher + * + * @Since 2.1 + */ +public class NamespaceMatcher extends AbstractMatcher<NamespaceMatch> { + public NamespaceMatcher(PatternMatcher<?> patternMatcher, + Set<String> namespaces) { + super(patternMatcher); + for (String name : namespaces) { + if (!patternMatcher.isLiteral(name)) { + addPattern(name, new NamespaceMatch(name, null), false); + } + } + } + + @Override + protected NamespaceMatch convert(String path, NamespaceMatch orig, Map<String, String> vars) { + /*Map<String,String> origVars = (Map<String,String>)vars; + Map<String,String> map = new HashMap<String,String>(); + for (Map.Entry<String,String> entry : origVars.entrySet()) { + if (entry.getKey().length() == 1) { + map.put("ns"+entry.getKey(), entry.getValue()); + } + } + */ + return new NamespaceMatch(orig.getPattern(), vars); + } +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html Sun Dec 27 18:00:13 2009 @@ -0,0 +1 @@ +<body>Configuration implementation classes.</body> Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html Sun Dec 27 18:00:13 2009 @@ -0,0 +1 @@ +<body>Configuration core classes.</body> Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/package.html ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2002-2006 by OpenSymphony + * All rights reserved. + */ +package com.opensymphony.xwork2.config.providers; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.entities.InterceptorConfig; +import com.opensymphony.xwork2.config.entities.InterceptorLocator; +import com.opensymphony.xwork2.config.entities.InterceptorMapping; +import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; +import com.opensymphony.xwork2.interceptor.Interceptor; +import com.opensymphony.xwork2.util.location.Location; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + + +/** + * Builds a list of interceptors referenced by the refName in the supplied PackageConfig. + * + * @author Mike + * @author Rainer Hermanns + * @author tmjee + * @version $Date$ $Id$ + */ +public class InterceptorBuilder { + + private static final Logger LOG = LoggerFactory.getLogger(InterceptorBuilder.class); + + + /** + * Builds a list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object). + * + * @param interceptorLocator + * @param refName + * @param refParams + * @return list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object). + * @throws ConfigurationException + */ + public static List<InterceptorMapping> constructInterceptorReference(InterceptorLocator interceptorLocator, + String refName, Map<String,String> refParams, Location location, ObjectFactory objectFactory) throws ConfigurationException { + Object referencedConfig = interceptorLocator.getInterceptorConfig(refName); + List<InterceptorMapping> result = new ArrayList<InterceptorMapping>(); + + if (referencedConfig == null) { + throw new ConfigurationException("Unable to find interceptor class referenced by ref-name " + refName, location); + } else { + if (referencedConfig instanceof InterceptorConfig) { + InterceptorConfig config = (InterceptorConfig) referencedConfig; + Interceptor inter = null; + try { + + inter = objectFactory.buildInterceptor(config, refParams); + result.add(new InterceptorMapping(refName, inter)); + } catch (ConfigurationException ex) { + LOG.warn("Unable to load config class " + config.getClassName() + " at " + + ex.getLocation() + " probably due to a missing jar, which might " + + "be fine if you never plan to use the " + config.getName() + " interceptor"); + LOG.error("Actual exception", ex); + } + + } else if (referencedConfig instanceof InterceptorStackConfig) { + InterceptorStackConfig stackConfig = (InterceptorStackConfig) referencedConfig; + + if ((refParams != null) && (refParams.size() > 0)) { + result = constructParameterizedInterceptorReferences(interceptorLocator, stackConfig, refParams, objectFactory); + } else { + result.addAll(stackConfig.getInterceptors()); + } + + } else { + LOG.error("Got unexpected type for interceptor " + refName + ". Got " + referencedConfig); + } + } + + return result; + } + + /** + * Builds a list of interceptors referenced by the refName in the supplied PackageConfig overriding the properties + * of the referenced interceptor with refParams. + * + * @param interceptorLocator + * @param stackConfig + * @param refParams The overridden interceptor properies + * @return list of interceptors referenced by the refName in the supplied PackageConfig overridden with refParams. + */ + private static List<InterceptorMapping> constructParameterizedInterceptorReferences( + InterceptorLocator interceptorLocator, InterceptorStackConfig stackConfig, Map<String,String> refParams, + ObjectFactory objectFactory) { + List<InterceptorMapping> result; + Map<String, Map<String, String>> params = new LinkedHashMap<String, Map<String, String>>(); + + /* + * We strip + * + * <interceptor-ref name="someStack"> + * <param name="interceptor1.param1">someValue</param> + * <param name="interceptor1.param2">anotherValue</param> + * </interceptor-ref> + * + * down to map + * interceptor1 -> [param1 -> someValue, param2 -> anotherValue] + * + * or + * <interceptor-ref name="someStack"> + * <param name="interceptorStack1.interceptor1.param1">someValue</param> + * <param name="interceptorStack1.interceptor1.param2">anotherValue</param> + * </interceptor-ref> + * + * down to map + * interceptorStack1 -> [interceptor1.param1 -> someValue, interceptor1.param2 -> anotherValue] + * + */ + for (String key : refParams.keySet()) { + String value = refParams.get(key); + + try { + String name = key.substring(0, key.indexOf('.')); + key = key.substring(key.indexOf('.') + 1); + + Map<String, String> map; + if (params.containsKey(name)) { + map = params.get(name); + } else { + map = new LinkedHashMap<String, String>(); + } + + map.put(key, value); + params.put(name, map); + + } catch (Exception e) { + LOG.warn("No interceptor found for name = " + key); + } + } + + result = new ArrayList<InterceptorMapping>(stackConfig.getInterceptors()); + + for (String key : params.keySet()) { + + Map<String, String> map = params.get(key); + + + Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key); + + /* + * Now we attempt to separate out param that refers to Interceptor + * and Interceptor stack, eg. + * + * <interceptor-ref name="someStack"> + * <param name="interceptor1.param1">someValue</param> + * ... + * </interceptor-ref> + * + * vs + * + * <interceptor-ref name="someStack"> + * <param name="interceptorStack1.interceptor1.param1">someValue</param> + * ... + * </interceptor-ref> + */ + if (interceptorCfgObj instanceof InterceptorConfig) { // interceptor-ref param refer to an interceptor + InterceptorConfig cfg = (InterceptorConfig) interceptorCfgObj; + Interceptor interceptor = objectFactory.buildInterceptor(cfg, map); + + InterceptorMapping mapping = new InterceptorMapping(key, interceptor); + if (result != null && result.contains(mapping)) { + // if an existing interceptor mapping exists, + // we remove from the result Set, just to make sure + // there's always one unique mapping. + int index = result.indexOf(mapping); + result.set(index, mapping); + } else { + result.add(mapping); + } + } else + if (interceptorCfgObj instanceof InterceptorStackConfig) { // interceptor-ref param refer to an interceptor stack + + // If its an interceptor-stack, we call this method recursively untill, + // all the params (eg. interceptorStack1.interceptor1.param etc.) + // are resolved down to a specific interceptor. + + InterceptorStackConfig stackCfg = (InterceptorStackConfig) interceptorCfgObj; + List<InterceptorMapping> tmpResult = constructParameterizedInterceptorReferences(interceptorLocator, stackCfg, map, objectFactory); + for (InterceptorMapping tmpInterceptorMapping : tmpResult) { + if (result.contains(tmpInterceptorMapping)) { + int index = result.indexOf(tmpInterceptorMapping); + result.set(index, tmpInterceptorMapping); + } else { + result.add(tmpInterceptorMapping); + } + } + } + } + + return result; + } +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java URL: http://svn.apache.org/viewvc/struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java?rev=894087&view=auto ============================================================================== --- struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java (added) +++ struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java Sun Dec 27 18:00:13 2009 @@ -0,0 +1,120 @@ +package com.opensymphony.xwork2.config.providers; + +import com.opensymphony.xwork2.ActionProxyFactory; +import com.opensymphony.xwork2.DefaultActionProxyFactory; +import com.opensymphony.xwork2.DefaultTextProvider; +import com.opensymphony.xwork2.DefaultUnknownHandlerManager; +import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.TextProviderSupport; +import com.opensymphony.xwork2.UnknownHandlerManager; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.config.ConfigurationProvider; +import com.opensymphony.xwork2.conversion.NullHandler; +import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; +import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer; +import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler; +import com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter; +import com.opensymphony.xwork2.conversion.impl.XWorkConverter; +import com.opensymphony.xwork2.inject.ContainerBuilder; +import com.opensymphony.xwork2.inject.Scope; +import com.opensymphony.xwork2.ognl.ObjectProxy; +import com.opensymphony.xwork2.ognl.OgnlReflectionContextFactory; +import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; +import com.opensymphony.xwork2.ognl.OgnlUtil; +import com.opensymphony.xwork2.ognl.OgnlValueStackFactory; +import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; +import com.opensymphony.xwork2.ognl.accessor.ObjectAccessor; +import com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor; +import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor; +import com.opensymphony.xwork2.util.CompoundRoot; +import com.opensymphony.xwork2.util.PatternMatcher; +import com.opensymphony.xwork2.util.ValueStackFactory; +import com.opensymphony.xwork2.util.WildcardHelper; +import com.opensymphony.xwork2.util.location.LocatableProperties; +import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory; +import com.opensymphony.xwork2.util.reflection.ReflectionProvider; +import com.opensymphony.xwork2.validator.ActionValidatorManager; +import com.opensymphony.xwork2.validator.AnnotationActionValidatorManager; +import com.opensymphony.xwork2.validator.DefaultActionValidatorManager; +import com.opensymphony.xwork2.validator.DefaultValidatorFactory; +import com.opensymphony.xwork2.validator.DefaultValidatorFileParser; +import com.opensymphony.xwork2.validator.ValidatorFactory; +import com.opensymphony.xwork2.validator.ValidatorFileParser; +import ognl.MethodAccessor; +import ognl.PropertyAccessor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class XWorkConfigurationProvider implements ConfigurationProvider { + + public void destroy() { + } + + public void init(Configuration configuration) throws ConfigurationException { + } + + public void loadPackages() throws ConfigurationException { + } + + public boolean needsReload() { + return false; + } + + public void register(ContainerBuilder builder, LocatableProperties props) + throws ConfigurationException { + + builder.factory(com.opensymphony.xwork2.ObjectFactory.class) + .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON) + .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON) + .factory(XWorkConverter.class, Scope.SINGLETON) + .factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON) + .factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON) + .factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON) + .factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON) + .factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON) + .factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON) + .factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON) + + // silly workarounds for ognl since there is no way to flush its caches + .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) + + .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) + .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON) + .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON) + .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) + .factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON) + .factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON) + .factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON) + .factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON) + .factory(TextProvider.class, TextProviderSupport.class, Scope.SINGLETON) + .factory(OgnlUtil.class, Scope.SINGLETON) + .factory(XWorkBasicConverter.class, Scope.SINGLETON); + props.setProperty("devMode", Boolean.FALSE.toString()); + props.setProperty("logMissingProperties", Boolean.FALSE.toString()); + props.setProperty("enableOGNLExpressionCache", Boolean.TRUE.toString()); + } + +} Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: struts/xwork/trunk/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL