mirror of
https://github.com/apache/struts.git
synced 2026-08-06 15:17:00 +00:00
WW-3998 Extracts interface and adds default implementation base on existing code
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@1456961 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -247,4 +247,6 @@ public final class StrutsConstants {
|
||||
public static final String STRUTS_CONVERTER_CREATOR = "struts.converter.creator";
|
||||
public static final String STRUTS_CONVERTER_HOLDER = "struts..converter.holder";
|
||||
|
||||
public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,7 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.inject.Context;
|
||||
import com.opensymphony.xwork2.inject.Factory;
|
||||
import com.opensymphony.xwork2.inject.Scope;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import com.opensymphony.xwork2.util.LocalizedTextUtil;
|
||||
import com.opensymphony.xwork2.util.PatternMatcher;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.*;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
@@ -276,6 +273,13 @@ import java.util.StringTokenizer;
|
||||
* <td>singleton</td>
|
||||
* <td>Holds user converters' instances</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>com.opensymphony.xwork2.util.TextParser</td>
|
||||
* <td>struts.expression.parser</td>
|
||||
* <td>singleton</td>
|
||||
* <td>Used to parse expressions like ${foo.bar} or %{bar.foo} but it is up tp the TextParser's
|
||||
* implementation what kind of opening char to use (#, $, %, etc)</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <!-- END SNIPPET: extensionPoints -->
|
||||
@@ -355,6 +359,8 @@ public class BeanSelectionProvider implements ConfigurationProvider {
|
||||
alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
|
||||
alias(UrlHelper.class, StrutsConstants.STRUTS_URL_HELPER, builder, props);
|
||||
|
||||
alias(TextParser.class, StrutsConstants.STRUTS_EXPRESSION_PARSER, builder, props);
|
||||
|
||||
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
|
||||
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
|
||||
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true");
|
||||
|
||||
@@ -197,13 +197,13 @@ public abstract class StrutsResultSupport implements Result, StrutsStatics {
|
||||
if (parse && param != null && invocation != null) {
|
||||
return TextParseUtil.translateVariables(param, invocation.getStack(),
|
||||
new TextParseUtil.ParsedValueEvaluator() {
|
||||
public Object evaluate(Object parsedValue) {
|
||||
public Object evaluate(String parsedValue) {
|
||||
if (encode) {
|
||||
if (parsedValue != null) {
|
||||
try {
|
||||
// use UTF-8 as this is the recommended encoding by W3C to
|
||||
// avoid incompatibilities.
|
||||
return URLEncoder.encode(parsedValue.toString(), "UTF-8");
|
||||
return URLEncoder.encode(parsedValue, "UTF-8");
|
||||
}
|
||||
catch(UnsupportedEncodingException e) {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
|
||||
<bean class="com.opensymphony.xwork2.ognl.OgnlUtil" />
|
||||
|
||||
<bean type="com.opensymphony.xwork2.util.TextParser" name="struts" class="com.opensymphony.xwork2.util.OgnlTextParser" scope="singleton"/>
|
||||
|
||||
<bean type="ognl.PropertyAccessor" name="com.opensymphony.xwork2.util.CompoundRoot" class="com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor" />
|
||||
<bean type="ognl.PropertyAccessor" name="java.lang.Object" class="com.opensymphony.xwork2.ognl.accessor.ObjectAccessor" />
|
||||
<bean type="ognl.PropertyAccessor" name="java.util.Iterator" class="com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor" />
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.opensymphony.xwork2.FileManager;
|
||||
import com.opensymphony.xwork2.FileManagerFactory;
|
||||
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.util.TextParser;
|
||||
import com.opensymphony.xwork2.util.OgnlTextParser;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
|
||||
import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;
|
||||
@@ -275,6 +277,8 @@ public class EmbeddedJSPResultTest extends TestCase {
|
||||
//mock container
|
||||
Container container = EasyMock.createNiceMock(Container.class);
|
||||
EasyMock.expect(container.getInstance(XWorkConverter.class)).andReturn(converter).anyTimes();
|
||||
TextParser parser = new OgnlTextParser();
|
||||
EasyMock.expect(container.getInstance(TextParser.class)).andReturn(parser).anyTimes();
|
||||
EasyMock.expect(container.getInstanceNames(FileManager.class)).andReturn(new HashSet<String>()).anyTimes();
|
||||
EasyMock.expect(container.getInstance(FileManager.class)).andReturn(fileManager).anyTimes();
|
||||
|
||||
|
||||
+5
-1
@@ -24,10 +24,12 @@ package org.apache.struts2.views.java.simple;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.util.TextParser;
|
||||
import com.opensymphony.xwork2.util.OgnlTextParser;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.components.Component;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
import org.apache.struts2.components.template.Template;
|
||||
@@ -107,6 +109,8 @@ public abstract class AbstractTest extends TestCase {
|
||||
XWorkConverter converter = new ConverterEx();
|
||||
EasyMock.expect(container.getInstance(String.class, StrutsConstants.STRUTS_TAG_ALTSYNTAX)).andReturn("true").anyTimes();
|
||||
EasyMock.expect(container.getInstance(XWorkConverter.class)).andReturn(converter).anyTimes();
|
||||
TextParser parser = new OgnlTextParser();
|
||||
EasyMock.expect(container.getInstance(TextParser.class)).andReturn(parser).anyTimes();
|
||||
stackContext.put(ActionContext.CONTAINER, container);
|
||||
|
||||
|
||||
|
||||
+3
-4
@@ -52,10 +52,7 @@ 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.PatternMatcher;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.WildcardHelper;
|
||||
import com.opensymphony.xwork2.util.*;
|
||||
import com.opensymphony.xwork2.util.fs.DefaultFileManager;
|
||||
import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
@@ -137,6 +134,8 @@ public class XWorkConfigurationProvider implements ConfigurationProvider {
|
||||
.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)
|
||||
|
||||
+1
-1
@@ -332,7 +332,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
|
||||
"Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage()
|
||||
});
|
||||
LOG.error(developerNotification);
|
||||
LOG.error(developerNotification, e);
|
||||
if (action instanceof ValidationAware) {
|
||||
((ValidationAware) action).addActionMessage(developerNotification);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* OGNL implementation of {@link TextParser}
|
||||
*/
|
||||
public class OgnlTextParser implements TextParser {
|
||||
|
||||
public Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount) {
|
||||
// deal with the "pure" expressions first!
|
||||
//expression = expression.trim();
|
||||
Object result = expression;
|
||||
for (char open : openChars) {
|
||||
int loopCount = 1;
|
||||
int pos = 0;
|
||||
|
||||
//this creates an implicit StringBuffer and shouldn't be used in the inner loop
|
||||
final String lookupChars = open + "{";
|
||||
|
||||
while (true) {
|
||||
int start = expression.indexOf(lookupChars, pos);
|
||||
if (start == -1) {
|
||||
pos = 0;
|
||||
loopCount++;
|
||||
start = expression.indexOf(lookupChars);
|
||||
}
|
||||
if (loopCount > maxLoopCount) {
|
||||
// translateVariables prevent infinite loop / expression recursive evaluation
|
||||
break;
|
||||
}
|
||||
int length = expression.length();
|
||||
int x = start + 2;
|
||||
int end;
|
||||
char c;
|
||||
int count = 1;
|
||||
while (start != -1 && x < length && count != 0) {
|
||||
c = expression.charAt(x++);
|
||||
if (c == '{') {
|
||||
count++;
|
||||
} else if (c == '}') {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
end = x - 1;
|
||||
|
||||
if ((start != -1) && (end != -1) && (count == 0)) {
|
||||
String var = expression.substring(start + 2, end);
|
||||
|
||||
Object o = evaluator.evaluate(var);
|
||||
|
||||
String left = expression.substring(0, start);
|
||||
String right = expression.substring(end + 1);
|
||||
String middle = null;
|
||||
if (o != null) {
|
||||
middle = o.toString();
|
||||
if (StringUtils.isEmpty(left)) {
|
||||
result = o;
|
||||
} else {
|
||||
result = left.concat(middle);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(right)) {
|
||||
result = result.toString().concat(right);
|
||||
}
|
||||
|
||||
expression = left.concat(middle).concat(right);
|
||||
} else {
|
||||
// the variable doesn't exist, so don't display anything
|
||||
expression = left.concat(right);
|
||||
result = expression;
|
||||
}
|
||||
pos = (left != null && left.length() > 0 ? left.length() - 1: 0) +
|
||||
(middle != null && middle.length() > 0 ? middle.length() - 1: 0) +
|
||||
1;
|
||||
pos = Math.max(pos, 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,6 @@ import com.opensymphony.xwork2.inject.Container;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class for text parsing.
|
||||
@@ -153,84 +151,26 @@ public class TextParseUtil {
|
||||
* @param evaluator
|
||||
* @return Converted object from variable translation.
|
||||
*/
|
||||
public static Object translateVariables(char[] openChars, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator, int maxLoopCount) {
|
||||
// deal with the "pure" expressions first!
|
||||
//expression = expression.trim();
|
||||
Object result = expression;
|
||||
for (char open : openChars) {
|
||||
int loopCount = 1;
|
||||
int pos = 0;
|
||||
public static Object translateVariables(char[] openChars, String expression, final ValueStack stack, final Class asType, final ParsedValueEvaluator evaluator, int maxLoopCount) {
|
||||
|
||||
//this creates an implicit StringBuffer and shouldn't be used in the inner loop
|
||||
final String lookupChars = open + "{";
|
||||
|
||||
while (true) {
|
||||
int start = expression.indexOf(lookupChars, pos);
|
||||
if (start == -1) {
|
||||
pos = 0;
|
||||
loopCount++;
|
||||
start = expression.indexOf(lookupChars);
|
||||
}
|
||||
if (loopCount > maxLoopCount) {
|
||||
// translateVariables prevent infinite loop / expression recursive evaluation
|
||||
break;
|
||||
}
|
||||
int length = expression.length();
|
||||
int x = start + 2;
|
||||
int end;
|
||||
char c;
|
||||
int count = 1;
|
||||
while (start != -1 && x < length && count != 0) {
|
||||
c = expression.charAt(x++);
|
||||
if (c == '{') {
|
||||
count++;
|
||||
} else if (c == '}') {
|
||||
count--;
|
||||
}
|
||||
}
|
||||
end = x - 1;
|
||||
|
||||
if ((start != -1) && (end != -1) && (count == 0)) {
|
||||
String var = expression.substring(start + 2, end);
|
||||
|
||||
Object o = stack.findValue(var, asType);
|
||||
if (evaluator != null) {
|
||||
o = evaluator.evaluate(o);
|
||||
}
|
||||
|
||||
|
||||
String left = expression.substring(0, start);
|
||||
String right = expression.substring(end + 1);
|
||||
String middle = null;
|
||||
if (o != null) {
|
||||
middle = o.toString();
|
||||
if (StringUtils.isEmpty(left)) {
|
||||
result = o;
|
||||
} else {
|
||||
result = left.concat(middle);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(right)) {
|
||||
result = result.toString().concat(right);
|
||||
}
|
||||
|
||||
expression = left.concat(middle).concat(right);
|
||||
} else {
|
||||
// the variable doesn't exist, so don't display anything
|
||||
expression = left.concat(right);
|
||||
result = expression;
|
||||
}
|
||||
pos = (left != null && left.length() > 0 ? left.length() - 1: 0) +
|
||||
(middle != null && middle.length() > 0 ? middle.length() - 1: 0) +
|
||||
1;
|
||||
pos = Math.max(pos, 1);
|
||||
} else {
|
||||
break;
|
||||
ParsedValueEvaluator ognlEval = new ParsedValueEvaluator() {
|
||||
public Object evaluate(String parsedValue) {
|
||||
Object o = stack.findValue(parsedValue, asType);
|
||||
if (evaluator != null) {
|
||||
o = evaluator.evaluate(o.toString());
|
||||
}
|
||||
return o;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TextParser parser = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(TextParser.class);
|
||||
|
||||
XWorkConverter conv = ((Container)stack.getContext().get(ActionContext.CONTAINER)).getInstance(XWorkConverter.class);
|
||||
|
||||
Object result = parser.evaluate(openChars, expression, ognlEval, maxLoopCount);
|
||||
|
||||
return conv.convertValue(stack.getContext(), result, asType);
|
||||
}
|
||||
|
||||
@@ -279,6 +219,6 @@ public class TextParseUtil {
|
||||
* @param parsedValue - value parsed by ognl value stack
|
||||
* @return return the evaluted value.
|
||||
*/
|
||||
Object evaluate(Object parsedValue);
|
||||
Object evaluate(String parsedValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
/**
|
||||
* Used to parse expressions like ${foo.bar} or %{bar.foo} but it is up tp the TextParser's
|
||||
* implementation what kind of opening char to use (#, $, %, etc)
|
||||
*/
|
||||
public interface TextParser {
|
||||
|
||||
Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount);
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class TextParseUtilTest extends XWorkTestCase {
|
||||
});
|
||||
|
||||
TextParseUtil.ParsedValueEvaluator evaluator = new TextParseUtil.ParsedValueEvaluator() {
|
||||
public Object evaluate(Object parsedValue) {
|
||||
public Object evaluate(String parsedValue) {
|
||||
return parsedValue.toString()+"Something";
|
||||
}
|
||||
};
|
||||
@@ -53,7 +53,7 @@ public class TextParseUtilTest extends XWorkTestCase {
|
||||
public void testTranslateVariables() {
|
||||
ValueStack stack = ActionContext.getContext().getValueStack();
|
||||
|
||||
Object s = TextParseUtil.translateVariables("foo: ${{1, 2, 3}}, bar: ${1}", stack);
|
||||
Object s = TextParseUtil.translateVariables("foo: ${{1, 2, 3}}, bar: %{1}", stack);
|
||||
assertEquals("foo: [1, 2, 3], bar: 1", s);
|
||||
|
||||
s = TextParseUtil.translateVariables("foo: %{{1, 2, 3}}, bar: %{1}", stack);
|
||||
|
||||
Reference in New Issue
Block a user