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:08 UTC
[3/3] struts git commit: WW-4687 Allows define interceptors with
dynamic parameters
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"/>