Ant: Исключить файлы из объединенного файла JAR

Для java-проекта я хотел бы объединить все сторонние jar-файлы, от которых это зависит, в основной jar-файл, созданный Apache Ant, что мне уже удалось сделать.

Проблема в том, что некоторые из этих jar-файлов содержат файлы сигнатур META-INF-каталогов, поэтому, когда я пытаюсь запустить свой jar-файл, я получаю сообщение об ошибке "Invalid signature file digest for Manifest main attributes", После того, как я вручную удалил файлы сигнатур, ошибка исчезла.

Я попытался отфильтровать файлы сигнатур в моем файле с excludes-атрибут или exclude-Tag, но, кажется, ничего не имеет никакого эффекта.

Это муравейник:

<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>

Как я могу отфильтровать файлы из полученной банки в этой муравейной задаче? Спасибо за вашу помощь!

6 ответов

Решение

Насколько мне известно, при использовании нет способа фильтрации: используемые там включения / исключения применяются к объединяемым архивам, а не к содержимому в них.

Если у вас есть хорошо известный набор файлов JAR для объединения, вы можете использовать отдельные записи для каждого из них; этот подход позволяет использовать include/ exclude для фильтрации содержимого исходного архива.

Альтернативный подход состоит в том, чтобы просто разархивировать все во временную папку, удалить / изменить ненужные биты, а затем заархивировать все обратно.

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> помещает все jar-файлы, которые он находит в lib/, в external-libs.jar, затем я заставляю его ждать одну секунду, чтобы избежать предупреждений о файлах с датами изменения в будущем, затем я объединяю свои файлы классов из каталога build/ с содержимое файла external-libs.jar, исключая файлы в его корне, которые в данном случае были файлами README и примерами.

Затем у меня есть собственный файл README, в котором содержится вся необходимая информация о тех библиотеках, которые я включаю в свое приложение, таких как лицензия, веб-сайт и т. Д.

Вы можете использовать exclude параметр в zipfileset тег для удаления содержимого из объединенных внешних файлов JAR, например:

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

Полученный файл JAR будет без подписи.

Ответ Альберто работает отлично, но требуется время, чтобы разархивировать и разархивировать архив. Я реализовал новую задачу 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>

Несколько часов боролся с той же проблемой, поэтому в итоге написал новую задачу, расширив существующую:

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>

Я также столкнулся с той же проблемой. Погуглил много и нашел то, что мне помогло. Un-JAR вы JAR файл удалить. Файлы META-INF / .SF, META-INF /.DSA. Снова запустите его и не показывайте сообщение об ошибке.

Причина ошибки объясняется здесь: http://qe-cafe.blogspot.in/2010/06/invalid-signature-file-digest-for.html

Другие вопросы по тегам