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

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

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

Я попытался отфильтровать файлы подписи в моем ant -file с excludes -attribute или exclude -tag, но ничего не имеет никакого эффекта.

Это ant -task:

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

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

Ответ 1

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

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

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

Ответ 2

carej прав. Я пытался это сделать, объединяя другие банки в моем приложении jar, исключая некоторые файлы, и нет возможности использовать для него <zipgroupfileset>.

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

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

Ответ 3

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

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

В результате JAR файл будет неподписанным.

Ответ 4

Ответ 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>

Ответ 5

У меня также была такая же проблема. Много искал и нашел что-то, что сработало для меня. Удалите файл jar файла. META-INF/.SF, META-INF/.DSA  файлы. Объедините его снова и запустите, не должно появляться сообщение об ошибке.

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

Ответ 6

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

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>