mirror of
https://github.com/apache/struts.git
synced 2026-08-05 14:47:09 +00:00
Merge branch 'master' of https://github.com/JCgH4164838Gh792C124B5/struts into localS2_26_OgnlUtilOptionalCache1
# Conflicts: # core/src/main/java/com/opensymphony/xwork2/config/providers/StrutsDefaultConfigurationProvider.java # core/src/main/resources/struts-default.xml Manually resolved conflicts.
This commit is contained in:
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
|
||||
+14
-16
@@ -27,22 +27,24 @@ import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.ParentPackage;
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
import org.apache.struts2.interceptor.validation.SkipValidation;
|
||||
import org.hibernate.validator.constraints.Email;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import org.hibernate.validator.constraints.ScriptAssert;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: beanValidatationExample -->
|
||||
*/
|
||||
// <!-- START SNIPPET: beanValidationExample -->
|
||||
@Namespace("/bean-validation")
|
||||
@ParentPackage("bean-validation")
|
||||
@Action(results = {
|
||||
@Result(name = "input", location = "bean-validation.jsp"),
|
||||
@Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp")
|
||||
@Result(name = "input", location = "bean-validation.jsp"),
|
||||
@Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp")
|
||||
})
|
||||
@FieldMatch(first = "fieldExpressionValidatorField", second = "requiredValidatorField", message = "requiredValidatorField and fieldExpressionValidatorField are not matching")
|
||||
@ScriptAssert(lang = "javascript", script = "_this.dateValidatorField != null && _this.dateValidatorField.before(new java.util.Date())", message = "Date need to before now")
|
||||
@@ -82,10 +84,10 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
private String fieldExpressionValidatorField = null;
|
||||
|
||||
@Action(value = "bean-validation", results = {
|
||||
@Result(name = "success", location = "bean-validation.jsp")
|
||||
@Result(name = "success", location = "bean-validation.jsp")
|
||||
})
|
||||
@SkipValidation
|
||||
public String beanValidation(){
|
||||
public String beanValidation() {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
}
|
||||
|
||||
public void setFieldExpressionValidatorField(
|
||||
String fieldExpressionValidatorField) {
|
||||
String fieldExpressionValidatorField) {
|
||||
this.fieldExpressionValidatorField = fieldExpressionValidatorField;
|
||||
}
|
||||
|
||||
@@ -163,8 +165,4 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <!-- END SNIPPET: beanValidatationExample -->
|
||||
*/
|
||||
|
||||
|
||||
// <!-- END SNIPPET: beanValidationExample -->
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><s:a value="%{home}" escapeHtmlBody="false"><i class="glyphicon glyphicon-home"></i> Home</s:a></li>
|
||||
<li><s:a value="%{home}"><i class="glyphicon glyphicon-home"></i> Home</s:a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="glyphicon glyphicon-cog"></i> Configuration
|
||||
@@ -239,7 +239,7 @@
|
||||
</li>
|
||||
<li><s:a value="/person/index.html">Person Manager</s:a></li>
|
||||
<li><s:a value="/skill/index.html">CRUD</s:a></li>
|
||||
<li><s:a value="/wait/index.html" escapeHtmlBody="false">Execute & Wait</s:a></li>
|
||||
<li><s:a value="/wait/index.html">Execute & Wait</s:a></li>
|
||||
<li><s:a value="/token/index.html">Token</s:a></li>
|
||||
<li><s:url var="url" namespace="/modelDriven" action="modelDriven"/><s:a
|
||||
href="%{url}">Model Driven</s:a></li>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
|
||||
<s:url var="url" action="download"/>
|
||||
<s:a href="%{url}" cssClass="btn btn-large btn-info" escapeHtmlBody="false"><i class="icon-picture"></i> Download image file.</s:a>
|
||||
<s:a href="%{url}" cssClass="btn btn-large btn-info"><i class="icon-picture"></i> Download image file.</s:a>
|
||||
</div>
|
||||
<div class="col-md-6" style="text-align: center;">
|
||||
<div class="alert alert-info">
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
|
||||
<s:url var="url" action="download2"/>
|
||||
<s:a href="%{url}" cssClass="btn btn-large btn-info" escapeHtmlBody="false"><i class="icon-download-alt"></i> Download ZIP file.</s:a>
|
||||
<s:a href="%{url}" cssClass="btn btn-large btn-info"><i class="icon-download-alt"></i> Download ZIP file.</s:a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
<#else>
|
||||
<img src="<@s.property value="%{#looseImageUrl}" />" width="381" height="44" />
|
||||
</#if>
|
||||
<@s.a href="%{#startHref}" escapeHtmlBody="false">
|
||||
<@s.a href="%{#startHref}">
|
||||
<img src="<@s.property value="%{#startImageUrl}" />" width="250" height="43" />
|
||||
</@s.a>
|
||||
<#else>
|
||||
@@ -139,7 +139,7 @@
|
||||
|
||||
<@s.a href="%{#url}"
|
||||
id="%{#currentCharacter}"
|
||||
escapeHtmlBody="false"
|
||||
|
||||
>
|
||||
<img height="36" alt="" src="<@s.property value="%{#chalkboardImageUrl}" />" width="36" border="0" />
|
||||
</@s.a>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<@s.submit value="Create person" cssClass="btn btn-primary" escapeHtmlBody="false"/>
|
||||
<@s.submit value="Create person" cssClass="btn btn-primary"/>
|
||||
</div>
|
||||
</@s.form>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<p>The text you've entered is ${text!''}<p/>
|
||||
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+4
-4
@@ -57,13 +57,13 @@
|
||||
|
||||
<@s.textfield label="Enter Some Text" name="text" />
|
||||
|
||||
<@s.submit action="actionPrefix" value="%{'action prefix'}" cssClass="btn" escapeHtmlBody="false" />
|
||||
<@s.submit action="actionPrefix" value="%{'action prefix'}" cssClass="btn" />
|
||||
|
||||
<@s.submit method="alternateMethod" value="%{'method prefix'}" cssClass="btn" escapeHtmlBody="false" />
|
||||
<@s.submit method="alternateMethod" value="%{'method prefix'}" cssClass="btn" />
|
||||
|
||||
<@s.submit value="Normal Submit" cssClass="btn" escapeHtmlBody="false" />
|
||||
<@s.submit value="Normal Submit" cssClass="btn" />
|
||||
|
||||
<@s.submit action="redirectActionPrefixAction" value="%{'redirectAction without prefix'}" cssClass="btn" escapeHtmlBody="false" />
|
||||
<@s.submit action="redirectActionPrefixAction" value="%{'redirectAction without prefix'}" cssClass="btn" />
|
||||
|
||||
</@s.form>
|
||||
</div>
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
<div class="col-md-12">
|
||||
|
||||
<p>You have come to this page because you used an <strong>method</strong> prefix.<p/>
|
||||
|
||||
|
||||
<p>The text you've enter is ${text!''}<p/>
|
||||
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
<div class="col-md-12">
|
||||
|
||||
<p>You have come to this page because you did a normal submit.<p/>
|
||||
|
||||
|
||||
<p>The text you've enter is %{text}<p/>
|
||||
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -32,13 +32,13 @@
|
||||
<div class="col-md-12">
|
||||
|
||||
<p>You have come to this page because you used an 'redirect-action' prefix.<p/>
|
||||
|
||||
|
||||
<p>Because this is a <strong>redirect-action</strong>, the text will be lost, due to a redirection
|
||||
implies a new request being issued from the client.<p/>
|
||||
|
||||
The text you've enter is ${text!''}<p/>
|
||||
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
<@s.a href="javascript:history.back();" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back</@s.a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@
|
||||
</s:iterator>
|
||||
|
||||
<s:url var="url" action="showAppendTagDemo" namespace="/tags/non-ui/appendIteratorTag" />
|
||||
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@
|
||||
|
||||
|
||||
<s:url var="url" action="showGeneratorTagDemo" namespace="/tags/non-ui/iteratorGeneratorTag" />
|
||||
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@
|
||||
</s:iterator>
|
||||
|
||||
<s:url var="url" action="showMergeTagDemo" namespace="/tags/non-ui/mergeIteratorTag" />
|
||||
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@
|
||||
</s:subset>
|
||||
|
||||
<s:url var="url" action="showSubsetTagDemo" namespace="/tags/non-ui/subsetIteratorTag" />
|
||||
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<@s.form action="transfer4">
|
||||
<@s.token/>
|
||||
<@s.textfield label="Amount" name="amount" required=true value="400"/>
|
||||
<@s.submit value="Transfer money" cssClass="btn btn-primary" escapeHtmlBody="false"/>
|
||||
<@s.submit value="Transfer money" cssClass="btn btn-primary"/>
|
||||
</@s.form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -44,7 +44,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>2.6-SNAPSHOT</struts-version.version>
|
||||
<struts-version.version>6.0.0-SNAPSHOT</struts-version.version>
|
||||
<maven.site.skip>true</maven.site.skip>
|
||||
<maven.site.deploy.skip>true</maven.site.deploy.skip>
|
||||
</properties>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-admin-bundle</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -342,7 +342,7 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
|
||||
|
||||
+6
@@ -56,6 +56,9 @@ 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.security.NotExcludedAcceptedPatternsChecker;
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.components.date.DateTimeFormatterAdapter;
|
||||
import org.apache.struts2.components.date.SimpleDateFormatAdapter;
|
||||
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
|
||||
import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
|
||||
@@ -227,6 +230,9 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
|
||||
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
|
||||
|
||||
.factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON)
|
||||
.factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON)
|
||||
|
||||
.factory(OgnlCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSIONCACHE_FACTORY, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
|
||||
.factory(OgnlCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFOCACHE_FACTORY, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
|
||||
;
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* <p>
|
||||
* Application wide conversion:<br>
|
||||
* The conversion rules will be assembled within the <code>xwork-conversion.properties</code> file within the classpath root.
|
||||
* The conversion rules will be assembled within the <code>struts-conversion.properties</code> or
|
||||
* <code>xwork-conversion.properties</code> (deprecated) file within the classpath root.
|
||||
* Set type to: <code>type = ConversionType.APPLICATION</code>
|
||||
* </p>
|
||||
* <!-- END SNIPPET: description -->
|
||||
|
||||
-187
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* 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 com.opensymphony.xwork2.conversion.metadata;
|
||||
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
|
||||
import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* <code>ConversionDescription</code>
|
||||
*
|
||||
* @author Rainer Hermanns
|
||||
* @version $Id$
|
||||
*
|
||||
* @deprecated class will be removed
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConversionDescription {
|
||||
|
||||
/**
|
||||
* Jakarta commons-logging reference.
|
||||
*/
|
||||
protected static Logger log = null;
|
||||
|
||||
|
||||
public static final String KEY_PREFIX = "Key_";
|
||||
public static final String ELEMENT_PREFIX = "Element_";
|
||||
public static final String KEY_PROPERTY_PREFIX = "KeyProperty_";
|
||||
public static final String DEPRECATED_ELEMENT_PREFIX = "Collection_";
|
||||
|
||||
/**
|
||||
* Key used for type conversion of maps.
|
||||
*/
|
||||
String MAP_PREFIX = "Map_";
|
||||
|
||||
public String property;
|
||||
public String typeConverter = "";
|
||||
public String rule = "";
|
||||
public String value = "";
|
||||
public String fullQualifiedClassName;
|
||||
public String type = null;
|
||||
|
||||
public ConversionDescription() {
|
||||
log = LogManager.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ConversionDescription with the specified property name.
|
||||
*
|
||||
* @param property property
|
||||
*/
|
||||
public ConversionDescription(String property) {
|
||||
this.property = property;
|
||||
log = LogManager.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Sets the property name to be inserted into the related conversion.properties file.<br>
|
||||
* Note: Do not add COLLECTION_PREFIX or MAP_PREFIX keys to property names.
|
||||
* </p>
|
||||
*
|
||||
* @param property The property to be converted.
|
||||
*/
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class name of the type converter to be used.
|
||||
*
|
||||
* @param typeConverter The class name of the type converter.
|
||||
*/
|
||||
public void setTypeConverter(String typeConverter) {
|
||||
this.typeConverter = typeConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rule the rule prefix for COLLECTION_PREFIX or MAP_PREFIX key. Defaults to en empty String.
|
||||
*/
|
||||
public void setRule(String rule) {
|
||||
if (rule != null && rule.length() > 0) {
|
||||
if (rule.equals(ConversionRule.COLLECTION.toString())) {
|
||||
this.rule = DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX;
|
||||
} else if (rule.equals(ConversionRule.ELEMENT.toString())) {
|
||||
this.rule = DefaultObjectTypeDeterminer.ELEMENT_PREFIX;
|
||||
} else if (rule.equals(ConversionRule.KEY.toString())) {
|
||||
this.rule = DefaultObjectTypeDeterminer.KEY_PREFIX;
|
||||
} else if (rule.equals(ConversionRule.KEY_PROPERTY.toString())) {
|
||||
this.rule = DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX;
|
||||
} else if (rule.equals(ConversionRule.MAP.toString())) {
|
||||
this.rule = MAP_PREFIX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conversion description as property entry.
|
||||
* <p>
|
||||
* Example:<br>
|
||||
* property.name = converter.className<br>
|
||||
* Collection_property.name = converter.className<br>
|
||||
* Map_property.name = converter.className
|
||||
* KeyProperty_name = id
|
||||
* </p>
|
||||
*
|
||||
* @return the conversion description as property entry.
|
||||
*/
|
||||
public String asProperty() {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter writer = null;
|
||||
try {
|
||||
writer = new PrintWriter(sw);
|
||||
writer.print(rule);
|
||||
writer.print(property);
|
||||
writer.print("=");
|
||||
if ( rule.startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX) && value != null && value.length() > 0 ) {
|
||||
writer.print(value);
|
||||
} else {
|
||||
writer.print(typeConverter);
|
||||
}
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
return sw.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fullQualifiedClassName attribute is used to create the special <code>conversion.properties</code> file name.
|
||||
*
|
||||
* @return full qualified class name
|
||||
*/
|
||||
public String getFullQualifiedClassName() {
|
||||
return fullQualifiedClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The fullQualifiedClassName attribute is used to create the special <code>conversion.properties</code> file name.
|
||||
*
|
||||
* @param fullQualifiedClassName a full qualified class name
|
||||
*/
|
||||
public void setFullQualifiedClassName(String fullQualifiedClassName) {
|
||||
this.fullQualifiedClassName = fullQualifiedClassName;
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* This interceptor sets all parameters on the value stack.
|
||||
@@ -50,8 +51,11 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
protected static final int PARAM_NAME_MAX_LENGTH = 100;
|
||||
|
||||
private static final Pattern DMI_IGNORED_PATTERN = Pattern.compile("^(action|method):.*", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
private int paramNameMaxLength = PARAM_NAME_MAX_LENGTH;
|
||||
private boolean devMode = false;
|
||||
private boolean dmiEnabled = false;
|
||||
|
||||
protected boolean ordered = false;
|
||||
|
||||
@@ -79,6 +83,11 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
this.acceptedPatterns = acceptedPatterns;
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, required = false)
|
||||
protected void setDynamicMethodInvocation(String dmiEnabled) {
|
||||
this.dmiEnabled = Boolean.parseBoolean(dmiEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the param name exceeds the configured maximum length it will not be
|
||||
* accepted.
|
||||
@@ -101,13 +110,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
/**
|
||||
* Compares based on number of '.' and '[' characters (fewer is higher)
|
||||
*/
|
||||
static final Comparator<String> rbCollator = new Comparator<String>() {
|
||||
public int compare(String s1, String s2) {
|
||||
int l1 = countOGNLCharacters(s1);
|
||||
int l2 = countOGNLCharacters(s2);
|
||||
return l1 < l2 ? -1 : (l2 < l1 ? 1 : s1.compareTo(s2));
|
||||
}
|
||||
|
||||
static final Comparator<String> rbCollator = (s1, s2) -> {
|
||||
int l1 = countOGNLCharacters(s1);
|
||||
int l2 = countOGNLCharacters(s2);
|
||||
return l1 < l2 ? -1 : (l2 < l1 ? 1 : s1.compareTo(s2));
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -286,6 +292,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
|
||||
protected boolean acceptableName(String name) {
|
||||
if (isIgnoredDMI(name)) {
|
||||
LOG.trace("DMI is enabled, ignoring DMI method: {}", name);
|
||||
return false;
|
||||
}
|
||||
boolean accepted = isWithinLengthLimit(name) && !isExcluded(name) && isAccepted(name);
|
||||
if (devMode && accepted) { // notify only when in devMode
|
||||
LOG.debug("Parameter [{}] was accepted and will be appended to action!", name);
|
||||
@@ -293,6 +303,14 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
private boolean isIgnoredDMI(String name) {
|
||||
if (dmiEnabled) {
|
||||
return DMI_IGNORED_PATTERN.matcher(name).matches();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isWithinLengthLimit(String name) {
|
||||
boolean matchLength = name.length() <= paramNameMaxLength;
|
||||
if (!matchLength) {
|
||||
|
||||
+18
-22
@@ -306,13 +306,13 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
|
||||
/**
|
||||
* A helper method for {@link ResourceBundle} bundle reload logic.
|
||||
*
|
||||
* Uses standard {@link ResourceBundle} methods to clear the bundle caches for the
|
||||
*
|
||||
* Uses standard {@link ResourceBundle} methods to clear the bundle caches for the
|
||||
* {@link ClassLoader} instances that this class is aware of at the time of the call.
|
||||
*
|
||||
* The <code>clearCache()</code> methods have been available since Java 1.6, so
|
||||
*
|
||||
* The <code>clearCache()</code> methods have been available since Java 1.6, so
|
||||
* it is anticipated the logic will work on any subsequent JVM versions.
|
||||
*
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
private void clearResourceBundleClassloaderCaches() {
|
||||
@@ -326,14 +326,14 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
/**
|
||||
* "Hacky" helper method that attempts to clear the Tomcat <code>ResourceEntry</code>
|
||||
* {@link Map} using knowledge of the Tomcat source code.
|
||||
*
|
||||
* It relies on the {@link #TOMCAT_RESOURCE_ENTRIES_FIELD} field name, base class name
|
||||
*
|
||||
* It relies on the {@link #TOMCAT_RESOURCE_ENTRIES_FIELD} field name, base class name
|
||||
* {@link #TOMCAT_WEBAPP_CLASSLOADER_BASE}. and descendant class names {@link #TOMCAT_WEBAPP_CLASSLOADER},
|
||||
* {@link #TOMCAT_PARALLEL_WEBAPP_CLASSLOADER}, to keep the values identified in the constants.
|
||||
* It appears to be valid for Tomcat versions 7-10 so far, but could become invalid at any time in the future
|
||||
* when the resource handling logic in Tomcat changes.
|
||||
*
|
||||
* Note: With Java 9+, calling this method may result in "Illegal reflective access" warnings. Be aware
|
||||
*
|
||||
* Note: With Java 9+, calling this method may result in "Illegal reflective access" warnings. Be aware
|
||||
* its logic may fail in a future version of Java that blocks the reflection calls needed for this method.
|
||||
*/
|
||||
private void clearTomcatCache() {
|
||||
@@ -367,10 +367,10 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
|
||||
/**
|
||||
* Helper method that is intended to clear a {@link Map} instance by name.
|
||||
*
|
||||
*
|
||||
* This method relies on reflection to perform its operations, and may be blocked in Java 9 and later,
|
||||
* depending on the accessibility of the field.
|
||||
*
|
||||
*
|
||||
* @param cl The {@link Class} of the obj parameter.
|
||||
* @param obj The {@link Object} from which the named field is to be extracted (may be <code>null</code> for a static field).
|
||||
* @param name The name of the field containing a {@link Map} reference.
|
||||
@@ -433,9 +433,9 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
* Set the {@link #searchDefaultBundlesFirst} flag state. This flag may be used by descendant TextProvider
|
||||
* implementations to determine if default bundles should be searched for messages first (before the standard
|
||||
* flow of the {@link LocalizedTextProvider} implementation the descendant provides).
|
||||
*
|
||||
*
|
||||
* @param searchDefaultBundlesFirst provide {@link String} "true" or "false" to set the flag state accordingly.
|
||||
*
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
@Inject(value = StrutsConstants.STRUTS_I18N_SEARCH_DEFAULTBUNDLES_FIRST, required = false)
|
||||
@@ -490,7 +490,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears all the internal lists.
|
||||
*
|
||||
@@ -566,17 +566,17 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
* against the default resource bundles. The default resource bundles are searched for a value using key first, then
|
||||
* alternateKey when the first search fails, then utilizing defaultMessage (which may be <code>null</code>) if <em>both</em>
|
||||
* key lookup operations fail.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* A known use case is when a key indexes a collection (e.g. user.phone[0]) for which some specific keys may exist, but not all,
|
||||
* along with a general key (e.g. user.phone[*]). In such cases the specific key would be passed in the key parameter and the
|
||||
* general key would be passed in the alternateKey parameter.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param key the initial key to search for a value within the default resource bundles.
|
||||
* @param alternateKey the alternate (fall-back) key to search for a value within the default resource bundles, if the initial key lookup fails.
|
||||
* @param locale the {@link Locale} to be used for the default resource bundle lookup.
|
||||
* @param valueStack the {@link ValueStack} associated with the operation.
|
||||
* @param valueStack the {@link ValueStack} associated with the operation.
|
||||
* @param args the argument array for parameterized messages (may be <code>null</code>).
|
||||
* @param defaultMessage the default message {@link String} to use if both key lookup operations fail.
|
||||
* @return the {@link GetDefaultMessageReturnArg} result containing the processed message lookup (by key first, then alternateKey if key's lookup fails).
|
||||
@@ -616,11 +616,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
|
||||
MessageFormat mf = buildMessageFormat(message, locale);
|
||||
return formatWithNullDetection(mf, args);
|
||||
} catch (MissingResourceException e) {
|
||||
if (devMode) {
|
||||
LOG.warn("Missing key [{}] in bundle [{}]!", key, bundleName);
|
||||
} else {
|
||||
LOG.debug("Missing key [{}] in bundle [{}]!", key, bundleName);
|
||||
}
|
||||
LOG.debug("Missing key [{}] in bundle [{}]!", key, bundleName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.struts2;
|
||||
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.dispatcher.mapper.CompositeActionMapper;
|
||||
|
||||
/**
|
||||
@@ -132,6 +133,9 @@ public final class StrutsConstants {
|
||||
/** A path to static content, by default and from historical point of view it's /static. */
|
||||
public static final String STRUTS_UI_STATIC_CONTENT_PATH = "struts.ui.staticContentPath";
|
||||
|
||||
/** A global flag to enable/disable html body escaping in tags, can be overwritten per tag */
|
||||
public static final String STRUTS_UI_ESCAPE_HTML_BODY = "struts.ui.escapeHtmlBody";
|
||||
|
||||
/** The maximize size of a multipart request (file upload) */
|
||||
public static final String STRUTS_MULTIPART_MAXSIZE = "struts.multipart.maxSize";
|
||||
|
||||
@@ -442,4 +446,7 @@ public final class StrutsConstants {
|
||||
public static final String STRUTS_CHAINING_COPY_FIELD_ERRORS = "struts.chaining.copyFieldErrors";
|
||||
public static final String STRUTS_CHAINING_COPY_MESSAGES = "struts.chaining.copyMessages";
|
||||
public static final String STRUTS_OBJECT_FACTORY_CLASSLOADER = "struts.objectFactory.classloader";
|
||||
|
||||
/** See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} */
|
||||
public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter";
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.apache.struts2.components;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -69,8 +70,7 @@ public class Anchor extends ClosingUIBean {
|
||||
protected UrlProvider urlProvider;
|
||||
protected UrlRenderer urlRenderer;
|
||||
protected boolean processingTagBody = false;
|
||||
protected boolean escapeHtmlBody = true;
|
||||
|
||||
|
||||
//these params are passed by the Param tag
|
||||
protected Map urlParameters = new LinkedHashMap();
|
||||
|
||||
@@ -96,18 +96,6 @@ public class Anchor extends ClosingUIBean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to set if body content should be HTML-escaped.
|
||||
*
|
||||
* @return true if body should be HTML-escaped, false otherwise.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
@Override
|
||||
public boolean escapeHtmlBody() {
|
||||
return escapeHtmlBody;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
@@ -124,6 +112,8 @@ public class Anchor extends ClosingUIBean {
|
||||
addParameter("href", ensureAttributeSafelyNotEscaped(builtHref));
|
||||
}
|
||||
}
|
||||
|
||||
addParameter("escapeHtmlBody", escapeHtmlBody);
|
||||
}
|
||||
|
||||
@Inject(StrutsConstants.STRUTS_URL_INCLUDEPARAMS)
|
||||
@@ -276,7 +266,7 @@ public class Anchor extends ClosingUIBean {
|
||||
urlProvider.setForceAddSchemeHostAndPort(forceAddSchemeHostAndPort);
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(required = false, description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "true")
|
||||
@StrutsTagAttribute(description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "false")
|
||||
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
|
||||
this.escapeHtmlBody = escapeHtmlBody;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,8 @@ public class Checkbox extends UIBean {
|
||||
}
|
||||
|
||||
if (submitUnchecked != null) {
|
||||
addParameter("submitUnchecked", findValue(submitUnchecked, Boolean.class));
|
||||
Object parsedValue = findValue(submitUnchecked, Boolean.class);
|
||||
addParameter("submitUnchecked", parsedValue == null ? Boolean.valueOf(submitUnchecked) : parsedValue);
|
||||
} else {
|
||||
addParameter("submitUnchecked", false);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
allowDynamicAttributes = true)
|
||||
public class CheckboxList extends ListUIBean {
|
||||
final public static String TEMPLATE = "checkboxlist";
|
||||
|
||||
|
||||
public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
}
|
||||
@@ -56,9 +56,19 @@ public class CheckboxList extends ListUIBean {
|
||||
protected String getDefaultTemplate() {
|
||||
return TEMPLATE;
|
||||
}
|
||||
|
||||
|
||||
public void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Checkboxlist tag requires lazy evaluation as list of tags is dynamically generated using <s:iterator/>
|
||||
*
|
||||
* @return boolean true by default
|
||||
*/
|
||||
@Override
|
||||
protected boolean lazyEvaluation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class Component {
|
||||
protected static ConcurrentMap<Class<?>, Collection<String>> standardAttributesMap = new ConcurrentHashMap<>();
|
||||
|
||||
protected boolean devMode = false;
|
||||
protected boolean escapeHtmlBody = false;
|
||||
protected ValueStack stack;
|
||||
protected Map<String, Object> parameters;
|
||||
protected ActionMapper actionMapper;
|
||||
@@ -116,6 +117,11 @@ public class Component {
|
||||
this.throwExceptionOnELFailure = BooleanUtils.toBoolean(throwException);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_UI_ESCAPE_HTML_BODY, required = false)
|
||||
public void setEscapeHtmlBody(String escapeHtmlBody) {
|
||||
this.escapeHtmlBody = BooleanUtils.toBoolean(escapeHtmlBody);
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setUrlHelper(UrlHelper urlHelper) {
|
||||
this.urlHelper = urlHelper;
|
||||
@@ -213,13 +219,13 @@ public class Component {
|
||||
* @return the component if found, <tt>null</tt> if not.
|
||||
*/
|
||||
protected Component findAncestor(Class<?> clazz) {
|
||||
Stack componentStack = getComponentStack();
|
||||
Stack<Component> componentStack = getComponentStack();
|
||||
int currPosition = componentStack.search(this);
|
||||
if (currPosition >= 0) {
|
||||
int start = componentStack.size() - currPosition - 1;
|
||||
|
||||
for (int i = start; i >= 0; i--) {
|
||||
Component component = (Component) componentStack.get(i);
|
||||
Component component = componentStack.get(i);
|
||||
if (clazz.isAssignableFrom(component.getClass()) && component != this) {
|
||||
return component;
|
||||
}
|
||||
@@ -378,9 +384,8 @@ public class Component {
|
||||
return expression;
|
||||
}
|
||||
} else {
|
||||
expression = stripExpression(expression);
|
||||
|
||||
return getStack().findValue(expression, toType, throwExceptionOnELFailure);
|
||||
String strippedExpression = stripExpression(expression);
|
||||
return getStack().findValue(strippedExpression, toType, throwExceptionOnELFailure);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +541,7 @@ public class Component {
|
||||
* @since 2.6
|
||||
*/
|
||||
public boolean escapeHtmlBody() {
|
||||
return true;
|
||||
return escapeHtmlBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,16 +577,16 @@ public class Component {
|
||||
/**
|
||||
* Request that the tag state be cleared during {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#doEndTag()} processing,
|
||||
* which may help with certain edge cases with tag logic running on servers that implement JSP Tag Pooling.
|
||||
*
|
||||
* <em>Note:</em> All Tag classes that extend {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport} must implement a setter for
|
||||
*
|
||||
* <em>Note:</em> All Tag classes that extend {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport} must implement a setter for
|
||||
* this attribute (same name), and it must be defined at the Tag class level.
|
||||
* Defining a setter in the superclass alone is insufficient (results in "Cannot find a setter method for the attribute").
|
||||
*
|
||||
*
|
||||
* See {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#clearTagStateForTagPoolingServers() for additional details.
|
||||
*
|
||||
*
|
||||
* @param performClearTagStateForTagPoolingServers true if tag state should be cleared, false otherwise.
|
||||
*/
|
||||
@StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing (if applicable)", type="Boolean", defaultValue="false", required = false)
|
||||
@StrutsTagAttribute(description="Whether to clear all tag state during doEndTag() processing (if applicable)", type="Boolean", defaultValue="false")
|
||||
public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) {
|
||||
this.performClearTagStateForTagPoolingServers = performClearTagStateForTagPoolingServers;
|
||||
}
|
||||
|
||||
@@ -18,29 +18,29 @@
|
||||
*/
|
||||
package org.apache.struts2.components;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
*
|
||||
* <p>
|
||||
* Format Date object in different ways.
|
||||
* <p>
|
||||
* The date tag will allow you to format a Date in a quick and easy way.
|
||||
@@ -59,6 +59,12 @@ import java.util.List;
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <b>Note</b>: Since Struts 2.6 a new Java 8 API has been used to format the Date, it's based on
|
||||
* <a href="https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html">DateTimeFormatter</a>
|
||||
* which uses a bit different patterns.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Configurable attributes are:
|
||||
* </p>
|
||||
*
|
||||
@@ -130,8 +136,8 @@ import java.util.List;
|
||||
* <td>if one is not found DateFormat.MEDIUM format will be used</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
* <p><b>Examples</b></p>
|
||||
@@ -145,12 +151,12 @@ import java.util.List;
|
||||
* </pre>
|
||||
*
|
||||
* <code>Date</code>
|
||||
*
|
||||
*/
|
||||
@StrutsTag(name="date", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.DateTag", description="Render a formatted date.")
|
||||
@StrutsTag(name = "date", tldBodyContent = "empty", tldTagClass = "org.apache.struts2.views.jsp.DateTag", description = "Render a formatted date.")
|
||||
public class Date extends ContextBean {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(Date.class);
|
||||
|
||||
/**
|
||||
* Property name to fall back when no format is specified
|
||||
*/
|
||||
@@ -202,17 +208,18 @@ public class Date extends ContextBean {
|
||||
|
||||
private String timezone;
|
||||
|
||||
private DateFormatter dateFormatter;
|
||||
|
||||
public Date(ValueStack stack) {
|
||||
super(stack);
|
||||
}
|
||||
|
||||
private TextProvider findProviderInStack() {
|
||||
for (Object o : getStack().getRoot()) {
|
||||
if (o instanceof TextProvider) {
|
||||
return (TextProvider) o;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* An instance of {@link DateFormatter}
|
||||
*/
|
||||
@Inject
|
||||
public void setDateFormatter(DateFormatter dateFormatter) {
|
||||
this.dateFormatter = dateFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,6 +287,8 @@ public class Date extends ContextBean {
|
||||
|
||||
@Override
|
||||
public boolean end(Writer writer, String body) {
|
||||
TextProvider textProvider = findProviderInStack();
|
||||
|
||||
ZonedDateTime date = null;
|
||||
final ZoneId tz = getTimeZone();
|
||||
// find the name on the valueStack
|
||||
@@ -292,26 +301,27 @@ public class Date extends ContextBean {
|
||||
date = Instant.ofEpochMilli((long) dateObject).atZone(tz);
|
||||
} else if (dateObject instanceof LocalDateTime) {
|
||||
date = ((LocalDateTime) dateObject).atZone(tz);
|
||||
} else if (dateObject instanceof LocalDate) {
|
||||
date = ((LocalDate) dateObject).atStartOfDay(tz);
|
||||
} else if (dateObject instanceof Instant) {
|
||||
date = ((Instant) dateObject).atZone(tz);
|
||||
} else {
|
||||
if (devMode) {
|
||||
TextProvider tp = findProviderInStack();
|
||||
String developerNotification = "";
|
||||
if (tp != null) {
|
||||
developerNotification = findProviderInStack().getText(
|
||||
"devmode.notification",
|
||||
"Developer Notification:\n{0}",
|
||||
new String[]{
|
||||
"Expression [" + name + "] passed to <s:date/> tag which was evaluated to [" + dateObject + "]("
|
||||
+ (dateObject != null ? dateObject.getClass() : "null") + ") isn't supported!"
|
||||
}
|
||||
if (textProvider != null) {
|
||||
developerNotification = textProvider.getText(
|
||||
"devmode.notification",
|
||||
"Developer Notification:\n{0}",
|
||||
new String[]{
|
||||
"Expression [" + name + "] passed to <s:date/> tag which was evaluated to [" + dateObject + "]("
|
||||
+ (dateObject != null ? dateObject.getClass() : "null") + ") isn't supported!"
|
||||
}
|
||||
);
|
||||
}
|
||||
LOG.warn(developerNotification);
|
||||
} else {
|
||||
LOG.debug("Expression [{}] passed to <s:date/> tag which was evaluated to [{}]({}) isn't supported!",
|
||||
name, dateObject, (dateObject != null ? dateObject.getClass() : "null"));
|
||||
name, dateObject, (dateObject != null ? dateObject.getClass() : "null"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,33 +331,11 @@ public class Date extends ContextBean {
|
||||
}
|
||||
String msg;
|
||||
if (date != null) {
|
||||
TextProvider tp = findProviderInStack();
|
||||
if (tp != null) {
|
||||
if (textProvider != null) {
|
||||
if (nice) {
|
||||
msg = formatTime(tp, date);
|
||||
msg = formatTime(textProvider, date);
|
||||
} else {
|
||||
DateTimeFormatter dtf;
|
||||
if (format == null) {
|
||||
String globalFormat = null;
|
||||
|
||||
// if the format is not specified, fall back using the
|
||||
// defined property DATETAG_PROPERTY
|
||||
globalFormat = tp.getText(DATETAG_PROPERTY);
|
||||
|
||||
// if tp.getText can not find the property then the
|
||||
// returned string is the same as input =
|
||||
// DATETAG_PROPERTY
|
||||
if (globalFormat != null
|
||||
&& !DATETAG_PROPERTY.equals(globalFormat)) {
|
||||
dtf = DateTimeFormatter.ofPattern(globalFormat, ActionContext.getContext().getLocale());
|
||||
} else {
|
||||
dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||
.withLocale(ActionContext.getContext().getLocale());
|
||||
}
|
||||
} else {
|
||||
dtf = DateTimeFormatter.ofPattern(format, ActionContext.getContext().getLocale());
|
||||
}
|
||||
msg = dtf.format(date);
|
||||
msg = formatDate(textProvider, date);
|
||||
}
|
||||
if (msg != null) {
|
||||
try {
|
||||
@@ -365,6 +353,20 @@ public class Date extends ContextBean {
|
||||
return super.end(writer, "");
|
||||
}
|
||||
|
||||
private String formatDate(TextProvider textProvider, ZonedDateTime date) {
|
||||
String useFormat = format;
|
||||
if (useFormat == null) {
|
||||
// if the format is not specified, fall back using the defined property DATETAG_PROPERTY
|
||||
useFormat = textProvider.getText(DATETAG_PROPERTY);
|
||||
if (DATETAG_PROPERTY.equals(useFormat)) {
|
||||
// if tp.getText can not find the property then the
|
||||
// returned string is the same as input = DATETAG_PROPERTY
|
||||
useFormat = null;
|
||||
}
|
||||
}
|
||||
return dateFormatter.format(date, useFormat);
|
||||
}
|
||||
|
||||
private ZoneId getTimeZone() {
|
||||
ZoneId tz = ZoneId.systemDefault();
|
||||
if (timezone != null) {
|
||||
@@ -378,17 +380,26 @@ public class Date extends ContextBean {
|
||||
return tz;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Date or DateTime format pattern", rtexprvalue=false)
|
||||
private TextProvider findProviderInStack() {
|
||||
for (Object o : getStack().getRoot()) {
|
||||
if (o instanceof TextProvider) {
|
||||
return (TextProvider) o;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description = "Date or DateTime format pattern")
|
||||
public void setFormat(String format) {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Whether to print out the date nicely", type="Boolean", defaultValue="false")
|
||||
@StrutsTagAttribute(description = "Whether to print out the date nicely", type = "Boolean", defaultValue = "false")
|
||||
public void setNice(boolean nice) {
|
||||
this.nice = nice;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description = "The specific timezone in which to format the date", required = false)
|
||||
@StrutsTagAttribute(description = "The specific timezone in which to format the date")
|
||||
public void setTimezone(String timezone) {
|
||||
this.timezone = timezone;
|
||||
}
|
||||
@@ -400,7 +411,7 @@ public class Date extends ContextBean {
|
||||
return name;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="The date value to format", required=true)
|
||||
@StrutsTagAttribute(description = "The date value to format", required = true)
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,6 @@ public abstract class ListUIBean extends UIBean {
|
||||
this.listTitle = listTitle;
|
||||
}
|
||||
|
||||
|
||||
public void setThrowExceptionOnNullValueAttribute(boolean throwExceptionOnNullValueAttribute) {
|
||||
this.throwExceptionOnNullValueAttribute = throwExceptionOnNullValueAttribute;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
allowDynamicAttributes = true)
|
||||
public class Radio extends ListUIBean {
|
||||
final public static String TEMPLATE = "radiomap";
|
||||
|
||||
|
||||
public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
}
|
||||
@@ -65,8 +65,19 @@ public class Radio extends ListUIBean {
|
||||
protected String getDefaultTemplate() {
|
||||
return TEMPLATE;
|
||||
}
|
||||
|
||||
|
||||
public void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Radio tag requires lazy evaluation as list of tags is dynamically generated using <s:iterator/>
|
||||
*
|
||||
* @return boolean true by default
|
||||
*/
|
||||
@Override
|
||||
protected boolean lazyEvaluation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ import java.io.Writer;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
|
||||
@@ -54,7 +57,6 @@ public class Submit extends FormButton {
|
||||
final public static String OPEN_TEMPLATE = "submit";
|
||||
final public static String TEMPLATE = "submit-close";
|
||||
protected String src;
|
||||
protected boolean escapeHtmlBody = true;
|
||||
|
||||
public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
@@ -73,7 +75,7 @@ public class Submit extends FormButton {
|
||||
value = "Submit";
|
||||
}
|
||||
|
||||
if (((key != null)) && (value == null)) {
|
||||
if ((key != null) && (value == null)) {
|
||||
this.value = "%{getText('"+key +"')}";
|
||||
}
|
||||
|
||||
@@ -83,8 +85,11 @@ public class Submit extends FormButton {
|
||||
public void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
|
||||
if (src != null)
|
||||
if (src != null) {
|
||||
addParameter("src", findString(src));
|
||||
}
|
||||
|
||||
addParameter("escapeHtmlBody", escapeHtmlBody);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +106,7 @@ public class Submit extends FormButton {
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(required = false, description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "true")
|
||||
@StrutsTagAttribute(description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "false")
|
||||
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
|
||||
this.escapeHtmlBody = escapeHtmlBody;
|
||||
}
|
||||
@@ -111,18 +116,6 @@ public class Submit extends FormButton {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to set if body content should be HTML-escaped.
|
||||
*
|
||||
* @return true if body should be HTML-escaped, false otherwise.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
@Override
|
||||
public boolean escapeHtmlBody() {
|
||||
return escapeHtmlBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides to be able to render body in a template rather than always before the template
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,9 @@ package org.apache.struts2.components;
|
||||
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -31,6 +33,7 @@ import org.apache.struts2.components.template.TemplateEngine;
|
||||
import org.apache.struts2.components.template.TemplateEngineManager;
|
||||
import org.apache.struts2.components.template.TemplateRenderingContext;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.util.ComponentUtils;
|
||||
import org.apache.struts2.util.TextProviderHelper;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
import org.apache.struts2.views.util.ContextUtil;
|
||||
@@ -699,11 +702,13 @@ public abstract class UIBean extends Component {
|
||||
}
|
||||
|
||||
if (requiredLabel != null) {
|
||||
addParameter("required", findValue(requiredLabel, Boolean.class));
|
||||
Object parsedValue = findValue(requiredLabel, Boolean.class);
|
||||
addParameter("required", parsedValue == null ? Boolean.valueOf(requiredLabel) : parsedValue);
|
||||
}
|
||||
|
||||
if (disabled != null) {
|
||||
addParameter("disabled", findValue(disabled, Boolean.class));
|
||||
Object parsedValue = findValue(disabled, Boolean.class);
|
||||
addParameter("disabled", parsedValue == null ? Boolean.valueOf(disabled) : parsedValue);
|
||||
}
|
||||
|
||||
if (tabindex != null) {
|
||||
@@ -883,9 +888,9 @@ public abstract class UIBean extends Component {
|
||||
this.addParameter("tooltipDelay", findString(this.tooltipDelay));
|
||||
|
||||
if (this.javascriptTooltip != null) {
|
||||
Boolean jsTooltips = (Boolean) findValue(this.javascriptTooltip, Boolean.class);
|
||||
Object jsTooltips = findValue(this.javascriptTooltip, Boolean.class);
|
||||
//TODO use a Boolean model when tooltipConfig is dropped
|
||||
this.addParameter("jsTooltipEnabled", jsTooltips.toString());
|
||||
this.addParameter("jsTooltipEnabled", jsTooltips == null ? this.javascriptTooltip : jsTooltips.toString());
|
||||
|
||||
if (form != null)
|
||||
form.addParameter("hasTooltip", jsTooltips);
|
||||
@@ -965,7 +970,7 @@ public abstract class UIBean extends Component {
|
||||
// 1] UI component's tooltipConfig attribute OR
|
||||
// 2] <param name="tooltip" value="" /> param tag value attribute
|
||||
|
||||
result = new LinkedHashMap<>((Map) tooltipConfigObj);
|
||||
result = new LinkedHashMap<String, String>((Map) tooltipConfigObj);
|
||||
} else if (tooltipConfigObj instanceof String) {
|
||||
|
||||
// we get this if its configured using
|
||||
@@ -1272,10 +1277,16 @@ public abstract class UIBean extends Component {
|
||||
|
||||
public void setDynamicAttributes(Map<String, String> tagDynamicAttributes) {
|
||||
for (Map.Entry<String, String> entry : tagDynamicAttributes.entrySet()) {
|
||||
String entryKey = entry.getKey();
|
||||
String attrName = entry.getKey();
|
||||
String attrValue = entry.getValue();
|
||||
|
||||
if (!isValidTagAttribute(entryKey)) {
|
||||
dynamicAttributes.put(entryKey, entry.getValue());
|
||||
if (!isValidTagAttribute(attrName)) {
|
||||
if (ComponentUtils.containsExpression(attrValue) && !lazyEvaluation()) {
|
||||
String translated = TextParseUtil.translateVariables('%', attrValue, stack);
|
||||
dynamicAttributes.put(attrName, ObjectUtils.defaultIfNull(translated, attrValue));
|
||||
} else {
|
||||
dynamicAttributes.put(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1296,4 +1307,14 @@ public abstract class UIBean extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to avoid evaluating attributes in {@link #evaluateParams()} or {@link #evaluateExtraParams()}
|
||||
* as evaluation will happen in tag's template
|
||||
*
|
||||
* @return boolean false if evaluation should be performed in ftl
|
||||
*/
|
||||
protected boolean lazyEvaluation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.components.date;
|
||||
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
* Allows defines a wrapper around different formatting APIs, like old SimpleDateFormat
|
||||
* and new DateTimeFormatter introduced in Java 8 Date/Time API
|
||||
* <p>
|
||||
* New instance will be injected using {@link org.apache.struts2.StrutsConstants#STRUTS_DATE_FORMATTER}
|
||||
*/
|
||||
public interface DateFormatter {
|
||||
|
||||
/**
|
||||
* Formats provided temporal with the given format
|
||||
*
|
||||
* @param temporal Java 8 {@link TemporalAccessor}
|
||||
* @param format implementation specific format
|
||||
* @return a string representation of the formatted `temporal`
|
||||
*/
|
||||
String format(TemporalAccessor temporal, String format);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.components.date;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Locale;
|
||||
|
||||
public class DateTimeFormatterAdapter implements DateFormatter {
|
||||
|
||||
@Override
|
||||
public String format(TemporalAccessor temporal, String format) {
|
||||
DateTimeFormatter dtf;
|
||||
Locale locale = ActionContext.getContext().getLocale();
|
||||
if (format == null) {
|
||||
dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||
.withLocale(locale);
|
||||
} else {
|
||||
dtf = DateTimeFormatter.ofPattern(format, locale);
|
||||
}
|
||||
return dtf.format(temporal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.components.date;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SimpleDateFormatAdapter implements DateFormatter {
|
||||
|
||||
@Override
|
||||
public String format(TemporalAccessor temporal, String format) {
|
||||
DateFormat df;
|
||||
Locale locale = ActionContext.getContext().getLocale();
|
||||
if (format == null) {
|
||||
df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
||||
} else {
|
||||
df = new SimpleDateFormat(format, locale);
|
||||
}
|
||||
return df.format(new Date(Instant.from(temporal).toEpochMilli()));
|
||||
}
|
||||
|
||||
}
|
||||
+3
-6
@@ -148,16 +148,13 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
}
|
||||
};
|
||||
|
||||
LOG.debug("Puts action on the top of ValueStack, just before the tag");
|
||||
action = stack.pop();
|
||||
LOG.debug("Push tag on top of the stack");
|
||||
stack.push(templateContext.getTag());
|
||||
stack.push(action);
|
||||
try {
|
||||
template.process(model, writer);
|
||||
} finally {
|
||||
stack.pop(); // removes action
|
||||
stack.pop(); // removes tag
|
||||
stack.push(action); // puts back action
|
||||
LOG.debug("Removes tag from top of the stack");
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,13 +54,12 @@ import com.opensymphony.xwork2.util.PatternMatcher;
|
||||
import com.opensymphony.xwork2.util.TextParser;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
|
||||
import com.opensymphony.xwork2.validator.ActionValidatorManager;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.components.UrlRenderer;
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.dispatcher.DispatcherErrorHandler;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
@@ -422,6 +421,8 @@ public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider {
|
||||
alias(NotExcludedAcceptedPatternsChecker.class, StrutsConstants.STRUTS_NOT_EXCLUDED_ACCEPTED_PATTERNS_CHECKER
|
||||
, builder, props, Scope.SINGLETON);
|
||||
|
||||
alias(DateFormatter.class, StrutsConstants.STRUTS_DATE_FORMATTER, builder, props, Scope.SINGLETON);
|
||||
|
||||
switchDevMode(props);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,25 +45,23 @@ import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>{@link ServletContextAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ServletContextAware}</li>
|
||||
* <li>{@link ServletRequestAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ServletRequestAware}</li>
|
||||
* <li>{@link ServletResponseAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ServletResponseAware}</li>
|
||||
* <li>{@link ParameterAware} - deprecated since 2.5.4, please use {@link HttpParametersAware}</li>
|
||||
*
|
||||
* <li>{@link HttpParametersAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ParametersAware}</li>
|
||||
* <li>{@link RequestAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ServletRequestAware}</li>
|
||||
* <li>{@link SessionAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.SessionAware}</li>
|
||||
* <li>{@link ApplicationAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.ApplicationAware}</li>
|
||||
* <li>{@link PrincipalAware}</li>
|
||||
*
|
||||
* <li>{@link org.apache.struts2.action.PrincipalAware}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: description -->
|
||||
@@ -101,13 +99,19 @@ import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
|
||||
* </pre>
|
||||
*
|
||||
* @see ServletContextAware
|
||||
* @see org.apache.struts2.action.ServletContextAware
|
||||
* @see ServletRequestAware
|
||||
* @see org.apache.struts2.action.ServletRequestAware
|
||||
* @see ServletResponseAware
|
||||
* @see org.apache.struts2.action.ServletResponseAware
|
||||
* @see ParameterAware
|
||||
* @see ParametersAware
|
||||
* @see org.apache.struts2.action.ParametersAware
|
||||
* @see SessionAware
|
||||
* @see org.apache.struts2.action.SessionAware
|
||||
* @see ApplicationAware
|
||||
* @see org.apache.struts2.action.ApplicationAware
|
||||
* @see PrincipalAware
|
||||
* @see org.apache.struts2.action.PrincipalAware
|
||||
*/
|
||||
public class ServletConfigInterceptor extends AbstractInterceptor implements StrutsStatics {
|
||||
|
||||
@@ -159,7 +163,7 @@ public class ServletConfigInterceptor extends AbstractInterceptor implements Str
|
||||
if (action instanceof ApplicationAware) {
|
||||
((ApplicationAware) action).setApplication(context.getApplication());
|
||||
}
|
||||
|
||||
|
||||
if (action instanceof org.apache.struts2.action.ApplicationAware) {
|
||||
((org.apache.struts2.action.ApplicationAware) action).withApplication(context.getApplication());
|
||||
}
|
||||
@@ -167,7 +171,7 @@ public class ServletConfigInterceptor extends AbstractInterceptor implements Str
|
||||
if (action instanceof SessionAware) {
|
||||
((SessionAware) action).setSession(context.getSession());
|
||||
}
|
||||
|
||||
|
||||
if (action instanceof org.apache.struts2.action.SessionAware) {
|
||||
((org.apache.struts2.action.SessionAware) action).withSession(context.getSession());
|
||||
}
|
||||
@@ -179,7 +183,7 @@ public class ServletConfigInterceptor extends AbstractInterceptor implements Str
|
||||
if (action instanceof PrincipalAware) {
|
||||
HttpServletRequest request = context.getServletRequest();
|
||||
if(request != null) {
|
||||
// We are in servtlet environment, so principal information resides in HttpServletRequest
|
||||
// We are in servlet environment, so principal information resides in HttpServletRequest
|
||||
((PrincipalAware) action).setPrincipalProxy(new ServletPrincipalProxy(request));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,11 +71,6 @@ public class TextProviderHelper {
|
||||
} else {
|
||||
LOG.warn("Could not locate the message resource '{}' as there is no TextProvider in the ValueStack.", key);
|
||||
}
|
||||
if (defaultMessage.equals(msg)) {
|
||||
LOG.warn("The default value expression '{}' was evaluated and did not match a property. The literal value '{}' will be used.", defaultMessage, defaultMessage);
|
||||
} else {
|
||||
LOG.warn("The default value expression '{}' evaluated to '{}'", defaultMessage, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return msg;
|
||||
|
||||
@@ -47,13 +47,13 @@ public class AnchorTag extends AbstractClosingTag {
|
||||
protected String portletUrlType;
|
||||
protected String anchor;
|
||||
protected String forceAddSchemeHostAndPort;
|
||||
protected boolean escapeHtmlBody = true; // Default - escape HTML body
|
||||
protected String escapeHtmlBody;
|
||||
|
||||
@Override
|
||||
public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
|
||||
return new Anchor(stack, req, res);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void populateParams() {
|
||||
super.populateParams();
|
||||
@@ -80,10 +80,12 @@ public class AnchorTag extends AbstractClosingTag {
|
||||
if (escapeAmp != null) {
|
||||
tag.setEscapeAmp(BooleanUtils.toBoolean(escapeAmp));
|
||||
}
|
||||
if (forceAddSchemeHostAndPort != null) {
|
||||
if (forceAddSchemeHostAndPort != null) {
|
||||
tag.setForceAddSchemeHostAndPort(BooleanUtils.toBoolean(forceAddSchemeHostAndPort));
|
||||
}
|
||||
tag.setEscapeHtmlBody(escapeHtmlBody);
|
||||
if (escapeHtmlBody != null) {
|
||||
tag.setEscapeHtmlBody(escapeHtmlBody);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHref(String href) {
|
||||
@@ -149,12 +151,12 @@ public class AnchorTag extends AbstractClosingTag {
|
||||
|
||||
/**
|
||||
* Set via parameter to control if body content should be HTML-escaped.
|
||||
*
|
||||
* @param escapeHtmlBody
|
||||
*
|
||||
*
|
||||
* @param escapeHtmlBody
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
|
||||
public void setEscapeHtmlBody(String escapeHtmlBody) {
|
||||
this.escapeHtmlBody = escapeHtmlBody;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class SubmitTag extends AbstractClosingTag {
|
||||
protected String method;
|
||||
protected String type;
|
||||
protected String src;
|
||||
protected boolean escapeHtmlBody = true; // Default - escape HTML body
|
||||
protected boolean escapeHtmlBody = false;
|
||||
|
||||
@Override
|
||||
public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
|
||||
@@ -78,9 +78,9 @@ public class SubmitTag extends AbstractClosingTag {
|
||||
|
||||
/**
|
||||
* Set via parameter to control if body content should be HTML-escaped.
|
||||
*
|
||||
* @param escapeHtmlBody
|
||||
*
|
||||
*
|
||||
* @param escapeHtmlBody
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
|
||||
|
||||
@@ -151,6 +151,11 @@ struts.ui.theme.expansion.token=~~~
|
||||
### Sets the default template type. Either ftl, vm, or jsp
|
||||
struts.ui.templateSuffix=ftl
|
||||
|
||||
### Sets a global flag which will escape html body of Anchor, Submit and Component tag
|
||||
### You can control this flag per tag, e.g.: <s:a ... escapeHtmlTag="true">...</s:a>
|
||||
### and this take precedence over the global flag
|
||||
# struts.ui.escapeHtmlBody=true
|
||||
|
||||
### Configuration reloading
|
||||
### This will cause the configuration to reload struts.xml when it is changed
|
||||
# struts.configuration.xml.reload=false
|
||||
@@ -256,7 +261,7 @@ struts.handle.exception=true
|
||||
|
||||
### Applies maximum length allowed on OGNL expressions for security enhancement (optional)
|
||||
###
|
||||
### **WARNING**: If developers enable this option (by configuration) they should make sure that they understand the implications of setting
|
||||
### **WARNING**: If developers enable this option (by configuration) they should make sure that they understand the implications of setting
|
||||
### struts.ognl.expressionMaxLength. They must choose a value large enough to permit ALL valid OGNL expressions used within the application.
|
||||
### Values larger than the 200-400 range have diminishing security value (at which point it is really only a "style guard" for long OGNL
|
||||
### expressions in an application. Setting a value of null or "" will also disable the feature.
|
||||
@@ -264,4 +269,10 @@ struts.handle.exception=true
|
||||
### NOTE: The sample line below is *INTENTIONALLY* commented out, as this feature is disabled by default.
|
||||
# struts.ognl.expressionMaxLength=256
|
||||
|
||||
### Defines which named instance of DateFormatter to use, there are two instances:
|
||||
### - simpleDateFormatter (based on SimpleDateFormat)
|
||||
### - dateTimeFormatter (based on Java 8 Date/Time API)
|
||||
### These formatters are using a slightly different patterns, please check JavaDocs of both and more details is in WW-5016
|
||||
struts.date.formatter=dateTimeFormatter
|
||||
|
||||
### END SNIPPET: complete_file
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
<bean type="com.opensymphony.xwork2.UnknownHandlerManager" class="com.opensymphony.xwork2.DefaultUnknownHandlerManager" name="struts" />
|
||||
|
||||
<bean type="org.apache.struts2.dispatcher.DispatcherErrorHandler" name="struts" class="org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler" />
|
||||
|
||||
|
||||
<!-- Silly workarounds for OGNL since there is currently no way to flush its internal caches -->
|
||||
<bean type="ognl.PropertyAccessor" name="java.util.ArrayList" class="com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor" />
|
||||
<bean type="ognl.PropertyAccessor" name="java.util.HashSet" class="com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor" />
|
||||
@@ -228,6 +228,9 @@
|
||||
|
||||
<bean type="com.opensymphony.xwork2.config.providers.ValueSubstitutor" class="com.opensymphony.xwork2.config.providers.EnvsValueSubstitutor" scope="singleton"/>
|
||||
|
||||
<bean type="org.apache.struts2.components.date.DateFormatter" name="simpleDateFormatter" class="org.apache.struts2.components.date.SimpleDateFormatAdapter" scope="singleton"/>
|
||||
<bean type="org.apache.struts2.components.date.DateFormatter" name="dateTimeFormatter" class="org.apache.struts2.components.date.DateTimeFormatterAdapter" scope="singleton"/>
|
||||
|
||||
<bean type="com.opensymphony.xwork2.ognl.OgnlCacheFactory" name="struts.ognl.expressionCacheFactory" class="com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory" scope="singleton"/>
|
||||
<bean type="com.opensymphony.xwork2.ognl.OgnlCacheFactory" name="struts.ognl.beanInfoCacheFactory" class="com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory" scope="singleton"/>
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<#assign itemKeyStr = stack.findString('top')>
|
||||
</#if>
|
||||
<#if parameters.listLabelKey??>
|
||||
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
|
||||
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
|
||||
file for it's localized value. This is then used as a label -->
|
||||
<#assign itemValue = struts.getText(stack.findString(parameters.listLabelKey))/>
|
||||
<#elseif parameters.listValue??>
|
||||
@@ -95,9 +95,10 @@
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
|
||||
<#global evaluate_dynamic_attributes = true/>
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
|
||||
/>
|
||||
<label<#rt/>
|
||||
<label<#rt/>
|
||||
<#if parameters.id?has_content>
|
||||
for="${parameters.id}-${itemCount}"<#rt/>
|
||||
<#else>
|
||||
@@ -106,11 +107,10 @@
|
||||
class="checkboxLabel">${itemValue}</label>
|
||||
</@s.iterator>
|
||||
<#else>
|
||||
|
||||
</#if>
|
||||
<input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}"
|
||||
value=""<#rt/>
|
||||
<#if parameters.disabled!false>
|
||||
disabled="disabled"<#rt/>
|
||||
</#if>
|
||||
/>
|
||||
/>
|
||||
|
||||
@@ -30,7 +30,11 @@
|
||||
<#list aKeys?filter(acceptKey) as aKey><#rt/>
|
||||
<#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
|
||||
<#if keyValue?is_string>
|
||||
<#assign value = struts.translateVariables(keyValue)!keyValue/>
|
||||
<#if evaluate_dynamic_attributes!false == true>
|
||||
<#assign value = struts.translateVariables(keyValue)!keyValue/><#rt/>
|
||||
<#else>
|
||||
<#assign value = keyValue/><#rt/>
|
||||
</#if>
|
||||
<#else>
|
||||
<#assign value = keyValue?string/>
|
||||
</#if>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<#assign itemKeyStr = stack.findString('top')>
|
||||
</#if>
|
||||
<#if parameters.listValueKey??>
|
||||
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
|
||||
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
|
||||
file for it's localized value. This is then used as a label -->
|
||||
<#assign valueKey = stack.findString(parameters.listValueKey)!''/>
|
||||
<#if valueKey?has_content>
|
||||
@@ -94,9 +94,10 @@
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
|
||||
<#global evaluate_dynamic_attributes = true/>
|
||||
<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
|
||||
/><#rt/>
|
||||
<label for="${parameters.id}${itemKeyStr?replace(".", "_")}"<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl"/>><#rt/>
|
||||
${itemValue}<#t/>
|
||||
</label>
|
||||
</@s.iterator>
|
||||
</@s.iterator>
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
<tr>
|
||||
<td align="left" valign="top">escapeHtmlBody</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">true</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">Boolean</td>
|
||||
<td align="left" valign="top">Specifies whether to HTML-escape the tag body or not</td>
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
<tr>
|
||||
<td align="left" valign="top">escapeHtmlBody</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">true</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">false</td>
|
||||
<td align="left" valign="top">Boolean</td>
|
||||
<td align="left" valign="top">Specifies whether to HTML-escape the tag body or not</td>
|
||||
|
||||
@@ -730,6 +730,33 @@ public class ParametersInterceptorTest extends XWorkTestCase {
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
public void testDMIMethodsAreIgnored() throws Exception {
|
||||
// given
|
||||
ParametersInterceptor interceptor = createParametersInterceptor();
|
||||
final Map<String, Object> actual = injectValueStackFactory(interceptor);
|
||||
ValueStack stack = injectValueStack(actual);
|
||||
|
||||
final Map<String, Object> expected = new HashMap<String, Object>() {
|
||||
{
|
||||
put("ordinary.bean", "value");
|
||||
}
|
||||
};
|
||||
|
||||
Map<String, Object> parameters = new HashMap<String, Object>() {
|
||||
{
|
||||
put("ordinary.bean", "value");
|
||||
put("action:", "myAction");
|
||||
put("method:", "doExecute");
|
||||
}
|
||||
};
|
||||
|
||||
// when
|
||||
interceptor.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
|
||||
|
||||
// then
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
public void testBeanListSingleValue() throws Exception {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("beanList.name", new String[]{"Superman"});
|
||||
|
||||
@@ -18,14 +18,11 @@
|
||||
*/
|
||||
package org.apache.struts2.components;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.TestConfigurationProvider;
|
||||
import org.apache.struts2.views.jsp.AbstractTagTest;
|
||||
import org.apache.struts2.views.jsp.ActionTag;
|
||||
import org.apache.struts2.views.jsp.BeanTag;
|
||||
import org.apache.struts2.views.jsp.ElseIfTag;
|
||||
import org.apache.struts2.views.jsp.ElseTag;
|
||||
@@ -42,17 +39,19 @@ import org.apache.struts2.views.jsp.iterator.MergeIteratorTag;
|
||||
import org.apache.struts2.views.jsp.ui.TextFieldTag;
|
||||
import org.apache.struts2.views.jsp.ui.UpDownSelectTag;
|
||||
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
import java.util.HashMap;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Test case for method findAncestor(Class) in Component and some commons
|
||||
* test cases for Component in general.
|
||||
*
|
||||
*/
|
||||
public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
public void testFindAncestorTest() throws Exception {
|
||||
public void testFindAncestorTest() {
|
||||
Property property = new Property(stack);
|
||||
Form form = new Form(stack, request, response);
|
||||
ActionComponent actionComponent = new ActionComponent(stack, request, response);
|
||||
@@ -61,8 +60,8 @@ public class ComponentTest extends AbstractTagTest {
|
||||
TextField textField = new TextField(stack, request, response);
|
||||
|
||||
|
||||
Stack stack = property.getComponentStack();
|
||||
Iterator i = stack.iterator();
|
||||
Stack<Component> stack = property.getComponentStack();
|
||||
Iterator<Component> i = stack.iterator();
|
||||
|
||||
|
||||
try {
|
||||
@@ -107,8 +106,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
assertEquals(textField.findAncestor(Anchor.class), anchor);
|
||||
assertEquals(textField.findAncestor(ActionComponent.class), actionComponent);
|
||||
assertEquals(textField.findAncestor(Property.class), property);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
property.getComponentStack().pop();
|
||||
property.getComponentStack().pop();
|
||||
property.getComponentStack().pop();
|
||||
@@ -118,16 +116,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
}
|
||||
|
||||
// Action Component
|
||||
/*
|
||||
public void testActionComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
ConfigurationManager.clearConfigurationProviders();
|
||||
ConfigurationManager.addConfigurationProvider(new TestConfigurationProvider());
|
||||
ConfigurationManager.getConfiguration().reload();
|
||||
|
||||
ActionContext actionContext = new ActionContext(context);
|
||||
actionContext.setValueStack(stack);
|
||||
ActionContext.setContext(actionContext);
|
||||
|
||||
public void testActionComponentDisposeItselfFromComponentStack() {
|
||||
request.setupGetServletPath(TestConfigurationProvider.TEST_NAMESPACE + "/" + "foo.action");
|
||||
try {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
@@ -145,17 +134,14 @@ public class ComponentTest extends AbstractTagTest {
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// AppendInterator
|
||||
public void testAppendIteratorDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testAppendIteratorDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -170,8 +156,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -179,7 +164,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Bean
|
||||
public void testBeanComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testBeanComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -195,8 +180,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
@@ -204,7 +188,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// ElseIf
|
||||
public void testElseIfComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testElseIfComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -219,8 +203,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -228,7 +211,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Else
|
||||
public void testElseComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testElseComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -243,8 +226,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -252,7 +234,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// If
|
||||
public void testIfComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testIfComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -268,8 +250,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -277,7 +258,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Iterator
|
||||
public void testIteratorComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testIteratorComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -291,15 +272,14 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doStartTag();
|
||||
assertEquals(tag.getComponent().getComponentStack().peek(), tag.getComponent());
|
||||
int endIt = tag.doAfterBody();
|
||||
while(TagSupport.EVAL_BODY_AGAIN == endIt) {
|
||||
while (TagSupport.EVAL_BODY_AGAIN == endIt) {
|
||||
assertEquals(tag.getComponent().getComponentStack().peek(), tag.getComponent());
|
||||
endIt = tag.doAfterBody();
|
||||
}
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -307,7 +287,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// MergeIterator
|
||||
public void testMergeIteratorComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testMergeIteratorComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -322,8 +302,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -331,7 +310,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Property
|
||||
public void testPropertyComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testPropertyComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -346,8 +325,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -355,7 +333,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Push
|
||||
public void testPushComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testPushComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -371,8 +349,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -380,7 +357,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Set
|
||||
public void testSetComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testSetComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -397,8 +374,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -406,7 +382,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
|
||||
// Text
|
||||
public void testTextComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testTextComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -422,15 +398,14 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testI18nComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testI18nComponentDisposeItselfFromComponentStack() {
|
||||
stack.getActionContext().withLocale(Locale.getDefault());
|
||||
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
@@ -450,15 +425,14 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// URL
|
||||
public void testURLComponentDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testURLComponentDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -473,15 +447,14 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// updownselect
|
||||
public void testUpDownSelectDisposeItselfFromComponentStack() throws Exception {
|
||||
public void testUpDownSelectDisposeItselfFromComponentStack() {
|
||||
TextFieldTag t = new TextFieldTag();
|
||||
t.setPageContext(pageContext);
|
||||
t.setName("textFieldName");
|
||||
@@ -499,8 +472,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
tag.doEndTag();
|
||||
assertEquals(t.getComponent().getComponentStack().peek(), t.getComponent());
|
||||
t.doEndTag();
|
||||
}
|
||||
catch(Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
@@ -508,22 +480,22 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
/**
|
||||
* Test the expected default behaviour for component body state methods.
|
||||
*/
|
||||
*/
|
||||
public void testComponentDefaultBodyStates() {
|
||||
Component component = new Component(stack);
|
||||
// Test expected default results for: usesBody(), escapeHtmlBody().
|
||||
assertFalse("Component default usesBody not false ?", component.usesBody());
|
||||
assertTrue("Component default htmlEscapeBody not true ?", component.escapeHtmlBody());
|
||||
assertFalse("Component default htmlEscapeBody not false ?", component.escapeHtmlBody());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour for Anchor body state methods.
|
||||
*/
|
||||
*/
|
||||
public void testAnchorBodyStates() {
|
||||
Anchor anchor = new Anchor(stack, request, response);
|
||||
// Test expected default results for: usesBody(), escapeHtmlBody().
|
||||
assertTrue("Anchor default usesBody not true ?", anchor.usesBody());
|
||||
assertTrue("Anchor default htmlEscapeBody not true ?", anchor.escapeHtmlBody());
|
||||
assertFalse("Anchor default htmlEscapeBody not false ?", anchor.escapeHtmlBody());
|
||||
anchor.setEscapeHtmlBody(false);
|
||||
assertFalse("Anchor htmlEscapeBody not false after set false ?", anchor.escapeHtmlBody());
|
||||
anchor.setEscapeHtmlBody(true);
|
||||
@@ -532,12 +504,12 @@ public class ComponentTest extends AbstractTagTest {
|
||||
|
||||
/**
|
||||
* Test the behaviour for Submit body state methods.
|
||||
*/
|
||||
public void testAnchortBodyStates() {
|
||||
*/
|
||||
public void testSubmitBodyStates() {
|
||||
Submit submit = new Submit(stack, request, response);
|
||||
// Test expected default results for: usesBody(), escapeHtmlBody().
|
||||
assertTrue("Submit default usesBody not true ?", submit.usesBody());
|
||||
assertTrue("Submit default htmlEscapeBody not true ?", submit.escapeHtmlBody());
|
||||
assertFalse("Submit default htmlEscapeBody not false ?", submit.escapeHtmlBody());
|
||||
submit.setEscapeHtmlBody(false);
|
||||
assertFalse("Submit htmlEscapeBody not false after set false ?", submit.escapeHtmlBody());
|
||||
submit.setEscapeHtmlBody(true);
|
||||
@@ -547,10 +519,8 @@ public class ComponentTest extends AbstractTagTest {
|
||||
/**
|
||||
* Attempt some code coverage tests for {@link Component} that can be achieved without
|
||||
* too much difficulty.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testComponent_coverageTest() throws Exception {
|
||||
public void testComponent_coverageTest() {
|
||||
HashMap<String, Object> propertyMap = new HashMap<>();
|
||||
Exception exception = new Exception("Generic exception");
|
||||
Property property = new Property(stack);
|
||||
@@ -586,8 +556,7 @@ public class ComponentTest extends AbstractTagTest {
|
||||
assertFalse("Initial performClearTagStateForTagPoolingServers not false ?", actionComponent.getPerformClearTagStateForTagPoolingServers());
|
||||
actionComponent.setPerformClearTagStateForTagPoolingServers(true);
|
||||
assertTrue("performClearTagStateForTagPoolingServers false after setting to true ?", actionComponent.getPerformClearTagStateForTagPoolingServers());
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
property.getComponentStack().pop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.components;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import org.apache.struts2.StrutsInternalTestCase;
|
||||
import org.apache.struts2.components.date.SimpleDateFormatAdapter;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Map;
|
||||
|
||||
public class DateTest extends StrutsInternalTestCase {
|
||||
|
||||
private Map<String, Object> context;
|
||||
private ValueStack stack;
|
||||
|
||||
public void testSupportSimpleDateTimeFormat() {
|
||||
// given
|
||||
Date date = new Date(stack);
|
||||
date.setDateFormatter(new SimpleDateFormatAdapter());
|
||||
|
||||
String format = "EEEE MMMM dd, hh:mm aa";
|
||||
java.util.Date now = new java.util.Date();
|
||||
|
||||
String expected = new SimpleDateFormat(format, ActionContext.getContext().getLocale()).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
|
||||
// when
|
||||
date.setFormat(format);
|
||||
date.setName("myDate");
|
||||
date.setNice(false);
|
||||
date.start(writer);
|
||||
date.end(writer, "");
|
||||
|
||||
// then
|
||||
assertEquals(expected, writer.toString());
|
||||
}
|
||||
|
||||
public void testDefaultFormat() {
|
||||
// given
|
||||
Date date = new Date(stack);
|
||||
date.setDateFormatter(new SimpleDateFormatAdapter());
|
||||
|
||||
java.util.Date now = new java.util.Date();
|
||||
|
||||
String expected = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM, ActionContext.getContext().getLocale()).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
|
||||
// when
|
||||
date.setName("myDate");
|
||||
date.setNice(false);
|
||||
date.start(writer);
|
||||
date.end(writer, "");
|
||||
|
||||
// then
|
||||
assertEquals(expected, writer.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
stack = container.getInstance(ValueStackFactory.class).createValueStack();
|
||||
context = stack.getContext();
|
||||
}
|
||||
}
|
||||
@@ -18,17 +18,15 @@
|
||||
*/
|
||||
package org.apache.struts2.views.jsp.ui;
|
||||
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.TestAction;
|
||||
import org.apache.struts2.components.Anchor;
|
||||
import org.apache.struts2.views.jsp.AbstractUITagTest;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
public class AnchorTest extends AbstractUITagTest {
|
||||
|
||||
public void testBeanInfo() throws Exception {
|
||||
@@ -72,7 +70,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
AnchorTag freshTag = new AnchorTag();
|
||||
freshTag.setPerformClearTagStateForTagPoolingServers(true);
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is unequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
@@ -111,7 +109,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
AnchorTag freshTag = new AnchorTag();
|
||||
freshTag.setPerformClearTagStateForTagPoolingServers(true);
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is unequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
@@ -156,7 +154,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
AnchorTag freshTag = new AnchorTag();
|
||||
freshTag.setPerformClearTagStateForTagPoolingServers(true);
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is unequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
@@ -201,7 +199,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
AnchorTag freshTag = new AnchorTag();
|
||||
freshTag.setPerformClearTagStateForTagPoolingServers(true);
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is unequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
@@ -211,7 +209,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
testAction.setFoo("bar");
|
||||
}
|
||||
|
||||
private AnchorTag createTag() throws JspException {
|
||||
private AnchorTag createTag() {
|
||||
AnchorTag tag = new AnchorTag();
|
||||
tag.setPageContext(pageContext);
|
||||
|
||||
@@ -221,8 +219,6 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
|
||||
/**
|
||||
* Test anchor tag body supported
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSimpleWithBody() throws Exception {
|
||||
createAction();
|
||||
@@ -242,8 +238,6 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
|
||||
/**
|
||||
* Test that by default anchor tag body is HTML-escaped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSimpleWithBodyHTMLEscaped() throws Exception {
|
||||
createAction();
|
||||
@@ -254,6 +248,7 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
StrutsBodyContent body = new StrutsBodyContent(null);
|
||||
body.print("should HTML escape: < & >");
|
||||
tag.setBodyContent(body);
|
||||
tag.setEscapeHtmlBody("true");
|
||||
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
@@ -263,15 +258,13 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
|
||||
/**
|
||||
* Test that with htmlEscapeBody false anchor tag body is not HTML-escaped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSimpleWithBodyNotHTMLEscaped() throws Exception {
|
||||
createAction();
|
||||
|
||||
AnchorTag tag = createTag();
|
||||
tag.setHref("a");
|
||||
tag.setEscapeHtmlBody(false);
|
||||
tag.setEscapeHtmlBody("false");
|
||||
|
||||
StrutsBodyContent body = new StrutsBodyContent(null);
|
||||
body.print("should not HTML escape: < & >");
|
||||
@@ -282,4 +275,50 @@ public class AnchorTest extends AbstractUITagTest {
|
||||
|
||||
verifyResource("href-5.txt");
|
||||
}
|
||||
|
||||
public void testInjectEscapeHtmlBodyFlag() throws Exception {
|
||||
// given
|
||||
initDispatcherWithConfigs("struts-default.xml, struts-escape-body.xml");
|
||||
String escapeHtmlBody = container.getInstance(String.class, StrutsConstants.STRUTS_UI_ESCAPE_HTML_BODY);
|
||||
assertEquals("true", escapeHtmlBody);
|
||||
|
||||
createMocks();
|
||||
|
||||
createAction();
|
||||
|
||||
AnchorTag tag = createTag();
|
||||
|
||||
// when
|
||||
tag.doStartTag();
|
||||
|
||||
// then
|
||||
Anchor component = (Anchor) tag.getComponent();
|
||||
assertTrue(component.escapeHtmlBody());
|
||||
|
||||
tag.doEndTag();
|
||||
}
|
||||
|
||||
public void testTagAttributeTakesPrecedenceOverInjectEscapeHtmlBodyFlag() throws Exception {
|
||||
// given
|
||||
initDispatcherWithConfigs("struts-default.xml, struts-escape-body.xml");
|
||||
String escapeHtmlBody = container.getInstance(String.class, StrutsConstants.STRUTS_UI_ESCAPE_HTML_BODY);
|
||||
assertEquals("true", escapeHtmlBody);
|
||||
|
||||
createMocks();
|
||||
|
||||
createAction();
|
||||
|
||||
AnchorTag tag = createTag();
|
||||
tag.setEscapeHtmlBody("false");
|
||||
|
||||
// when
|
||||
tag.doStartTag();
|
||||
|
||||
// then
|
||||
Anchor component = (Anchor) tag.getComponent();
|
||||
assertFalse(component.escapeHtmlBody());
|
||||
|
||||
tag.doEndTag();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ public class CheckboxTest extends AbstractUITagTest {
|
||||
* as key.
|
||||
*/
|
||||
@Override
|
||||
protected Map initializedGenericTagTestProperties() {
|
||||
Map result = super.initializedGenericTagTestProperties();
|
||||
protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
|
||||
Map<String, PropertyHolder> result = super.initializedGenericTagTestProperties();
|
||||
new PropertyHolder("value", "true").addToMap(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -19,35 +19,33 @@
|
||||
package org.apache.struts2.views.jsp.ui;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
|
||||
import org.apache.struts2.TestAction;
|
||||
import org.apache.struts2.components.Component;
|
||||
import org.apache.struts2.components.DateTextField;
|
||||
import org.apache.struts2.views.jsp.AbstractTagTest;
|
||||
import org.apache.struts2.views.jsp.DateTag;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
import org.apache.struts2.components.Component;
|
||||
import org.apache.struts2.components.DateTextField;
|
||||
|
||||
/**
|
||||
* Unit test for {@link org.apache.struts2.components.Date}.
|
||||
*
|
||||
*/
|
||||
public class DateTagTest extends AbstractTagTest {
|
||||
|
||||
private DateTag tag;
|
||||
|
||||
public void testCustomFormat() throws Exception {
|
||||
public void testCustomFormatForDateTime() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
@@ -62,13 +60,55 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatForLong() throws Exception {
|
||||
String format = "yyyy/MM/dd";
|
||||
long now = new Date().getTime();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(Instant.ofEpochMilli(now).atZone(ZoneId.systemDefault()));
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
tag.setNice(false);
|
||||
tag.setFormat(format);
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
assertEquals(formatted, writer.toString());
|
||||
|
||||
// Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
|
||||
DateTag freshTag = new DateTag();
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatForDate() throws Exception {
|
||||
String format = "yyyy/MM/dd";
|
||||
LocalDate now = LocalDate.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
tag.setNice(false);
|
||||
tag.setFormat(format);
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
assertEquals(formatted, writer.toString());
|
||||
|
||||
// Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
|
||||
DateTag freshTag = new DateTag();
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormat_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -86,13 +126,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomGlobalFormatFormat() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
((TestAction) action).setText(org.apache.struts2.components.Date.DATETAG_PROPERTY, format);
|
||||
@@ -106,10 +146,8 @@ public class DateTagTest extends AbstractTagTest {
|
||||
|
||||
public void testCustomFormatWithTimezone() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
|
||||
String formatted = sdf.format(now);
|
||||
LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+1"));
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
@@ -126,15 +164,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatWithTimezone_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+1")).getTime();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
|
||||
String formatted = sdf.format(now);
|
||||
LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+1"));
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -153,15 +189,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatWithTimezoneAsExpression() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
|
||||
String formatted = sdf.format(now);
|
||||
LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+2"));
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
context.put("myTimezone", "GMT+2");
|
||||
|
||||
@@ -178,15 +212,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatWithTimezoneAsExpression_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = Calendar.getInstance(TimeZone.getTimeZone("GMT+2")).getTime();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
|
||||
String formatted = sdf.format(now);
|
||||
LocalDateTime now = LocalDateTime.now(ZoneId.of("GMT+2"));
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
context.put("myTimezone", "GMT+2");
|
||||
|
||||
@@ -206,13 +238,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatCalendar() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
String formatted = new SimpleDateFormat(format).format(calendar.getTime());
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(calendar.toInstant().atZone(ZoneId.systemDefault()));
|
||||
context.put("myDate", calendar);
|
||||
|
||||
tag.setName("myDate");
|
||||
@@ -227,13 +259,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatCalendar_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
String formatted = new SimpleDateFormat(format).format(calendar.getTime());
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(calendar.toInstant().atZone(ZoneId.systemDefault()));
|
||||
context.put("myDate", calendar);
|
||||
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -251,13 +283,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatLong() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date date = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(date);
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(date.toInstant().atZone(ZoneId.systemDefault()));
|
||||
// long
|
||||
context.put("myDate", date.getTime());
|
||||
|
||||
@@ -273,13 +305,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatLong_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date date = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(date);
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(date.toInstant().atZone(ZoneId.systemDefault()));
|
||||
// long
|
||||
context.put("myDate", date.getTime());
|
||||
|
||||
@@ -298,7 +330,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatLocalDateTime() throws Exception {
|
||||
@@ -332,7 +364,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
public void testDefaultFormat() throws Exception {
|
||||
Date now = new Date();
|
||||
String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM,
|
||||
ActionContext.getContext().getLocale()).format(now);
|
||||
ActionContext.getContext().getLocale()).format(now);
|
||||
|
||||
context.put("myDate", now);
|
||||
tag.setName("myDate");
|
||||
@@ -346,13 +378,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testDefaultFormat_clearTagStateSet() throws Exception {
|
||||
Date now = new Date();
|
||||
String formatted = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM,
|
||||
ActionContext.getContext().getLocale()).format(now);
|
||||
ActionContext.getContext().getLocale()).format(now);
|
||||
|
||||
context.put("myDate", now);
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -369,13 +401,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatAndComponent() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
@@ -388,7 +420,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
org.apache.struts2.components.Date component = (org.apache.struts2.components.Date) tag.getComponent();
|
||||
assertEquals("myDate", component.getName());
|
||||
assertEquals(format, component.getFormat());
|
||||
assertEquals(false, component.isNice());
|
||||
assertFalse(component.isNice());
|
||||
|
||||
tag.doEndTag();
|
||||
|
||||
@@ -399,13 +431,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testCustomFormatAndComponent_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -420,7 +452,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
org.apache.struts2.components.Date component = (org.apache.struts2.components.Date) tag.getComponent();
|
||||
assertEquals("myDate", component.getName());
|
||||
assertEquals(format, component.getFormat());
|
||||
assertEquals(false, component.isNice());
|
||||
assertFalse(component.isNice());
|
||||
|
||||
tag.doEndTag();
|
||||
|
||||
@@ -432,13 +464,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testSetId() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
@@ -454,13 +486,13 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testSetId_clearTagStateSet() throws Exception {
|
||||
String format = "yyyy/MM/dd hh:mm:ss";
|
||||
Date now = new Date();
|
||||
String formatted = new SimpleDateFormat(format).format(now);
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setPerformClearTagStateForTagPoolingServers(true); // Explicitly request tag state clearing.
|
||||
@@ -479,7 +511,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureNiceHour() throws Exception {
|
||||
@@ -501,7 +533,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureNiceHour_clearTagStateSet() throws Exception {
|
||||
@@ -526,7 +558,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testPastNiceHour() throws Exception {
|
||||
@@ -548,7 +580,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testPastNiceHour_clearTagStateSet() throws Exception {
|
||||
@@ -573,7 +605,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureNiceHourMinSec() throws Exception {
|
||||
@@ -596,7 +628,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureNiceHourMinSec_clearTagStateSet() throws Exception {
|
||||
@@ -622,7 +654,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testPastNiceHourMin() throws Exception {
|
||||
@@ -645,7 +677,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testPastNiceHourMin_clearTagStateSet() throws Exception {
|
||||
@@ -671,7 +703,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneMin() throws Exception {
|
||||
@@ -693,7 +725,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneMin_clearTagStateSet() throws Exception {
|
||||
@@ -718,7 +750,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneHour() throws Exception {
|
||||
@@ -740,7 +772,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneHour_clearTagStateSet() throws Exception {
|
||||
@@ -765,7 +797,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneYear() throws Exception {
|
||||
@@ -787,7 +819,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureLessOneYear_clearTagStateSet() throws Exception {
|
||||
@@ -812,7 +844,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureTwoYears() throws Exception {
|
||||
@@ -838,7 +870,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testFutureTwoYears_clearTagStateSet() throws Exception {
|
||||
@@ -867,7 +899,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testNoDateObjectInContext() throws Exception {
|
||||
@@ -884,7 +916,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
public void testNoDateObjectInContext_clearTagStateSet() throws Exception {
|
||||
@@ -904,7 +936,7 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -912,10 +944,8 @@ public class DateTagTest extends AbstractTagTest {
|
||||
* since that tag does not have its own unit tests, and it also appears to be
|
||||
* a broken tag. The code coverage tests can be moved if the tag is fixed, or
|
||||
* removed if the tag is dropped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testDateTextFieldTag_artificialCoverageTest() throws Exception {
|
||||
public void testDateTextFieldTag_artificialCoverageTest() throws JspException {
|
||||
final String format = "yyyy/MM/dd hh:mm:ss";
|
||||
DateTextFieldTag dateTextFieldTag = createDateTextFieldTag();
|
||||
dateTextFieldTag.setFormat(format);
|
||||
@@ -939,20 +969,40 @@ public class DateTagTest extends AbstractTagTest {
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(dateTextFieldTag, freshTag));
|
||||
strutsBodyTagsAreReflectionEqual(dateTextFieldTag, freshTag));
|
||||
}
|
||||
|
||||
public void testNewJava8Format() throws Exception {
|
||||
String format = "EEEE MMMM dd, hh:mm a";
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String formatted = DateTimeFormatter.ofPattern(format, ActionContext.getContext().getLocale()).format(now);
|
||||
context.put("myDate", now);
|
||||
|
||||
tag.setName("myDate");
|
||||
tag.setNice(false);
|
||||
tag.setFormat(format);
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
assertEquals(formatted, writer.toString());
|
||||
|
||||
// Basic sanity check of clearTagStateForTagPoolingServers() behaviour for Struts Tags after doEndTag().
|
||||
DateTag freshTag = new DateTag();
|
||||
freshTag.setPageContext(pageContext);
|
||||
assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set. " +
|
||||
"May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
|
||||
strutsBodyTagsAreReflectionEqual(tag, freshTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create a new {@link DateTextFieldTag} instance for code coverage tests.
|
||||
*
|
||||
* <p>
|
||||
* Note: There is no datetextfield.ftl template for the tag, so it does not appear that it can
|
||||
* actually be used in practice. We can perform basic coverage tests from within this
|
||||
* unit test class until the {@link DateTextFieldTag} is fixed or removed.
|
||||
*
|
||||
* actually be used in practice. We can perform basic coverage tests from within this
|
||||
* unit test class until the {@link DateTextFieldTag} is fixed or removed.
|
||||
*
|
||||
* @return a basic {@link DateTextFieldTag} instance
|
||||
* @throws Exception
|
||||
*/
|
||||
private DateTextFieldTag createDateTextFieldTag() throws Exception {
|
||||
private DateTextFieldTag createDateTextFieldTag() {
|
||||
DateTextFieldTag tag = new DateTextFieldTag();
|
||||
tag.setPageContext(pageContext);
|
||||
tag.setName("myDate");
|
||||
|
||||
@@ -96,8 +96,8 @@ public class FileTest extends AbstractUITagTest {
|
||||
* as key.
|
||||
*/
|
||||
@Override
|
||||
protected Map initializedGenericTagTestProperties() {
|
||||
Map result = super.initializedGenericTagTestProperties();
|
||||
protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
|
||||
Map<String, PropertyHolder> result = super.initializedGenericTagTestProperties();
|
||||
new PropertyHolder("accept", "someAccepted").addToMap(result);
|
||||
new PropertyHolder("size", "101").addToMap(result);
|
||||
new PropertyHolder("value", "", "").addToMap(result);
|
||||
|
||||
@@ -630,8 +630,8 @@ public class SubmitTest extends AbstractUITagTest {
|
||||
* as key.
|
||||
*/
|
||||
@Override
|
||||
protected Map initializedGenericTagTestProperties() {
|
||||
Map result = new HashMap();
|
||||
protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
|
||||
Map<String, PropertyHolder> result = new HashMap<>();
|
||||
new PropertyHolder("title", "someTitle").addToMap(result);
|
||||
new PropertyHolder("cssClass", "cssClass1", "class=\"cssClass1\"").addToMap(result);
|
||||
new PropertyHolder("cssStyle", "cssStyle1", "style=\"cssStyle1\"").addToMap(result);
|
||||
@@ -652,8 +652,6 @@ public class SubmitTest extends AbstractUITagTest {
|
||||
|
||||
/**
|
||||
* Test that by default submit tag body is HTML-escaped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSubmitWithBodyHTMLEscaped() throws Exception {
|
||||
TestAction testAction = (TestAction) action;
|
||||
@@ -670,6 +668,7 @@ public class SubmitTest extends AbstractUITagTest {
|
||||
StrutsBodyContent body = new StrutsBodyContent(null);
|
||||
body.print("should HTML escape: < & >");
|
||||
tag.setBodyContent(body);
|
||||
tag.setEscapeHtmlBody(true);
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
|
||||
@@ -678,8 +677,6 @@ public class SubmitTest extends AbstractUITagTest {
|
||||
|
||||
/**
|
||||
* Test that with htmlEscapeBody false submit tag body is not HTML-escaped.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSubmitWithBodyNotHTMLEscaped() throws Exception {
|
||||
TestAction testAction = (TestAction) action;
|
||||
|
||||
@@ -130,8 +130,8 @@ public class TextareaTest extends AbstractUITagTest {
|
||||
* as key.
|
||||
*/
|
||||
@Override
|
||||
protected Map initializedGenericTagTestProperties() {
|
||||
Map result = super.initializedGenericTagTestProperties();
|
||||
protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
|
||||
Map<String, PropertyHolder> result = super.initializedGenericTagTestProperties();
|
||||
new PropertyHolder("cols", "10").addToMap(result);
|
||||
new PropertyHolder("rows", "11").addToMap(result);
|
||||
new PropertyHolder("readonly", "true", "readonly=\"readonly\"").addToMap(result);
|
||||
|
||||
@@ -347,6 +347,7 @@ public class TextfieldTest extends AbstractUITagTest {
|
||||
tag.setValue("%{foo}");
|
||||
tag.setSize("10");
|
||||
tag.setDynamicAttribute(null, "anotherAttr", "%{foo}");
|
||||
tag.setDynamicAttribute(null, "secondAttr", "second_%{foo}");
|
||||
|
||||
tag.doStartTag();
|
||||
tag.doEndTag();
|
||||
@@ -373,6 +374,7 @@ public class TextfieldTest extends AbstractUITagTest {
|
||||
tag.setValue("%{foo}");
|
||||
tag.setSize("10");
|
||||
tag.setDynamicAttribute(null, "anotherAttr", "%{foo}");
|
||||
tag.setDynamicAttribute(null, "secondAttr", "second_%{foo}");
|
||||
|
||||
tag.doStartTag();
|
||||
setComponentTagClearTagState(tag, true); // Ensure component tag state clearing is set true (to match tag).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<tr>
|
||||
<td class="tdLabel"><label for="myname" class="label">mylabel:</label></td>
|
||||
<td class="tdInput"><input type="text" name="myname" size="10" value="%{1+1}" id="myname" anotherAttr="%{1+1}"/></td>
|
||||
<td class="tdInput"><input type="text" name="myname" size="10" value="%{1+1}" id="myname" anotherAttr="%{1+1}" secondAttr="second_%{1+1}"/></td>
|
||||
</tr>
|
||||
|
||||
+11
-1
@@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
@@ -18,4 +19,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<body>Type conversion meta data classes.</body>
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.6//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.6.dtd">
|
||||
<struts>
|
||||
<constant name="struts.ui.escapeHtmlBody" value="true"/>
|
||||
|
||||
<package name="default" extends="struts-default">
|
||||
</package>
|
||||
|
||||
</struts>
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-async-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -44,11 +44,6 @@
|
||||
<version>2.0.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
@@ -60,6 +55,17 @@
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- this library is excluded in the parent pom as it clashes with Easymock dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
The Java EE API modules listed below are all marked @Deprecated(forRemoval=true), because they are scheduled
|
||||
@@ -94,4 +100,4 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
+17
-4
@@ -20,17 +20,20 @@
|
||||
*/
|
||||
package org.apache.struts.beanvalidation.constraints.impl;
|
||||
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts.beanvalidation.constraints.FieldMatch;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
|
||||
public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(FieldMatchValidator.class);
|
||||
|
||||
private String firstFieldName;
|
||||
private String secondFieldName;
|
||||
|
||||
@@ -41,13 +44,23 @@ public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Obje
|
||||
|
||||
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||
try {
|
||||
final Object firstObj = PropertyUtils.getProperty(value, this.firstFieldName);
|
||||
final Object secondObj = PropertyUtils.getProperty(value, this.secondFieldName);
|
||||
final Object firstObj = readPropertyValue(value, this.firstFieldName);
|
||||
final Object secondObj = readPropertyValue(value, this.secondFieldName);
|
||||
return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
|
||||
} catch (final Exception ex) {
|
||||
LOG.info("Error while getting values from object", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Object readPropertyValue(Object bean, String propertyName) throws Exception {
|
||||
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
|
||||
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
|
||||
if (propertyName.equals(descriptor.getName())) {
|
||||
return descriptor.getReadMethod().invoke(bean);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.struts.beanvalidation.constraints.impl;
|
||||
|
||||
import org.apache.struts.beanvalidation.constraints.FieldMatch;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class FieldMatchValidatorTest {
|
||||
|
||||
@Test
|
||||
public void matchingFields() {
|
||||
// given
|
||||
FieldMatchValidator validator = new FieldMatchValidator();
|
||||
validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class));
|
||||
|
||||
ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class);
|
||||
|
||||
// when
|
||||
FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "12345678");
|
||||
|
||||
boolean valid = validator.isValid(bean, context);
|
||||
|
||||
// then
|
||||
assertTrue(valid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notMatchingFields() {
|
||||
// given
|
||||
FieldMatchValidator validator = new FieldMatchValidator();
|
||||
validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class));
|
||||
|
||||
ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class);
|
||||
|
||||
// when
|
||||
FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "87654321");
|
||||
|
||||
boolean valid = validator.isValid(bean, context);
|
||||
|
||||
// then
|
||||
assertFalse(valid);
|
||||
}
|
||||
|
||||
@FieldMatch(first = "password", second = "repeatPassword")
|
||||
public static class FieldMatchTestBean {
|
||||
String password;
|
||||
String repeatPassword;
|
||||
|
||||
public FieldMatchTestBean(String password, String repeatPassword) {
|
||||
this.password = password;
|
||||
this.repeatPassword = repeatPassword;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getRepeatPassword() {
|
||||
return repeatPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-cdi-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-config-browser-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-dwr-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-embeddedjsp-plugin</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-gxp-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jasperreports-plugin</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-javatemplates-plugin</artifactId>
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.LinkedHashMap;
|
||||
*/
|
||||
public class Attributes extends LinkedHashMap<String, String> {
|
||||
|
||||
private static final long serialVersionUID = 4103241472140545630L;
|
||||
private static final long serialVersionUID = 4103241472140545630L;
|
||||
|
||||
public Attributes add(String key, String value) {
|
||||
return add(key, value, true);
|
||||
@@ -74,15 +74,17 @@ public class Attributes extends LinkedHashMap<String, String> {
|
||||
* @return this
|
||||
*/
|
||||
public Attributes addIfTrue(String attrName, Object paramValue) {
|
||||
if (paramValue != null) {
|
||||
if ((paramValue instanceof Boolean && ((Boolean) paramValue).booleanValue()) ||
|
||||
(Boolean.valueOf(paramValue.toString()).booleanValue())) {
|
||||
put(attrName, attrName);
|
||||
}
|
||||
if (paramValue != null && isTrue(paramValue)) {
|
||||
put(attrName, attrName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean isTrue(Object paramValue) {
|
||||
return (paramValue instanceof Boolean && (Boolean) paramValue)
|
||||
|| (Boolean.parseBoolean(paramValue.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key/value pair to the attributes, if the value is null, it will be set as an empty string.
|
||||
* Value is html encoded.
|
||||
|
||||
+7
-6
@@ -22,14 +22,15 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
/**
|
||||
* Default implementation of TagHandlerFactory
|
||||
* Default implementation of TagHandlerFactory
|
||||
*/
|
||||
public class DefaultTagHandlerFactory implements TagHandlerFactory {
|
||||
private static final Logger LOG = LogManager.getLogger(DefaultTagHandlerFactory.class);
|
||||
|
||||
private Class tagHandlerClass;
|
||||
|
||||
public DefaultTagHandlerFactory(Class tagHandlerClass) {
|
||||
private static final Logger LOG = LogManager.getLogger(DefaultTagHandlerFactory.class);
|
||||
|
||||
private final Class<?> tagHandlerClass;
|
||||
|
||||
public DefaultTagHandlerFactory(Class<?> tagHandlerClass) {
|
||||
this.tagHandlerClass = tagHandlerClass;
|
||||
}
|
||||
|
||||
@@ -41,7 +42,7 @@ public class DefaultTagHandlerFactory implements TagHandlerFactory {
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to instantiate tag handler class [{}]", tagHandlerClass.getName(), e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -37,16 +37,20 @@ public class AnchorHandler extends AbstractTagHandler implements TagGenerator {
|
||||
Attributes attrs = new Attributes();
|
||||
|
||||
attrs.addIfExists("name", params.get("name"))
|
||||
.addIfExists("id", params.get("id"))
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"))
|
||||
.addIfExists("href", params.get("href"), false)
|
||||
.addIfExists("title", params.get("title"))
|
||||
.addIfExists("tabindex", params.get("tabindex"));
|
||||
.addIfExists("id", params.get("id"))
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"))
|
||||
.addIfExists("href", params.get("href"), false)
|
||||
.addIfTrue("disabled", params.get("disabled"))
|
||||
.addIfExists("title", params.get("title"))
|
||||
.addIfExists("tabindex", params.get("tabindex"));
|
||||
|
||||
start("a", attrs);
|
||||
String body = (String) params.get("body");
|
||||
if (StringUtils.isNotEmpty(body))
|
||||
characters(body, false);
|
||||
Boolean escapeHtmlBody = (Boolean) params.get("escapeHtmlBody");
|
||||
if (StringUtils.isNotEmpty(body)) {
|
||||
characters(body, escapeHtmlBody);
|
||||
}
|
||||
end("a");
|
||||
}
|
||||
}
|
||||
|
||||
+22
-17
@@ -18,13 +18,14 @@
|
||||
*/
|
||||
package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.views.java.Attributes;
|
||||
import org.apache.struts2.views.java.TagGenerator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.apache.struts2.views.java.Attributes;
|
||||
import org.apache.struts2.views.java.TagGenerator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CheckboxHandler extends AbstractTagHandler implements TagGenerator {
|
||||
public void generate() throws IOException {
|
||||
@@ -35,29 +36,33 @@ public class CheckboxHandler extends AbstractTagHandler implements TagGenerator
|
||||
String id = (String) params.get("id");
|
||||
String name = (String) params.get("name");
|
||||
Object disabled = params.get("disabled");
|
||||
boolean submitUnchecked = Boolean.parseBoolean(Objects.toString(params.get("submitUnchecked"), "false"));
|
||||
|
||||
attrs.add("type", "checkbox")
|
||||
.add("name", name)
|
||||
.add("value", fieldValue)
|
||||
.addIfTrue("checked", params.get("nameValue"))
|
||||
.addIfTrue("readonly", params.get("readonly"))
|
||||
.addIfTrue("disabled", disabled)
|
||||
.addIfExists("tabindex", params.get("tabindex"))
|
||||
.addIfExists("id", id)
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"))
|
||||
.addIfExists("title", params.get("title"));
|
||||
.add("name", name)
|
||||
.add("value", fieldValue)
|
||||
.addIfTrue("checked", params.get("nameValue"))
|
||||
.addIfTrue("readonly", params.get("readonly"))
|
||||
.addIfTrue("disabled", disabled)
|
||||
.addIfExists("tabindex", params.get("tabindex"))
|
||||
.addIfExists("id", id)
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"))
|
||||
.addIfExists("title", params.get("title"));
|
||||
start("input", attrs);
|
||||
end("input");
|
||||
|
||||
//hidden input
|
||||
attrs = new Attributes();
|
||||
attrs.add("type", "hidden")
|
||||
if (submitUnchecked) {
|
||||
//hidden input
|
||||
attrs = new Attributes();
|
||||
|
||||
attrs.add("type", "hidden")
|
||||
.add("id", "__checkbox_" + StringUtils.defaultString(StringEscapeUtils.escapeHtml4(id)))
|
||||
.add("name", "__checkbox_" + StringUtils.defaultString(StringEscapeUtils.escapeHtml4(name)))
|
||||
.add("value", "__checkbox_" + StringUtils.defaultString(StringEscapeUtils.escapeHtml4(fieldValue)))
|
||||
.addIfTrue("disabled", disabled);
|
||||
start("input", attrs);
|
||||
end("input");
|
||||
start("input", attrs);
|
||||
end("input");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -40,9 +40,13 @@ public class LinkHandler extends AbstractTagHandler implements TagGenerator {
|
||||
.addIfExists("referrerpolicy", params.get("referrerpolicy"))
|
||||
.addIfExists("type", params.get("type"))
|
||||
.addIfExists("as", params.get("as"))
|
||||
.addIfExists("disabled", params.get("disabled"))
|
||||
.addIfExists("title", params.get("title"));
|
||||
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#attr-disabled
|
||||
if ("stylesheet".equals(params.get("rel"))) {
|
||||
attrs.addIfTrue("disabled", params.get("disabled"));
|
||||
}
|
||||
|
||||
start("link", attrs);
|
||||
end("link");
|
||||
}
|
||||
|
||||
+9
-8
@@ -18,9 +18,9 @@
|
||||
*/
|
||||
package org.apache.struts2.views.java.simple;
|
||||
|
||||
import org.apache.struts2.views.java.TagGenerator;
|
||||
import org.apache.struts2.views.java.Attributes;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.struts2.views.java.Attributes;
|
||||
import org.apache.struts2.views.java.TagGenerator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
@@ -34,12 +34,13 @@ public class ResetHandler extends AbstractTagHandler implements TagGenerator {
|
||||
boolean isButton = "button".equals(params.get("type"));
|
||||
|
||||
attrs.addDefaultToEmpty("name", params.get("name"))
|
||||
.add("type", "reset")
|
||||
.addIfExists("value", params.get("nameValue"))
|
||||
.addIfExists("tabindex", params.get("tabindex"))
|
||||
.addIfExists("id", params.get("id"))
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"));
|
||||
.add("type", "reset")
|
||||
.addIfExists("value", params.get("nameValue"))
|
||||
.addIfTrue("disabled", params.get("disabled"))
|
||||
.addIfExists("tabindex", params.get("tabindex"))
|
||||
.addIfExists("id", params.get("id"))
|
||||
.addIfExists("class", params.get("cssClass"))
|
||||
.addIfExists("style", params.get("cssStyle"));
|
||||
|
||||
if (!isButton)
|
||||
attrs.addIfExists("title", params.get("title"));
|
||||
|
||||
+3
-3
@@ -65,13 +65,13 @@ public class SimpleTheme extends DefaultTheme {
|
||||
setName("simple");
|
||||
}
|
||||
|
||||
private class FactoryList extends ArrayList<TagHandlerFactory> {
|
||||
private static class FactoryList extends ArrayList<TagHandlerFactory> {
|
||||
|
||||
private static final long serialVersionUID = -1551895041394434032L;
|
||||
|
||||
public FactoryList(Class... classes) {
|
||||
public FactoryList(Class<?>... classes) {
|
||||
super();
|
||||
for (Class cls : classes) {
|
||||
for (Class<?> cls : classes) {
|
||||
add(new DefaultTagHandlerFactory(cls));
|
||||
}
|
||||
add(new DefaultTagHandlerFactory(XHTMLTagSerializer.class));
|
||||
|
||||
+9
-5
@@ -73,6 +73,7 @@ public class SubmitHandler extends AbstractTagHandler implements TagGenerator {
|
||||
public void generate() throws IOException {
|
||||
Map<String, Object> params = context.getParameters();
|
||||
String body = (String) params.get("body");
|
||||
Boolean escapeHtmlBody = (Boolean) params.get("escapeHtmlBody");
|
||||
|
||||
String type = StringUtils.defaultString((String) params.get("type"), "input");
|
||||
if ("button".equals(type)) {
|
||||
@@ -81,16 +82,19 @@ public class SubmitHandler extends AbstractTagHandler implements TagGenerator {
|
||||
characters(body, false);
|
||||
else if (params.containsKey("label")) {
|
||||
String label = (String) params.get("label");
|
||||
if (StringUtils.isNotEmpty(label))
|
||||
characters(label, false);
|
||||
if (StringUtils.isNotEmpty(label)) {
|
||||
characters(label, escapeHtmlBody);
|
||||
}
|
||||
}
|
||||
end("button");
|
||||
} else if ("image".equals(type)) {
|
||||
if (StringUtils.isNotEmpty(body))
|
||||
characters(body, false);
|
||||
if (StringUtils.isNotEmpty(body)) {
|
||||
characters(body, escapeHtmlBody);
|
||||
}
|
||||
end("input");
|
||||
} else
|
||||
} else {
|
||||
end("input");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-1
@@ -43,7 +43,7 @@ public class AnchorTest extends AbstractTest {
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<a name='name_' id='id_' class='class' style='style' href='http://sometest.com?ab=10' title='title' tabindex='1'></a>");
|
||||
String expected = s("<a name='name_' id='id_' class='class' style='style' href='http://sometest.com?ab=10' disabled='disabled' title='title' tabindex='1'></a>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,42 @@ public class AnchorTest extends AbstractTest {
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
public void testEnableEscapeBody() {
|
||||
tag.setName("name_");
|
||||
tag.setHref("http://sometest.com?ab=10");
|
||||
tag.setEscapeHtmlBody(true);
|
||||
tag.evaluateParams();
|
||||
|
||||
map.putAll(tag.getParameters());
|
||||
context.getParameters().put("body", s("<i class='i-image'/>"));
|
||||
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<a name='name_' id='name_' href='http://sometest.com?ab=10'><i class="i-image"/></a>");
|
||||
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
public void testDefaultDisabledEscapeBody() {
|
||||
tag.setName("name_");
|
||||
tag.setHref("http://sometest.com?ab=10");
|
||||
//tag.setEscapeHtmlBody(true);
|
||||
tag.evaluateParams();
|
||||
|
||||
map.putAll(tag.getParameters());
|
||||
context.getParameters().put("body", s("<i class='i-image'/>"));
|
||||
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<a name='name_' id='name_' href='http://sometest.com?ab=10'><i class='i-image'/></a>");
|
||||
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
+22
-4
@@ -29,7 +29,7 @@ public class CheckboxTest extends AbstractCommonAttributesTest {
|
||||
|
||||
public void testRenderCheckbox() {
|
||||
tag.setName("name_");
|
||||
tag.setDisabled("true");
|
||||
tag.setDisabled("false");
|
||||
tag.setTabindex("1");
|
||||
tag.setId("id_");
|
||||
tag.setCssClass("class");
|
||||
@@ -41,20 +41,38 @@ public class CheckboxTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input type='checkbox' name='name_' value='xyz' tabindex='1' id='id_' class='class' style='style' title='title'></input><input type='hidden' id='__checkbox_id_' name='__checkbox_name_' value='__checkbox_xyz'></input>");
|
||||
String expected = s("<input type='checkbox' name='name_' value='xyz' tabindex='1' id='id_' class='class' style='style' title='title'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
public void testRenderUncheckCheckbox() {
|
||||
tag.setName("name_");
|
||||
tag.setDisabled("true");
|
||||
tag.setTabindex("1");
|
||||
tag.setId("id_");
|
||||
tag.setCssClass("class");
|
||||
tag.setCssStyle("style");
|
||||
tag.setTitle("title");
|
||||
tag.setFieldValue("xyz");
|
||||
tag.setSubmitUnchecked("true");
|
||||
|
||||
tag.evaluateParams();
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input type='checkbox' name='name_' value='xyz' disabled='disabled' tabindex='1' id='id_' class='class' style='style' title='title'></input><input type='hidden' id='__checkbox_id_' name='__checkbox_name_' value='__checkbox_xyz' disabled='disabled'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
public void testRenderCheckboxWithNameValue() {
|
||||
tag.setName("name_");
|
||||
tag.setValue("%{someValue}");
|
||||
tag.setDisabled("true");
|
||||
|
||||
tag.evaluateParams();
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input type='checkbox' name='name_' value='true' checked='checked' id='name_'></input><input type='hidden' id='__checkbox_name_' name='__checkbox_name_' value='__checkbox_true'></input>");
|
||||
String expected = s("<input type='checkbox' name='name_' value='true' checked='checked' id='name_'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public class FileTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input name='name' type='file' size='10' value='val1' accept='accept_' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
String expected = s("<input name='name' type='file' size='10' value='val1' disabled='disabled' accept='accept_' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class HiddenTest extends AbstractTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input name='name' type='hidden' value='val1' id='id1' class='class1' style='style1'></input>");
|
||||
String expected = s("<input name='name' type='hidden' value='val1' disabled='disabled' id='id1' class='class1' style='style1'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+48
-15
@@ -31,7 +31,7 @@ public class LinkTest extends AbstractTest{
|
||||
|
||||
private static final String NONCE_VAL = "r4andom";
|
||||
|
||||
public void testRenderScriptTag() {
|
||||
public void testRenderLinkTag() {
|
||||
tag.setHref("testhref");
|
||||
tag.setHreflang("test");
|
||||
tag.setRel("module");
|
||||
@@ -41,27 +41,60 @@ public class LinkTest extends AbstractTest{
|
||||
tag.setCrossorigin("same-origin");
|
||||
tag.setType("anonymous");
|
||||
tag.setAs("test");
|
||||
tag.setDisabled("disabled_");
|
||||
tag.setDisabled("true");
|
||||
tag.setTitle("test");
|
||||
|
||||
tag.evaluateParams();
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String s = writer.getBuffer().toString();
|
||||
String output = writer.getBuffer().toString();
|
||||
|
||||
assertTrue("Incorrect href attribute for link tag", s.contains("href=\"testhref\""));
|
||||
assertTrue("Incorrect hreflang attribute for link tag", s.contains("hreflang=\"test\""));
|
||||
assertTrue("Incorrect rel attribute for link tag", s.contains("rel=\"module\""));
|
||||
assertTrue("Incorrect media attribute for link tag", s.contains("media=\"foo\""));
|
||||
assertTrue("Incorrect referrerpolicy attribute for link tag", s.contains("referrerpolicy=\"test\""));
|
||||
assertTrue("Incorrect sizes attribute for link tag", s.contains("sizes=\"foo\""));
|
||||
assertTrue("Incorrect crossorigin attribute for link tag", s.contains("crossorigin=\"same-origin\""));
|
||||
assertTrue("Incorrect type attribute for link tag", s.contains("type=\"anonymous\""));
|
||||
assertTrue("Incorrect as attribute for link tag", s.contains("as=\"test\""));
|
||||
assertTrue("Non-existent disabled attribute for link tag", s.contains("disabled=\"disabled_\""));
|
||||
assertTrue("Incorrect title attribute for link tag", s.contains("title=\"test\""));
|
||||
assertTrue("Incorrect nonce attribute for link tag", s.contains("nonce=\"" + NONCE_VAL+"\""));
|
||||
assertTrue("Incorrect href attribute for link tag", output.contains(s("href='testhref'")));
|
||||
assertTrue("Incorrect hreflang attribute for link tag", output.contains(s("hreflang='test'")));
|
||||
assertTrue("Incorrect rel attribute for link tag", output.contains(s("rel='module'")));
|
||||
assertTrue("Incorrect media attribute for link tag", output.contains(s("media='foo'")));
|
||||
assertTrue("Incorrect referrerpolicy attribute for link tag", output.contains(s("referrerpolicy='test'")));
|
||||
assertTrue("Incorrect sizes attribute for link tag", output.contains(s("sizes='foo'")));
|
||||
assertTrue("Incorrect crossorigin attribute for link tag", output.contains(s("crossorigin='same-origin'")));
|
||||
assertTrue("Incorrect type attribute for link tag", output.contains(s("type='anonymous'")));
|
||||
assertTrue("Incorrect as attribute for link tag", output.contains(s("as='test'")));
|
||||
assertFalse("Non-existent disabled attribute for link tag", output.contains(s("disabled='disabled'")));
|
||||
assertTrue("Incorrect title attribute for link tag", output.contains(s("title='test'")));
|
||||
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL+"'")));
|
||||
}
|
||||
|
||||
public void testRenderLinkTagAsStylesheet() {
|
||||
tag.setHref("testhref");
|
||||
tag.setHreflang("test");
|
||||
tag.setRel("stylesheet");
|
||||
tag.setMedia("foo");
|
||||
tag.setReferrerpolicy("test");
|
||||
tag.setSizes("foo");
|
||||
tag.setCrossorigin("same-origin");
|
||||
tag.setType("anonymous");
|
||||
tag.setAs("test");
|
||||
tag.setDisabled("true");
|
||||
tag.setTitle("test");
|
||||
|
||||
tag.evaluateParams();
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
|
||||
assertTrue("Incorrect href attribute for link tag", output.contains(s("href='testhref'")));
|
||||
assertTrue("Incorrect hreflang attribute for link tag", output.contains(s("hreflang='test'")));
|
||||
assertTrue("Incorrect rel attribute for link tag", output.contains(s("rel='stylesheet'")));
|
||||
assertTrue("Incorrect media attribute for link tag", output.contains(s("media='foo'")));
|
||||
assertTrue("Incorrect referrerpolicy attribute for link tag", output.contains(s("referrerpolicy='test'")));
|
||||
assertTrue("Incorrect sizes attribute for link tag", output.contains(s("sizes='foo'")));
|
||||
assertTrue("Incorrect crossorigin attribute for link tag", output.contains(s("crossorigin='same-origin'")));
|
||||
assertTrue("Incorrect type attribute for link tag", output.contains(s("type='anonymous'")));
|
||||
assertTrue("Incorrect as attribute for link tag", output.contains(s("as='test'")));
|
||||
assertTrue("Incorrect disabled attribute for link tag", output.contains(s("disabled='disabled'")));
|
||||
assertTrue("Incorrect title attribute for link tag", output.contains(s("title='test'")));
|
||||
assertTrue("Incorrect nonce attribute for link tag", output.contains(s("nonce='" + NONCE_VAL+"'")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UIBean getUIBean() throws Exception {
|
||||
return tag;
|
||||
|
||||
+3
-5
@@ -24,11 +24,10 @@ import org.apache.struts2.components.Password;
|
||||
import org.apache.struts2.components.UIBean;
|
||||
|
||||
public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
|
||||
private Password tag;
|
||||
private boolean showPassword;
|
||||
|
||||
public void testRenderPassword() throws Exception {
|
||||
this.showPassword = false;
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
|
||||
@@ -47,12 +46,11 @@ public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input name='name' type='password' size='10' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
String expected = s("<input name='name' type='password' size='10' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
public void testRenderPasswordShowIt() throws Exception {
|
||||
this.showPassword = true;
|
||||
super.setUp();
|
||||
this.tag = new Password(stack, request, response);
|
||||
|
||||
@@ -71,7 +69,7 @@ public class PasswordTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input value='val1' name='name' type='password' size='10' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
String expected = s("<input value='val1' name='name' type='password' size='10' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class SelectTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<select name='name_' size='10' tabindex='1' id='id_' class='class' style='style' title='title'></select>");
|
||||
String expected = s("<select name='name_' size='10' disabled='disabled' tabindex='1' id='id_' class='class' style='style' title='title'></select>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -47,7 +47,7 @@ public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<button name='name' type='submit' value='val1' tabindex='1' id='id1' class='class1' style='style1'><span>hey hey hey, here I go now</span></button>");
|
||||
String expected = s("<button name='name' type='submit' value='val1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1'><span>hey hey hey, here I go now</span></button>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<button name='name' type='submit' value='val1' tabindex='1' id='id1' class='class1' style='style1'>Just as soon as I belong, than its time I disappear</button>");
|
||||
String expected = s("<button name='name' type='submit' value='val1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1'>Just as soon as I belong, than its time I disappear</button>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input name='name' type='submit' value='val1' tabindex='1' id='id1' class='class1' style='style1'></input>");
|
||||
String expected = s("<input name='name' type='submit' value='val1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public class SubmitTest extends AbstractCommonAttributesTest {
|
||||
theme.renderTag(getTagName(), context);
|
||||
theme.renderTag(getTagName() + "-close", context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input name='name' type='submit' value='val1' tabindex='1' id='id1' class='class1' style='style1'></input>");
|
||||
String expected = s("<input name='name' type='submit' value='val1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ public class TextAreaTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<textarea name='name' cols='2' rows='1' tabindex='1' id='id1' class='class1' style='style1' title='title'>val1</textarea>");
|
||||
String expected = s("<textarea name='name' cols='2' rows='1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1' title='title'>val1</textarea>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class TextAreaTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<textarea name='' cols='' rows='' tabindex='1' id='id1' class='class1' style='style1' title='title'>val1</textarea>");
|
||||
String expected = s("<textarea name='' cols='' rows='' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1' title='title'>val1</textarea>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class TextFieldTest extends AbstractCommonAttributesTest {
|
||||
map.putAll(tag.getParameters());
|
||||
theme.renderTag(getTagName(), context);
|
||||
String output = writer.getBuffer().toString();
|
||||
String expected = s("<input type='text' name='name' size='10' maxlength='11' value='val1' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
String expected = s("<input type='text' name='name' size='10' maxlength='11' value='val1' disabled='disabled' tabindex='1' id='id1' class='class1' style='style1' title='title'></input>");
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jfreechart-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-json-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.6-SNAPSHOT</version>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-junit-plugin</artifactId>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user