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