在 Eclipse 包中使用来自 Eclipse Orbit 的 Apache POI

Using Apache POI from Eclipse Orbit in Eclipse bundle

我正在尝试使用来自 Eclipse Orbit Drop R20200831200620 的 Apache POI 4.1。这是 MANIFEST.MF 的相关部分的样子:

Require-Bundle: org.eclipse.emf.edit.ui,
 org.eclipse.equinox.registry,
 org.eclipse.swt,
 org.eclipse.ui,
 org.eclipse.jface,
 com.google.guava,
 org.eclipse.core.runtime,
 org.eclipse.core.expressions,
 org.apache.xmlbeans,
 org.apache.poi,
 org.apache.poi.ooxml,
 org.apache.poi.ooxml.schemas

所有必需的包都是目标平台的一部分,我可以在运行时 Eclipse 的插件列表中看到它们。但是,当尝试在运行时加载 Excel 文件时,我得到以下堆栈跟踪:

org.apache.poi.ooxml.POIXMLException
    at org.apache.poi.ooxml.POIXMLFactory.createDocumentPart(POIXMLFactory.java:66)
    at org.apache.poi.ooxml.POIXMLDocumentPart.read(POIXMLDocumentPart.java:657)
    at org.apache.poi.ooxml.POIXMLDocument.load(POIXMLDocument.java:180)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:282)
    at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory.createWorkbook(XSSFWorkbookFactory.java:88)
    at org.apache.poi.xssf.usermodel.XSSFWorkbookFactory.createWorkbook(XSSFWorkbookFactory.java:116)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.apache.poi.ss.usermodel.WorkbookFactory.createWorkbook(WorkbookFactory.java:341)
    at org.apache.poi.ss.usermodel.WorkbookFactory.createXSSFWorkbook(WorkbookFactory.java:316)
    at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:304)
    at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:273)
    at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:254)
    at org.eclipse.capra.ui.office.utils.CapraOfficeUtils.getExcelWorkbook(CapraOfficeUtils.java:124)
    at org.eclipse.capra.ui.office.views.OfficeView.parseExcelDocument(OfficeView.java:330)
    at org.eclipse.capra.ui.office.views.OfficeView.parseGenericFile(OfficeView.java:299)
    at org.eclipse.capra.ui.office.views.OfficeView$SelectionDropAdapter.performDrop(OfficeView.java:217)
    at org.eclipse.jface.viewers.ViewerDropAdapter.drop(ViewerDropAdapter.java:273)
    at org.eclipse.swt.dnd.DNDListener.handleEvent(DNDListener.java:94)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4385)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1512)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1535)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1520)
    at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:1324)
    at org.eclipse.swt.dnd.DropTarget.drop(DropTarget.java:725)
    at org.eclipse.swt.dnd.DropTarget.tableView_acceptDrop_row_dropOperation(DropTarget.java:964)
    at org.eclipse.swt.dnd.DropTarget.dropTargetProc(DropTarget.java:470)
    at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
    at org.eclipse.swt.dnd.DropTarget.dndCallSuper(DropTarget.java:210)
    at org.eclipse.swt.dnd.DropTarget.performDragOperation(DropTarget.java:736)
    at org.eclipse.swt.dnd.DropTarget.dropTargetProc(DropTarget.java:451)
    at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
    at org.eclipse.swt.widgets.Widget.callSuper(Widget.java:235)
    at org.eclipse.swt.widgets.Widget.mouseDownSuper(Widget.java:1146)
    at org.eclipse.swt.widgets.Tree.mouseDownSuper(Tree.java:2156)
    at org.eclipse.swt.widgets.Widget.mouseDown(Widget.java:1138)
    at org.eclipse.swt.widgets.Control.mouseDown(Control.java:2621)
    at org.eclipse.swt.widgets.Tree.mouseDown(Tree.java:2123)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:6012)
    at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
    at org.eclipse.swt.widgets.Widget.callSuper(Widget.java:235)
    at org.eclipse.swt.widgets.Widget.windowSendEvent(Widget.java:2150)
    at org.eclipse.swt.widgets.Shell.windowSendEvent(Shell.java:2401)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:6136)
    at org.eclipse.swt.internal.cocoa.OS.objc_msgSendSuper(Native Method)
    at org.eclipse.swt.widgets.Display.applicationSendEvent(Display.java:5386)
    at org.eclipse.swt.widgets.Display.applicationProc(Display.java:5522)
    at org.eclipse.swt.internal.cocoa.OS.objc_msgSend(Native Method)
    at org.eclipse.swt.internal.cocoa.NSApplication.sendEvent(NSApplication.java:117)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3786)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1157)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1046)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:155)
    at org.eclipse.ui.internal.Workbench.lambda(Workbench.java:644)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:338)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:153)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:150)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:401)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:657)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:594)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
    at org.eclipse.equinox.launcher.Main.main(Main.java:1438)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
    at org.apache.poi.xssf.usermodel.XSSFFactory.createDocumentPart(XSSFFactory.java:56)
    at org.apache.poi.ooxml.POIXMLFactory.createDocumentPart(POIXMLFactory.java:63)
    ... 74 more
Caused by: java.lang.ExceptionInInitializerError
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
    at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1044)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
    at java.base/jdk.internal.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:186)
    at java.base/java.lang.reflect.Field.acquireFieldAccessor(Field.java:1105)
    at java.base/java.lang.reflect.Field.getFieldAccessor(Field.java:1086)
    at java.base/java.lang.reflect.Field.get(Field.java:418)
    at org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(XmlBeans.java:775)
    at org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument.<clinit>(Unknown Source)
    at org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument$Factory.parse(Unknown Source)
    at org.apache.poi.xssf.model.ThemesTable.<init>(ThemesTable.java:86)
    ... 81 more
Caused by: java.lang.RuntimeException: Cannot load org.apache.xmlbeans.impl.SchemaTypeSystemImpl: make sure xbean.jar is on the classpath.
    at schemaorg_apache_xmlbeans.system.sD023D6490046BA0250A839A9AD24C443.TypeSystemHolder.loadTypeSystem(Unknown Source)
    at schemaorg_apache_xmlbeans.system.sD023D6490046BA0250A839A9AD24C443.TypeSystemHolder.<clinit>(Unknown Source)
    ... 92 more
Caused by: java.lang.ClassNotFoundException: org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl cannot be found by org.apache.poi.ooxml.schemas_4.1.1.v20200820-1148
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:516)
    at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:171)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:415)
    ... 94 more

为了确保我没有搞砸配置,我添加了以下代码,灵感来自 Apache POI FAQ 到包 Activator.java:

    @Override
    public void start(BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
        ClassLoader classloader = org.apache.poi.poifs.filesystem.POIFSFileSystem.class.getClassLoader();
        URL res = classloader.getResource("org/apache/poi/poifs/filesystem/POIFSFileSystem.class");
        String path = res.getPath();
        System.out.println("POI Core came from " + path);

        classloader = org.apache.poi.ooxml.POIXMLDocument.class.getClassLoader();
        res = classloader.getResource("org/apache/poi/ooxml/POIXMLDocument.class");
        path = res.getPath();
        System.out.println("POI OOXML came from " + path);

        classloader = org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl.class.getClassLoader();
        res = classloader.getResource("org/apache/xmlbeans/impl/schema/SchemaTypeSystemImpl.class");
        path = res.getPath();
        System.out.println("XML Beans came from " + path);

    }

我确实得到了预期的控制台输出:

POI Core came from /org/apache/poi/poifs/filesystem/POIFSFileSystem.class
POI OOXML came from /org/apache/poi/ooxml/POIXMLDocument.class
XML Beans came from /org/apache/xmlbeans/impl/schema/SchemaTypeSystemImpl.class

在这一点上,我被难住了。常见问题解答还有一个提示,在 OSGI 上下文中使用 POI 时设置自定义类加载器,但是 API 似乎已经更改并且片段 POIXMLTypeLoader.setClassLoader(CTTable.class.getClassLoader()); 不起作用,因为 POIXMLTypeLoader 没有 setClassLoader()方法。

有什么想法吗?

我遇到了与 R20200831200620 相同的问题。您是否尝试了下一个版本 R20201130205003?

可能会有所不同,因为

其他更新版本

  • R20210223232630
  • R20210602031627
  • R20210825222808

还包含新的 jar 文件,这可能是一个提示,即 POI 版本 4.1.1.v20200820-1148 的 R20200831200620 出现了问题。