首页 > 解决方案 > 从现有的非脂肪罐创建一个脂肪罐

问题描述

无论出于何种原因,我一直在使用的一个应用程序要求所有类都位于相同的基本层次结构中(意味着 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
    

标签: javajar

解决方案


这是我为这个问题所做的解决方案,尽管它不能很好地处理命名冲突。

如果您想读取 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;
}

推荐阅读