org.xchain.tools.executeplugin.ExecuteMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.xchain.tools.executeplugin.ExecuteMojo.java

Source

/**
 *    Copyright 2011 meltmedia
 *
 *    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.
 */
package org.xchain.tools.executeplugin;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.surefire.booter.IsolatedClassLoader;
import org.xchain.tools.executeplugin.AbstractXChainMojo;

import org.hibernate.cfg.Configuration;

/**
 * Configure Hibernate.
 * 
 * Run an XChain.
 * 
 * @author John Trimble
 * @author Jason Rose
 * @requiresDependencyResolution runtime
 * @goal execute-xchain
 */
public class ExecuteMojo extends AbstractXChainMojo {

    private static final String LIFE_CYCLE_CLASS_NAME = "org.xchain.framework.lifecycle.Lifecycle";
    private static final String HIBERNATE_LIFE_CYCLE_CLASS_NAME = "org.xchain.framework.hibernate.HibernateLifecycle";
    private static final String CONFIGURATION_CLASS_NAME = Configuration.class.getName();
    private static final String CONFIGURATION_CONFIGURE_CONFIGURATION_METHOD = "configure";
    private static final Class<?>[] CONFIGURATION_CONFIGURE_CONFIGURATION_ARGUMENTS = new Class<?>[] { File.class };
    private static final String CONFIGURATION_SET_CONFIGURATION_METHOD = "setConfiguration";
    private static final String CATALOG_FACTORY_CLASS_NAME = "org.xchain.framework.factory.CatalogFactory";
    private static final String CATALOG_CLASS_NAME = "org.xchain.Catalog";
    private static final String JXPATH_CONTEXT_CLASS_NAME = "org.apache.commons.jxpath.JXPathContext";
    private static final String LIFE_CYCLE_START_LIFE_CYCLE_METHOD = "startLifecycle";
    private static final String LIFE_CYCLE_STOP_LIFE_CYCLE_METHOD = "stopLifecycle";
    private static final String COMMAND_CLASS_NAME = "org.xchain.Command";
    private static final String CATALOG_FACTORY_INSTANCE_METHOD_NAME = "getInstance";
    private static final String CATALOG_FACTORY_CATALOG_METHOD_NAME = "getCatalog";
    private static final Class<?>[] CATALOG_FACTORY_CATALOG_ARGUMENT_TYPES = new Class<?>[] { String.class };
    private static final String CATALOG_COMMAND_METHOD_NAME = "getCommand";
    private static final Class<?>[] CATALOG_COMMAND_ARGUMENT_TYPES = new Class<?>[] { String.class };
    private static final String COMMAND_EXECUTE_METHOD_NAME = "execute";

    /**
      * @parameter expression="${catalog}"
      * @required
      */
    private String catalog;

    /**
     * Configuration has to be a File because we don't have the url resolver available before the xchains lifecycle has started, so we can't resolve "resource://context-class-loader" urls.
     * @parameter expression="${configuration}"
     */
    private File configuration;

    /**
     * @parameter expression="${dispatcherCommand}" default-value="dispatcher"
     * @required
     */
    private String dispatcherCommand;

    /**
     * @parameter expression="${command}" default-value="update-to-latest-build"
     */
    private String command;

    /**
     * @parameter default-value=false
     */
    private boolean exportSchema;

    /**
     * @parameter default-value=true
     */
    private boolean runXChainLifeCycle;

    public void execute() throws MojoExecutionException, MojoFailureException {
        ClassLoader chainClassLoader = createClassLoader(Thread.currentThread().getContextClassLoader(),
                this.classpathElements);

        try {
            Class<?> lifeCycleClass = chainClassLoader.loadClass(LIFE_CYCLE_CLASS_NAME);
            Class<?> hibernateLifeCycleClass = chainClassLoader.loadClass(HIBERNATE_LIFE_CYCLE_CLASS_NAME);
            Class<?> catalogFactoryClass = chainClassLoader.loadClass(CATALOG_FACTORY_CLASS_NAME);
            Class<?> catalogClass = chainClassLoader.loadClass(CATALOG_CLASS_NAME);
            Class<?> jxpathContextClass = chainClassLoader.loadClass(JXPATH_CONTEXT_CLASS_NAME);
            Class<?> scopedJXPathContextClass = chainClassLoader
                    .loadClass("org.xchain.framework.jxpath.ScopedJXPathContextImpl");
            Class<?> contextFactoryClass = chainClassLoader
                    .loadClass("org.xchain.framework.jxpath.JXPathContextFactoryImpl");
            Class<?> scopedQNameVariablesClass = chainClassLoader
                    .loadClass("org.xchain.framework.jxpath.ScopedQNameVariables");
            Class<?> commandClass = chainClassLoader.loadClass(COMMAND_CLASS_NAME);
            Class<?> configurationClass = chainClassLoader.loadClass(CONFIGURATION_CLASS_NAME);

            // LifeCycle methods
            Method startLifeCycleMethod = lifeCycleClass.getMethod(LIFE_CYCLE_START_LIFE_CYCLE_METHOD,
                    new Class<?>[] {});
            Method stopLifeCycleMethod = lifeCycleClass.getMethod(LIFE_CYCLE_STOP_LIFE_CYCLE_METHOD,
                    new Class<?>[] {});

            // CatalogFactory methods
            Method getInstanceMethod = catalogFactoryClass.getMethod(CATALOG_FACTORY_INSTANCE_METHOD_NAME,
                    new Class<?>[] {});
            Method getCatalogMethod = catalogFactoryClass.getMethod(CATALOG_FACTORY_CATALOG_METHOD_NAME,
                    CATALOG_FACTORY_CATALOG_ARGUMENT_TYPES);

            // Catalog methods
            Method getCommandMethod = catalogClass.getMethod(CATALOG_COMMAND_METHOD_NAME,
                    CATALOG_COMMAND_ARGUMENT_TYPES);

            // Command methods
            Method executeMethod = commandClass.getMethod(COMMAND_EXECUTE_METHOD_NAME, jxpathContextClass);

            // JXPathContext methods
            Method newContextMethod = contextFactoryClass.getMethod("newContext", jxpathContextClass, Object.class);
            Method declareVariableMethod = scopedQNameVariablesClass.getMethod("declareVariable", String.class,
                    Object.class);
            Method getVariablesMethod = scopedJXPathContextClass.getMethod("getVariables", new Class[] {});

            // Configuration methods
            Method configureMethod = configurationClass.getMethod(CONFIGURATION_CONFIGURE_CONFIGURATION_METHOD,
                    CONFIGURATION_CONFIGURE_CONFIGURATION_ARGUMENTS);
            Method setConfigurationMethod = hibernateLifeCycleClass
                    .getMethod(CONFIGURATION_SET_CONFIGURATION_METHOD, configurationClass);

            // Step 1: Switch Class loader
            ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(chainClassLoader);

            // Step 2: Configure Lifecycle
            Object configurationObject = null;
            if (configuration != null && configuration.exists()) {
                configurationObject = configurationClass.newInstance();
                configurationObject = configureMethod.invoke(configurationObject, this.configuration);
                setConfigurationMethod.invoke(null, new Object[] { configurationObject });
            }

            // Step 3: Start life cycle
            if (this.runXChainLifeCycle)
                startLifeCycleMethod.invoke(null, new Object[] {});

            // Step 4: Get the catalog
            Object catalogFactoryObject = getInstanceMethod.invoke(null, new Object[] {});
            Object catalogObject = getCatalogMethod.invoke(catalogFactoryObject, new Object[] { this.catalog });

            // Step 5: Get the command
            Object commandObject = getCommandMethod.invoke(catalogObject, new Object[] { this.dispatcherCommand });

            // Step 6: Configure the context
            Object jxpathContextFactoryObject = contextFactoryClass.newInstance();
            Object jxpathContextObject = newContextMethod.invoke(jxpathContextFactoryObject, null, new Object());
            Object variablesObject = getVariablesMethod.invoke(jxpathContextObject, new Object[] {});
            declareVariableMethod.invoke(variablesObject, "command", this.command);
            declareVariableMethod.invoke(variablesObject, "exportSchema", this.exportSchema);
            declareVariableMethod.invoke(variablesObject, "configuration", configurationObject);

            // Step 7: Execute the command
            executeMethod.invoke(commandObject, jxpathContextObject);

            // Step 8: Stop life cycle
            if (this.runXChainLifeCycle)
                stopLifeCycleMethod.invoke(null, new Object[] {});

            // Step 9: Switch Class loader back
            Thread.currentThread().setContextClassLoader(originalContextClassLoader);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    private ClassLoader createClassLoader(ClassLoader parent, Collection<String> classPathElementFilePaths) {
        IsolatedClassLoader isolatedClassLoader = new IsolatedClassLoader(parent);
        if (classPathElementFilePaths != null && classPathElementFilePaths.size() > 0) {
            for (String classElementString : classPathElementFilePaths) {
                File classElementFile = new File(classElementString);
                try {
                    URL url = classElementFile.toURL();
                    isolatedClassLoader.addURL(url);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        }

        return isolatedClassLoader;
    }
}