Building patches for Eclipse

Frustrated by mysterious error messages from PDE? Overwhelmed by Buckminster?

If you need to apply a simple patch to a plug-in for Eclipse, there is a more simple way. Follow this recipe:

  1. Download the source for the plug-in
  2. Create a new project
  3. Add all plug-ins in the eclipse/plugins folder to the build path. Use the variable eclipse_home. This is most simple if you use an ANT build script. If you want to waste time, try to figure out which plugins you need and only add those.
  4. Extract the few Java source files that you need to modify and copy them into your project.
  5. Copy the JARs of plugins you want to patch into your project.
  6. Fix the bugs.
  7. Use a bit of ANT magic to replace the Java classes in the JARs you copied in step #5 with the fixed versions. The trick here is that most Eclipse JARs are signed. You’ll need to remove the cryptographic keys in order to be able to load the JARs. See below for a piece of code that does the trick.
  8. Add a rule to your build.xml to copy the fixed JARs back into the plugins folder of Eclipse.
  9. Exit Eclipse (or start another instance) to test your fixes.

Here is the source to strip the SHA1-Digest keys from a MANIFEST.MF file:

// Needs commons-io 1.4
public class FilterManifest {

    public static void main( String[] args ) {
        try {
            FilterManifest tool = new FilterManifest();
            tool.run( args );
        } catch( Exception e ) {
            e.printStackTrace();
            System.exit( 1 );
        }
    }

    private void run( String[] args ) throws Exception {
        File manifestFile = new File( args[0] );
        Manifest manifest = readManifest( manifestFile );

        manifest.getEntries().clear();

        File backup = new File( manifestFile.getAbsolutePath() + ".bak" );
        if(! manifestFile.renameTo( backup ) ) {
            throw new RuntimeException( "Can't backup file" );
        }

        save( manifest, manifestFile );
    }

    private void save( Manifest manifest, File manifestFile ) throws IOException {
        FileOutputStream stream = new FileOutputStream( manifestFile );
        try {
            manifest.write( stream );
        } finally {
            IOUtils.closeQuietly( stream );
        }
    }

    private Manifest readManifest( File manifestFile ) throws IOException {
        FileInputStream stream = new FileInputStream( manifestFile );
        try {
            return new Manifest( stream );
        } finally {
            IOUtils.closeQuietly( stream );
        }
    }

}

To use this code, use this ANT code:

    <target name="fix-org.eclipse.birt.engine" depends="init">
        <unjar src="plugins/org.eclipse.birt.report.engine_2.6.1.v20100915.jar" dest="tmp">
            <patternset>
                <include name="META-INF/MANIFEST.MF"/>
            </patternset>
        </unjar>
        <java classname="tools.FilterManifest">
            <arg file="tmp/META-INF/MANIFEST.MF"/>
            
            <classpath>
                <pathelement location="target-eclipse/classes" />
                <pathelement location="target/classes" />
                <pathelement location="${m2_repo}/commons-io/commons-io/1.4/commons-io-1.4.jar" />
            </classpath>
        </java>
        <jar destfile="tmp/org.eclipse.birt.report.engine_2.6.1.v20100915.jar"
            compress="true" update="true" duplicate="preserve" index="true"
            manifest="tmp/META-INF/MANIFEST.MF"
        >
            <fileset dir="target-eclipse/classes">
                <include name="org/eclipse/birt/report/engine/**/*" />
            </fileset>
            <zipfileset src="plugins/org.eclipse.birt.report.engine_2.6.1.v20100915.jar">
                <exclude name="META-INF/*"/>
            </zipfileset>
        </jar>
    </target>

The two <pathelement> elements are necessary to make the code work from Eclipse and command line Maven (I’m using different target directories for Eclipse and Maven).

The complex <jar> target allows to copy everything from the existing plugin JAR but the crypto info.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s