Return-Path: X-Original-To: apmail-struts-commits-archive@minotaur.apache.org Delivered-To: apmail-struts-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D56E018F27 for ; Wed, 17 Jun 2015 21:09:20 +0000 (UTC) Received: (qmail 77489 invoked by uid 500); 17 Jun 2015 21:09:04 -0000 Delivered-To: apmail-struts-commits-archive@struts.apache.org Received: (qmail 77434 invoked by uid 500); 17 Jun 2015 21:09:04 -0000 Mailing-List: contact commits-help@struts.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@struts.apache.org Delivered-To: mailing list commits@struts.apache.org Received: (qmail 75377 invoked by uid 99); 17 Jun 2015 21:09:02 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Jun 2015 21:09:02 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B79C8DFFC0; Wed, 17 Jun 2015 21:09:02 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: lukaszlenart@apache.org To: commits@struts.apache.org Date: Wed, 17 Jun 2015 21:09:46 -0000 Message-Id: <8e8243f0fa9b43119191a59e553cc3d3@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [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 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 extends Located implements Factory { + + + 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() { + { + 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 packages = new HashMap<>(); + private Set loadedFiles = new HashSet<>(); + private Container container; + protected List 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 getPackageConfigNames() { + return packages.keySet(); + } + + public Map 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 providers) throws ConfigurationException { + throw new UnsupportedOperationException(); + } + + public PackageConfig removePackageConfig(String name) { + return packages.remove(name); + } + + public Container getContainer() { + return container; + } + + public Set getLoadedFileNames() { + return loadedFiles; + } + + public List reloadContainer( + List containerProviders) + throws ConfigurationException { + throw new UnsupportedOperationException(); + } + + public List getUnknownHandlerStack() { + return unknownHandlerStack; + } + + public void setUnknownHandlerStack(List 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 variables; + + public NamespaceMatch(String pattern, Map 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 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 { + public NamespaceMatcher(PatternMatcher patternMatcher, + Set 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 vars) { + /*Map origVars = (Map)vars; + Map map = new HashMap(); + for (Map.Entry 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 @@ +Configuration implementation classes. 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 @@ +Configuration core classes. 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 { + private static final String marked = "marked"; + private static final String complete = "complete"; + private DirectedGraph graph; + private Map marks; + private List verticesInCycles; + + public CycleDetector(DirectedGraph 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 localCycles = new ArrayList(); + 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 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 implements Iterable { + private final Map> mGraph = new HashMap>(); + + /** + * 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()); + 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 edgesFrom(T node) { + /* Check that the node exists. */ + Set 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 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 constructInterceptorReference(InterceptorLocator interceptorLocator, + String refName, Map refParams, Location location, ObjectFactory objectFactory) throws ConfigurationException { + Object referencedConfig = interceptorLocator.getInterceptorConfig(refName); + List 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 constructParameterizedInterceptorReferences( + InterceptorLocator interceptorLocator, InterceptorStackConfig stackConfig, Map refParams, + ObjectFactory objectFactory) { + List result; + Map> params = new LinkedHashMap<>(); + + /* + * We strip + * + * + * someValue + * anotherValue + * + * + * down to map + * interceptor1 -> [param1 -> someValue, param2 -> anotherValue] + * + * or + * + * someValue + * anotherValue + * + * + * 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 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 map = params.get(key); + + + Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key); + + /* + * Now we attempt to separate out param that refers to Interceptor + * and Interceptor stack, eg. + * + * + * someValue + * ... + * + * + * vs + * + * + * someValue + * ... + * + */ + 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 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()); + } + +}