From 156db8e5dfb82c394564d8268d9ef553f28356af Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Tue, 6 Sep 2016 21:33:31 +0200 Subject: [PATCH] WW-4685 Supports evaluating expressions from tiles definitions as a Struts values --- .../tiles/StrutsAttributeEvaluator.java | 91 +++++++++++++++++++ .../tiles/StrutsTilesContainerFactory.java | 24 ++++- 2 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java new file mode 100644 index 000000000..8b98ab2a2 --- /dev/null +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsAttributeEvaluator.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.struts2.tiles; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.LocaleProvider; +import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.TextProviderFactory; +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.ognl.OgnlUtil; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; +import ognl.OgnlException; +import org.apache.struts2.ServletActionContext; +import org.apache.tiles.context.TilesRequestContext; +import org.apache.tiles.evaluator.AbstractAttributeEvaluator; +import org.apache.tiles.evaluator.EvaluationException; +import org.apache.tiles.servlet.context.ServletUtil; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +public class StrutsAttributeEvaluator extends AbstractAttributeEvaluator { + + private static final Logger LOG = LoggerFactory.getLogger(StrutsAttributeEvaluator.class); + + public Object evaluate(String expression, TilesRequestContext request) { + try { + Object result = null; + + HttpServletRequest httpRequest = ServletUtil.getServletRequest(request).getRequest(); + ActionContext ctx = ServletActionContext.getActionContext(httpRequest); + + if (ctx == null) { + LOG.error("Cannot obtain HttpServletRequest from [{}]", request.getClass().getName()); + throw new ConfigurationException("There is no ActionContext for current request!"); + } + + TextProviderFactory tpf = new TextProviderFactory(); + ctx.getContainer().inject(tpf); + LocaleProvider localeProvider = ctx.getContainer().getInstance(LocaleProvider.class); + + TextProvider textProvider = tpf.createInstance(ctx.getActionInvocation().getAction().getClass(), localeProvider); + + if (textProvider != null) { + LOG.debug("Trying find text [{}] using TextProvider {}", expression, textProvider); + result = textProvider.getText(expression); + if (expression.equals(result)) { + LOG.debug("Could not evaluate expression [{}] as a I18N key", expression); + result = null; + } + } + + if (result == null) { + OgnlUtil ognlUtil = ctx.getContainer().getInstance(OgnlUtil.class); + LOG.debug("Trying evaluate expression [{}] using OgnlUtil's getValue", expression); + result = ognlUtil.getValue(expression, ctx.getContextMap(), ctx.getValueStack().getRoot()); + } + + LOG.debug("Final result of evaluating expression [{}] is: {}", expression, result); + + if (result == null) { + return expression; + } else { + return result; + } + } catch (OgnlException e) { + throw new EvaluationException(e); + } + } + + public void init(Map initParameters) { + } +} diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java index 0ed8c5ca7..ee6cbfed2 100644 --- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java +++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java @@ -83,9 +83,9 @@ import java.util.Set; /** * Dedicated Struts factory to build Tiles container with support for: * - Freemarker - * - OGNL (as default) + * - Struts I18N & ValueStack (as default) + * - OGNL * - EL - * - Wildcards * * If you need additional features create your own listener and factory, * you can base on code from Tiles' CompleteAutoloadTilesContainerFactory @@ -108,6 +108,13 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory { */ public static final String TILES_DEFAULT_PATTERN = "tiles*.xml"; + /** + * Supported expression languages + */ + public static final String OGNL = "OGNL"; + public static final String EL = "EL"; + public static final String S2 = "S2"; + @Override protected BasicTilesContainer instantiateContainer(TilesApplicationContext applicationContext) { CachingTilesContainer tilesContainer = new CachingTilesContainer(); @@ -182,8 +189,13 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory { LocaleResolver resolver) { BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator()); - attributeEvaluatorFactory.registerAttributeEvaluator("OGNL", createOGNLEvaluator()); - attributeEvaluatorFactory.registerAttributeEvaluator("EL", createELEvaluator(applicationContext)); + attributeEvaluatorFactory.registerAttributeEvaluator(S2, createStrutsEvaluator()); + attributeEvaluatorFactory.registerAttributeEvaluator(OGNL, createOGNLEvaluator()); + + ELAttributeEvaluator elEvaluator = createELEvaluator(applicationContext); + if (elEvaluator != null) { + attributeEvaluatorFactory.registerAttributeEvaluator(EL, elEvaluator); + } return attributeEvaluatorFactory; } @@ -252,6 +264,10 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory { return evaluator; } + protected StrutsAttributeEvaluator createStrutsEvaluator() { + return new StrutsAttributeEvaluator(); + } + protected OGNLAttributeEvaluator createOGNLEvaluator() { try { PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class);