Author: gwoolsey
Date: Sat Mar 30 19:33:02 2019
New Revision: 1856647
URL: http://svn.apache.org/viewvc?rev=1856647&view=rev
Log:
#63291 CellFormat global cache isn't thread-safe
move date format synchronization down to where the problem instance is held.
Added:
poi/trunk/.settings/com.vaadin.designer.prefs
Modified:
poi/trunk/src/java/org/apache/poi/ss/format/CellDateFormatter.java
poi/trunk/src/java/org/apache/poi/ss/format/CellFormatter.java
poi/trunk/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
poi/trunk/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
Added: poi/trunk/.settings/com.vaadin.designer.prefs
URL:
http://svn.apache.org/viewvc/poi/trunk/.settings/com.vaadin.designer.prefs?rev=1856647&view=auto
==============================================================================
--- poi/trunk/.settings/com.vaadin.designer.prefs (added)
+++ poi/trunk/.settings/com.vaadin.designer.prefs Sat Mar 30 19:33:02 2019
@@ -0,0 +1,2 @@
+applicationTheme=Project structure is not supported.
+eclipse.preferences.version=1
Modified: poi/trunk/src/java/org/apache/poi/ss/format/CellDateFormatter.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/format/CellDateFormatter.java?rev=1856647&r1=1856646&r2=1856647&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/format/CellDateFormatter.java
(original)
+++ poi/trunk/src/java/org/apache/poi/ss/format/CellDateFormatter.java Sat Mar
30 19:33:02 2019
@@ -163,7 +163,7 @@ public class CellDateFormatter extends C
}
/** {@inheritDoc} */
- public void formatValue(StringBuffer toAppendTo, Object value) {
+ public synchronized void formatValue(StringBuffer toAppendTo, Object
value) {
if (value == null)
value = 0.0;
if (value instanceof Number) {
Modified: poi/trunk/src/java/org/apache/poi/ss/format/CellFormatter.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/format/CellFormatter.java?rev=1856647&r1=1856646&r2=1856647&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/format/CellFormatter.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/format/CellFormatter.java Sat Mar 30
19:33:02 2019
@@ -57,6 +57,11 @@ public abstract class CellFormatter {
/**
* Format a value according the format string.
+ * <p/>
+ * NOTE: this method must be thread safe! In particular, if it uses a
+ * Format instance that is not thread safe, i.e. DateFormat, this method
+ * must be synchronized, either on the method, if the format is a final
+ * property, or on the format instance itself.
*
* @param toAppendTo The buffer to append to.
* @param value The value to format.
@@ -65,6 +70,11 @@ public abstract class CellFormatter {
/**
* Format a value according to the type, in the most basic way.
+ * <p/>
+ * NOTE: this method must be thread safe! In particular, if it uses a
+ * Format instance that is not thread safe, i.e. DateFormat, this method
+ * must be synchronized, either on the method, if the format is a final
+ * property, or on the format instance itself.
*
* @param toAppendTo The buffer to append to.
* @param value The value to format.
Modified: poi/trunk/src/java/org/apache/poi/ss/usermodel/DataFormatter.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/usermodel/DataFormatter.java?rev=1856647&r1=1856646&r2=1856647&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/usermodel/DataFormatter.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/usermodel/DataFormatter.java Sat Mar
30 19:33:02 2019
@@ -309,7 +309,7 @@ public class DataFormatter implements Ob
return getFormat(cell.getNumericCellValue(), formatIndex, formatStr);
}
- private synchronized Format getFormat(double cellValue, int formatIndex,
String formatStrIn) {
+ private Format getFormat(double cellValue, int formatIndex, String
formatStrIn) {
localeChangedObservable.checkForLocaleChange();
// Might be better to separate out the n p and z formats, falling back
to p when n and z are not set.
Modified:
poi/trunk/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
URL:
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java?rev=1856647&r1=1856646&r2=1856647&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
(original)
+++ poi/trunk/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
Sat Mar 30 19:33:02 2019
@@ -939,9 +939,10 @@ public class TestDataFormatter {
@Test
public void testConcurrentCellFormat() throws Exception {
- DataFormatter formatter = new DataFormatter();
- doFormatTestSequential(formatter);
- doFormatTestConcurrent(formatter);
+ DataFormatter formatter1 = new DataFormatter();
+ DataFormatter formatter2 = new DataFormatter();
+ doFormatTestSequential(formatter1);
+ doFormatTestConcurrent(formatter1, formatter2);
}
private void doFormatTestSequential(DataFormatter formatter) {
@@ -951,14 +952,21 @@ public class TestDataFormatter {
}
}
- private void doFormatTestConcurrent(DataFormatter formatter) throws
Exception {
+ private void doFormatTestConcurrent(DataFormatter formatter1,
DataFormatter formatter2) throws Exception {
ArrayList<CompletableFuture<Boolean>> futures = new ArrayList<>();
for (int i = 0; i < 1_000; i++) {
final int iteration = i;
CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(
() -> {
- boolean r1 = doFormatTest(formatter,
43551.50990171296, "3/27/19 12:14:15 PM", iteration);
- boolean r2 = doFormatTest(formatter,
36104.424780092595, "11/5/98 10:11:41 AM", iteration);
+ boolean r1 = doFormatTest(formatter1,
43551.50990171296, "3/27/19 12:14:15 PM", iteration);
+ boolean r2 = doFormatTest(formatter1,
36104.424780092595, "11/5/98 10:11:41 AM", iteration);
+ return r1 && r2;
+ });
+ futures.add(future);
+ future = CompletableFuture.supplyAsync(
+ () -> {
+ boolean r1 = doFormatTest(formatter2,
43551.50990171296, "3/27/19 12:14:15 PM", iteration);
+ boolean r2 = doFormatTest(formatter2,
36104.424780092595, "11/5/98 10:11:41 AM", iteration);
return r1 && r2;
});
futures.add(future);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]