java - 从现有的非脂肪罐创建一个脂肪罐
问题描述
无论出于何种原因,我一直在使用的一个应用程序要求所有类都位于相同的基本层次结构中(意味着 jar 不能在 jar 内,否则它将失败)。因为我正在创建自己的应用程序供其他人使用,我无法控制他们是否有一个胖罐子,所以我必须想办法“变胖”?一个已经做好的罐子。
可以使用 JarFile 并且每次遇到 jar 文件时,将 jar 写入自己的文件并重新执行;但是,为了访问 JarFile 条目列表而复制这样的内容,感觉绝对是浪费内存和时间
Ex: test.jar
-com.package
-main.class
-dependency1.jar
-com.depedency1
-test.class
and what was needed:
test.jar
-com.package
-main.class
-com.dependency1
-test.class
解决方案
这是我为这个问题所做的解决方案,尽管它不能很好地处理命名冲突。
如果您想读取 jar 中的所有类,readJar 可能对其他几个任务有帮助。
public class JarUtils extends Base {
public static File fatJar(File dest, File file) throws IOException {
finer("Generating Fat Jar:" + file);
try (JarInputStream zis = new JarInputStream(new BufferedInputStream(new FileInputStream(file)));
JarOutputStream zos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)), zis.getManifest())) {
final byte[] buffer = new byte[1024];
readJar(file.getName(), zis, (entry, is) -> {
int len;
zos.putNextEntry(entry);
while ((len = is.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
}, new ArrayList<>());
zos.finish();
}
return dest;
}
private static void readJar(String jarName, JarInputStream zis, JarEntryWalker walker, List<String> checkedEntries) throws IOException {
ZipEntry entry;
if (!jarName.endsWith("/")) jarName += "/";
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().contains(".jar")) {
readJar(entry.getName(), new JarInputStream(zis), walker, checkedEntries);
} else {
String name = (entry.getName().contains("META-INF/") ? jarName : "") + entry.getName();
if (!checkedEntries.contains(name)) {
ZipEntry zipEntry = new ZipEntry(name);
zipEntry.setComment(entry.getComment());
zipEntry.setExtra(entry.getExtra());
zipEntry.setCreationTime(entry.getCreationTime());
zipEntry.setLastAccessTime(entry.getLastAccessTime());
zipEntry.setLastModifiedTime(entry.getLastModifiedTime());
walker.entry(zipEntry, zis);
checkedEntries.add(name);
}
}
}
}
}
interface JarEntryWalker {
void entry(ZipEntry zipEntry, InputStream is) throws IOException;
}
推荐阅读
- sql - 来自 vertabelo 的此模式中重复事件的 SQL 查询
- javascript - 未捕获(承诺中)类型错误:无法读取未定义的属性“过滤器”
- elasticsearch - Elasticsearch:获取字段中具有特定值的文档
- angular - Angular 8 - 将组件动态插入另一个组件
- javascript - 如果 PHP 回显代码返回一个值,则运行脚本。别的什么都没有
- regex - 创建信用卡正则表达式
- excel - 复制后如何关闭源文件?
- python - Matplotlib 使用什么样的 RGB 颜色空间?
- c# - 从 Blazor 客户端模块查询本地 Active Directory?
- amp-html - 如何使用自定义 JavaScript 验证 AMP 页面并在移动设备和桌面设备上浏览