Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I exclude extraDependency META-INF files for exec-war goal?

My question is exactly the problem faced by this user of maven-shade plugin:

How to exclude META-INF files from bundle?

But I am using tomcat7-maven-plugin to build a self-running webapp. I have recently switched database drivers to use Microsoft's own driver which implements JDBC4. Now I have problems including it as an extraDependency in my exec-war goal. Here is the relevant part of the pom.xml.

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.1</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <path>/oases</path>
                <contextFile>applicationContext.xml</contextFile>
                <extraDependencies>
                    <extraDependency>
                        <groupId>com.microsoft.sqlserver</groupId>
                        <artifactId>sqljdbc4</artifactId>
                        <version>4.0</version>
                    </extraDependency>
                </extraDependencies>
                <excludes>
                    <exclude>META-INF/MSFTSIG.RSA</exclude>
                </excludes>
           </configuration>
       </execution>
    </executions>
</plugin>

The project builds fine except that maven does not obey the excludedirective so that the sqljdbc4 RSA file is included in the META-INF directory. This means that when I try to run my exec-war jar file I get this error.

Exception in thread "main" java.lang.SecurityException: Invalid 
    signature file digest for Manifest main attributes

I have read the code and as far as I can tell the plugin is correctly configured to exclude the sqljdbc4 META-INF files. Here is the plugin code for version 2.2, which is what I am using. It looks like this should do what I want. However, the exec-war jar still includes META-INF/MSFTSIG.RSA

org.apache.tomcat.maven.plugin.tomcat7.run.AbstractExecWarMojo.java

protected void extractJarToArchive( JarFile file, ArchiveOutputStream os, String[] excludes )
    throws IOException
    {
        Enumeration<? extends JarEntry> entries = file.entries();
        while ( entries.hasMoreElements() )
        {
            JarEntry j = entries.nextElement();
            if ( excludes != null && excludes.length > 0 )
            {
                for ( String exclude : excludes )
                {
                    if ( SelectorUtils.match( exclude, j.getName() ) )
                    {
                        continue;
                    }
                }
            }

            if ( StringUtils.equalsIgnoreCase( j.getName(), "META-INF/MANIFEST.MF" ) )
            {
                continue;
            }
            os.putArchiveEntry( new JarArchiveEntry( j.getName() ) );
            IOUtils.copy( file.getInputStream( j ), os );
            os.closeArchiveEntry();
        }
        if ( file != null )
        {
            file.close();
        }
    }
}

EDITS

  1. Reverted to plugin version 2.1 due to the version 2.2 bug noted in this answer https://stackoverflow.com/a/23436438/980454
  2. One workaround is to create an unsigned version of the dependency jar.
like image 331
carbontax Avatar asked Apr 16 '15 21:04

carbontax


1 Answers

The code you posted for AbstractExecWarMojo has a bug: the continue in the inner for loop has no effect whatsoever. Instead, It should be continuing on the outer while loop in order to skip placing archive entries whenever an exclude is matched, as follows:

protected void extractJarToArchive( JarFile file, ArchiveOutputStream os, String[] excludes )
    throws IOException
    {
        Enumeration<? extends JarEntry> entries = file.entries();
        outer:
        while ( entries.hasMoreElements() )
        {
            JarEntry j = entries.nextElement();
            if ( excludes != null && excludes.length > 0 )
            {
                for ( String exclude : excludes )
                {
                    if ( SelectorUtils.match( exclude, j.getName() ) )
                    {
                        continue outer;
                    }
                }
            }

            if ( StringUtils.equalsIgnoreCase( j.getName(), "META-INF/MANIFEST.MF" ) )
            {
                continue;
            }
            os.putArchiveEntry( new JarArchiveEntry( j.getName() ) );
            IOUtils.copy( file.getInputStream( j ), os );
            os.closeArchiveEntry();
        }
        if ( file != null )
        {
            file.close();
        }
    }
}

To fix this problem in your project, you can checkout/modify/build the tomcat7-maven-plugin from source. If you do so, and you test it out successfully, it would be great if you contributed a patch. I already filed an issue for it.

like image 141
heenenee Avatar answered Nov 12 '22 01:11

heenenee