如何使用gradle连接fat jar中的文本文件

时间:2017-11-07 09:35:36

标签: java gradle concatenation executable-jar

我正在用下面的代码构建一个胖罐子。但是,我在不同的jar中有多个具有相同名称的属性文件,这些文件被收集到胖罐中。

我想解决方法是将具有相同名称的文件连接/合并到一个文件中,但我该怎么做?我发现了这个问题How do I concatenate multiple files in Gradle?

如何在it对象中访问和合并属性文件(我们将它们命名为myproperties.properties)?

task fatJar(type: Jar) {
 def mainClass = "myclass"
 def jarName = "myjarname"
    zip64=true
    manifest {
      attributes(
        'Main-Class': mainClass,
        'Class-Path': configurations.compile.collect { it.getName() }.join(' ')
      )
    }
    baseName = project.name + '-' + jarName + '-all'
    from { 
      configurations.compile.collect {
        it.isDirectory() ? it : zipTree(it) 
      } 
    }
    {
      exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
    }
    with jar
 }

解决方案: 我将给出的答案标记为解决方案,尽管我没有尝试过。相反,我们通过创建多个jar并将其添加到类路径来解决问题。

1 个答案:

答案 0 :(得分:0)

您可以编写自定义MergeCopy任务。例如

public interface FileMerger implements Serializable {
    public void merge(String path, List<File> files, OutputStream out) throws IOException;
}

public class MergeCopy extends DefaultTask {
    private File outputDir;
    private List<FileTree> fileTrees = []

    @TaskInput
    FileMerger merger

    @OutputDirectory
    File getOutputDir() {
       return outputDir
    }

    @InputFiles
    List<FileTree> getFileTrees() {
       return fileTrees
    }

    void from(FileTree fileTree) {
        fileTrees.add(fileTree)
    }

    void into(Object into) {
        outputDir = project.file(into)
    }

    @TaskAction
    void copyAndMerge() {
       Map<String, List<File>> fileMap = [:]
       FileTree allTree = project.files().asFileTree
       fileTrees.each { FileTree fileTree ->
           allTree = allTree.plus(fileTree)
           fileTree.visit { FileVisitDetails fvd ->
               String path = fvd.path.path
               List<File> matches = fileMap[path] ?: []
               matches << fvd.file
               fileMap[path] = matches
           }
       }
       Set<String> dupPaths = [] as Set
       Set<String> nonDupPaths = [] as Set
       fileMap.each { String path, List<File> matches ->
           if (matches.size() > 1) {
              dupPaths << path
           } else {
              nonDupPaths << path
           }
       }
       FileTree nonDups = allTree.matching {
           exclude dupPaths
       }
       project.copy {
           from nonDups
           into outputDir
       }
       for (String dupPath : dupPaths) {
           List<File> matches = fileMap[dupPath]
           File outFile = new File(outputDir, dupPath)
           outFile.parentFile.mkdirs()
           try (OutputStream out = new FileOutputStream(outFile)) {
               merger.merge(dupPath, matches, out)
               out.flush()
           }
       }
    }
}

然后你可以做

task mergeCopy(type: MergeCopy) {
    configurations.compile.files.each {
        from it.directory ? fileTree(it) : zipTree(it)
    } 
    into "$buildDir/mergeCopy"
    merger = { String path, List<File> files, OutputStream out ->
       // TODO: implement
    }
}

task fatJar(type: Jar) {
    dependsOn mergeCopy
    from mergeCopy.outputDir
    ...
}