Plugins : Class Enhancer

DataNucleus is developed as a plugin-driven framework and one of the components that is pluggable is the enhancer of classes.

DataNucleus relies on byte-code enhancement of classes to implement the PersistenceCapable and Detachable interfaces. It provides class enhancer plugins using Apache BCEL and ObjectWeb ASM. You can extend DataNucleus's capabilities using the plugin extension org.datanucleus.enhancer.enhancer .

Plugin extension-point Key Description Location
org.datanucleus.enhancer.enhancer bcel Class Enhancer using Apache BCEL datanucleus-enhancer
org.datanucleus.enhancer.enhancer asm Class Enhancer using ASM datanucleus-enhancer


Interface

Any class enhancer plugin will need to implement org.datanucleus.enhancer.ClassEnhancer . So you need to implement the following interface

package org.datanucleus.enhancer;

public interface ClassEnhancer
{
    /**
     * Check whether the class is enhanced.
     * @return Whether the class is already enhanced.
     */
    boolean checkEnhanced();

    /**
     * Method to enhance the class definition internally.
     * @return Whether the class was enhanced successfully
     */
    boolean enhance();

    /**
     * Method to save the (current) class definition bytecode into a class file.
     * Only has effect if the bytecode has been modified (by enhance()).
     * If directoryName is specified it will be written to $directoryName/className.class
     * else will overwrite the existing class.
     * @param directoryName Name of a directory (or null to overwrite the class)
     * @throws IOException If an I/O error occurs in the write.
     */
    void save(String directoryName) throws IOException;

    /**
     * Access the class bytecode.
     * @return the class in byte array format
     */
    byte[] getBytes();

    /**
     * Method to verify the enhancement state.
     * @throws Exception Thrown if an error occurs while verifying
     **/
    void verify() throws Exception;

    /**
     * Accessor for the ClassLoaderResolver in use.
     * @return ClassLoader resolver
     */
    ClassLoaderResolver getClassLoaderResolver();

    /**
     * Accessor for the ClassMetaData for the class.
     * @return MetaData for the class
     */
    ClassMetaData getClassMetaData();
}

Be aware that you can extend org.datanucleus.enhancer.AbstractClassEnhancer .

Plugin Specification

When we have defined our "ClassEnhancer" we just need to make it into a DataNucleus plugin. To do this you simply add a file plugin.xml to your JAR at the root. The file plugin.xml should look like this

<?xml version="1.0"?>
<plugin id="mydomain" name="DataNucleus plug-ins" provider-name="My Company">
    <extension point="org.datanucleus.enhancer.enhancer">
        <class-enhancer name="MyEnhancer" api="jdo" class-name="mydomain.MyClassEnhancer"
            test-class="mydomain.SomeClassInTheClasspath"/>
    </extension>
</plugin>

The test-class should be the name of a class that needs to be in the CLASSPATH when running your enhancer. For example, with BCEL we may specify "org.apache.bcel.generic.ClassGen". The api is the API that your enhancer is to be run against. You can specify it for JDO and JPA by adding two lines above (one for each).

Plugin Usage

The only thing remaining is to use your new ClassEnhancer plugin. You do this by having your plugin in the CLASSPATH at runtime, and passing the argument enhancerName with value MyEnhancer (the name you specified in the plugin.xml file) to the DataNucleus Enhancer.