Package org.jpox.enhancer

Source Code of org.jpox.enhancer.JPOXEnhancer

/**********************************************************************
Copyright (c) 2004 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
2004 Marco Schulze (NightLabs.de) - added verbose output of classpath
2004 Andy Jefferson - updated formatting of user output. Added version, vendor
2006 Andy Jefferson - restructured to have modular ClassEnhancer and use BCEL by default
2007 Andy Jefferson - swap across to using ASM
    ...
**********************************************************************/
package org.jpox.enhancer;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

import org.jpox.ClassLoaderResolver;
import org.jpox.OMFContext;
import org.jpox.PersistenceConfiguration;
import org.jpox.api.ApiAdapter;
import org.jpox.exceptions.JPOXException;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.metadata.ClassMetaData;
import org.jpox.metadata.ClassPersistenceModifier;
import org.jpox.metadata.FileMetaData;
import org.jpox.metadata.MetaDataFactory;
import org.jpox.metadata.MetaDataManager;
import org.jpox.metadata.PackageMetaData;
import org.jpox.metadata.PersistenceUnitMetaData;
import org.jpox.util.ClassUtils;
import org.jpox.util.CommandLine;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;
import org.jpox.util.StringUtils;

/**
* JPOX Byte-Code Enhancer.
* This provides the entry point for enhancement. Enhancement is performed using a ClassEnhancer.
* JPOX currently provides a ClassEnhancer using Apache BCEL, and one using ASM.
* <p>
* You can use the JPOXEnhancer in two ways
* <ul>
* <li>Via the command line, entering via the main method. This creates a JPOXEnhancer object, sets the
* options necessary and calls the execute method.</li>
* <li>Programmatically, creating the JPOXEnhancer object settings options and running etc.</li>
* </ul>
* The proggrammatic way would be something like this
* <pre>
* JPOXEnhancer enhancer = new JPOXEnhancer();
* enhancer.setVerbose();
* enhancer.setPersistenceUnitName("myPersistenceUnit");
* enhancer.execute();
* </pre>
* enhancing all classes specified by the persistence unit.
*
* @version $Revision: 1.86 $
*/
public class JPOXEnhancer extends PersistenceConfiguration
{
    protected static Localiser LOCALISER = Localiser.getInstance("org.jpox.enhancer.Localisation",
        ClassEnhancer.class.getClassLoader());

    /** ObjectManagerFactory Context **/
    private OMFContext omfContext;

    /** Version number of the enhancer. */
    private static String jpoxVersion;

    /** Vendor of the enhancer. */
    private static String jpoxVendor;

    /** only check if classes are enhanced **/
    private static final String ENHANCER_OPTION_CHECKONLY="org.jpox.enhancer.checkOnly";

    /** work in verbose mode **/
    private static final String ENHANCER_OPTION_VERBOSE="org.jpox.enhancer.verbose";

    /** verify the enhanced classes after enhancing **/
    private static final String ENHANCER_OPTION_VERIFY="org.jpox.enhancer.verify";

    /** destination of the enhanced files **/
    private static final String ENHANCER_OPTION_DESTINATION="org.jpox.enhancer.destination";

    /** API adapter to use for enhancement (default is JDO). */
    private String api = "JDO";

    /** The symbolic name of the ClassEnhancer to use (default is ASM). */
    private String enhancerName = "ASM";

    /** ClassEnhancer class. */
    private Class classEnhancerClass = null;

    /** verify the enhanced classes after enhancing **/
    private boolean verify=false;

    /** default command line arguments **/
    private String[] defaultArgs = new String[0];
   
    /** ClassLoader resolver for use during the enhancement process. */
    private ClassLoaderResolver clr;

    private static Class[] CLASS_ENHANCER_CONSTRUCTOR_ARGS_TYPES = new Class[] {ClassMetaData.class, ClassLoaderResolver.class};

    /** Whether to output to System.out (as well as logging). */
    private boolean systemOut = false;

    /**
     * Constructor.
     */
    public JPOXEnhancer()
    {
        omfContext = new OMFContext(this);
        clr = omfContext.getClassLoaderResolver(null);
    }

    /**
     * Accessor for the ClassLoaderResolver.
     * @return ClassLoader resolver
     */
    public ClassLoaderResolver getClassLoaderResolver()
    {
        return clr;
    }

    /**
     * Set the command line arguments.
     * @param args The args
     */
    public void setCommandLineArgs(String[] args)
    {
        CommandLine cmd = new CommandLine();
        cmd.addOption("d", "dest", "<directory>", "output directory");
        cmd.addOption("api", "api", "<adapter-name>", "API Adapter (JDO, JPA, etc)");
        cmd.addOption("enhancerName", "enhancerName", "<enhancer-name>", "Class Enhancer name (ASM, BCEL, etc)");
        cmd.addOption("v", "verbose", null, "verbose output");
        cmd.addOption("verify", "verify", null, "verify the enhancement");
        cmd.addOption("checkonly", "checkonly", null, "only check if the class is enhanced");
        cmd.addOption("check", "check", null, "after enhancement, check if the class was enhanced");
        cmd.addOption("persistenceUnit", "persistenceUnit", "<name-of-persistence-unit>", "name of the persistence unit to enhance");

        cmd.parse(args);

        if (cmd.hasOption("api"))
        {
            api = cmd.getOptionArg("api");
            omfContext.setApi(api);
        }
        if (cmd.hasOption("enhancerName"))
        {
            setEnhancerName(cmd.getOptionArg("enhancerName"));
        }

        if (cmd.hasOption("d"))
        {
            String destination = cmd.getOptionArg("d");
            File tmp = new File(destination);
            if (tmp.exists())
            {
                if (!tmp.isDirectory())
                {
                    System.out.println(destination + " is not directory. please set directory.");
                    System.exit(1);
                }
            }
            else
            {
                tmp.mkdirs();
            }
            setDestination(destination);
        }
       
        defaultArgs = cmd.getDefaultArgs();

        // populate options
        ApiAdapter adapter = omfContext.getApiAdapter();
        Map map = adapter.getDefaultFactoryProperties();
        setOptions(map);
        if (cmd.hasOption("persistenceUnit"))
        {
            setProperty("org.jpox.PersistenceUnitName", cmd.getOptionArg("persistenceUnit"));
        }
        if (cmd.hasOption("api"))
        {
            setProperty("org.jpox.persistenceApiName", cmd.getOptionArg("api"));
        }
        if (cmd.hasOption("verify"))
        {
            setProperty(ENHANCER_OPTION_VERIFY, "true");
        }
        if (cmd.hasOption("v"))
        {
            setProperty(ENHANCER_OPTION_VERBOSE, "true");
        }
        if (cmd.hasOption("checkonly"))
        {
            setProperty(ENHANCER_OPTION_CHECKONLY, "true");
        }
    }

    /**
     * Accessor for the command line args.
     * @return The args
     */
    public String[] getDefaultArgs()
    {
        return defaultArgs;
    }

    /**
     * Acessor for the checkOnly
     * @return the checkonly
     */
    public boolean isCheckonly()
    {
        return getBooleanProperty(ENHANCER_OPTION_CHECKONLY);
    }

    /**
     * Acessor for the checkOnly
     * @param checkonly the checkonly to set
     */
    public void setCheckonly(boolean checkonly)
    {
        setProperty(ENHANCER_OPTION_CHECKONLY, new Boolean(checkonly));
    }

    /**
     * Acessor for the destination
     * @return the destination
     */
    public String getDestination()
    {
        return getStringProperty(ENHANCER_OPTION_DESTINATION);
    }

    /**
     * Mutator for the destination
     * @param destination the destination to set
     */
    public void setDestination(String destination)
    {
        setProperty(ENHANCER_OPTION_DESTINATION, destination);
    }

    /**
     * Acessor for the API (JDO, JPA)
     * @return the API
     */
    public String getApi()
    {
        return getStringProperty("org.jpox.persistenceApiName");
    }

    /**
     * Mutator for the API (JDO, JPA)
     * @param api the API
     */
    public void setApi(String api)
    {
        setProperty("org.jpox.persistenceApiName", api);
    }

    /**
     * Acessor for the name of the ClassEnhancer
     * @return Name of the ClassEnhancer to use
     */
    public String getEnhancerName()
    {
        return enhancerName;
    }

    /**
     * Mutator for the ClassEnhancer
     * @param enhancer the ClassEnhancer to use
     */
    public void setEnhancerName(String enhancer)
    {
        if (enhancerName == null)
        {
            return;
        }

        this.enhancerName = enhancer;
    }

    /**
     * Accessor for the ClassEnhancer class.
     * @param clr ClassLoader resolver
     * @return The class of the ClassEnhancer
     */
    public Class getClassEnhancerClass(ClassLoaderResolver clr)
    {
        if (classEnhancerClass != null)
        {
            // We already have the class
            return classEnhancerClass;
        }

        String className = null;
        try
        {
            className = (String) omfContext.getPluginManager().getAttributeValueForExtension("org.jpox.enhancer.enhancer",
                new String[]{"name", "api"}, new String[]{ enhancerName, api}, "class-name");
            classEnhancerClass = clr.classForName(className,Enhancer.class.getClassLoader());
        }
        catch (Exception e)
        {
            throw new JPOXException(LOCALISER.msg("Enhancer.ClassEnhancer.ClassNotFound", enhancerName, className), e);
        }
        return classEnhancerClass;
    }

    /**
     * Accessor for the name of the test class for this ClassEnhancer
     * @return Test class name for the ClassEnhancer
     */
    public String getClassEnhancerTestClassName()
    {
        // Find the "test-class" attribute for this ClassEnhancer/API
        try
        {
            return (String) omfContext.getPluginManager().getAttributeValueForExtension("org.jpox.enhancer.enhancer",
                new String[]{"name", "api"}, new String[]{ enhancerName, api}, "test-class");
        }
        catch (Exception e)
        {
            throw new JPOXException(LOCALISER.msg("Enhancer.ClassEnhancer.TestClassConstructionFailure", enhancerName, e));
        }
    }

    /**
     * Accessor for the name of the MetaDataFactory for this ClassEnhancer (if any).
     * @return MetaData factory class name for the ClassEnhancer
     */
    public String getClassEnhancerMetadataFactoryName()
    {
        // Find the "metadata-factory" attribute for this ClassEnhancer/API
        try
        {
            return (String) omfContext.getPluginManager().getAttributeValueForExtension("org.jpox.enhancer.enhancer",
                new String[]{"name", "api"}, new String[]{ enhancerName, api}, "metadata-factory");
        }
        catch (Exception e)
        {
            throw new JPOXException(LOCALISER.msg("Enhancer.ClassEnhancer.TestClassConstructionFailure", enhancerName, e));
        }
    }

    /**
     * Acessor for the verbose
     * @return the verbose
     */
    public boolean isVerbose()
    {
        return getBooleanProperty(ENHANCER_OPTION_VERBOSE);
    }

    /**
     * Mutator for the verbose flag
     * @param verbose the verbose to set
     */
    public void setVerbose(boolean verbose)
    {
        setProperty(ENHANCER_OPTION_VERBOSE, new Boolean(verbose));
    }

    /**
     * Mutator for whether to output to system out.
     * @param sysout Whether to use sysout
     */
    public void setSystemOut(boolean sysout)
    {
        systemOut = sysout;
    }

    /**
     * Acessor for the verify
     * @return the verify
     */
    public boolean isVerify()
    {
        return verify;
    }

    /**
     * Mutator for using verify mode
     * @param verify the verify to set
     */
    public void setVerify(boolean verify)
    {
        this.verify = verify;
    }

    /**
     * Method to perform the specified enhancement task with the specified input.
     * Should be called after setting the various parameters required.
     * @return Number of classes successfully enhanced. -1 implies failure to enhance
     * @throws JPOXException If an error occurs
     */
    public int execute()
    {
        boolean success = true;
        int numberOfClasses = 0;

        String msg = null;
        ClassLoaderResolver clr = omfContext.getClassLoaderResolver(null);

        // Obtain a MetaDataManager to work with
        MetaDataManager metaDataMgr = omfContext.getMetaDataManager();
        metaDataMgr.setEnhancing();
        String metadataFactory = getClassEnhancerMetadataFactoryName();
        if (!StringUtils.isWhitespace(metadataFactory))
        {
            try
            {
                Class factoryCls = clr.classForName(metadataFactory);
                MetaDataFactory factory = (MetaDataFactory)ClassUtils.newInstance(factoryCls,
                    new Class[] {MetaDataManager.class}, new Object[] {metaDataMgr});
                metaDataMgr.setMetaDataFactory(factory);
            }
            catch (Exception e)
            {
                throw new JPOXUserException(e.getMessage(), e);
            }
        }

        // Obtain MetaData for all classes to be processed
        long startTime = System.currentTimeMillis();
        FileMetaData[] filemds = null;
        String puName = getStringProperty("org.jpox.PersistenceUnitName");
        if (puName != null)
        {
            // Enhancement via "persistence-unit"
            if (isVerbose())
            {
                msg = LOCALISER.msg("Enhancer.PersistenceUnit", puName);
                addMessage(msg);
            }

            PersistenceUnitMetaData pumd = null;
            try
            {
                pumd = metaDataMgr.getMetaDataForPersistenceUnit(puName);
            }
            catch (JPOXException jpe)
            {
                // No "persistence.xml" files found yet they have specified a persistence-unit name!
                throw new JPOXUserException(LOCALISER.msg("Enhancer.PersistenceUnit.NoPersistenceFiles", puName));
            }

            if (pumd == null)
            {
                throw new JPOXUserException(LOCALISER.msg("Enhancer.PersistenceUnit.NoSuchUnit", puName));
            }

            // Initialise the MetaDataManager using the mapping files and classes
            filemds = metaDataMgr.initialise(pumd, clr);
        }
        else
        {
            // Enhancement via "Input Files" (jdo/class) on command line
            String[] inputfiles = getDefaultArgs();
            if (inputfiles == null)
            {
                msg = LOCALISER.msg("Enhancer.NoInputFilesError");
                JPOXLogger.ENHANCER.error(msg);
                throw new JPOXUserException(msg);
            }

            if (isVerbose())
            {
                msg = LOCALISER.msg("Enhancer.InputFiles");
                addMessage(msg);
                for (int i = 0; i < inputfiles.length; i++)
                {
                    String entry = LOCALISER.msg("Enhancer.InputFiles.Entry", inputfiles[i]);
                    JPOXLogger.ENHANCER.info(entry);
                    System.out.println(entry);
                }
                addMessage("");
            }

            // Read in the specified MetaData files - errors in MetaData will return exceptions and so we stop
            Class classEnhancerClass = getClassEnhancerClass(clr);
            try
            {
                // Split the input files into MetaData files and classes
                JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.ReadInputFilesStart", "" + inputfiles.length));
                HashSet metadataFiles = new HashSet();
                HashSet classNames = new HashSet();
                for (int i=0;i<inputfiles.length;i++)
                {
                    if (inputfiles[i].endsWith(".class"))
                    {
                        if (!StringUtils.getFileForFilename(inputfiles[i]).exists())
                        {
                            msg = LOCALISER.msg("Enhancer.InputFiles.Invalid", inputfiles[i]);
                            if (systemOut)
                            {
                                System.out.println(msg);
                            }
                            JPOXLogger.ENHANCER.error(msg);
                        }
                        else
                        {
                            // Class file so get the name of the class for this file
                            try
                            {
                                Method method = classEnhancerClass.getMethod("getClassNameForFileName",
                                    new Class[] {String.class});
                                String className = (String)method.invoke(null, new String[] {inputfiles[i]});
                                classNames.add(className);
                            }
                            catch (InvocationTargetException ex)
                            {
                                msg = LOCALISER.msg("Enhancer.ClassEnhancer.MethodNotFound",
                                    enhancerName, classEnhancerClass.getName(), "getClassNameForFileName", ex.getTargetException());
                                if (systemOut)
                                {
                                    System.out.println(msg);
                                }
                                JPOXLogger.ENHANCER.error(msg);
                            }
                            catch (Exception e)
                            {
                                msg = LOCALISER.msg("Enhancer.ClassEnhancer.MethodNotFound",
                                    enhancerName, classEnhancerClass.getName(), "getClassNameForFileName", e);
                                if (systemOut)
                                {
                                    System.out.println(msg);
                                }
                                JPOXLogger.ENHANCER.error(msg);
                            }
                        }
                    }
                    else
                    {
                        // MetaData file
                        metadataFiles.add(inputfiles[i]);
                    }
                }

                // Initialise the MetaDataManager using the mapping files and class names
                filemds = metaDataMgr.initialise((String[])metadataFiles.toArray(new String[metadataFiles.size()]),
                    (String[])classNames.toArray(new String[classNames.size()]), clr);
                JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.ReadInputFilesEnd", "" + inputfiles.length));
            }
            catch (JPOXException jpe)
            {
                // Error reading input files
                Throwable[] nesteds = jpe.getNestedExceptions();
                if (nesteds != null && nesteds.length == 1)
                {
                    msg = LOCALISER.msg("Enhancer.ErrorReadingInputFiles", nesteds[0].getMessage());
                }
                else
                {
                    msg = LOCALISER.msg("Enhancer.ErrorReadingInputFiles", jpe.getMessage());
                }
                if (nesteds != null)
                {
                    for (int i=0;i<nesteds.length;i++)
                    {
                        JPOXLogger.ENHANCER.error(msg, nesteds[i]);
                    }
                }
                else
                {
                    JPOXLogger.ENHANCER.error(msg, jpe);
                }
                throw jpe;
            }
            catch (Exception e)
            {
                // Error reading input files
                msg = LOCALISER.msg("Enhancer.ErrorReadingInputFiles", e.getMessage());
                JPOXLogger.ENHANCER.error(msg, e);
                throw new JPOXUserException(msg, e);
            }
        }
        if (filemds == null)
        {
            // Invalid input provided so exit
            msg = LOCALISER.msg("Enhancer.NoValidInputFilesError");
            JPOXLogger.ENHANCER.error(msg);
            throw new JPOXUserException(msg);
        }
        long inputTime = System.currentTimeMillis();

        // Obtain the required ClassEnhancer to do the work
        Class classEnhancerClass = getClassEnhancerClass(clr);
        Constructor ctr = null;
        try
        {
            ctr = classEnhancerClass.getConstructor(CLASS_ENHANCER_CONSTRUCTOR_ARGS_TYPES);
        }
        catch (Exception e)
        {
            msg = LOCALISER.msg("Enhancer.ClassEnhancer.ConstructorNotFound",
                enhancerName, classEnhancerClass.getName(), e.getMessage());
            JPOXLogger.ENHANCER.error(msg, e);
            throw new JPOXException(msg, e);
        }

        // Process the classes implied by the FileMetaData
        HashSet enhancedClassNames = new HashSet();
        for (int filenum = 0; filenum < filemds.length; filenum++)
        {
            FileMetaData filemd = filemds[filenum];
            for (int packagenum = 0; packagenum < filemd.getNoOfPackages(); packagenum++)
            {
                PackageMetaData pmd = filemd.getPackage(packagenum);
                for (int classnum = 0; classnum < pmd.getNoOfClasses(); classnum++)
                {
                    ClassMetaData cmd = pmd.getClass(classnum);
                    if (enhancedClassNames.contains(cmd.getFullClassName()))
                    {
                        // Already processed, maybe via annotations and this is MetaData
                        continue;
                    }

                    ClassEnhancer classEnhancer = null;
                    try
                    {
                        // Create a ClassEnhancer to enhance this class
                        classEnhancer = (ClassEnhancer)ctr.newInstance(new Object[] {cmd, clr});
                        enhancedClassNames.add(cmd.getFullClassName());

                        if (isCheckonly())
                        {
                            checkClass(cmd, classEnhancer);
                            numberOfClasses++;
                        }
                        else if (isVerify())
                        {
                            verifyClass(cmd, classEnhancer);
                            numberOfClasses++;
                        }
                        else
                        {
                            if (enhanceClass(cmd, classEnhancer, true))
                            {
                                numberOfClasses++;
                            }
                        }
                    }
                    catch (InvocationTargetException e)
                    {
                        // Error creating the ClassEnhancer
                        msg = LOCALISER.msg("Enhancer.ClassEnhancer.ConstructorError",
                            enhancerName, classEnhancerClass.getName(), e.getTargetException());
                        JPOXLogger.ENHANCER.error(msg, e);
                        throw new JPOXException(msg, e);
                    }
                    catch (Exception e)
                    {
                        // Error creating the ClassEnhancer
                        msg = LOCALISER.msg("Enhancer.ClassEnhancer.ConstructorError",
                            enhancerName, classEnhancerClass.getName(), e.getMessage());
                        JPOXLogger.ENHANCER.error(msg, e);
                        throw new JPOXException(msg, e);
                    }
                }
            }
        }
        long enhanceTime = System.currentTimeMillis();

        // Log info about timings
        msg = LOCALISER.msg("Enhancer.Success", "" + numberOfClasses,
            "" + (inputTime-startTime), "" + (enhanceTime-inputTime), "" + (enhanceTime-startTime));
        addMessage(msg);

        if (success)
        {
            return numberOfClasses;
        }
        else
        {
            return -1;
        }
    }

    /**
     * Method to add a message at the required output level.
     * @param msg The message
     */
    protected void addMessage(String msg)
    {
        JPOXLogger.ENHANCER.info(msg);
        if (systemOut)
        {
            System.out.println(msg);
        }
    }

    /**
     * Method to enhance the class defined by the MetaData.
     * @param cmd MetaData for the class
     * @param enhancer ClassEnhancer to use
     * @param store Whether to store the class after enhancing
     * @return Whether the operation performed without error
     */
    protected boolean enhanceClass(ClassMetaData cmd, ClassEnhancer enhancer, boolean store)
    {
        boolean success = true;
        try
        {
            if (JPOXLogger.ENHANCER.isDebugEnabled())
            {
                JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.EnhanceClassStart", cmd.getFullClassName()));
            }
            boolean enhanced = enhancer.enhance();
            if (enhanced)
            {
                if (store)
                {
                    enhancer.save(getDestination());
                }
                if (isVerbose())
                {
                    if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
                    {
                        System.out.println("ENHANCED (PersistenceCapable) : " + cmd.getFullClassName());
                    }
                    else if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
                    {
                        System.out.println("ENHANCED (PersistenceAware) : " + cmd.getFullClassName());
                    }
                    else
                    {
                        System.out.println("NOT ENHANCED (NonPersistent) : " + cmd.getFullClassName());
                    }
                }
            }
            else
            {
                if (isVerbose())
                {
                    if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
                    {
                        System.out.println("ERROR (PersistenceCapable) : " + cmd.getFullClassName());
                    }
                    else if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
                    {
                        System.out.println("ERROR (PersistenceAware) : " + cmd.getFullClassName());
                    }
                    else
                    {
                        System.out.println("NOT ENHANCED (NonPersistent) : " + cmd.getFullClassName());
                    }
                }
                if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE ||
                        cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
                {
                    // Error in enhancement
                    success = false;
                }
            }
        }
        catch (IOException ioe)
        {
            // Exception thrown in saving the enhanced file
            if (isVerbose())
            {
                System.out.println("ERROR (NonPersistent) : " + cmd.getFullClassName());
            }

            String msg = LOCALISER.msg("Enhancer.ErrorEnhancingClass", cmd.getFullClassName(), ioe.getMessage());
            JPOXLogger.ENHANCER.error(msg, ioe);
            System.out.println(msg);

            success = false;
        }

        if (JPOXLogger.ENHANCER.isDebugEnabled())
        {
            JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.EnhanceClassEnd", cmd.getFullClassName()));
        }

        return success;
    }

    /**
     * Method to check the enhancement state of the class defined by the MetaData.
     * @param cmd MetaData for the class
     * @param enhancer ClassEnhancer to use
     * @return Always returns true since there is nothing that can go wrong
     */
    protected boolean checkClass(ClassMetaData cmd, ClassEnhancer enhancer)
    {
        if (JPOXLogger.ENHANCER.isDebugEnabled())
        {
            JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.CheckClassStart", cmd.getFullClassName()));
        }

        boolean enhanced = enhancer.checkEnhanced();
        if (enhanced)
        {
            if (isVerbose())
            {
                if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
                {
                    System.out.println("ENHANCED (PersistenceCapable) : " + cmd.getFullClassName());
                }
                else if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
                {
                    System.out.println("ENHANCED (PersistenceAware) : " + cmd.getFullClassName());
                }
                else
                {
                    System.out.println("NOT ENHANCED (NonPersistent) : " + cmd.getFullClassName());
                }
            }
        }
        else
        {
            if (isVerbose())
            {
                if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE)
                {
                    System.out.println("NOT ENHANCED (PersistenceCapable) : " + cmd.getFullClassName());
                }
                else if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_AWARE)
                {
                    System.out.println("NOT ENHANCED (PersistenceAware) : " + cmd.getFullClassName());
                }
                else
                {
                    System.out.println("NOT ENHANCED (NonPersistent) : " + cmd.getFullClassName());
                }
            }
        }

        if (JPOXLogger.ENHANCER.isDebugEnabled())
        {
            JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.CheckClassEnd", cmd.getFullClassName()));
        }

        return true;
    }

    /**
     * Method to verify the state of the class defined by the MetaData.
     * @param cmd MetaData for the class
     * @param enhancer ClassEnhancer to use
     * @return Whether the operation performed without error
     */
    protected boolean verifyClass(ClassMetaData cmd, ClassEnhancer enhancer)
    {
        boolean success = true;
        if (JPOXLogger.ENHANCER.isDebugEnabled())
        {
            JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.VerifyClassStart", cmd.getFullClassName()));
        }

        try
        {
            enhancer.verify();
            if (isVerbose())
            {
                System.out.println("VERIFIED : " + cmd.getFullClassName());
            }
        }
        catch (Exception e)
        {
            // Errors in verification
            if (isVerbose())
            {
                System.out.println("NOT VERIFIED : " + cmd.getFullClassName());
            }

            String msg = LOCALISER.msg("Enhancer.ErrorEnhancingClass", cmd.getFullClassName(), e);
            JPOXLogger.ENHANCER.error(msg, e);
            System.out.println(msg);

            success = false;
        }

        if (JPOXLogger.ENHANCER.isDebugEnabled())
        {
            JPOXLogger.ENHANCER.debug(LOCALISER.msg("Enhancer.VerifyClassEnd", cmd.getFullClassName()));
        }

        return success;
    }

    /**
     * Utility to get the version of JPOX Enhancer.
     * @return Version number for JPOX Enhancer.
     **/
    public static String getVersionNumber()
    {
        if (jpoxVersion != null)
        {
            return jpoxVersion;
        }
       
        String version="Unknown";
        try
        {
            ResourceBundle bundle=ResourceBundle.getBundle("org.jpox.enhancer.JPOXVersion");
            try
            {
                version = bundle.getString("jpox.enhancer.version");
            }
            catch (Exception e1)
            {
                //do nothing
            }
        }
        catch (Exception e)
        {
            //do nothing
        }
       
        return jpoxVersion = version;
    }

    /**
     * Utility to get the vendor of JPOX Enhancer.
     * @return Vendor name for JPOX Enhancer.
     **/
    public static String getVendorName()
    {
        if (jpoxVendor != null)
        {
            return jpoxVendor;
        }
       
        String vendor="JPOX";
        try
        {
            ResourceBundle bundle=ResourceBundle.getBundle("org.jpox.enhancer.JPOXVersion");
            try
            {
                vendor = bundle.getString("jpox.enhancer.vendor");
            }
            catch (Exception e1)
            {
                //do nothing
            }
        }
        catch (Exception e)
        {
            //do nothing
        }

        return jpoxVendor = vendor;
    }

    /**
     * Entry point for command line JPOX enhancer.
     * The process here is in 3 parts
     * <ol>
     * <li>Process the input for obvious errors and print out summary as required</li>
     * <li>Convert the input into a set of FileMetaData</li>
     * <li>Enhance all classes specified in the FileMetaData</li>
     * </ol>
     * @param args Command line arguments
     * @throws Exception Thrown if an error occurs
     **/
    public static void main(String args[])
    throws Exception
    {
        JPOXEnhancer enhancer = new JPOXEnhancer();
        enhancer.setCommandLineArgs(args);

        String msg = null;
        if (!enhancer.isVerify() && !enhancer.isCheckonly())
        {
            msg = LOCALISER.msg("Enhancer.Title.Enhance", getVersionNumber());
        }
        else if (enhancer.isCheckonly())
        {
            msg = LOCALISER.msg("Enhancer.Title.CheckOnly", getVersionNumber());
        }
        else
        {
            msg = LOCALISER.msg("Enhancer.Title.Verify", getVersionNumber());
        }
        JPOXLogger.ENHANCER.info(msg);
        System.out.println(msg);
        System.out.println();

        // Classpath
        JPOXLogger.ENHANCER.info(LOCALISER.msg("Enhancer.Classpath"));
        if (enhancer.isVerbose())
        {
            System.out.println(LOCALISER.msg("Enhancer.Classpath"));
        }
        StringTokenizer tokeniser = new StringTokenizer(System.getProperty("java.class.path"), File.pathSeparator);
        while (tokeniser.hasMoreTokens())
        {
            String entry = LOCALISER.msg("Enhancer.Classpath.Entry", tokeniser.nextToken());
            JPOXLogger.ENHANCER.info(entry);
            if (enhancer.isVerbose())
            {
                System.out.println(entry);
            }
        }
        if (enhancer.isVerbose())
        {
            System.out.println();
            System.out.flush();
        }

        // Class Enhancer
        msg = LOCALISER.msg("Enhancer.ClassEnhancer", enhancer.getEnhancerName(), enhancer.getApi());
        JPOXLogger.ENHANCER.info(msg);
        if (enhancer.isVerbose())
        {
            System.out.println(LOCALISER.msg("Enhancer.ClassEnhancer", enhancer.getEnhancerName(), enhancer.getApi()));
            System.out.println();
            System.out.flush();
        }
        String enhancerTestClass = enhancer.getClassEnhancerTestClassName();
        if (enhancerTestClass != null)
        {
            // Check if the ClassEnhancer "test-class" is present in the CLASSPATH
            try
            {
                enhancer.getClassLoaderResolver().classForName(enhancerTestClass);
            }
            catch (Exception e)
            {
                msg = LOCALISER.msg("Enhancer.ClassEnhancerTestClassNotFound", enhancer.enhancerName);
                JPOXLogger.ENHANCER.error(msg, e);
                System.out.println(msg);
                System.out.flush();
                System.exit(2);
                return;
            }
        }
        enhancer.setSystemOut(true);

        // Perform the enhancement/checks using the specified FileMetaData
        int numClasses = 0;
        try
        {
            numClasses = enhancer.execute();
        }
        catch (JPOXException jpe)
        {
            System.out.println(jpe.getMessage());
            msg = LOCALISER.msg("Enhancer.Failure");
            JPOXLogger.ENHANCER.error(msg, jpe);
            System.out.println(msg);
        }

        if (numClasses == 0)
        {
            msg = LOCALISER.msg("Enhancer.NoClassesEnhanced");
            JPOXLogger.ENHANCER.info(msg);
            System.out.println(msg);
        }
    }
}
TOP

Related Classes of org.jpox.enhancer.JPOXEnhancer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.