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());
+ }
+
+}