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 2017/01/09 09:08:06 UTC

[1/3] struts git commit: WW-4731 Moves detailed description to wiki

Repository: struts
Updated Branches:
  refs/heads/master 97419283e -> 2b12f06b0


WW-4731 Moves detailed description to wiki


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/14d56fbb
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/14d56fbb
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/14d56fbb

Branch: refs/heads/master
Commit: 14d56fbb93866646eb0152c0c56b64430c8a5704
Parents: 9741928
Author: Lukasz Lenart <lu...@apache.org>
Authored: Sun Jan 8 20:29:58 2017 +0100
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Sun Jan 8 20:29:58 2017 +0100

----------------------------------------------------------------------
 .../apache/struts2/views/xslt/XSLTResult.java   | 177 ++-----------------
 1 file changed, 13 insertions(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/14d56fbb/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
index fb5068c..c264a59 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
+++ b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
@@ -43,162 +43,8 @@ import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
-
 /**
- * <!-- START SNIPPET: description -->
- *
- * XSLTResult uses XSLT to transform an action object to XML. The recent version
- * has been specifically modified to deal with Xalan flaws. When using Xalan you
- * may notice that even though you have a very minimal stylesheet like this one
- * <pre>
- * &lt;xsl:template match="/result"&gt;
- *   &lt;result/&gt;
- * &lt;/xsl:template&gt;</pre>
- *
- * <p>
- * Xalan would still iterate through every property of your action and all
- * its descendants.
- * </p>
- *
- * <p>
- * If you had double-linked objects, Xalan would work forever analysing an
- * infinite object tree. Even if your stylesheet was not constructed to process
- * them all. It's because the current Xalan eagerly and extensively converts
- * everything to its internal DTM model before further processing.
- * </p>
- *
- * <p>
- * That's why there's a loop eliminator added that works by indexing every
- * object-property combination during processing. If it notices that some
- * object's property was already walked through, it doesn't go any deeper.
- * Say you have two objects, x and y, with the following properties set
- * (pseudocode):
- * </p>
- * <pre>
- * x.y = y;
- * and
- * y.x = x;
- * action.x=x;</pre>
- *
- * <p>
- * Due to that modification, the resulting XML document based on x would be:
- * </p>
- *
- * <pre>
- * &lt;result&gt;
- *   &lt;x&gt;
- *     &lt;y/&gt;
- *   &lt;/x&gt;
- * &lt;/result&gt;</pre>
- *
- * <p>
- * Without it there would be endless x/y/x/y/x/y/... elements.
- * </p>
- *
- * <p>
- * The XSLTResult code tries also to deal with the fact that DTM model is built
- * in a manner that children are processed before siblings. The result is that if
- * there is object x that is both set in action's x property, and very deeply
- * under action's a property then it would only appear under a, not under x.
- * That's not what we expect, and that's why XSLTResult allows objects to repeat
- * in various places to some extent.
- * </p>
- *
- * <p>
- * Sometimes the object mesh is still very dense and you may notice that even
- * though you have a relatively simple stylesheet, execution takes a tremendous
- * amount of time. To help you to deal with that obstacle of Xalan, you may
- * attach regexp filters to elements paths (xpath).
- * </p>
- *
- * <p>
- * <b>Note:</b> In your .xsl file the root match must be named <tt>result</tt>.
- * <br>This example will output the username by using <tt>getUsername</tt> on your
- * action class:
- * <pre>
- * &lt;xsl:template match="result"&gt;
- *   &lt;html&gt;
- *   &lt;body&gt;
- *   Hello &lt;xsl:value-of select="username"/&gt; how are you?
- *   &lt;/body&gt;
- *   &lt;/html&gt;
- * &lt;/xsl:template&gt;
- * </pre>
- *
- * <p>
- * In the following example the XSLT result would only walk through action's
- * properties without their childs. It would also skip every property that has
- * "hugeCollection" in their name. Element's path is first compared to
- * excludingPattern - if it matches it's no longer processed. Then it is
- * compared to matchingPattern and processed only if there's a match.
- * </p>
- *
- * <!-- END SNIPPET: description -->
- *
- * <pre><!-- START SNIPPET: description.example -->
- * &lt;result name="success" type="xslt"&gt;
- *   &lt;param name="location"&gt;foo.xslt&lt;/param&gt;
- *   &lt;param name="matchingPattern"&gt;^/result/[^/*]$&lt;/param&gt;
- *   &lt;param name="excludingPattern"&gt;.*(hugeCollection).*&lt;/param&gt;
- * &lt;/result&gt;
- * <!-- END SNIPPET: description.example --></pre>
- *
- * <p>
- * In the following example the XSLT result would use the action's user property
- * instead of the action as it's base document and walk through it's properties.
- * The exposedValue uses an ognl expression to derive it's value.
- * </p>
- *
- * <pre>
- * &lt;result name="success" type="xslt"&gt;
- *   &lt;param name="location"&gt;foo.xslt&lt;/param&gt;
- *   &lt;param name="exposedValue"&gt;user$&lt;/param&gt;
- * &lt;/result&gt;
- * </pre>
- * *
- * <b>This result type takes the following parameters:</b>
- *
- * <!-- START SNIPPET: params -->
- *
- * <ul>
- *
- * <li><b>location (default)</b> - the location to go to after execution.</li>
- * <li><b>encoding</b> - character encoding used in XML, default UTF-8.</li>
- *
- * <li><b>parse</b> - true by default. If set to false, the location param will
- * not be parsed for Ognl expressions.</li>
- *
- * <!--
- * <li><b>matchingPattern</b> - Pattern that matches only desired elements, by
- * default it matches everything.</li>
- *
- * <li><b>excludingPattern</b> - Pattern that eliminates unwanted elements, by
- * default it matches none.</li>
- * -->
- *
- * </ul>
- *
- * <p>
- * <code>struts.properties</code> related configuration:
- * </p>
- * <ul>
- *
- * <li><b>struts.xslt.nocache</b> - Defaults to false. If set to true, disables
- * stylesheet caching. Good for development, bad for production.</li>
- *
- * </ul>
- *
- * <!-- END SNIPPET: params -->
- * <p>
- * <b>Example:</b>
- * </p>
- *
- * <pre>
- * <!-- START SNIPPET: example -->
- * &lt;result name="success" type="xslt"&gt;foo.xslt&lt;/result&gt;
- * <!-- END SNIPPET: example -->
- * </pre>
- *
+ * XSLTResult uses XSLT to transform an action object to XML.
  */
 public class XSLTResult implements Result {
 
@@ -233,7 +79,7 @@ public class XSLTResult implements Result {
     /** Indicates the property name patterns which should be excluded from the xml. */
     private String excludingPattern;
 
-    /** Indicates the ognl expression respresenting the bean which is to be exposed as xml. */
+    /** Indicates the ognl expression representing the bean which is to be exposed as xml. */
     private String exposedValue;
 
     /** Indicates the status to return in the response */
@@ -258,8 +104,6 @@ public class XSLTResult implements Result {
     }
 
     public void setStylesheetLocation(String location) {
-        if (location == null)
-            throw new IllegalArgumentException("Null location");
         this.stylesheetLocation = location;
     }
 
@@ -306,12 +150,15 @@ public class XSLTResult implements Result {
         long startTime = System.currentTimeMillis();
         String location = getStylesheetLocation();
 
+        if (location == null) {
+            throw new IllegalArgumentException("Parameter 'stylesheetLocation' cannot be null!");
+        }
+
         if (parse) {
             ValueStack stack = ActionContext.getContext().getValueStack();
             location = TextParseUtil.translateVariables(location, stack);
         }
 
-
         try {
             HttpServletResponse response = ServletActionContext.getResponse();
             response.setStatus(status);
@@ -331,10 +178,12 @@ public class XSLTResult implements Result {
             transformer.setErrorListener(buildErrorListener());
 
             String mimeType;
-            if (templates == null)
+            if (templates == null) {
                 mimeType = "text/xml"; // no stylesheet, raw xml
-            else
+            } else {
                 mimeType = templates.getOutputProperties().getProperty(OutputKeys.MEDIA_TYPE);
+            }
+
             if (mimeType == null) {
                 // guess (this is a servlet, so text/html might be the best guess)
                 mimeType = "text/html";
@@ -383,8 +232,9 @@ public class XSLTResult implements Result {
     }
 
     protected AdapterFactory getAdapterFactory() {
-        if (adapterFactory == null)
+        if (adapterFactory == null) {
             adapterFactory = new AdapterFactory();
+        }
         return adapterFactory;
     }
 
@@ -428,8 +278,7 @@ public class XSLTResult implements Result {
         return templates;
     }
 
-    protected Source getDOMSourceForStack(Object value)
-            throws IllegalAccessException, InstantiationException {
+    protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException {
         return new DOMSource(getAdapterFactory().adaptDocument("result", value) );
     }
 }


[3/3] struts git commit: WW-4687 Allows define interceptors with dynamic parameters

Posted by lu...@apache.org.
WW-4687 Allows define interceptors with dynamic parameters


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/2b12f06b
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/2b12f06b
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/2b12f06b

Branch: refs/heads/master
Commit: 2b12f06b01f01fb02f4fae0370ae1be48bf81be3
Parents: b9c05a7
Author: Lukasz Lenart <lu...@apache.org>
Authored: Mon Jan 9 10:07:20 2017 +0100
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Mon Jan 9 10:07:20 2017 +0100

----------------------------------------------------------------------
 .../xwork2/DefaultActionInvocation.java         | 20 ++++++-
 .../config/entities/InterceptorMapping.java     | 14 ++++-
 .../config/providers/InterceptorBuilder.java    | 10 ++--
 .../factory/DefaultInterceptorFactory.java      | 12 +++-
 .../xwork2/interceptor/WithLazyParams.java      | 63 ++++++++++++++++++++
 .../xwork2/DefaultActionInvocationTest.java     | 34 +++++++++++
 .../xwork2/mock/MockLazyInterceptor.java        | 39 ++++++++++++
 core/src/test/resources/xwork-sample.xml        |  8 +++
 core/src/test/resources/xwork-test-default.xml  |  3 +-
 9 files changed, 191 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
index 639bf95..754ae5a 100644
--- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
+++ b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java
@@ -21,7 +21,9 @@ import com.opensymphony.xwork2.config.entities.InterceptorMapping;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.Interceptor;
 import com.opensymphony.xwork2.interceptor.PreResultListener;
+import com.opensymphony.xwork2.interceptor.WithLazyParams;
 import com.opensymphony.xwork2.ognl.OgnlUtil;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -67,6 +69,7 @@ public class DefaultActionInvocation implements ActionInvocation {
     protected Container container;
     protected UnknownHandlerManager unknownHandlerManager;
     protected OgnlUtil ognlUtil;
+    protected WithLazyParams.LazyParamInjector lazyParamInjector;
 
     public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
         this.extraContext = extraContext;
@@ -233,11 +236,15 @@ public class DefaultActionInvocation implements ActionInvocation {
             }
 
             if (interceptors.hasNext()) {
-                final InterceptorMapping interceptor = interceptors.next();
-                String interceptorMsg = "interceptor: " + interceptor.getName();
+                final InterceptorMapping interceptorMapping = interceptors.next();
+                String interceptorMsg = "interceptorMapping: " + interceptorMapping.getName();
                 UtilTimerStack.push(interceptorMsg);
                 try {
-                    resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
+                    Interceptor interceptor = interceptorMapping.getInterceptor();
+                    if (interceptor instanceof WithLazyParams) {
+                        interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
+                    }
+                    resultCode = interceptor.intercept(DefaultActionInvocation.this);
                 } finally {
                     UtilTimerStack.pop(interceptorMsg);
                 }
@@ -400,6 +407,13 @@ public class DefaultActionInvocation implements ActionInvocation {
         invocationContext.setName(proxy.getActionName());
 
         createInterceptors(proxy);
+
+        prepareLazyParamInjector(invocationContext.getValueStack());
+    }
+
+    protected void prepareLazyParamInjector(ValueStack valueStack) {
+        lazyParamInjector = new WithLazyParams.LazyParamInjector(valueStack);
+        container.inject(lazyParamInjector);
     }
 
     protected void createInterceptors(ActionProxy proxy) {

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
index 846575e..36ba95c 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
@@ -19,6 +19,8 @@ package com.opensymphony.xwork2.config.entities;
 import com.opensymphony.xwork2.interceptor.Interceptor;
 
 import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * <code>InterceptorMapping</code>
@@ -30,10 +32,16 @@ public class InterceptorMapping implements Serializable {
 
     private String name;
     private Interceptor interceptor;
+    private final Map<String, String> params;
 
     public InterceptorMapping(String name, Interceptor interceptor) {
+        this(name, interceptor, new HashMap<String, String>());
+    }
+
+    public InterceptorMapping(String name, Interceptor interceptor, Map<String, String> params) {
         this.name = name;
         this.interceptor = interceptor;
+        this.params = params;
     }
 
     public String getName() {
@@ -44,6 +52,10 @@ public class InterceptorMapping implements Serializable {
         return interceptor;
     }
 
+    public Map<String, String> getParams() {
+        return params;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -65,7 +77,7 @@ public class InterceptorMapping implements Serializable {
 
     @Override
     public String toString() {
-        return "InterceptorMapping: [" + name + "] => [" + interceptor.getClass().getName() + ']';
+        return "InterceptorMapping: [" + name + "] => [" + interceptor.getClass().getName() + "] with params [" + params + "]" ;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/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
index fcf2484..8044c1a 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java
@@ -25,6 +25,7 @@ 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 org.apache.logging.log4j.message.ParameterizedMessage;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -43,7 +44,6 @@ 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).
      *
@@ -67,13 +67,11 @@ public class InterceptorBuilder {
                 InterceptorConfig config = (InterceptorConfig) referencedConfig;
                 Interceptor inter;
                 try {
-
                     inter = objectFactory.buildInterceptor(config, refParams);
-                    result.add(new InterceptorMapping(refName, inter));
+                    result.add(new InterceptorMapping(refName, inter, refParams));
                 } 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);
+              	    LOG.warn(new ParameterizedMessage("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()), ex);
                 }
 
             } else if (referencedConfig instanceof InterceptorStackConfig) {

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java
index 407aa35..3cdf6b5 100644
--- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java
+++ b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java
@@ -5,7 +5,10 @@ import com.opensymphony.xwork2.config.ConfigurationException;
 import com.opensymphony.xwork2.config.entities.InterceptorConfig;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.interceptor.WithLazyParams;
 import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -15,6 +18,8 @@ import java.util.Map;
  */
 public class DefaultInterceptorFactory implements InterceptorFactory {
 
+    private static final Logger LOG = LogManager.getLogger(DefaultInterceptorFactory.class);
+
     private ObjectFactory objectFactory;
     private ReflectionProvider reflectionProvider;
 
@@ -40,7 +45,12 @@ public class DefaultInterceptorFactory implements InterceptorFactory {
         try {
             // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context
             Object o = objectFactory.buildBean(interceptorClassName, null);
-            reflectionProvider.setProperties(params, o);
+            if (o instanceof WithLazyParams) {
+                LOG.debug("Interceptor {} is marked with interface {} and params will be set during action invocation",
+                        interceptorClassName, WithLazyParams.class.getName());
+            } else {
+                reflectionProvider.setProperties(params, o);
+            }
 
             if (o instanceof Interceptor) {
                 Interceptor interceptor = (Interceptor) o;

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java
new file mode 100644
index 0000000..e54cc73
--- /dev/null
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java
@@ -0,0 +1,63 @@
+package com.opensymphony.xwork2.interceptor;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.ognl.OgnlUtil;
+import com.opensymphony.xwork2.util.TextParseUtil;
+import com.opensymphony.xwork2.util.TextParser;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+
+import java.util.Map;
+
+/**
+ * Interceptors marked with this interface won't be fully initialised during initialisation.
+ * Appropriated params will be injected just before usage of the interceptor.
+ *
+ * Please be aware that in such case {@link Interceptor#init()} method must be prepared for this.
+ *
+ * @since 2.5.9
+ */
+public interface WithLazyParams {
+
+    class LazyParamInjector {
+
+        protected OgnlUtil ognlUtil;
+        protected TextParser textParser;
+        protected ReflectionProvider reflectionProvider;
+
+        private final TextParseUtil.ParsedValueEvaluator valueEvaluator;
+
+        public LazyParamInjector(final ValueStack valueStack) {
+            valueEvaluator = new TextParseUtil.ParsedValueEvaluator() {
+                public Object evaluate(String parsedValue) {
+                    return valueStack.findValue(parsedValue); // no asType !!!
+                }
+            };
+        }
+
+        @Inject
+        public void setTextParser(TextParser textParser) {
+            this.textParser = textParser;
+        }
+
+        @Inject
+        public void setReflectionProvider(ReflectionProvider reflectionProvider) {
+            this.reflectionProvider = reflectionProvider;
+        }
+
+        @Inject
+        public void setOgnlUtil(OgnlUtil ognlUtil) {
+            this.ognlUtil = ognlUtil;
+        }
+
+        public Interceptor injectParams(Interceptor interceptor, Map<String, String> params, ActionContext invocationContext) {
+            for (Map.Entry<String, String> entry : params.entrySet()) {
+                Object paramValue = textParser.evaluate(new char[]{ '$' }, entry.getValue(), valueEvaluator, TextParser.DEFAULT_LOOP_COUNT);
+                ognlUtil.setProperty(entry.getKey(), paramValue, interceptor, invocationContext.getContextMap());
+            }
+
+            return interceptor;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
index 7b7b3fe..98e3b1f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/DefaultActionInvocationTest.java
@@ -3,16 +3,20 @@ package com.opensymphony.xwork2;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
 import com.opensymphony.xwork2.config.entities.InterceptorMapping;
 import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
 import com.opensymphony.xwork2.mock.MockActionProxy;
 import com.opensymphony.xwork2.mock.MockContainer;
 import com.opensymphony.xwork2.mock.MockInterceptor;
+import com.opensymphony.xwork2.mock.MockLazyInterceptor;
 import com.opensymphony.xwork2.ognl.OgnlUtil;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.ValueStackFactory;
+import org.apache.struts2.dispatcher.HttpParameters;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -298,6 +302,36 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
         assertEquals("success", result);
     }
 
+    public void testInvokeWithLazyParams() throws Exception {
+        HashMap<String, Object> params = new HashMap<>();
+        params.put("blah", "this is blah");
+
+        HashMap<String, Object> extraContext = new HashMap<>();
+        extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
+
+        DefaultActionInvocation defaultActionInvocation = new DefaultActionInvocation(extraContext, true);
+        container.inject(defaultActionInvocation);
+
+        ActionProxy actionProxy = actionProxyFactory.createActionProxy( "", "LazyFoo", null, extraContext);
+        defaultActionInvocation.init(actionProxy);
+        defaultActionInvocation.invoke();
+
+        SimpleAction action = (SimpleAction) defaultActionInvocation.getAction();
+
+        assertEquals("this is blah", action.getBlah());
+        assertEquals("this is blah", action.getName());
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // ensure we're using the default configuration, not simple config
+        XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
+        container.inject(configurationProvider);
+        loadConfigurationProviders(configurationProvider);
+    }
+
 }
 
 class DefaultActionInvocationTester extends DefaultActionInvocation {

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/test/java/com/opensymphony/xwork2/mock/MockLazyInterceptor.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/mock/MockLazyInterceptor.java b/core/src/test/java/com/opensymphony/xwork2/mock/MockLazyInterceptor.java
new file mode 100644
index 0000000..b43ee66
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/mock/MockLazyInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * 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.mock;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.SimpleAction;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import com.opensymphony.xwork2.interceptor.Interceptor;
+import com.opensymphony.xwork2.interceptor.WithLazyParams;
+import org.junit.Assert;
+
+public class MockLazyInterceptor extends AbstractInterceptor implements WithLazyParams {
+
+    private String foo = "";
+
+    public void setFoo(String foo) {
+        this.foo = foo;
+    }
+
+    public String intercept(ActionInvocation invocation) throws Exception {
+        if (invocation.getAction() instanceof SimpleAction) {
+            ((SimpleAction) invocation.getAction()).setName(foo);
+        }
+        return invocation.invoke();
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/test/resources/xwork-sample.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-sample.xml b/core/src/test/resources/xwork-sample.xml
index 7f5e547..2cdee20 100644
--- a/core/src/test/resources/xwork-sample.xml
+++ b/core/src/test/resources/xwork-sample.xml
@@ -26,6 +26,14 @@
             <interceptor-ref name="defaultStack"/>
         </action>
 
+        <action name="LazyFoo" class="com.opensymphony.xwork2.SimpleAction">
+          <result name="error" type="void" />
+          <interceptor-ref name="params"/>
+          <interceptor-ref name="lazy">
+            <param name="foo">${blah}</param>
+          </interceptor-ref>
+        </action>
+
         <action name="WildCard" class="com.opensymphony.xwork2.SimpleAction">
             <param name="foo">17</param>
             <param name="bar">23</param>

http://git-wip-us.apache.org/repos/asf/struts/blob/2b12f06b/core/src/test/resources/xwork-test-default.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/xwork-test-default.xml b/core/src/test/resources/xwork-test-default.xml
index bceeb32..fdfc609 100644
--- a/core/src/test/resources/xwork-test-default.xml
+++ b/core/src/test/resources/xwork-test-default.xml
@@ -19,10 +19,11 @@
             <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
             <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
             <interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
-			<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
+			      <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
             <interceptor name="test" class="com.opensymphony.xwork2.mock.MockInterceptor">
                 <param name="foo">expectedFoo</param>
             </interceptor>
+            <interceptor name="lazy" class="com.opensymphony.xwork2.mock.MockLazyInterceptor"/>
 
             <interceptor-stack name="defaultStack">
                 <interceptor-ref name="staticParams"/>


[2/3] struts git commit: Extracts default loop count constant

Posted by lu...@apache.org.
Extracts default loop count constant


Project: http://git-wip-us.apache.org/repos/asf/struts/repo
Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/b9c05a71
Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/b9c05a71
Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/b9c05a71

Branch: refs/heads/master
Commit: b9c05a7181836d8484ccd455b8b0318ecfce61a5
Parents: 14d56fb
Author: Lukasz Lenart <lu...@apache.org>
Authored: Mon Jan 9 09:12:35 2017 +0100
Committer: Lukasz Lenart <lu...@apache.org>
Committed: Mon Jan 9 09:12:35 2017 +0100

----------------------------------------------------------------------
 .../java/com/opensymphony/xwork2/util/TextParseUtil.java     | 8 +++-----
 .../main/java/com/opensymphony/xwork2/util/TextParser.java   | 2 ++
 2 files changed, 5 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/struts/blob/b9c05a71/core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java b/core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
index 4f48685..0e5c9a1 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/TextParseUtil.java
@@ -31,8 +31,6 @@ import java.util.*;
  */
 public class TextParseUtil {
 
-    private static final int MAX_RECURSION = 1;
-
     /**
      * Converts all instances of ${...}, and %{...} in <code>expression</code> to the value returned
      * by a call to {@link ValueStack#findValue(java.lang.String)}. If an item cannot
@@ -108,7 +106,7 @@ public class TextParseUtil {
      * @return Converted object from variable translation.
      */
     public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
-        return translateVariables(new char[]{open} , expression, stack, asType, evaluator, MAX_RECURSION);
+        return translateVariables(new char[]{open} , expression, stack, asType, evaluator, TextParser.DEFAULT_LOOP_COUNT);
     }
 
     /**
@@ -122,7 +120,7 @@ public class TextParseUtil {
      * @return Converted object from variable translation.
      */
     public static Object translateVariables(char[] openChars, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
-        return translateVariables(openChars, expression, stack, asType, evaluator, MAX_RECURSION);
+        return translateVariables(openChars, expression, stack, asType, evaluator, TextParser.DEFAULT_LOOP_COUNT);
     }
 
     /**
@@ -178,7 +176,7 @@ public class TextParseUtil {
      * @return converted objects
      */
     public static Collection<String>  translateVariablesCollection(String expression, ValueStack stack, boolean excludeEmptyElements, ParsedValueEvaluator evaluator) {
-        return translateVariablesCollection(new char[]{'$', '%'}, expression, stack, excludeEmptyElements, evaluator, MAX_RECURSION);
+        return translateVariablesCollection(new char[]{'$', '%'}, expression, stack, excludeEmptyElements, evaluator, TextParser.DEFAULT_LOOP_COUNT);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/struts/blob/b9c05a71/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java b/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java
index 54b18ef..2f53bb0 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java
@@ -6,6 +6,8 @@ package com.opensymphony.xwork2.util;
  */
 public interface TextParser {
 
+    int DEFAULT_LOOP_COUNT = 1;
+
     Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount);
 
 }