Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

subclassing an open-source library

I am using a large open source library and need to generate personal subclasses of a few of the classes. What are the best strategies? I would like to keep the original library unaltered and be easily able to reconfigure when it is updated. It is unlikely that my code is worth contributing to the project (though I am happy to write in a way that permits this).

The problem is a general one but I will illustrate it with my example. I am using Apache PDFBox which has a routine to write to java.awt.Graphics2D. I have replaced this by the Apache Batik toolkit which provides a subclass of Graphics2D (org.apache.batik.svggen.SVGGraphics2D) so I can capture the SVG representation. I create an instance

public static org.apache.batik.svggen.SVGGraphics2D createSVG() {
    org.w3c.dom.DOMImplementation domImpl =
    org.apache.batik.dom.GenericDOMImplementation.getDOMImplementation();
        org.w3c.dom.Document document = 
            domImpl.createDocument("http://www.w3.org/2000/svg", "svg", null);
        return new org.apache.batik.svggen.SVGGraphics2D(document);
    }

The place where PDFBox uses the graphics is org.apache.pdfbox.PDFReader which I have edited to allow for the new graphics:

    protected void showPage(int pageNumber)
{
    try 
    {
        PageDrawer drawer = new PageDrawer();
        PageWrapper wrapper = new PageWrapper( this );
        PDPage page = (PDPage)pages.get(pageNumber);
        wrapper.displayPage( page );
        PDRectangle cropBox = page.findCropBox();
        Dimension drawDimension = cropBox.createDimension();
        svg = PDFPagePanel.createSVG();          // MY EDIT!!!!!!!!!
        drawer.drawPage( svg, page, drawDimension );
        writeSVG(pageNumber);
    }
    catch (IOException exception)
    {
        exception.printStackTrace();
    }
}

I have got it to work (that's not the problem). My concern is that I have had to hack/edit and recompile a number of the distributed PDFBox classes simply to generate and use the subclass. I end up with classes such as PMRPDFReader in the same packages as the library. It's very messy - I can't immediately remember where I made the edits, etc.

I feel I ought ought to be able to use the library as-is and simply add/link my subclasses. I use maven so maybe there is a way of excluding the original classes.

like image 982
peter.murray.rust Avatar asked Apr 25 '12 08:04

peter.murray.rust


1 Answers

Here's how I would do this:

  • Create a separate project that contains your source code changes. Check it into source code/revision control (SVN, Git, whatever you're using). This project will only contain your changes.
  • Make sure it's a Maven project. Use the same version number as the original open source project, but add an appendix to the version. If you're using version 1.2, create your project to have version 1.2-Peter-1 or something similar. This way, you'll always know which version it's based on you're also able to provide multiple versions/revisions of your changes. It will also not conflict with the official versions. Use the same group/artifact IDs as the official ones.
  • Use the original project as a dependency in your own.

For deployment, you then have two options:

  • Deploy both your JAR (which just has your changes) and the original one, but make sure that your one is first in the classpath.
  • Use the Maven Shade plugin to create one jar that mixes the original classes and your own ones: http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html
like image 121
nwinkler Avatar answered Oct 05 '22 12:10

nwinkler