Ant:从合并的jar文件中排除文件

时间:2009-08-13 22:04:47

标签: ant jar

对于一个java项目,我想将它依赖的所有第三方jar合并到Apache Ant创建的主jar中,我已经设法做了。

问题是这些jar文件中的一些在其META-INF目录中有签名文件,所以当我尝试运行我的jar文件时,我收到错误消息"Invalid signature file digest for Manifest main attributes"。手动删除签名文件后,错误就消失了。

我尝试使用excludes - 属性或exclude标记过滤我的ant文件中的签名文件,但似乎没有任何效果。

这是蚂蚁任务:

<target name="jar" description="Creates the jar file">
  <mkdir dir="${jar}"/>
  <jar destfile="${jar}/${ant.project.name}.jar" level="9" filesetmanifest="mergewithoutmain">
    <zipgroupfileset dir="${lib}" includes="*.jar"/>
    <zipfileset dir="${class}"/>
    <manifest>
      <attribute name="Main-Class" value="${mainclass}"/>
    </manifest>
  </jar>
</target>

如何在此ant任务中从生成的jar中过滤文件?谢谢你的帮助!

6 个答案:

答案 0 :(得分:38)

carej是对的。我一直在尝试这样做,将其他jar合并到我的应用程序jar中,不包括某些文件,并且没有办法使用<zipgroupfileset>

我的解决方案是unzip / clean-up / jar方法的一种变体:我首先将所有外部库jar合并到一个<zipgroupfileset>,然后将其合并到我的<zipfileset>中,这允许过滤。在我的情况下,它的工作速度明显更快,并且比将文件解压缩到磁盘更清晰:

<jar jarfile="${dist}/lib/external-libs.jar">
  <zipgroupfileset dir="lib/">
    <include name="**/*.jar"/>
  </zipgroupfileset>
</jar>
<sleep seconds="1"/>
<jar jarfile="${dist}/lib/historadar-${DSTAMP}.jar" manifest="Manifest.txt">
  <fileset dir="${build}" includes="**/*.*"/>
  <zipfileset src="${dist}/lib/external-libs.jar">
    <exclude name="*"/>
  </zipfileset>
</jar>

第一个<jar>将它在lib /中找到的所有jar放入external-libs.jar,然后我等待一秒钟,以避免在将来收到有关修改日期的文件的警告,然后我将build /目录中的类文件与external-libs.jar的内容合并,不包括其根目录中的文件,在本例中为README文件和示例。

然后我有自己的README文件,列出了我在应用程序中包含的所有库所需的信息,例如许可证,网站等。

答案 1 :(得分:11)

据我所知,使用&lt; zipgroupfileset&gt;时无法过滤:使用的include / excludes适用于要合并的拉链,而不是其中的内容。

如果要合并一组众所周知的JAR,可以使用个人&lt; zipset&gt;每个条目;此方法允许使用include / exclude过滤源存档的内容。

另一种方法是简单地将所有内容解压缩到一个临时位置,删除/修改不需要的位,然后将所有内容拉回来。

答案 2 :(得分:3)

您可以使用exclude标记中的zipfileset参数从合并的外部JAR文件中删除内容,如下所示:

<jar jarfile="${dist}/lib/external-libs.jar">
  <zipgroupfileset dir="lib/" excludes="META-INF/**/*">
    <include name="**/*.jar"/>
  </zipgroupfileset>
</jar>

生成的JAR文件将是未签名的。

答案 3 :(得分:2)

Alberto的回答很好但是需要时间来解压缩和重新压缩存档。我实现了一个新的Ant任务来使用内置的过滤功能,从而加快执行速度:

public class FilterZipTask extends Task {

  private Zip zipTask;

  private List<FileSet> groupfilesets = new ArrayList<FileSet>();

  private String excludes;

  public void setExcludesInZips(String excludes) {
    this.excludes = excludes;
  }

  public void addZipGroupFileset(FileSet set) {
    groupfilesets.add(set);
  }

  public void addZip(Zip zipTask) {
    this.zipTask = zipTask;
  }

  @Override
  public void execute() throws BuildException {
    for (FileSet fileset : groupfilesets) {
      Iterator<FileResource> iterator = fileset.iterator();
      while (iterator.hasNext()) {
        ZipFileSet zfs = new ZipFileSet();
        FileResource resource = iterator.next();
        zfs.setSrc(resource.getFile());
        zfs.setExcludes(excludes);
        zipTask.addZipfileset(zfs);
      }
    }
    zipTask.execute();
  }
}

并在构建文件中使用它如下:

<taskdef name="filterzip" classname="FilterZipTask"/>
<filterzip excludesInZips="META-INF/*.*">
  <zipgroupfileset dir="${deps.dir}" includes="*.jar" />
  <zip destfile="${destjar}" />
</filterzip>

答案 4 :(得分:0)

我也遇到了同样的问题。谷歌搜索了很多,找到了适合我的东西。 un jar jar jar文件删除。 META-INF / .SF, META-INF / .DSA  文件。再次将其运行并运行它不应显示错误消息。

错误原因在此解释:http://qe-cafe.blogspot.in/2010/06/invalid-signature-file-digest-for.html

答案 5 :(得分:0)

几个小时一直在努力解决同样的问题,所以最后通过扩展现有任务来完成新任务:

import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.ZipFileSet;

public class CustomizedJarTask extends Jar {

    protected Set<String> filters;

    @Override
    public void add(ResourceCollection resources) {
        if (filters != null && resources instanceof ZipFileSet) {
            ZipFileSet set = ZipFileSet.class.cast(resources);
            for (String filter : filters)
                set.createExclude().setName(filter);
        }
        super.add(resources);
    }

    public void setFilters(String patterns) {
        StringTokenizer tokenizer = new StringTokenizer(patterns, ", ", false);
        while (tokenizer.hasMoreTokens()) {
            if (filters == null)
                filters = new HashSet<>();
            filters.add(tokenizer.nextToken());
        }
    }

}

有了上述内容,构建文件中我需要的只是:

<taskdef name="customized-jar" classname="CustomizedJarTask" classpath="${basedir}/bin/" />
<customized-jar jarfile="${directory.build}/external-libs.jar" duplicate="fail" filters="META-INF/**">
    <zipgroupfileset dir="${directory.libs}">
        <include name="**/*.jar" />
    </zipgroupfileset>
</customized-jar>