From 7c0327c8b101fcd093aae5a83b37a99f0809ffd1 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Tue, 22 Sep 2020 12:42:18 +0000 Subject: [PATCH] OSGi support: register service providers in bundle activator git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1881924 13f79535-47bb-0310-9956-ffa450edef68 --- osgi/pom.xml | 3 + .../java/org/apache/poi/osgi/Activator.java | 36 +++++- .../org/apache/poi/osgi/BaseOSGiTestCase.java | 49 +++++++ .../org/apache/poi/osgi/OSGiExtractorsIT.java | 120 ++++++++++++++++++ .../org/apache/poi/osgi/OSGiSlideShowIT.java | 98 ++++++++++++++ .../apache/poi/osgi/OSGiSpreadsheetIT.java | 72 +++-------- .../poi/extractor/ExtractorFactory.java | 7 + .../poi/sl/usermodel/SlideShowFactory.java | 8 ++ .../poi/ss/usermodel/WorkbookFactory.java | 8 ++ 9 files changed, 347 insertions(+), 54 deletions(-) create mode 100755 osgi/src/test/java/org/apache/poi/osgi/BaseOSGiTestCase.java create mode 100755 osgi/src/test/java/org/apache/poi/osgi/OSGiExtractorsIT.java create mode 100755 osgi/src/test/java/org/apache/poi/osgi/OSGiSlideShowIT.java diff --git a/osgi/pom.xml b/osgi/pom.xml index 483db264ef..9672252444 100644 --- a/osgi/pom.xml +++ b/osgi/pom.xml @@ -50,6 +50,9 @@ true + + org.apache.poi.osgi.Activator + org.apache.poi.*, org.openxmlformats.schemas.*, diff --git a/osgi/src/main/java/org/apache/poi/osgi/Activator.java b/osgi/src/main/java/org/apache/poi/osgi/Activator.java index 2f0212bd4e..eef4ab4319 100644 --- a/osgi/src/main/java/org/apache/poi/osgi/Activator.java +++ b/osgi/src/main/java/org/apache/poi/osgi/Activator.java @@ -17,12 +17,44 @@ package org.apache.poi.osgi; +import org.apache.poi.extractor.ExtractorFactory; +import org.apache.poi.extractor.MainExtractorFactory; +import org.apache.poi.extractor.ole2.OLE2ScratchpadExtractorFactory; +import org.apache.poi.hslf.usermodel.HSLFSlideShowFactory; +import org.apache.poi.hssf.usermodel.HSSFWorkbookFactory; +import org.apache.poi.ooxml.extractor.POIXMLExtractorFactory; +import org.apache.poi.sl.usermodel.SlideShowFactory; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.xslf.usermodel.XSLFSlideShowFactory; +import org.apache.poi.xssf.usermodel.XSSFWorkbookFactory; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { - public void start(BundleContext context) throws Exception { + + @Override + public void start(BundleContext context) { + WorkbookFactory.addProvider(new HSSFWorkbookFactory()); + WorkbookFactory.addProvider(new XSSFWorkbookFactory()); + + SlideShowFactory.addProvider(new HSLFSlideShowFactory()); + SlideShowFactory.addProvider(new XSLFSlideShowFactory()); + + ExtractorFactory.addProvider(new OLE2ScratchpadExtractorFactory()); + ExtractorFactory.addProvider(new POIXMLExtractorFactory()); + ExtractorFactory.addProvider(new MainExtractorFactory()); } - public void stop(BundleContext context) throws Exception { + + @Override + public void stop(BundleContext context) { + WorkbookFactory.removeProvider(HSSFWorkbookFactory.class); + WorkbookFactory.removeProvider(XSSFWorkbookFactory.class); + + SlideShowFactory.removeProvider(HSLFSlideShowFactory.class); + SlideShowFactory.removeProvider(XSLFSlideShowFactory.class); + + ExtractorFactory.removeProvider(OLE2ScratchpadExtractorFactory.class); + ExtractorFactory.removeProvider(POIXMLExtractorFactory.class); + ExtractorFactory.removeProvider(MainExtractorFactory.class); } } diff --git a/osgi/src/test/java/org/apache/poi/osgi/BaseOSGiTestCase.java b/osgi/src/test/java/org/apache/poi/osgi/BaseOSGiTestCase.java new file mode 100755 index 0000000000..4b5178ce3f --- /dev/null +++ b/osgi/src/test/java/org/apache/poi/osgi/BaseOSGiTestCase.java @@ -0,0 +1,49 @@ +/* ==================================================================== + 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.poi.osgi; + +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.osgi.framework.BundleContext; + +import javax.inject.Inject; +import java.io.File; +import java.io.IOException; + +import static org.ops4j.pax.exam.CoreOptions.*; + +/** + * Test to ensure that all our main formats can create, write + * and read back in, when running under OSGi + */ +public class BaseOSGiTestCase { + + @Inject + private BundleContext bc; + + @Configuration + public Option[] configuration() throws IOException { + String bundlePath = System.getProperty("bundle.filename"); + if(bundlePath == null){ + throw new IllegalStateException("-Dbundle.filename property is not set."); + } + return options( + junitBundles(), + bundle(new File(bundlePath).toURI().toURL().toString())); + } +} diff --git a/osgi/src/test/java/org/apache/poi/osgi/OSGiExtractorsIT.java b/osgi/src/test/java/org/apache/poi/osgi/OSGiExtractorsIT.java new file mode 100755 index 0000000000..8ee1258fa4 --- /dev/null +++ b/osgi/src/test/java/org/apache/poi/osgi/OSGiExtractorsIT.java @@ -0,0 +1,120 @@ +/* ==================================================================== + 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.poi.osgi; + +import org.apache.poi.extractor.ExtractorFactory; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.TextBox; +import org.apache.poi.sl.usermodel.TextShape; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import java.awt.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import static org.junit.Assert.assertEquals; + +/** + * Test to ensure that all our main formats can create, write + * and read back in, when running under OSGi + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class OSGiExtractorsIT extends BaseOSGiTestCase { + + + byte[] createSlideShow(SlideShow ppt) throws Exception { + Slide slide = ppt.createSlide(); + + TextBox box = slide.createTextBox(); + box.setTextPlaceholder(TextShape.TextPlaceholder.TITLE); + box.setText("Hello, World!"); + box.setAnchor(new Rectangle(36, 15, 648, 65)); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ppt.write(out); + return out.toByteArray(); + } + + byte[] createWorkbook(Workbook wb) throws Exception { + Sheet s = wb.createSheet("OSGi"); + s.createRow(0).createCell(0).setCellValue("Hello, World!"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + wb.write(out); + return out.toByteArray(); + + + } + + /** + * this should invoke OLE2ScratchpadExtractorFactory + */ + @Test + public void testHSLF() throws Exception { + byte[] bytes = createSlideShow(new HSLFSlideShow()); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + + String text = ExtractorFactory.createExtractor(is).getText().trim(); + assertEquals("Hello, World!", text); + } + + /** + * this should invoke POIXMLExtractorFactory + */ + @Test + public void testXSLF() throws Exception { + byte[] bytes = createSlideShow(new XMLSlideShow()); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + + String text = ExtractorFactory.createExtractor(is).getText().trim(); + assertEquals("Hello, World!", text); + } + + @Test + public void testHSSF() throws Exception { + byte[] bytes = createWorkbook(new HSSFWorkbook()); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + + String text = ExtractorFactory.createExtractor(is).getText().trim(); + assertEquals("OSGi\nHello, World!", text); + } + + /** + * this should invoke POIXMLExtractorFactory + */ + @Test + public void testXSSF() throws Exception { + byte[] bytes = createWorkbook(new XSSFWorkbook()); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + + String text = ExtractorFactory.createExtractor(is).getText().trim(); + assertEquals("OSGi\nHello, World!", text); + } +} diff --git a/osgi/src/test/java/org/apache/poi/osgi/OSGiSlideShowIT.java b/osgi/src/test/java/org/apache/poi/osgi/OSGiSlideShowIT.java new file mode 100755 index 0000000000..ef18f1cc95 --- /dev/null +++ b/osgi/src/test/java/org/apache/poi/osgi/OSGiSlideShowIT.java @@ -0,0 +1,98 @@ +/* ==================================================================== + 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.poi.osgi; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import java.awt.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * Test to ensure that all our main formats can create, write + * and read back in, when running under OSGi + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerClass.class) +public class OSGiSlideShowIT extends BaseOSGiTestCase { + + + // create a workbook, validate and write back + void testSS(SlideShow ppt) throws Exception { + Slide slide = ppt.createSlide(); + + TextBox box1 = slide.createTextBox(); + box1.setTextPlaceholder(TextShape.TextPlaceholder.TITLE); + box1.setText("HSLF in a Nutshell"); + box1.setAnchor(new Rectangle(36, 15, 648, 65)); + + TextBox box2 = slide.createTextBox(); + box2.setTextPlaceholder(TextShape.TextPlaceholder.BODY); + box2.setText( + "HSLF provides a way to read, create and modify MS PowerPoint presentations\r" + + "Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" + + "Comprehensive support of PowerPoint objects\r" + + "Rich text\r" + + "Tables\r" + + "Shapes\r" + + "Pictures\r" + + "Master slides\r" + + "Access to low level data structures" + ); + + List> tp = box2.getTextParagraphs(); + for (int i : new byte[]{0, 1, 2, 8}) { + tp.get(i).getTextRuns().get(0).setFontSize(28d); + } + for (int i : new byte[]{3, 4, 5, 6, 7}) { + tp.get(i).getTextRuns().get(0).setFontSize(24d); + tp.get(i).setIndentLevel(1); + } + box2.setAnchor(new Rectangle(36, 80, 648, 400)); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ppt.write(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + ppt = SlideShowFactory.create(bais); + assertEquals(1, ppt.getSlides().size()); + slide = (Slide) ppt.getSlides().iterator().next(); + assertEquals(2, slide.getShapes().size()); + } + + @Test + public void testHSLF() throws Exception { + testSS(new HSLFSlideShow()); + } + + @Test + public void testXSLF() throws Exception { + testSS(new XMLSlideShow()); + } + +} diff --git a/osgi/src/test/java/org/apache/poi/osgi/OSGiSpreadsheetIT.java b/osgi/src/test/java/org/apache/poi/osgi/OSGiSpreadsheetIT.java index ea139e7e50..0ea95602c9 100644 --- a/osgi/src/test/java/org/apache/poi/osgi/OSGiSpreadsheetIT.java +++ b/osgi/src/test/java/org/apache/poi/osgi/OSGiSpreadsheetIT.java @@ -17,85 +17,47 @@ package org.apache.poi.osgi; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.ops4j.pax.exam.CoreOptions.bundle; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.options; - -import javax.inject.Inject; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.util.Arrays; - import org.apache.poi.hssf.usermodel.HSSFWorkbook; - import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.Test; import org.junit.runner.RunWith; -import org.ops4j.pax.exam.Configuration; -import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; -import org.ops4j.pax.exam.spi.reactors.PerMethod; -import org.osgi.framework.BundleContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.ops4j.pax.exam.spi.reactors.PerClass; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import static org.junit.Assert.assertEquals; /** * Test to ensure that all our main formats can create, write - * and read back in, when running under OSGi + * and read back in, when running under OSGi */ @RunWith(PaxExam.class) -@ExamReactorStrategy(PerMethod.class) -public class OSGiSpreadsheetIT { - private final static Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public static final String POI_BUNDLE_SYMBOLIC_NAME = "org.apache.poi.bundle"; +@ExamReactorStrategy(PerClass.class) +public class OSGiSpreadsheetIT extends BaseOSGiTestCase { - @Inject - private BundleContext bc; - - @Configuration - public Option[] configuration() throws IOException { - String bundlePath = System.getProperty("bundle.filename"); - return options( - junitBundles(), - bundle(new File(bundlePath).toURI().toURL().toString())); - } - - @Test - public void testBundleLoaded() { - boolean hasBundle = Arrays.stream(bc.getBundles()).anyMatch(b -> - POI_BUNDLE_SYMBOLIC_NAME.equals(b.getSymbolicName())); - assertTrue(POI_BUNDLE_SYMBOLIC_NAME + " not found", hasBundle); - } // create a workbook, validate and write back void testWorkbook(Workbook wb) throws Exception { - logger.info("testing " + wb.getClass().getSimpleName()); - Sheet s = wb.createSheet("OSGi"); s.createRow(0).createCell(0).setCellValue("With OSGi"); + s.createRow(1).createCell(0).setCellFormula("SUM(A1:B3)"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); wb.write(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - if(wb instanceof HSSFWorkbook) - wb = new HSSFWorkbook(bais); - else - wb = new XSSFWorkbook(bais); + wb = WorkbookFactory.create(bais); assertEquals(1, wb.getNumberOfSheets()); s = wb.getSheet("OSGi"); assertEquals("With OSGi", s.getRow(0).getCell(0).toString()); + assertEquals("SUM(A1:B3)", s.getRow(1).getCell(0).toString()); } @@ -112,6 +74,12 @@ public class OSGiSpreadsheetIT { @Test public void testSXSSF() throws Exception { - testWorkbook(new SXSSFWorkbook()); + testWorkbook(new XSSFWorkbook()); + } + + @Test + public void testFormulaEvaluation() throws Exception { + testWorkbook(new XSSFWorkbook()); } + } diff --git a/src/java/org/apache/poi/extractor/ExtractorFactory.java b/src/java/org/apache/poi/extractor/ExtractorFactory.java index ccab16a213..6b3ec00df6 100644 --- a/src/java/org/apache/poi/extractor/ExtractorFactory.java +++ b/src/java/org/apache/poi/extractor/ExtractorFactory.java @@ -309,4 +309,11 @@ public final class ExtractorFactory { "or you haven't provide the poi-ooxml*.jar and/or poi-scratchpad*.jar in the classpath/modulepath - FileMagic: "+fm); } + public static void addProvider(ExtractorProvider provider){ + Singleton.INSTANCE.provider.add(provider); + } + + public static void removeProvider(Class provider){ + Singleton.INSTANCE.provider.removeIf(p -> p.getClass().getName().equals(provider.getName())); + } } diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java index 8155fccb8d..83d3ae6e70 100644 --- a/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java +++ b/src/java/org/apache/poi/sl/usermodel/SlideShowFactory.java @@ -292,4 +292,12 @@ public final class SlideShowFactory { throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream " + "or you haven't provide the poi-ooxml*.jar in the classpath/modulepath - FileMagic: "+fm); } + + public static void addProvider(SlideShowProvider provider){ + Singleton.INSTANCE.provider.add(provider); + } + + public static void removeProvider(Class provider){ + Singleton.INSTANCE.provider.removeIf(p -> p.getClass().getName().equals(provider.getName())); + } } diff --git a/src/java/org/apache/poi/ss/usermodel/WorkbookFactory.java b/src/java/org/apache/poi/ss/usermodel/WorkbookFactory.java index 965666904c..ede792368a 100644 --- a/src/java/org/apache/poi/ss/usermodel/WorkbookFactory.java +++ b/src/java/org/apache/poi/ss/usermodel/WorkbookFactory.java @@ -298,4 +298,12 @@ public final class WorkbookFactory { throw new IOException("Your InputStream was neither an OLE2 stream, nor an OOXML stream " + "or you haven't provide the poi-ooxml*.jar in the classpath/modulepath - FileMagic: "+fm); } + + public static void addProvider(WorkbookProvider provider){ + Singleton.INSTANCE.provider.add(provider); + } + + public static void removeProvider(Class provider){ + Singleton.INSTANCE.provider.removeIf(p -> p.getClass().getName().equals(provider.getName())); + } } -- 2.39.5