2009-08-13 25 views
15

Para un proyecto de Java, me gustaría fusionar todos los archivos jar de terceros, depende del contenedor principal creado por Apache Ant, que ya he logrado.Ant: excluir archivos del archivo jar fusionado

El problema es que algunos de estos archivos jar tienen archivos de firma en sus directorios META-INF, así que cuando intento ejecutar mi archivo jar, aparece el mensaje de error "Invalid signature file digest for Manifest main attributes". Después de eliminar manualmente los archivos de firma, el error desapareció.

Intenté filtrar los archivos de firma en mi archivo ant con un excludes -tributo o un exclude -tag, pero nada parece tener ningún efecto.

Esta es la hormiga-tarea:

<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 los archivos de la jarra que resulta en esta hormiga-tarea? ¡Gracias por tu ayuda!

+0

consulte el error [zipgroupfileset debe soportar una especificación del patrón anidado] (https://bz.apache.org/bugzilla/show_bug.cgi?id=34403). –

Respuesta

8

Que yo sepa, no hay forma de filtrar cuando se utiliza <zipgroupfileset>: las inclusiones/exclusiones usadas allí se aplican a las cremalleras que se fusionarán, no el contenido dentro de ellas.

Si tiene un conjunto bien conocido de JAR para fusionar, puede usar entradas individuales de <zipset> para cada una; este enfoque permite usar incluir/excluir 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, luego comprimir todo de nuevo.

34

carej es correcto. He intentado hacer esto, fusionando otros archivos jar en mi jar de aplicación excluyendo algunos archivos, y no hay forma de usarlo para el <zipgroupfileset>.

Mi solución es una variante del método de descomprimir/limpiar/jar: Primero fusiono todos los frascos de biblioteca externos en uno con <zipgroupfileset>, luego lo fusiono en el mío con <zipfileset> que permite el filtrado. En mi caso funciona mucho 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> 

La primera <jar> pone todos los frascos que encuentra en lib/externa en-libs.jar, entonces me hacen esperar a que uno segundo para evitar recibir advertencias sobre los archivos que tienen fechas de modificación en el futuro, entonces fusiono mis archivos de clase de la compilación/directorio con el contenido de libs-jar externo excluyendo los archivos en su raíz, que en este caso eran archivos README y ejemplos.

entonces tengo mi propio archivo README que enumera toda la información necesaria acerca de aquellas bibliotecas que incluyo en mi solicitud, tales como licencia, página web, etc.

+0

gracias, ¡esto fue realmente útil! – tth

2

Usted puede utilizar el parámetro exclude en zipfileset etiqueta para eliminar el contenido de archivos JAR externos fusionados, como este:

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

El archivo JAR resultante no estará firmado.

2

La respuesta de Alberto funciona bien pero tarda un tiempo en descomprimir & volver a descomprimir el archivo.He implementado una nueva tarea Ant para uso integrado en el funciones de filtrado, que se traduce en la ejecución mucho más rápido:

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 utilizarlo en fichero de construcción de la siguiente manera:

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

han estado luchando con el mismo problema durante unas horas, por lo que terminó escribiendo una nueva tarea mediante la ampliación de la ya 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 el arriba, todo lo que necesito en el fichero de construcció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> 
Cuestiones relacionadas