Author: centic
Date: Mon May 26 20:03:08 2014
New Revision: 1597637

URL: http://svn.apache.org/r1597637
Log:
Fix for 56563 - Multithreading bug when reading 2 similar files

Added:
    poi/trunk/test-data/spreadsheet/56563a.xls
    poi/trunk/test-data/spreadsheet/56563b.xls
Modified:
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java?rev=1597637&r1=1597636&r2=1597637&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java 
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFCellStyle.java Mon May 
26 20:03:08 2014
@@ -101,30 +101,36 @@ public final class HSSFCellStyle impleme
         return _format.getFormatIndex();
     }
 
+    // we keep the cached data in ThreadLocal members in order to
+    // avoid multi-threading issues when different workbooks are accessed in 
+    // multiple threads at the same time
+    private static ThreadLocal<Short> lastDateFormat = new 
ThreadLocal<Short>() {
+        protected Short initialValue() {
+            return Short.MIN_VALUE;
+        }
+    };
+    private static ThreadLocal<List<FormatRecord>> lastFormats = new 
ThreadLocal<List<FormatRecord>>();
+    private static ThreadLocal<String> getDataFormatStringCache = new 
ThreadLocal<String>();
+
     /**
      * Get the contents of the format string, by looking up
      *  the DataFormat against the bound workbook
      * @see org.apache.poi.hssf.usermodel.HSSFDataFormat
      * @return the format string or "General" if not found
      */
-     
-    private static short lastDateFormat = Short.MIN_VALUE;
-    private static List<FormatRecord> lastFormats = null;
-    private static String getDataFormatStringCache = null;
-    
     public String getDataFormatString() {
-        if (getDataFormatStringCache != null) {
-            if (lastDateFormat == getDataFormat() && 
_workbook.getFormats().equals(lastFormats)) {
-                return getDataFormatStringCache;
+        if (getDataFormatStringCache.get() != null) {
+            if (lastDateFormat.get() == getDataFormat() && 
_workbook.getFormats().equals(lastFormats.get())) {
+                return getDataFormatStringCache.get();
             }
         }
 
-        lastFormats = _workbook.getFormats();
-        lastDateFormat = getDataFormat();
+        lastFormats.set(_workbook.getFormats());
+        lastDateFormat.set(getDataFormat());
 
-        getDataFormatStringCache = getDataFormatString(_workbook);
+        getDataFormatStringCache.set(getDataFormatString(_workbook));
 
-        return getDataFormatStringCache;
+        return getDataFormatStringCache.get();
     }
 
     /**
@@ -862,9 +868,9 @@ public final class HSSFCellStyle impleme
        // Handle matching things if we cross workbooks
        if(_workbook != source._workbook) {
 
-            lastDateFormat = Short.MIN_VALUE;
-            lastFormats = null;
-            getDataFormatStringCache = null;
+            lastDateFormat.set(Short.MIN_VALUE);
+            lastFormats.set(null);
+            getDataFormatStringCache.set(null);
           
                        // Then we need to clone the format string,
                        //  and update the format record for this

Modified: 
poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java?rev=1597637&r1=1597636&r2=1597637&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java 
(original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java 
Mon May 26 20:03:08 2014
@@ -26,7 +26,11 @@ import java.util.Date;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.util.TempFile;
 
 /**
@@ -405,4 +409,62 @@ public final class TestCellStyle extends
        assertEquals(false, r.getCell(0).getCellStyle().getShrinkToFit());
        assertEquals(true,  r.getCell(1).getCellStyle().getShrinkToFit());
     }
+    
+    
+    
+    private static class CellFormatBugExample extends Thread {
+        private String fileName;
+        private Throwable exception = null;
+
+        public CellFormatBugExample(String fileName) {
+            this.fileName = fileName;
+        }
+
+        @Override
+        public void run() {
+            try {
+                for(int i = 0;i< 10;i++) {
+                    Workbook wb = 
HSSFTestDataSamples.openSampleWorkbook(fileName);
+                    Sheet sheet = wb.getSheetAt(0);
+        
+                    for (Row row : sheet) {
+                        for (Integer idxCell = 0; idxCell < 
row.getLastCellNum(); idxCell++) {
+        
+                            Cell cell = row.getCell(idxCell);
+                            cell.getCellStyle().getDataFormatString();
+                            if (cell.getCellType() == 
HSSFCell.CELL_TYPE_NUMERIC) {
+                                boolean isDate = 
HSSFDateUtil.isCellDateFormatted(cell);
+                                if (idxCell > 0 && isDate) {
+                                    fail("cell " + idxCell + " is not a date: 
" + idxCell.toString());
+                                }
+                            }
+                        }
+                    }
+                }
+            } catch (Throwable e) {
+                exception = e;
+            }
+        }
+
+        public Throwable getException() {
+            return exception;
+        }
+    };
+    
+    public void test56563() throws Throwable {
+        CellFormatBugExample threadA = new CellFormatBugExample("56563a.xls");
+        threadA.start();
+        CellFormatBugExample threadB = new CellFormatBugExample("56563b.xls");
+        threadB.start();
+        
+        threadA.join();
+        threadB.join();
+        
+        if(threadA.getException() != null) {
+            throw threadA.getException();
+        }
+        if(threadB.getException() != null) {
+            throw threadB.getException();
+        }
+    }
 }

Added: poi/trunk/test-data/spreadsheet/56563a.xls
URL: 
http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/56563a.xls?rev=1597637&view=auto
==============================================================================
Files poi/trunk/test-data/spreadsheet/56563a.xls (added) and 
poi/trunk/test-data/spreadsheet/56563a.xls Mon May 26 20:03:08 2014 differ

Added: poi/trunk/test-data/spreadsheet/56563b.xls
URL: 
http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/56563b.xls?rev=1597637&view=auto
==============================================================================
Files poi/trunk/test-data/spreadsheet/56563b.xls (added) and 
poi/trunk/test-data/spreadsheet/56563b.xls Mon May 26 20:03:08 2014 differ



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@poi.apache.org
For additional commands, e-mail: commits-h...@poi.apache.org

Reply via email to