org.specrunner.hibernate3.PluginConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for org.specrunner.hibernate3.PluginConfiguration.java

Source

/*
SpecRunner - Acceptance Test Driven Development Tool
Copyright (C) 2011-2018  Thiago Santos
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package org.specrunner.hibernate3;

import java.lang.reflect.Method;
import java.util.Iterator;

import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PreInsertEventListener;
import org.hibernate.mapping.PersistentClass;
import org.specrunner.SRServices;
import org.specrunner.concurrency.IConcurrentMapping;
import org.specrunner.context.IContext;
import org.specrunner.features.IFeatureManager;
import org.specrunner.plugins.ENext;
import org.specrunner.plugins.PluginException;
import org.specrunner.result.IResultSet;
import org.specrunner.result.status.Success;
import org.specrunner.util.UtilLog;

import nu.xom.Attribute;
import nu.xom.Element;
import nu.xom.Node;

/**
 * Creates/recovers a configuration instance and add it to the global context.
 * It can be done by using two strategies:
 * <ul>
 * <li>by setting 'type' attribute to a class that implements
 * <code>IConfigurationProvider</code>, i.e.
 * <code>type='myclass.MyConfigurationProvider'</code>;</li>
 * <li>or by setting 'factory' to any type and 'method' to a parameterless
 * static method which returns a <code>Configuration</code>, i.e.
 * <code>factory="myclass.Any" method="getConfig"</code>.
 * </ul>
 * 
 * To make configuration thread safe for in memory databases like Hypersonic the
 * URL connection can be changed for example to
 * 'jdbc:hsqldb:mem:phonebook<thread name>'. To allow this behavior set
 * threadsafe='true', or set the feature FEATURE_THREADSAFE to 'true'.
 * 
 * @author Thiago Santos
 * 
 */
public class PluginConfiguration extends AbstractPluginFactory {

    /**
     * Default configuration name.
     */
    public static final String SESSION_CONFIGURATION = "sessionConfiguration";

    /**
     * Feature to set configuration provider class name.
     */
    public static final String FEATURE_TYPE = PluginConfiguration.class.getName() + ".type";
    /**
     * Feature to set configuration factory class.
     */
    public static final String FEATURE_FACTORY = PluginConfiguration.class.getName() + ".factory";
    /**
     * Feature to set method factory name.
     */
    public static final String FEATURE_METHOD = PluginConfiguration.class.getName() + ".method";

    @Override
    public void initialize(IContext context) throws PluginException {
        super.initialize(context);
        IFeatureManager fm = SRServices.getFeatureManager();
        if (type == null) {
            fm.set(FEATURE_TYPE, this);
        }
        if (factory == null) {
            fm.set(FEATURE_FACTORY, this);
        }
        if (method == null) {
            fm.set(FEATURE_METHOD, this);
        }
    }

    @Override
    public ENext doStart(IContext context, IResultSet result) throws PluginException {
        if (type == null && (factory == null || method == null)) {
            throw new PluginException(
                    "Parameter 'type', or 'factory' and 'method' missing. In 'type' use an subtype of IConfigurationProvider, or choose a class in 'factory' whose 'method' is static and returns a Hibernate Configuration.");
        }
        try {
            Configuration cfg = null;
            if (type != null) {
                if (UtilLog.LOG.isInfoEnabled()) {
                    UtilLog.LOG.info("Configuration by type: " + type + ".");
                }
                Class<?> typeInstance = Class.forName(type);
                IConfigurationProvider conf = (IConfigurationProvider) typeInstance.newInstance();
                cfg = conf.getConfiguration();
            } else {
                if (UtilLog.LOG.isInfoEnabled()) {
                    UtilLog.LOG.info("Configuration by factory/method: " + factory + "." + method + "()");
                }
                Class<?> typeInstance = Class.forName(factory);
                Method m = typeInstance.getMethod(method);
                cfg = (Configuration) m.invoke(null);
            }
            setListeners(cfg);

            if (getThreadsafe()) {
                changeUrl(context, cfg);
            }

            String str = getName() != null ? getName() : SESSION_CONFIGURATION;
            context.saveGlobal(str, cfg);
            result.addResult(Success.INSTANCE, context.peek());

            SRServices.getObjectManager().clear();
            for (Iterator<?> ite = cfg.getClassMappings(); ite.hasNext();) {
                PersistentClass persistent = (PersistentClass) ite.next();
                PluginInsert pin = new PluginInsert();
                pin.setTypeInstance(Class.forName(persistent.getClassName()));
                SRServices.getObjectManager().bind(pin);
            }
        } catch (Exception e) {
            if (UtilLog.LOG.isDebugEnabled()) {
                UtilLog.LOG.debug(e.getMessage(), e);
            }
            throw new PluginException(e);
        }
        return ENext.SKIP;
    }

    /**
     * Set listeners of plugin.
     * 
     * @param cfg
     *            The configuration.
     */
    public void setListeners(Configuration cfg) {
        HibernateListener listener = new HibernateListener(SRServices.getObjectManager().getEntities());
        PreInsertEventListener[] oldIn = cfg.getEventListeners().getPreInsertEventListeners();
        PreInsertEventListener[] in = null;
        if (oldIn != null) {
            in = new PreInsertEventListener[oldIn.length + 1];
            System.arraycopy(oldIn, 0, in, 0, oldIn.length);
            in[in.length - 1] = listener;
        } else {
            in = new PreInsertEventListener[] { listener };
        }
        cfg.getEventListeners().setPreInsertEventListeners(in);

        PostInsertEventListener[] oldOut = cfg.getEventListeners().getPostInsertEventListeners();
        PostInsertEventListener[] out = null;
        if (oldOut != null) {
            out = new PostInsertEventListener[oldOut.length + 1];
            System.arraycopy(oldOut, 0, out, 0, oldOut.length);
            out[out.length - 1] = listener;
        } else {
            out = new PostInsertEventListener[] { listener };
        }
        cfg.getEventListeners().setPostInsertEventListeners(out);
    }

    /**
     * Change URL if thread safe is true.
     * 
     * @param context
     *            The context.
     * @param cfg
     *            The configuration.
     */
    protected void changeUrl(IContext context, Configuration cfg) {
        String url = String
                .valueOf(SRServices.get(IConcurrentMapping.class).get("url", cfg.getProperty(Environment.URL)));
        cfg.setProperty(Environment.URL, url);
        Node node = context.getNode();
        if (node instanceof Element) {
            Element ele = (Element) node;
            Attribute att = ele.getAttribute("title");
            if (att == null) {
                att = new Attribute("title", "");
                ele.addAttribute(att);
            }
            att.setValue("URL='" + url + "'");
        }
        if (UtilLog.LOG.isInfoEnabled()) {
            UtilLog.LOG.info("Connection URL set to '" + url + "'.");
        }
    }

    /**
     * Gets the configuration object bound to the environment with a given name.
     * 
     * @param context
     *            The context.
     * @param name
     *            The presumed name of configuration.
     * @return The configuration with the given name, if exists, otherwise the
     *         configuration with default name, if exists, or null.
     * @throws PluginException
     *             On configuration lookup error.
     */
    public static Configuration getConfiguration(IContext context, String name) throws PluginException {
        String str = name != null ? name : SESSION_CONFIGURATION;
        Configuration cfg = (Configuration) context.getByName(str);
        if (cfg == null) {
            throw new PluginException(
                    "Instance of '" + str + "' not found. Use " + PluginConfiguration.class.getName() + " before.");
        }
        return cfg;
    }
}