Ubuntu 22.04 安装 Apache Whisker 指南
在 Ubuntu 22.04 上从零部署 Apache Whisker 0.2-SNAPSHOT,覆盖 JDK 17 兼容性缺陷的单行修复、官方快照 jar 下载校验、最小元数据描述符编写、generate/audit/skeleton 三命令实测与 Maven 插件集成,命令回显均实测通过。
Ubuntu 22.04 安装 Apache Whisker 指南
目标:在 Ubuntu 22.04 上部署 Apache Creadur 家族的许可证合规审计工具 Apache Whisker(实测版本 0.2-SNAPSHOT,官方从未向 Maven Central 发布正式版,本文如实采用 Apache 官方快照仓库的最新构建),跑通
--help、--generate、--audit、--skeleton全部命令行能力与 Maven 插件集成;本文全部命令与回显均已在 Ubuntu 22.04 实测通过。
Apache Whisker 隶属 Apache Creadur 项目(与 Apache Rat、Apache Tentacles 同门),定位是"为组装发行版维护正确的法律文档":按 XML 元数据描述应用中每个资源的许可证与版权归属,自动生成 LICENSE/NOTICE 文档并输出审计报告。它是纯 Java 命令行工具,没有常驻服务与监听端口,安装的本质是「装好 JDK → 拿到可执行 jar(或 Maven 插件)→ 写最小元数据描述符 → 跑通三个命令」。本文给出两种落地方式:面向无构建体系的官方快照 jar 直跑方案,以及面向 Maven 工程的插件集成方案。
一、环境信息
本节先固定可复现的基线环境,后续所有命令均在此环境执行。
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- JDK:OpenJDK 17.0.20.1(apt 包
openjdk-17-jdk-headless,另备openjdk-8-jdk作零补丁回退路径) - 构建工具:Apache Maven 3.6.3(apt 包
maven,方案 B 使用) - 组件版本:Apache Whisker 0.2-SNAPSHOT(
org.apache.creadur.whisker:apache-whisker-cli:0.2-SNAPSHOT,快照编号 20261014.173522-582) - 仓库坐标:Maven Central 无任何 Whisker 构件,唯一官方 Maven 仓库为 Apache 快照仓库
https://repository.apache.org/content/repositories/snapshots/ - 验证用工作目录:
/root/whisker(jar 与元数据)、/root/whisker/app(演示发行目录)、/root/whisker/work(generate 工作目录)、/root/plugin-demo(方案 B 工程)
系统与架构确认(实时回显):
cat /etc/os-release | head -3
uname -m
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
x86_64
💡 说明:Whisker 是一次性运行的 CLI 工具,环境中不存在需要常驻的守护进程;「安装完成」的判定标准是
java -jar能跑通--help并对一份最小元数据描述符产出 generate/audit 结果,而不是某个端口处于监听状态。
二、前置条件
本节说明安装前必须满足的条件。
- 具有 root 或 sudo 权限的 Ubuntu 22.04 系统。
- 可访问 Ubuntu 官方软件源(
apt update能正常拉取索引)。 - 可访问 Apache 快照仓库
repository.apache.org与 Maven 中央仓库repo.maven.apache.org(方案 B 需要后者拉取插件传递依赖)。 - 至少 1 GB 可用磁盘空间(JDK 约 250 MB,Whisker 可执行 jar 约 4.6 MB)。
网络连通性确认(实时回显):
curl -4 -sI --max-time 30 https://repository.apache.org/content/repositories/snapshots/ | head -1
HTTP/1.1 200 OK
⚠️ 注意:部分内网环境访问
search.maven.org会因 IPv6 路由问题超时,repository.apache.org与repo1.maven.org直连正常即可,本文所有下载均不依赖search.maven.org。
三、版本选型说明
本节给出 Whisker 的版本事实与选型结论。这是一个小众低频维护项目,版本状况与常见 Java 组件差异很大,以下全部为 2026-10-15 的真实查询结果。
事实一:Maven Central 上没有任何 Whisker 构件。 分别用中央仓库搜索接口与目录路径核实:
curl -4 -s --max-time 30 "https://search.maven.org/solrsearch/select?q=g:%22org.apache.creadur.whisker%22&rows=40&wt=json" | grep -o '"numFound":[0-9]*'
"numFound":0
curl -4 -s -o /dev/null -w "%{http_code}\n" --max-time 30 https://repo1.maven.org/maven2/org/apache/creadur/whisker/
404
事实二:Apache 官方快照仓库是唯一 Maven 来源,且只有 0.2-SNAPSHOT 一个版本线。 元数据(实时回显):
curl -4 -s --max-time 30 "https://repository.apache.org/content/repositories/snapshots/org/apache/creadur/whisker/apache-whisker-app/maven-metadata.xml"
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>org.apache.creadur.whisker</groupId>
<artifactId>apache-whisker-app</artifactId>
<versioning>
<latest>0.2-SNAPSHOT</latest>
<release></release>
<versions>
<version>0.2-SNAPSHOT</version>
</versions>
<lastUpdated>20261014173522</lastUpdated>
</versioning>
</metadata>
快照由持续集成每日构建,<lastUpdated> 与最新快照编号一致;快照仓库同目录下并存 app、cli、model、scan、xml、velocity、maven-plugin、plugin4maven 八个子构件。
事实三:源码仓库只有 0.1 一个正式 tag,站点快照持续更新但从未出 0.2 正式版。 GitHub 仓库 apache/creadur-whisker 仅有一个标签 apache-whisker-0.1;项目官网 https://creadur.apache.org/whisker/ 页头标注 Version: 0.2-SNAPSHOT | Last Published: 2026-07-22;最近的提交是 2026-10-02 的依赖版本机器人合并,属于典型的低频维护状态。
| 来源 | 版本 | 结论 |
|---|---|---|
| Maven Central | 无 | 不可用,网传 whisker-* 中央仓库坐标均不存在 |
| Apache 快照仓库 | 0.2-SNAPSHOT(每日构建) | 本文实测采用,官方唯一 Maven 渠道 |
| 源码 tag | apache-whisker-0.1 | 唯一历史正式版,未发布到任何 Maven 仓库,需自行源码构建 |
本文实际采用 0.2-SNAPSHOT(cli 快照编号 20261014.173522-582,sha1 a107b429d7a995c68da71de45f69b61b35a17a5e)。快照构件的可用性以构建当日为准,升级时替换下载链接中的时间戳即可,操作步骤完全相同。该 jar 内嵌全部依赖(约 4.6 MB、2900 余个类文件),字节码主版本号为 52(即 Java 8 基线),JDK 8 与 JDK 17 均可运行(JDK 17 需第四章的单行修复)。
💡 技术拓展:许可证合规审计工具对比(本文采用 Whisker 的理由见末行)——
工具 隶属 核心机制 适用场景 Apache Rat Apache Creadur 扫描源码文件头注释,报告缺失许可证声明 源码级合规检查,CI 门禁 Apache Whisker Apache Creadur 按 XML 元数据描述组件归属,生成 LICENSE/NOTICE 并审计 组装发行版的对外法律文档维护 Apache Tentacles Apache Creadur 从 Maven 仓库批量拉取发行包做合规核查 对仓库中第三方构件做批量审计 license-maven-plugin(mcumings) 社区 下载并聚合各依赖的 license 文件 依赖清单归档 Rat 回答「源码文件是否带了许可证头」,Whisker 回答「发行版整体对外提供的 LICENSE/NOTICE 是否完整一致」,二者互补;本文采用 Whisker,用于维护组装应用的对外法律文档。
四、方案 A:官方快照 jar 直用(推荐)
本节面向无构建体系的场景,直接使用 Apache 快照仓库发布的可执行 jar,用 java -jar 完成全部操作。
4.1 方案说明
链路是:apt 安装 JDK → curl 下载 cli 模块快照 jar 并校验 sha1 → java -jar --help 验证 → 应用 JDK 17 兼容性单行修复 → 编写最小元数据描述符 → 跑通 --generate/--audit/--skeleton。cli 模块的 jar 即官方文档指名的可运行入口(内嵌全部依赖)。
4.2 安装 JDK 17
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-17-jdk-headless
# 输出节选(实测)
openjdk-17-jdk-headless is already the newest version (17.0.20.1+1-1~22.04).
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
安装后确认版本(jar 工具随 headless 包提供,4.5 节修复时需要):
java -version
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
验证点:java -version 输出 17.0.x 且 command -v jar 指向 /usr/bin/jar 即就绪。
4.3 下载 cli 快照 jar 并校验
创建工作目录,从 Apache 快照仓库下载并校验(快照编号以构建当日为准,可先浏览目录取最新文件名):
mkdir -p /root/whisker && cd /root/whisker
curl -4 -sO --max-time 120 "https://repository.apache.org/content/repositories/snapshots/org/apache/creadur/whisker/apache-whisker-cli/0.2-SNAPSHOT/apache-whisker-cli-0.2-20261014.173522-582.jar"
curl -4 -s --max-time 30 "https://repository.apache.org/content/repositories/snapshots/org/apache/creadur/whisker/apache-whisker-cli/0.2-SNAPSHOT/apache-whisker-cli-0.2-20261014.173522-582.jar.sha1"
sha1sum apache-whisker-cli-0.2-20261014.173522-582.jar
a107b429d7a995c68da71de45f69b61b35a17a5e
a107b429d7a995c68da71de45f69b61b35a17a5e apache-whisker-cli-0.2-20261014.173522-582.jar
两行 sha1 逐字一致即下载完整。重命名为稳定文件名便于后续命令引用:
mv apache-whisker-cli-0.2-20261014.173522-582.jar apache-whisker-cli-0.2-SNAPSHOT.jar
ls -l apache-whisker-cli-0.2-SNAPSHOT.jar
-rw-r--r-- 1 root root 4816276 Oct 15 14:22 apache-whisker-cli-0.2-SNAPSHOT.jar
4.4 首次运行 --help
cd /root/whisker && java -jar apache-whisker-cli-0.2-SNAPSHOT.jar --help
完整回显(实测全量):
usage: apache-whisker-cli -a | -g | -t [-h] -l <file> [-s <dir>]
Pass the descriptor containing license meta-data and the act to be done.
-a,--audit report audit details
-g,--generate generate license and notice
-h,--help print help then exit, ignoring other
options.
-l,--license-descriptor <file> use given license descriptor
-s,--source <dir> application source
-t,--skeleton generates skeleton meta-data
Apache Whisker assists assembled applications maintain correct legal
documentation. Whisker is part of the Apache Creadur suite of tools for
auditing and comprehending software distributions, and is open source
community developed software. Get involved at http://www.apache.org.
命令面就此固定:互斥的动作 -a(审计)/-g(生成)/-t(骨架),加 -l 指定元数据描述符、-s 指定发行目录。验证点:能打印上述 usage 且退出码为 0,说明 jar 可执行、依赖完整。
4.5 JDK 17 兼容性缺陷与单行修复
在 JDK 17 上,--help 正常,但执行任意实际动作会崩溃(实测回显):
java -jar apache-whisker-cli-0.2-SNAPSHOT.jar --generate --license-descriptor main.xml
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.apache.creadur.whisker.cli.Main.configure(Main.java:131)
at org.apache.creadur.whisker.cli.Main.configure(Main.java:119)
at org.apache.creadur.whisker.cli.Main.run(Main.java:176)
at org.apache.creadur.whisker.cli.Main.main(Main.java:70)
Caused by: java.lang.UnsupportedOperationException: No class provided, and an appropriate one cannot be found.
at org.apache.logging.log4j.LogManager.callerClass(LogManager.java:531)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:556)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:543)
at org.apache.creadur.whisker.out.velocity.LoggingVelocityEngine.<clinit>(LoggingVelocityEngine.java:37)
定位:这个可执行 jar 把 log4j-api 一并打进了包内,且 jar 里带有 META-INF/versions/9/ 的多版本类目录,但 MANIFEST 缺少 Multi-Release: true 声明。JDK 9+ 因此不会加载 versions/9 里的新版 StackLocator,退回旧实现后在计算调用者类时抛出上述异常。修复只需向 MANIFEST 追加这一行(jar 命令由 4.2 节的 JDK 提供):
cd /root/whisker && printf 'Multi-Release: true\n' > mr.mf
jar ufm apache-whisker-cli-0.2-SNAPSHOT.jar mr.mf
确认属性已写入:
unzip -p apache-whisker-cli-0.2-SNAPSHOT.jar META-INF/MANIFEST.MF | grep -E 'Multi-Release|Main-Class'
Main-Class: org.apache.creadur.whisker.cli.Main
Multi-Release: true
重跑 4.5 节的 generate 命令即恢复正常(见 4.7 节实测回显)。若不想打补丁,改用 JDK 8 运行该 jar 则天然无此问题,见 4.10 节。
4.6 编写最小元数据描述符
Whisker 的唯一配置面是一份 XML 元数据描述符:先把许可证(licence)、组织(organization)、声明各定义一次并指定 id,再通过 id 引用。创建 /root/whisker/main.xml(完整内容,MIT 单许可证最小样例):
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<licenses>
<license name='MIT License'
id='osi:mit'
url='https://www.opensource.org/licenses/mit-license.php'>
<text>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</text>
</license>
</licenses>
<notices/>
<organisations>
<organisation id='example.org'
name='Example Technology Ltd.'
url='https://www.example.org'/>
</organisations>
<primary-license id='osi:mit'>
<copyright-notice>Copyright (c) 2026 Example Technology Ltd.</copyright-notice>
</primary-license>
<primary-organisation id='example.org'/>
<within dir='.'>
<with-license id='osi:mit'>
<by-organisation id='example.org'>
<resource name='readme.txt'/>
<resource name='run.sh'/>
</by-organisation>
</with-license>
</within>
<within dir='alpha'>
<with-license id='osi:mit'>
<by-organisation id='example.org'>
<resource name='five.js'/>
<resource name='six.rb'/>
</by-organisation>
</with-license>
</within>
</manifest>
再准备一份与描述符对应的演示发行目录:
mkdir -p /root/whisker/app/alpha && cd /root/whisker/app
echo 'Whisker demo application readme.' > readme.txt
printf '#!/bin/sh\necho demo\n' > run.sh
echo 'console.log(5);' > alpha/five.js
echo 'puts 6' > alpha/six.rb
目录结构与描述符的 within 清单一一对应:根目录的 readme.txt、run.sh 与子目录 alpha 的 five.js、six.rb。
4.7 generate:生成 LICENSE 文档
mkdir -p /root/whisker/work && cd /root/whisker/work
java -jar /root/whisker/apache-whisker-cli-0.2-SNAPSHOT.jar --generate --license-descriptor ../main.xml --source ../app
实测回显(头部与尾部,正文为 MIT 许可证全文):
Copyright (c) 2026 Example Technology Ltd.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
(输出节选:MIT 许可证正文已折叠)
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
命令行方式的 generate 把生成的文档写到标准输出(设计如此,源码中固定使用 WriteResultsToSystemOutFactory),落盘用重定向即可:
java -jar /root/whisker/apache-whisker-cli-0.2-SNAPSHOT.jar --generate --license-descriptor ../main.xml > LICENSE
wc -l LICENSE
23 LICENSE
验证点:输出首行为 primary-license 里的 copyright-notice,正文为 license/text 定义;需要 NOTICE 的场景(见 4.8 节后的说明)建议改用方案 B 的插件方式落盘。
4.8 audit:审计发行目录
cd /root/whisker/work
java -jar /root/whisker/apache-whisker-cli-0.2-SNAPSHOT.jar --audit --license-descriptor ../main.xml --source ../app
干净目录的实测回显:
No issues found.
No missing licenses.
No duplicate definitions.
No resources are missing required source links.
No extra licenses
在发行目录中故意放入一个描述符未声明的文件再审计(实测回显):
echo undeclared > /root/whisker/app/extra-undeclared.txt
java -jar /root/whisker/apache-whisker-cli-0.2-SNAPSHOT.jar --audit --license-descriptor ../main.xml --source ../app
rm /root/whisker/app/extra-undeclared.txt
Resources missing licenses:
extra-undeclared.txt in .
No duplicate definitions.
No resources are missing required source links.
No extra licenses
验证点:审计把「存在于目录但描述符未声明」的资源逐条列在 Resources missing licenses 下。注意这是报告不是失败——即使列出缺失项,进程退出码仍为 0,接入 CI 需要自行检查输出内容。
4.9 skeleton:生成骨架描述符
--skeleton 扫描发行目录并生成可编辑的骨架元数据(同样输出到标准输出),实测:
cd /root/whisker && java -jar apache-whisker-cli-0.2-SNAPSHOT.jar --skeleton --license-descriptor main.xml --source app
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest [
<!ELEMENT manifest (licenses, organisations, primary-license, primary-notice?, within*)>
<!ELEMENT licenses (license*)>
<!ELEMENT license (template?, text)>
<!ATTLIST license name CDATA #REQUIRED>
<!ATTLIST license url CDATA #IMPLIED>
<!ATTLIST license id ID #REQUIRED>
(输出节选:DTD 定义中段已折叠)
<!ELEMENT within (public-domain?, with-license*)>
<!ATTLIST within dir CDATA #REQUIRED>
<!ELEMENT with-license (copyright-notice?, license-parameters?, by-organisation*)>
<!ATTLIST with-license id IDREF #REQUIRED>
<!ELEMENT copyright-notice (#PCDATA)>
<!ELEMENT license-parameters (parameter*)>
<!ELEMENT parameter (name, value)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT value (#PCDATA)>
<!ELEMENT public-domain (by-organisation*)>
<!ELEMENT by-organisation (resource*)>
<!ATTLIST by-organisation id IDREF #REQUIRED>
<!ELEMENT resource EMPTY>
<!ATTLIST resource name CDATA #REQUIRED>
<!ATTLIST resource sha1 CDATA #IMPLIED>
]>
<manifest>
(输出节选:骨架正文按目录列出 resource 清单,许可与组织定义段已折叠)
</manifest>
验证点:骨架自带完整 DTD,within 段按实际目录穷举 resource;许可与组织定义是示例值,替换成真实信息后即可作为正式描述符。骨架中许可与组织段的示例值是程序自带的占位样例,务必整段替换后再使用。
4.10 零补丁路径:JDK 8 直跑
若运维口径要求零修改运行,安装 openjdk-8 并用它执行该 jar(字节码基线 Java 8,补丁前即为兼容):
DEBIAN_FRONTEND=noninteractive apt-get install -y openjdk-8-jdk-headless
/usr/lib/jvm/java-8-openjdk-amd64/bin/java -jar /root/whisker/apache-whisker-cli-0.2-SNAPSHOT.jar --audit --license-descriptor /root/whisker/main.xml --source /root/whisker/app
No issues found.
No missing licenses.
No duplicate definitions.
No resources are missing required source links.
No extra licenses
两种路径产出一致:JDK 8 直跑胜在零改动,JDK 17 加单行修复胜在统一运行时。
五、方案 B:Maven 插件集成(工程内落盘)
本节面向 Maven 工程,用 apache-whisker-maven-plugin 把生成动作挂进构建生命周期,产物直接写入 target/。
5.1 方案说明
链路是:apt 安装 Maven → 建最小工程 → 在 pom 中声明 Apache 快照插件仓库与 apache-whisker-maven-plugin:0.2-SNAPSHOT → 执行 mvn generate-resources 触发 generate 目标 → 产物写入 target/。与方案 A 的标准输出不同,插件把 LICENSE/NOTICE 写成文件,是获取 NOTICE 文档的可靠途径。
5.2 安装 Maven
DEBIAN_FRONTEND=noninteractive apt-get install -y maven
# 输出节选(实测)
maven is already the newest version (3.6.3-5).
0 upgraded, 0 newly installed, 0 to remove and 3 not upgraded.
mvn -v | head -3
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
验证点:Java version 显示 17.0.x,apt 版 Maven 通过 PATH 自动定位 JDK,无需设置 JAVA_HOME。
5.3 创建插件演示工程
mkdir -p /root/plugin-demo
/root/plugin-demo/pom.xml(完整内容,直接照抄):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>demo</groupId>
<artifactId>whisker-plugin-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/content/repositories/snapshots/</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.creadur.whisker</groupId>
<artifactId>apache-whisker-maven-plugin</artifactId>
<version>0.2-SNAPSHOT</version>
<configuration>
<descriptor>${project.basedir}/main.xml</descriptor>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
把 4.6 节的 main.xml 复制进工程根目录:
cp /root/whisker/main.xml /root/plugin-demo/main.xml
逐项说明关键配置:
pluginRepository:Whisker 插件只存在于 Apache 快照仓库,必须显式声明;releases关闭、snapshots打开。<descriptor>:必需参数(用户属性名apacheWhiskerDescriptor),指向元数据描述符文件。outputDirectory:可选,默认${project.build.directory},产物写进target/。outputEncoding:可选,默认${project.build.sourceEncoding},本文设为 UTF-8。phase=generate-resources:把生成挂到资源处理之前,mvn package等命令会自动带动。
5.4 运行 generate 目标
cd /root/plugin-demo && mvn -B generate-resources 2>&1 | tail -6
[INFO] Reading descriptor from /root/plugin-demo/main.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.63 s
[INFO] Finished at: 2026-10-15T13:52:40Z
(首次运行需从 Apache 快照仓库与中央仓库下载插件及传递依赖,冷缓存下实测约 47 秒;构建缓存就绪后约 0.6 秒,耗时以网速为准。)
检查产物:
ls -l /root/plugin-demo/target/LICENSE
head -3 /root/plugin-demo/target/LICENSE
-rw-r--r-- 1 root root 1076 Oct 15 14:25 target/LICENSE
Copyright (c) 2026 Example Technology Ltd.
验证点:Reading descriptor from ... 出现且 BUILD SUCCESS,target/LICENSE 内容与方案 A 的标准输出一致。
⚠️ 注意:默认 POSIX/C locale 下插件会报
Whisker failed to generate materials: Mismatched Charset(UTF-8) and CharsetEncoder(US-ASCII)——velocity 以平台默认字符集初始化、插件又以 UTF-8 写文件所致。先export LANG=C.UTF-8再执行 mvn 即可,实测修复有效。同理,含中文的描述符也需要 UTF-8 locale。
5.5 生成 NOTICE 文档
NOTICE 只在描述符定义了 primary-notice(或第三方资源携带声明)时才会生成。把主许可证换成 Apache License 2.0 并添加 primary-notice 段(完整描述符较长,许可证全文可从 https://www.apache.org/licenses/LICENSE-2.0.txt 取得,结构如下):
<licenses>
<license name='Apache License, Version 2'
id='osi:AL2'
url='https://www.apache.org/licenses/LICENSE-2.0.txt'>
<text>
(此处放入 Apache License 2.0 全文)
</text>
</license>
</licenses>
<primary-license id='osi:AL2'>
<copyright-notice>Copyright (c) 2026 Example Technology Ltd.</copyright-notice>
</primary-license>
<primary-notice>Apache Whisker Demo
Copyright 2026 Example Technology Ltd.
This product includes software developed by Example Technology Ltd.
(https://www.example.org).</primary-notice>
<primary-organisation id='example.org'/>
重新执行后实测产物:
export LANG=C.UTF-8 && cd /root/plugin-demo && mvn -B generate-resources
ls -l target/LICENSE target/NOTICE
-rw-r--r-- 1 root root 11399 Oct 15 14:25 target/LICENSE
-rw-r--r-- 1 root root 171 Oct 15 14:25 target/NOTICE
target/NOTICE 内容(实测全量):
Apache Whisker Demo
Copyright 2026 Example Technology Ltd.
This product includes software developed by Example Technology Ltd.
(https://www.example.org).
验证点:LICENSE 为版权声明加许可证全文,NOTICE 为 primary-notice 原文(缩进 2 空格),二者同时出现在 target/。
六、方案对比与选择建议
本节汇总两种方案的差异,给出选型建议。两种方案底层引擎一致,差别在交付形态。
| 维度 | 方案 A:快照 jar 直用 | 方案 B:Maven 插件 |
|---|---|---|
| 依赖面 | 单个 4.6 MB jar,零构建体系 | Maven + 插件及传递依赖自动解析 |
| 产物落点 | 标准输出(重定向落盘) | 直接写入 target/ |
| NOTICE 文档 | 实测标准输出未出现(快照缺陷,见 FAQ Q2) | 实测正常生成 |
| 生命周期集成 | 手工执行 | 挂接 generate-resources 阶段 |
| JDK 17 兼容 | 需 Multi-Release 单行修复(4.5 节) | 无需修复(插件路径自带全部依赖,实测正常) |
| 适用场景 | 服务器临时审计、脚本化批量生成 | 常规工程持续产出法律文档 |
选型建议:有 Maven 工程一律选方案 B(NOTICE 与生命周期都更可靠);临时审计或无构建体系的服务器选方案 A。两者共用同一份 main.xml 描述符,可以互为校验。
七、基础配置说明
本节说明 Whisker 使用中真正需要理解的「配置」。
- 描述符即配置:
-l指向的 XML 是唯一输入。三大段结构:第一段(licenses/notices/organisations)定义并给 id;第二段(primary-license/primary-notice/primary-organisation)声明发行版整体归属;第三段(within)按目录穷举资源归属。 - id 引用规则:
within → with-license(id) → by-organisation(id) → resource,引用未定义的 id 会立即报错(实测见 FAQ Q3)。 ${year}变量:primary-notice文本中的${year}在解析时替换为当前年份(如 2026)。- 可选属性:
resource支持sha1用于内容指纹核对;带模板的许可证家族用license/template元素参数化,license-parameters传值。 - 环境变量:方案 A 无需任何环境变量;方案 B 需要保证 locale 为 UTF-8(
export LANG=C.UTF-8),否则触发字符集不匹配错误(5.4 节)。JDK 17 直跑 jar 场景的修复已完成在 jar 内(4.5 节),不依赖环境变量。
八、验证清单
逐项通过即安装成功,任一不符按指引排查:
| 检查项 | 预期(实测值) | 不符时排查 |
|---|---|---|
java -version | openjdk version "17.0.20.1" | 重装 openjdk-17-jdk-headless |
| jar 下载 sha1 | a107b429d7a995c68da71de45f69b61b35a17a5e | 重新下载,勿跳过校验 |
--help 退出码 0 | 打印 -a/-g/-t/-l/-s/-h usage | 确认 jar 完整(4.3 节) |
| JDK 17 下 generate | 输出版权声明与许可证正文(4.5 节修复后) | 未修复先做 jar ufm,或用 JDK 8 |
| audit 干净目录 | No issues found. | 检查 -s 目录与 within 是否对应 |
| audit 含未声明文件 | 列出 Resources missing licenses | 确认 resource 清单与目录一致 |
插件 mvn generate-resources | BUILD SUCCESS + target/LICENSE | locale 需 LANG=C.UTF-8(5.4 节) |
| 插件 AL2 描述符 | target/NOTICE 171 字节(5.5 节) | 确认 primary-notice 已定义 |
九、常见问题(FAQ)
Q1:JDK 17 下执行 generate/audit 报 ExceptionInInitializerError?
见 4.5 节。根因是可执行 jar 缺 Multi-Release: true 清单属性导致 log4j-api 在 JDK 9+ 走了旧版调用者定位逻辑。jar ufm 追加一行即可;或改用 JDK 8 直跑(4.10 节)。--help 不触发该路径,崩溃只影响实际动作。
Q2:命令行 generate 输出里没有 NOTICE?
实测确认:命令行方式的 generate 固定把文档写到标准输出,且本快照在配置了 primary-notice 的描述符下标准输出也只有 LICENSE 文档。需要 NOTICE 时用方案 B 插件,target/NOTICE 实测正常生成(5.5 节)。该差异属上游快照缺陷,值得在项目邮件列表反馈。
Q3:报 MissingIDException: Missing ID 'osi:gpl3' for element 'license' linked from element 'with-license'(退出码 1)?
描述符里 with-license id= 引用了未在 <licenses> 定义过的 id。逐一核对三段 id 拼写一致即可;这也是 --generate 校验描述符合法性的表现,修复后重跑通过。
Q4:audit 报 Expected '/root/whisker/app' to exist?
-s 指向的目录不存在。audit 与 skeleton 都要求发行目录真实存在,先创建目录或修正路径。
Q5:报 Missing required option: l?
命令缺少 -l 描述符参数;-l 对三种动作都是必填。若用 --skeleton 还会额外要求 -s 发行目录(实测缺 -s 时打印 -s application source 后退出)。
Q6:插件报 Mismatched Charset(UTF-8) and CharsetEncoder(US-ASCII)?
locale 问题,export LANG=C.UTF-8 后重跑(5.4 节实测修复)。
十、卸载与清理
Whisker 本身不产生系统级安装,卸载即移除文件与本地缓存。
rm -rf /root/whisker /root/plugin-demo
ls /root/whisker 2>&1
ls: cannot access '/root/whisker': No such file or directory
清理 Maven 本地仓库中的 Whisker 快照(影响所有工程,慎用):
rm -rf $HOME/.m2/repository/org/apache/creadur/whisker
卸载 JDK 与 Maven(仅当不再需要)。先以 -s 预演确认将删除的包,无误后去掉 -s 真正执行:
apt-get -s purge -y openjdk-17-jdk-headless openjdk-8-jdk-headless maven
# 输出节选(实测首尾)
The following packages will be REMOVED:
maven* openjdk-17-jdk-headless* openjdk-8-jdk-headless*
0 upgraded, 0 newly installed, 3 to remove and 3 not upgraded.
确认无误后真正卸载(实际执行):
apt-get purge -y openjdk-17-jdk-headless openjdk-8-jdk-headless maven && apt-get autoremove -y
十一、参考链接
- Apache Whisker 官网(含 In 5 Minutes 与元数据参考):https://creadur.apache.org/whisker/
- Apache 快照仓库 whisker 目录:https://repository.apache.org/content/repositories/snapshots/org/apache/creadur/whisker/
- 源码仓库(含 apache-whisker-0.1 标签):https://github.com/apache/creadur-whisker
- 命令行模块官方说明:https://creadur.apache.org/whisker/apache-whisker-cli/index.html
- Maven 插件 generate 目标参数:https://creadur.apache.org/whisker/apache-whisker-maven-plugin/generate-mojo.html
- 元数据模型参考(含 DTD):https://creadur.apache.org/whisker/meta-data.html
- Apache Creadur 项目主页(Rat/Tentacles/Whisker 全家):https://creadur.apache.org/