que - Ant: Excluye archivos del archivo jar fusionado
generar jar con ant (6)
Para un proyecto en java, me gustaría fusionar todos los frascos de terceros que dependan del frasco principal creado por Apache Ant, que ya logré hacer.
El problema es que algunos de estos archivos jar tienen archivos de firma en sus directorios META-INF
, por lo que cuando intento ejecutar mi archivo jar, aparece el mensaje de error "Invalid signature file digest for Manifest main attributes"
. Después de eliminar los archivos de firma manualmente, el error desaparece.
Intenté filtrar los archivos de firmas en mi archivo ant con un atributo excludes
o un tag exclude
, pero nada parece tener ningún efecto.
Esta es la tarea 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>
¿Cómo puedo filtrar archivos del archivo jar resultante en esta tarea previa? ¡Gracias por tu ayuda!
Carej tiene razón. He estado tratando de hacer esto, fusionando otros archivos jar en mi aplicación jar excluyendo algunos archivos, y no hay manera de usar <zipgroupfileset>
para ello.
Mi solución es una variante del método unzip / clean-up / jar: primero fusiono todos los archivos jar externos de la biblioteca en uno con <zipgroupfileset>
, luego lo <zipfileset>
con el mío con <zipfileset>
que permite el filtrado. En mi caso, funciona notablemente más rápido y es más limpio que descomprimir los archivos en el disco:
<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>
El primer <jar>
coloca todos los archivos <jar>
que encuentra en lib / en external-libs.jar, luego hago que espere un segundo para evitar recibir advertencias sobre los archivos que tienen fechas de modificación en el futuro, luego fusiono mis archivos de clase de el directorio build / con el contenido de external-libs.jar excluyendo los archivos en su raíz, que en este caso eran archivos y ejemplos README.
Luego tengo mi propio archivo README que enumera toda la información necesaria sobre las bibliotecas que incluyo en mi solicitud, como licencia, sitio web, etc.
He estado luchando con el mismo problema durante unas pocas horas, por lo que terminé escribiendo una nueva tarea extendiendo la existente:
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());
}
}
}
Con lo anterior, todo lo que necesito en el archivo de compilación es:
<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>
La respuesta de Alberto funciona bien pero toma tiempo para descomprimir y volver a comprimir el archivo. Implementé una nueva tarea Ant para usar funciones de filtrado integradas, lo que resulta en una ejecución mucho más rápida:
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();
}
}
Y úselo en el archivo de compilación de la siguiente manera:
<taskdef name="filterzip" classname="FilterZipTask"/>
<filterzip excludesInZips="META-INF/*.*">
<zipgroupfileset dir="${deps.dir}" includes="*.jar" />
<zip destfile="${destjar}" />
</filterzip>
Puede usar el parámetro exclude
en la etiqueta zipfileset
para eliminar el contenido de los archivos JAR externos fusionados, como esto:
<jar jarfile="${dist}/lib/external-libs.jar">
<zipgroupfileset dir="lib/" excludes="META-INF/**/*">
<include name="**/*.jar"/>
</zipgroupfileset>
</jar>
El archivo JAR resultante se anulará.
Que yo sepa, no hay forma de filtrar cuando se usa <zipgroupfileset>: la inclusión / exclusión utilizada se aplica a las cremalleras que se fusionarán, no al contenido que contienen.
Si tiene un conjunto conocido de JARs para fusionar, puede usar entradas <zipset> individuales para cada uno; este enfoque permite utilizar la inclusión / exclusión para filtrar los contenidos del archivo fuente.
Un enfoque alternativo es simplemente descomprimir todo en una ubicación temporal, eliminar / modificar los bits no deseados y luego volver a comprimir todo.
Yo también estaba enfrentando el mismo problema. Busqué en Google y encontré algo que me funcionó. Deshacerte de eliminar el archivo jar. Archivos META-INF / .SF, META-INF / .DSA. Vuelva a cargarlo y ejecutarlo no debería mostrar el mensaje de error.
La causa del error se explica aquí: http://qe-cafe.blogspot.in/2010/06/invalid-signature-file-digest-for.html