首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将报表部分与Gradle和shadowJar合并

如何将报表部分与Gradle和shadowJar合并
EN

Stack Overflow用户
提问于 2021-02-23 12:59:12
回答 1查看 728关注 0票数 4

我所需要的

我们用Gradle和shadowJar包装我们的产品。我们使用的一些库使用Jar舱单中的个别章节,特别是像实现-标题和实现-版本之类的属性。这些产品有时会显示在我们的产品中,所以我希望它们能在这个过程中幸存下来。

示例

Lib1.jar/META/MANIFEST.MF

代码语言:javascript
复制
Manifest-Version: 1.0
...

Name: org/some/lib
...
Implementation-Title: someLib
Implementation-Version: 2.3
...

Lib2.jar/META/MANIFEST.MF

代码语言:javascript
复制
Manifest-Version: 1.0
...

Name: org/some/other/lib
...
Implementation-Title: someOtherLib
Implementation-Version: 5.7-RC
...

=> Product.jar/META/MANIFEST.MF

代码语言:javascript
复制
Manifest-Version: 1.0
...

Name: org/some/lib
...
Implementation-Title: someLib
Implementation-Version: 2.3
...

Name: org/some/other/lib
...
Implementation-Title: someOtherLib
Implementation-Version: 5.7-RC
...

我所发现的

代码语言:javascript
复制
project.shadowJar {
    manifest {
        attributes(["Implementation-Title" : "someLib"], "org/some/lib")
        attributes(["Implementation-Title" : "someOtherLib"], "org/some/other/lib")
    }
}

静态地生成我想要的东西。

  • shadowJar可以为我提供依赖项列表。但是,当我像这样迭代FileCollection时
代码语言:javascript
复制
project.shadowJar {
    manifest {
        for (dependency in includedDependencies) {
            // read in jar file and set attributes
        }
    }
}

Gradle不高兴:“无法更改依赖项配置的依赖关系':project:products::compile‘在依赖项解决方案中包含了它之后。”

  • 当我定义一个新任务时
代码语言:javascript
复制
def dependencies = [];
project.tasks.register('resolveDependencies') {
    doFirst {
        gradleProject.configurations.compile.resolvedConfiguration.resolvedArtifacts.each {
            dependencies.add(it.file)
        }
    }
}
project.tasks['shadowJar'].dependsOn(project.tasks['resolveDependencies']);

project.shadowJar {
    manifest {
        // dependencies will be empty when this code is called
        for (dependency in dependencies) {
            // read in jar file and set attributes
        }
    }
}

依赖关系没有及时解决。

我想知道的是

如何在不扰乱Gradle的情况下访问依赖项?或者,是否有另一种方法可以将命名的各个部分与shadowJar合并?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-03-04 13:12:54

根据https://github.com/johnrengelman/shadow/issues/369的要求,应该使用shadowJar的变压器接口来实现这一点。

所以来了:

代码语言:javascript
复制
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer;
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext;

import java.io.ByteArrayOutputStream;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.Map.Entry;

import shadow.org.apache.tools.zip.ZipOutputStream;
import shadow.org.apache.tools.zip.ZipEntry;
import shadow.org.codehaus.plexus.util.IOUtil;

import org.gradle.api.file.FileTreeElement;

import static java.nio.charset.StandardCharsets.*
import static java.util.jar.JarFile.*;

/**ManifestVersionMergeTransformer appends all version information sections from manifest files to the resulting manifest file.
  * @author Robert Lichtenberger
  */
public class ManifestMergeTransformer implements Transformer {

    String includePackages; // regular expression that must match a given package
    String excludePackages; // regular expression that must not match a given package

    private Manifest manifest;

    @Override
    public boolean canTransformResource(FileTreeElement element) {
        MANIFEST_NAME.equalsIgnoreCase(element.relativePath.pathString);
    }

    @Override
    public void transform(TransformerContext context) {
        if (manifest == null) {
            manifest = new Manifest(context.is);
        } else {
            Manifest toMerge = new Manifest(context.is);
            for (Entry<String, Attributes> entry : toMerge.getEntries().entrySet()) {
                if (mustInclude(entry.getKey())) {
                    manifest.getEntries().put(entry.getKey(), entry.getValue());
                }
            }
        }
        IOUtil.close(context.is);
    }

    private boolean mustInclude(String packageName) {
        return (includePackages == null || packageName.matches(includePackages)) && (excludePackages == null || !packageName.matches(excludePackages));
    }

    @Override
    public boolean hasTransformedResource() {
        return true;
    }

    @Override
    public void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) {
        ZipEntry entry = new ZipEntry(MANIFEST_NAME);
        entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time);
        os.putNextEntry(entry);
        if (manifest != null) {
            ByteArrayOutputStream manifestContents = new ByteArrayOutputStream();
            manifest.write(manifestContents);
            os.write(manifestContents.toByteArray());
        }
    }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66333597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档