You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2015/06/17 23:09:46 UTC

[46/57] [partial] struts git commit: Merges xwork packages into struts

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
new file mode 100644
index 0000000..eb218f8
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java
@@ -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

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
new file mode 100644
index 0000000..2f95dfe
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java
@@ -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

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java
new file mode 100644
index 0000000..d5359fe
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2002-2003,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.config.impl;
+
+import com.opensymphony.xwork2.XWorkConstants;
+import com.opensymphony.xwork2.config.*;
+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.*;
+
+
+/**
+ * Simple configuration used for unit testing
+ */
+public class MockConfiguration implements Configuration {
+
+    private Map<String, PackageConfig> packages = new HashMap<>();
+    private Set<String> loadedFiles = new HashSet<>();
+    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(XWorkConstants.DEV_MODE, "false");
+        builder.constant(XWorkConstants.RELOAD_XML_CONFIGURATION, "true");
+        builder.constant(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE, "true");
+        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;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java
new file mode 100644
index 0000000..52a0886
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java
new file mode 100644
index 0000000..3d64c33
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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);
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html b/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html
new file mode 100644
index 0000000..cdfed5f
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html
@@ -0,0 +1 @@
+<body>Configuration implementation classes.</body>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/package.html
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/package.html b/core/src/main/java/com/opensymphony/xwork2/config/package.html
new file mode 100644
index 0000000..a3de692
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/package.html
@@ -0,0 +1 @@
+<body>Configuration core classes.</body>

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java
new file mode 100644
index 0000000..82a7266
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java
@@ -0,0 +1,59 @@
+package com.opensymphony.xwork2.config.providers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CycleDetector<T> {
+    private static final String marked = "marked";
+    private static final String complete = "complete";
+    private DirectedGraph<T> graph;
+    private Map<T, String> marks;
+    private List<T> verticesInCycles;
+
+    public CycleDetector(DirectedGraph<T> graph) {
+        this.graph = graph;
+        marks = new HashMap<>();
+        verticesInCycles = new ArrayList<>();
+    }
+
+    public boolean containsCycle() {
+        for (T v : graph) {
+            if (!marks.containsKey(v)) {
+                if (mark(v)) {
+                    // return true;
+                }
+            }
+        }
+        // return false;
+        return !verticesInCycles.isEmpty();
+    }
+
+    private boolean mark(T vertex) {
+        /*
+         * return statements commented out for fail slow behavior detect all nodes in cycles instead of just the first one
+         */
+        List<T> localCycles = new ArrayList<T>();
+        marks.put(vertex, marked);
+        for (T u : graph.edgesFrom(vertex)) {
+            if (marks.containsKey(u) && marks.get(u).equals(marked)) {
+                localCycles.add(vertex);
+                // return true;
+            } else if (!marks.containsKey(u)) {
+                if (mark(u)) {
+                    localCycles.add(vertex);
+                    // return true;
+                }
+            }
+        }
+        marks.put(vertex, complete);
+        // return false;
+        verticesInCycles.addAll(localCycles);
+        return !localCycles.isEmpty();
+    }
+
+    public List<T> getVerticesInCycles() {
+        return verticesInCycles;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/providers/DirectedGraph.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/DirectedGraph.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/DirectedGraph.java
new file mode 100644
index 0000000..d7c6edc
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/DirectedGraph.java
@@ -0,0 +1,143 @@
+package com.opensymphony.xwork2.config.providers;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+public final class DirectedGraph<T> implements Iterable<T> {
+    private final Map<T, Set<T>> mGraph = new HashMap<T, Set<T>>();
+
+    /**
+     * Adds a new node to the graph. If the node already exists, this function is a no-op.
+     * 
+     * @param node
+     *            The node to add.
+     * @return Whether or not the node was added.
+     */
+    public boolean addNode(T node) {
+        /* If the node already exists, don't do anything. */
+        if (mGraph.containsKey(node))
+            return false;
+
+        /* Otherwise, add the node with an empty set of outgoing edges. */
+        mGraph.put(node, new HashSet<T>());
+        return true;
+    }
+
+    /**
+     * Given a start node, and a destination, adds an arc from the start node to the destination. If an arc already exists, this operation is a no-op.
+     * If either endpoint does not exist in the graph, throws a NoSuchElementException.
+     * 
+     * @param start
+     *            The start node.
+     * @param dest
+     *            The destination node.
+     * @throws NoSuchElementException
+     *             If either the start or destination nodes do not exist.
+     */
+    public void addEdge(T start, T dest) {
+        /* Confirm both endpoints exist. */
+        if (!mGraph.containsKey(start)) {
+            throw new NoSuchElementException("The start node does not exist in the graph.");
+        } else if (!mGraph.containsKey(dest)) {
+            throw new NoSuchElementException("The destination node does not exist in the graph.");
+        }
+
+        /* Add the edge. */
+        mGraph.get(start).add(dest);
+    }
+
+    /**
+     * Removes the edge from start to dest from the graph. If the edge does not exist, this operation is a no-op. If either endpoint does not exist,
+     * this throws a NoSuchElementException.
+     * 
+     * @param start
+     *            The start node.
+     * @param dest
+     *            The destination node.
+     * @throws NoSuchElementException
+     *             If either node is not in the graph.
+     */
+    public void removeEdge(T start, T dest) {
+        /* Confirm both endpoints exist. */
+        if (!mGraph.containsKey(start)) {
+            throw new NoSuchElementException("The start node does not exist in the graph.");
+        } else if (!mGraph.containsKey(dest)) {
+            throw new NoSuchElementException("The destination node does not exist in the graph.");
+        }
+
+        mGraph.get(start).remove(dest);
+    }
+
+    /**
+     * Given two nodes in the graph, returns whether there is an edge from the first node to the second node. If either node does not exist in the
+     * graph, throws a NoSuchElementException.
+     * 
+     * @param start
+     *            The start node.
+     * @param end
+     *            The destination node.
+     * @return Whether there is an edge from start to end.
+     * @throws NoSuchElementException
+     *             If either endpoint does not exist.
+     */
+    public boolean edgeExists(T start, T end) {
+        /* Confirm both endpoints exist. */
+        if (!mGraph.containsKey(start)) {
+            throw new NoSuchElementException("The start node does not exist in the graph.");
+        } else if (!mGraph.containsKey(end)) {
+            throw new NoSuchElementException("The end node does not exist in the graph.");
+        }
+
+        return mGraph.get(start).contains(end);
+    }
+
+    /**
+     * Given a node in the graph, returns an immutable view of the edges leaving that node as a set of endpoints.
+     * 
+     * @param node
+     *            The node whose edges should be queried.
+     * @return An immutable view of the edges leaving that node.
+     * @throws NoSuchElementException
+     *             If the node does not exist.
+     */
+    public Set<T> edgesFrom(T node) {
+        /* Check that the node exists. */
+        Set<T> arcs = mGraph.get(node);
+        if (arcs == null)
+            throw new NoSuchElementException("Source node does not exist.");
+
+        return Collections.unmodifiableSet(arcs);
+    }
+
+    /**
+     * Returns an iterator that can traverse the nodes in the graph.
+     * 
+     * @return An iterator that traverses the nodes in the graph.
+     */
+    public Iterator<T> iterator() {
+        return mGraph.keySet().iterator();
+    }
+
+    /**
+     * Returns the number of nodes in the graph.
+     * 
+     * @return The number of nodes in the graph.
+     */
+    public int size() {
+        return mGraph.size();
+    }
+
+    /**
+     * Returns whether the graph is empty.
+     * 
+     * @return Whether the graph is empty.
+     */
+    public boolean isEmpty() {
+        return mGraph.isEmpty();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java
new file mode 100644
index 0000000..1328205
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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 org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+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 = LogManager.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<>();
+
+        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;
+                try {
+
+                    inter = objectFactory.buildInterceptor(config, refParams);
+                    result.add(new InterceptorMapping(refName, inter));
+                } catch (ConfigurationException ex) {
+              	    LOG.warn("Unable to load config class {} at {} probably due to a missing jar, which might be fine if you never plan to use the {} interceptor",
+                            config.getClassName(), ex.getLocation(), config.getName());
+                    LOG.error("Unable to load config class {}", config.getClassName(), 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 {}. Got {}", refName, 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<>();
+
+        /*
+         * 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<>();
+                }
+
+                map.put(key, value);
+                params.put(name, map);
+
+            } catch (Exception e) {
+                LOG.warn("No interceptor found for name = {}", key);
+            }
+        }
+
+        result = new ArrayList<>(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 until,
+                // 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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/31af5842/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
new file mode 100644
index 0000000..4ade520
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java
@@ -0,0 +1,191 @@
+package com.opensymphony.xwork2.config.providers;
+
+import com.opensymphony.xwork2.ActionProxyFactory;
+import com.opensymphony.xwork2.DefaultActionProxyFactory;
+import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
+import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
+import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
+import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
+import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
+import com.opensymphony.xwork2.DefaultLocaleProvider;
+import com.opensymphony.xwork2.DefaultTextProvider;
+import com.opensymphony.xwork2.DefaultUnknownHandlerManager;
+import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
+import com.opensymphony.xwork2.FileManager;
+import com.opensymphony.xwork2.FileManagerFactory;
+import com.opensymphony.xwork2.LocaleProvider;
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.TextProvider;
+import com.opensymphony.xwork2.TextProviderSupport;
+import com.opensymphony.xwork2.UnknownHandlerManager;
+import com.opensymphony.xwork2.XWorkConstants;
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.ConfigurationProvider;
+import com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor;
+import com.opensymphony.xwork2.conversion.ConversionFileProcessor;
+import com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor;
+import com.opensymphony.xwork2.conversion.NullHandler;
+import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
+import com.opensymphony.xwork2.conversion.TypeConverterCreator;
+import com.opensymphony.xwork2.conversion.TypeConverterHolder;
+import com.opensymphony.xwork2.conversion.impl.ArrayConverter;
+import com.opensymphony.xwork2.conversion.impl.CollectionConverter;
+import com.opensymphony.xwork2.conversion.impl.DateConverter;
+import com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor;
+import com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor;
+import com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor;
+import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
+import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterCreator;
+import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterHolder;
+import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler;
+import com.opensymphony.xwork2.conversion.impl.NumberConverter;
+import com.opensymphony.xwork2.conversion.impl.StringConverter;
+import com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.factory.ActionFactory;
+import com.opensymphony.xwork2.factory.ConverterFactory;
+import com.opensymphony.xwork2.factory.DefaultActionFactory;
+import com.opensymphony.xwork2.factory.DefaultConverterFactory;
+import com.opensymphony.xwork2.factory.DefaultInterceptorFactory;
+import com.opensymphony.xwork2.factory.DefaultResultFactory;
+import com.opensymphony.xwork2.factory.InterceptorFactory;
+import com.opensymphony.xwork2.factory.ResultFactory;
+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.OgnlTextParser;
+import com.opensymphony.xwork2.util.PatternMatcher;
+import com.opensymphony.xwork2.util.TextParser;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.util.WildcardHelper;
+import com.opensymphony.xwork2.util.fs.DefaultFileManager;
+import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory;
+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(ObjectFactory.class)
+                .factory(ActionFactory.class, DefaultActionFactory.class)
+                .factory(ResultFactory.class, DefaultResultFactory.class)
+                .factory(InterceptorFactory.class, DefaultInterceptorFactory.class)
+                .factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class)
+                .factory(ConverterFactory.class, DefaultConverterFactory.class)
+                .factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class)
+
+                .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
+                .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
+
+                .factory(XWorkConverter.class, Scope.SINGLETON)
+                .factory(XWorkBasicConverter.class, Scope.SINGLETON)
+                .factory(ConversionPropertiesProcessor.class, DefaultConversionPropertiesProcessor.class, Scope.SINGLETON)
+                .factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON)
+                .factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
+                .factory(TypeConverterCreator.class, DefaultTypeConverterCreator.class, Scope.SINGLETON)
+                .factory(TypeConverterHolder.class, DefaultTypeConverterHolder.class, Scope.SINGLETON)
+
+                .factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON)
+                .factory(FileManagerFactory.class, DefaultFileManagerFactory.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(TextParser.class, OgnlTextParser.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(LocaleProvider.class, DefaultLocaleProvider.class, Scope.SINGLETON)
+                .factory(OgnlUtil.class, Scope.SINGLETON)
+                .factory(CollectionConverter.class, Scope.SINGLETON)
+                .factory(ArrayConverter.class, Scope.SINGLETON)
+                .factory(DateConverter.class, Scope.SINGLETON)
+                .factory(NumberConverter.class, Scope.SINGLETON)
+                .factory(StringConverter.class, Scope.SINGLETON)
+
+                .factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.DEFAULT)
+                .factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.DEFAULT)
+        ;
+
+        props.setProperty(XWorkConstants.DEV_MODE, Boolean.FALSE.toString());
+        props.setProperty(XWorkConstants.LOG_MISSING_PROPERTIES, Boolean.FALSE.toString());
+        props.setProperty(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE, Boolean.TRUE.toString());
+        props.setProperty(XWorkConstants.ENABLE_OGNL_EVAL_EXPRESSION, Boolean.FALSE.toString());
+        props.setProperty(XWorkConstants.RELOAD_XML_CONFIGURATION, Boolean.FALSE.toString());
+    }
+
+}