mirror of
https://github.com/apache/struts.git
synced 2026-08-05 14:47:09 +00:00
Merge pull request #529 from apache/WW-5016-uses-proper-format
[WW-5016] Adds support for LocalDate and adjusts tests to use the new Java 8 API
This commit is contained in:
+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;
|
||||
@@ -218,6 +221,9 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
, Scope.SINGLETON)
|
||||
|
||||
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
|
||||
|
||||
.factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON)
|
||||
.factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON)
|
||||
;
|
||||
|
||||
props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString());
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.struts2;
|
||||
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.dispatcher.mapper.CompositeActionMapper;
|
||||
|
||||
/**
|
||||
@@ -384,4 +385,6 @@ public final class StrutsConstants {
|
||||
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";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -243,4 +243,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"/>
|
||||
|
||||
<package name="struts-default" abstract="true">
|
||||
<result-types>
|
||||
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user