Repository: metamodel Updated Branches: refs/heads/master 325656dd5 -> 9f81506fe
METAMODEL-1205: Add JDK9+ support for Excel module with POI 4.0.0 Closes #194 Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/9f81506f Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/9f81506f Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/9f81506f Branch: refs/heads/master Commit: 9f81506feeb3901f51beacea7b72540eac211861 Parents: 325656d Author: Kasper Sørensen <[email protected]> Authored: Mon Nov 26 08:12:55 2018 -0800 Committer: Kasper Sørensen <[email protected]> Committed: Mon Nov 26 08:12:55 2018 -0800 ---------------------------------------------------------------------- .../insert/AbstractInsertBuilderTest.java | 104 +++++++++---------- excel/pom.xml | 2 +- .../excel/DefaultSpreadsheetReaderDelegate.java | 4 +- .../metamodel/excel/ExcelUpdateCallback.java | 2 +- .../org/apache/metamodel/excel/ExcelUtils.java | 53 ++++------ .../metamodel/excel/XlsxSheetToRowsHandler.java | 39 ++++--- 6 files changed, 100 insertions(+), 104 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/core/src/test/java/org/apache/metamodel/insert/AbstractInsertBuilderTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/insert/AbstractInsertBuilderTest.java b/core/src/test/java/org/apache/metamodel/insert/AbstractInsertBuilderTest.java index cf22c04..ec5b2b1 100644 --- a/core/src/test/java/org/apache/metamodel/insert/AbstractInsertBuilderTest.java +++ b/core/src/test/java/org/apache/metamodel/insert/AbstractInsertBuilderTest.java @@ -31,62 +31,62 @@ import org.apache.metamodel.util.MutableRef; public class AbstractInsertBuilderTest extends TestCase { - public void testInsertValues() throws Exception { - final MutableRef<Boolean> executed = new MutableRef<Boolean>(false); - final MutableTable table = new MutableTable("foo"); - table.addColumn(new MutableColumn("foo")); - table.addColumn(new MutableColumn("bar")); - table.addColumn(new MutableColumn("baz")); - RowInsertionBuilder insertBuilder = new AbstractRowInsertionBuilder<UpdateCallback>( - null, table) { - @Override - public void execute() throws MetaModelException { - assertEquals("[1, 2, 3]", Arrays.toString(getValues())); - executed.set(true); - } - }; + public void testInsertValues() throws Exception { + final MutableRef<Boolean> executed = new MutableRef<Boolean>(false); + final MutableTable table = new MutableTable("foo"); + table.addColumn(new MutableColumn("foo")); + table.addColumn(new MutableColumn("bar")); + table.addColumn(new MutableColumn("baz")); + RowInsertionBuilder insertBuilder = new AbstractRowInsertionBuilder<UpdateCallback>(null, table) { + @Override + public void execute() throws MetaModelException { + assertEquals("[1, 2, 3]", Arrays.toString(getValues())); + executed.set(true); + } + }; - assertFalse(executed.get().booleanValue()); + assertFalse(executed.get().booleanValue()); - insertBuilder.value(0, 1).value("bar", 2) - .value(table.getColumnByName("baz"), 3).execute(); + insertBuilder.value(0, 1).value("bar", 2).value(table.getColumnByName("baz"), 3).execute(); - assertTrue(executed.get()); - - assertEquals("Row[values=[1, 2, 3]]", insertBuilder.toRow().toString()); - - } + assertTrue(executed.get()); - public void testIllegalArguments() throws Exception { - final MutableTable table = new MutableTable("foo"); - table.addColumn(new MutableColumn("foo")); - RowInsertionBuilder insertBuilder = new AbstractRowInsertionBuilder<UpdateCallback>( - null, table) { - @Override - public void execute() throws MetaModelException { - } - }; - - try { - insertBuilder.value((Column)null, "foo"); - fail("Exception expected"); - } catch (IllegalArgumentException e) { - assertEquals("Column cannot be null", e.getMessage()); - } + assertEquals("Row[values=[1, 2, 3]]", insertBuilder.toRow().toString()); - try { - insertBuilder.value("hmm", "foo"); - fail("Exception expected"); - } catch (IllegalArgumentException e) { - assertEquals("No such column in table: hmm, available columns are: [Column[name=foo,columnNumber=0,type=null,nullable=null,nativeType=null,columnSize=null]]", e.getMessage()); - } + } - try { - insertBuilder.value(4, "foo"); - fail("Exception expected"); - } catch (ArrayIndexOutOfBoundsException e) { - assertTrue("4".equals(e.getMessage()) - || "Array index out of range: 4".equals(e.getMessage())); - } - } + public void testIllegalArguments() throws Exception { + final MutableTable table = new MutableTable("foo"); + table.addColumn(new MutableColumn("foo")); + RowInsertionBuilder insertBuilder = new AbstractRowInsertionBuilder<UpdateCallback>(null, table) { + @Override + public void execute() throws MetaModelException { + } + }; + + try { + insertBuilder.value((Column) null, "foo"); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertEquals("Column cannot be null", e.getMessage()); + } + + try { + insertBuilder.value("hmm", "foo"); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + assertEquals( + "No such column in table: hmm, available columns are: [Column[name=foo,columnNumber=0,type=null,nullable=null,nativeType=null,columnSize=null]]", + e.getMessage()); + } + + try { + insertBuilder.value(4, "foo"); + fail("Exception expected"); + } catch (ArrayIndexOutOfBoundsException e) { + final String message = e.getMessage().toLowerCase(); + assertTrue("Got message: " + message, message.contains("index 4") || "4".equals(message) + || "Array index out of range: 4".equals(message)); + } + } } http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/excel/pom.xml ---------------------------------------------------------------------- diff --git a/excel/pom.xml b/excel/pom.xml index 709717a..13ee4f0 100644 --- a/excel/pom.xml +++ b/excel/pom.xml @@ -40,7 +40,7 @@ under the License. <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> - <version>3.17</version> + <version>4.0.0</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java ---------------------------------------------------------------------- diff --git a/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java b/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java index 17f11ec..97ba50f 100644 --- a/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java +++ b/excel/src/main/java/org/apache/metamodel/excel/DefaultSpreadsheetReaderDelegate.java @@ -66,7 +66,7 @@ final class DefaultSpreadsheetReaderDelegate implements SpreadsheetReaderDelegat @Override public Schema createSchema(String schemaName) { final MutableSchema schema = new MutableSchema(schemaName); - final Workbook wb = ExcelUtils.readWorkbook(_resource); + final Workbook wb = ExcelUtils.readWorkbook(_resource, true); try { for (int i = 0; i < wb.getNumberOfSheets(); i++) { final Sheet currentSheet = wb.getSheetAt(i); @@ -83,7 +83,7 @@ final class DefaultSpreadsheetReaderDelegate implements SpreadsheetReaderDelegat @Override public DataSet executeQuery(Table table, List<Column> columns, int maxRows) { - final Workbook wb = ExcelUtils.readWorkbook(_resource); + final Workbook wb = ExcelUtils.readWorkbook(_resource, true); final Sheet sheet = wb.getSheet(table.getName()); if (sheet == null || sheet.getPhysicalNumberOfRows() == 0) { http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/excel/src/main/java/org/apache/metamodel/excel/ExcelUpdateCallback.java ---------------------------------------------------------------------- diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelUpdateCallback.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelUpdateCallback.java index f99ec89..f2375c4 100644 --- a/excel/src/main/java/org/apache/metamodel/excel/ExcelUpdateCallback.java +++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelUpdateCallback.java @@ -95,7 +95,7 @@ final class ExcelUpdateCallback extends AbstractUpdateCallback implements Update if (_workbook != null) { ExcelUtils.writeAndCloseWorkbook(_dataContext, _workbook); } - _workbook = ExcelUtils.readWorkbook(_dataContext); + _workbook = ExcelUtils.readWorkbookForUpdate(_dataContext); if (streamingAllowed && _workbook instanceof XSSFWorkbook) { _workbook = new SXSSFWorkbook((XSSFWorkbook) _workbook); } http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java ---------------------------------------------------------------------- diff --git a/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java b/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java index c7fe930..2da6ef3 100644 --- a/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java +++ b/excel/src/main/java/org/apache/metamodel/excel/ExcelUtils.java @@ -19,7 +19,6 @@ package org.apache.metamodel.excel; import java.io.File; -import java.io.OutputStream; import java.text.NumberFormat; import java.util.Date; import java.util.Iterator; @@ -39,7 +38,6 @@ import org.apache.metamodel.data.Style.SizeUnit; import org.apache.metamodel.data.StyleBuilder; import org.apache.metamodel.query.SelectItem; import org.apache.metamodel.schema.Table; -import org.apache.metamodel.util.Action; import org.apache.metamodel.util.DateUtils; import org.apache.metamodel.util.FileHelper; import org.apache.metamodel.util.FileResource; @@ -95,7 +93,15 @@ final class ExcelUtils { } } - public static Workbook readWorkbook(Resource resource) { + /** + * Opens a {@link Workbook} based on a {@link Resource}. + * + * @param resource + * @param allowFileOptimization whether or not to allow POI to use file handles which supposedly speeds things up, + * but creates issues when writing multiple times to the same file in short bursts of time. + * @return + */ + public static Workbook readWorkbook(Resource resource, boolean allowFileOptimization) { if (!resource.isExists()) { // resource does not exist- create a blank workbook if (isXlsxFile(resource)) { @@ -105,10 +111,11 @@ final class ExcelUtils { } } - if (resource instanceof FileResource) { + if (allowFileOptimization && resource instanceof FileResource) { final File file = ((FileResource) resource).getFile(); try { - return WorkbookFactory.create(file); + // open read-only mode + return WorkbookFactory.create(file, null, true); } catch (Exception e) { logger.error("Could not open workbook", e); throw new IllegalStateException("Could not open workbook", e); @@ -137,9 +144,9 @@ final class ExcelUtils { * * @return a workbook instance based on the ExcelDataContext. */ - public static Workbook readWorkbook(ExcelDataContext dataContext) { + public static Workbook readWorkbookForUpdate(ExcelDataContext dataContext) { Resource resource = dataContext.getResource(); - return readWorkbook(resource); + return readWorkbook(resource, false); } /** @@ -156,28 +163,12 @@ final class ExcelUtils { final Resource realResource = dataContext.getResource(); final Resource tempResource = new InMemoryResource(realResource.getQualifiedPath()); - tempResource.write(new Action<OutputStream>() { - @Override - public void run(OutputStream outputStream) throws Exception { - wb.write(outputStream); - } - }); - - if (wb instanceof HSSFWorkbook && realResource instanceof FileResource && realResource.isExists()) { - // TODO POI has a problem with closing a file-reference/channel - // after wb.write() is invoked. See POI issue to be fixed: - // https://bz.apache.org/bugzilla/show_bug.cgi?id=58480 - System.gc(); - System.runFinalization(); - try { - Thread.sleep(800); - } catch (InterruptedException e) { - } - } + tempResource.write(out -> wb.write(out)); FileHelper.safeClose(wb); FileHelper.copy(tempResource, realResource); + } public static String getCellValue(Workbook wb, Cell cell) { @@ -189,7 +180,7 @@ final class ExcelUtils { final String result; - switch (cell.getCellTypeEnum()) { + switch (cell.getCellType()) { case BLANK: case _NONE: result = null; @@ -238,7 +229,7 @@ final class ExcelUtils { result = cell.getRichStringCellValue().getString(); break; default: - throw new IllegalStateException("Unknown cell type: " + cell.getCellTypeEnum()); + throw new IllegalStateException("Unknown cell type: " + cell.getCellType()); } logger.debug("cell {} resolved to value: {}", cellCoordinate, result); @@ -296,7 +287,7 @@ final class ExcelUtils { } final CellStyle cellStyle = cell.getCellStyle(); - final short fontIndex = cellStyle.getFontIndex(); + final int fontIndex = cellStyle.getFontIndexAsInt(); final Font font = workbook.getFontAt(fontIndex); final StyleBuilder styleBuilder = new StyleBuilder(); @@ -312,7 +303,7 @@ final class ExcelUtils { } // Font size - final Font stdFont = workbook.getFontAt((short) 0); + final Font stdFont = workbook.getFontAt(0); final short fontSize = font.getFontHeightInPoints(); if (stdFont.getFontHeightInPoints() != fontSize) { styleBuilder.fontSize(fontSize, SizeUnit.PT); @@ -344,7 +335,7 @@ final class ExcelUtils { } // Background color - if (cellStyle.getFillPatternEnum() == FillPatternType.SOLID_FOREGROUND) { + if (cellStyle.getFillPattern() == FillPatternType.SOLID_FOREGROUND) { Color color = cellStyle.getFillForegroundColorColor(); if (color instanceof HSSFColor) { short[] triplet = ((HSSFColor) color).getTriplet(); @@ -363,7 +354,7 @@ final class ExcelUtils { } // alignment - switch (cellStyle.getAlignmentEnum()) { + switch (cellStyle.getAlignment()) { case LEFT: styleBuilder.leftAligned(); break; http://git-wip-us.apache.org/repos/asf/metamodel/blob/9f81506f/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java ---------------------------------------------------------------------- diff --git a/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java b/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java index 8b9f6c4..7e4a9c0 100644 --- a/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java +++ b/excel/src/main/java/org/apache/metamodel/excel/XlsxSheetToRowsHandler.java @@ -29,6 +29,7 @@ import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.FillPatternType; import org.apache.poi.ss.usermodel.FontUnderline; +import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.xssf.eventusermodel.XSSFReader; import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; @@ -47,15 +48,19 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** - * XML handler for transforming a sheet into rows. Uses an - * {@link XlsxRowCallback} to publish identified rows. + * XML handler for transforming a sheet into rows. Uses an {@link XlsxRowCallback} to publish identified rows. */ final class XlsxSheetToRowsHandler extends DefaultHandler { private static final Logger logger = LoggerFactory.getLogger(XlsxSheetToRowsHandler.class); private static enum XssfDataType { - BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, + BOOL, + ERROR, + FORMULA, + INLINESTR, + SSTINDEX, + NUMBER, } // global variables @@ -150,12 +155,12 @@ final class XlsxSheetToRowsHandler extends DefaultHandler { _dataType = XssfDataType.FORMULA; } - String cellStyleStr = attributes.getValue("s"); + final String cellStyleStr = attributes.getValue("s"); if (cellStyleStr != null) { // It's a number, but almost certainly one // with a special style or format - int styleIndex = Integer.parseInt(cellStyleStr); - XSSFCellStyle style = _stylesTable.getStyleAt(styleIndex); + final int styleIndex = Integer.parseInt(cellStyleStr); + final XSSFCellStyle style = _stylesTable.getStyleAt(styleIndex); configureStyle(style); @@ -186,8 +191,8 @@ final class XlsxSheetToRowsHandler extends DefaultHandler { } if (style.getFillPatternEnum() == FillPatternType.SOLID_FOREGROUND) { - XSSFColor fillForegroundXSSFColor = style.getFillForegroundXSSFColor(); - String argb = fillForegroundXSSFColor.getARGBHex(); + final XSSFColor fillForegroundXSSFColor = style.getFillForegroundXSSFColor(); + final String argb = fillForegroundXSSFColor.getARGBHex(); if (argb != null) { _style.background(argb.substring(2)); } @@ -199,7 +204,7 @@ final class XlsxSheetToRowsHandler extends DefaultHandler { _style.fontSize(fontHeight, SizeUnit.PT); } - XSSFColor fontColor = style.getFont().getXSSFColor(); + final XSSFColor fontColor = style.getFont().getXSSFColor(); if (fontColor != null) { String argbHex = fontColor.getARGBHex(); if (argbHex != null) { @@ -265,7 +270,7 @@ final class XlsxSheetToRowsHandler extends DefaultHandler { switch (_dataType) { case BOOL: - char first = _value.charAt(0); + final char first = _value.charAt(0); return first == '0' ? "false" : "true"; case ERROR: logger.warn("Error-cell occurred: {}", _value); @@ -273,19 +278,19 @@ final class XlsxSheetToRowsHandler extends DefaultHandler { case FORMULA: return _value.toString(); case INLINESTR: - XSSFRichTextString rtsi = new XSSFRichTextString(_value.toString()); + final XSSFRichTextString rtsi = new XSSFRichTextString(_value.toString()); return rtsi.toString(); case SSTINDEX: - String sstIndex = _value.toString(); - int idx = Integer.parseInt(sstIndex); - XSSFRichTextString rtss = new XSSFRichTextString(_sharedStringTable.getEntryAt(idx)); - return rtss.toString(); + final String sstIndex = _value.toString(); + final int idx = Integer.parseInt(sstIndex); + final RichTextString item = _sharedStringTable.getItemAt(idx); + return item.getString(); case NUMBER: final String numberString = _value.toString(); if (_formatString != null) { - DataFormatter formatter = getDataFormatter(); + final DataFormatter formatter = getDataFormatter(); if (HSSFDateUtil.isADateFormat(_formatIndex, _formatString)) { - Date date = DateUtil.getJavaDate(Double.parseDouble(numberString)); + final Date date = DateUtil.getJavaDate(Double.parseDouble(numberString)); return DateUtils.createDateFormat().format(date); } return formatter.formatRawCellContents(Double.parseDouble(numberString), _formatIndex, _formatString);
