poi-ooxml 在 gradle 上 publishmaven 的调整

摘抄
Apache POI 简介是用 Java 编写的免费开源的跨平台的 Java API,Apache POI 提供 API 给 Java 程式对 Microsoft Office(Excel、WORD、PowerPoint、Visio 等)格式档案读和写的功能。POI 为 “Poor Obfuscation Implementation” 的首字母缩写,意为 “可怜的模糊实现”。

官方主页: http://poi.apache.org/index.html

API 文档: http://poi.apache.org/apidocs/index.html

前言

项目中使用了 poi-ooxml,但是有些地方需要调整,所有拿到 1.4.2 的源码进行了适当的修改
源码使用了 gradle,理所当然的需要使用 gradle 将源码推送到仓库中,参见上一篇中的修改解析 word 内嵌文件名中文乱码

发现问题

  • 源码修改后无法 build

  • 使用 publishToMavenLocal 本地测试时发现,某些方法无法正常编译,原因是缺少包,定位到 poi-ooxml 依赖引入问题,我本地 publishToMavenLocal 的依赖和原先包的依赖不同。

无法 build 问题

根目录有一个 build.xml 会去下载一些 Office Open XML 规范之类的东西,无法 build 是因为这些地址太老已经 404
从网上搜索了一些替代镜像 https://docs.huihoo.com/ooxml/,但是不知道什么原因依旧无法 build

找到官网相关地址 https://www.ecma-international.org/publications-and-standards/standards/ecma-376/
image,下载,解压后本地搭建 http,替换原先地址一气呵成,成功解决 build 问题

publish 踩坑

以为是打包没有把依赖都加进去,因为缺少的正好是 ooxml-schemas

1
2
3
4
5
6
7
8
9
dependencies {
...

compile project(':main')
compile project(':scratchpad') // TODO: get rid of this dependency!
compile files('../../ooxml-lib/ooxml-schemas-1.4.jar')
compile files('../../ooxml-lib/ooxml-security-1.1.jar')
...
}

调整打包脚本发现包太大了,直线上升 40M,感觉应该不是这里的问题。

原本打包方式

参考原来项目自带的打包方式,发现原项目是用 sh 脚本打包的,使用 maven,项目下有.pom 文件

image-20210826112429037

gradle 生成的 pom 和这个有些差别,gradle 是根据本地引用来生成的,gradle 生成的里边有 11 个 dependencies(原项目写的只有四个依赖) 唯独缺少

1
2
3
4
5
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>@VERSION@</version>
</dependency>

image-20210826112649475

解决

经过搜索如何引入 pom 当做模板生成最终 pom,未果

找到的示例 maven-publish 插件只有新增,修改选项

基于此,通过查阅插件源码发现 Node 结点的文档 (见参考),找到删除方法

最终修改结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
publishing {
publications {
basic(MavenPublication) {
pom.withXml {
def root = asNode()
def oldDependenciesNode = root.getAt("dependencies")[0]
root.remove(oldDependenciesNode)
def dependenciesNode = root.appendNode('dependencies')
Node xml = new XmlParser().parse("../../maven/poi-ooxml.pom")
xml.dependencies.first().each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.getAt("groupId")[0].value())
dependencyNode.appendNode('artifactId', it.getAt("artifactId")[0].value())
def v = it.getAt("version")[0].value()
if(v.contains("@VERSION@")){
v = version
}
dependencyNode.appendNode('version',v)
}
}
artifactId = "poi-ooxml"
}
}
}

// 同时需要禁用gradle 元数据生成 https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html
// 因为如果不禁用,我们只修改了pom生成,元数据生成还是原来的,使用方如果是gradle,还会发生以前的问题

tasks.withType(GenerateModuleMetadata) {
enabled = false
}

参考

In Gradle, how can I generate a POM file with dynamic dependencies resolved to the actual version used?
gradle 源码
gradle-XmlProvider - 代码
groovy-Node 手册
Gradle 不包括已发布的 pom.xml 中的依赖项