com.redhat.rhn.common.hibernate.ConnectionManager.java Source code

Java tutorial

Introduction

Here is the source code for com.redhat.rhn.common.hibernate.ConnectionManager.java

Source

/**
 * Copyright (c) 2009--2012 Red Hat, Inc.
 *
 * This software is licensed to you under the GNU General Public License,
 * version 2 (GPLv2). There is NO WARRANTY for this software, express or
 * implied, including the implied warranties of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 * along with this software; if not, see
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
 *
 * Red Hat trademarks are not licensed under GPLv2. No permission is
 * granted to use or replicate Red Hat trademarks that are incorporated
 * in this software or its documentation.
 */
package com.redhat.rhn.common.hibernate;

import com.redhat.rhn.common.conf.Config;
import com.redhat.rhn.common.conf.ConfigDefaults;
import com.redhat.rhn.common.finder.FinderFactory;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.metadata.ClassMetadata;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * Manages the lifecycle of the Hibernate SessionFactory and associated
 * thread-scoped Hibernate sessions
 * @version $Rev$
 */
class ConnectionManager {

    private static final Logger LOG = Logger.getLogger(ConnectionManager.class);
    private static final String[] PACKAGE_NAMES = { "com.redhat.rhn.domain", "com.redhat.rhn.taskomatic" };

    private final List<Configurator> configurators = new LinkedList<Configurator>();
    private SessionFactory sessionFactory;
    private final ThreadLocal<SessionInfo> SESSION_TLS = new ThreadLocal<SessionInfo>() {

        @Override
        public SessionInfo get() {
            SessionInfo result = super.get();
            return result;
        }
    };
    private final Set<String> packageNames = new HashSet<String>(Arrays.asList(PACKAGE_NAMES));

    /**
     * enable possibility to load hbm.xml files from different path
     */
    void setAdditionalPackageNames(String[] packageNamesIn) {
        for (String pn : packageNamesIn) {
            packageNames.add(pn);
        }
    }

    /**
     * Register a class with HibernateFactory, to give the registered class a
     * chance to modify the Hibernate configuration before creating the
     * SessionFactory.
     * @param c Configurator to override Hibernate configuration.
     */
    public void addConfigurator(Configurator c) {
        // Yes, this is a race condition, but it will only ever happen at
        // startup, when we really shouldn't have multiple threads running,
        // so it isn't a real race condition.
        configurators.add(c);
    }

    public boolean isTransactionPending() {
        boolean retval = false;
        SessionInfo info = threadSessionInfo();
        if (info != null) {
            retval = info.getTransaction() != null;
        }
        return retval;
    }

    public ClassMetadata getMetadata(Object target) {
        ClassMetadata retval = null;
        if (target != null) {
            if (target instanceof Class) {
                retval = sessionFactory.getClassMetadata((Class) target);
            } else {
                retval = sessionFactory.getClassMetadata(target.getClass());
            }
        }
        return retval;
    }

    /**
     * Close the sessionFactory
     */
    public synchronized void close() {
        try {
            sessionFactory.close();
        } catch (HibernateException e) {
            LOG.debug("Could not close the SessionFactory", e);
        } finally {
            sessionFactory = null;
        }
    }

    public boolean isClosed() {
        return sessionFactory == null;
    }

    public boolean isInitialized() {
        return sessionFactory != null;
    }

    public synchronized void initialize() {
        if (isInitialized()) {
            return;
        }
        createSessionFactory();
    }

    /**
     * Create a SessionFactory, loading the hbm.xml files from the specified
     * location.
     * @param packageNames Package name to be searched.
     */
    private void createSessionFactory() {
        if (sessionFactory != null && !sessionFactory.isClosed()) {
            return;
        }

        List<String> hbms = new LinkedList<String>();

        for (Iterator<String> iter = packageNames.iterator(); iter.hasNext();) {
            String pn = iter.next();
            hbms.addAll(FinderFactory.getFinder(pn).find("hbm.xml"));
            if (LOG.isDebugEnabled()) {
                LOG.debug("Found: " + hbms);
            }
        }

        try {
            Configuration config = new Configuration();
            /*
             * Let's ask the RHN Config for all properties that begin with
             * hibernate.*
             */
            LOG.info("Adding hibernate properties to hibernate Configuration");
            Properties hibProperties = Config.get().getNamespaceProperties("hibernate");
            hibProperties.put("hibernate.connection.username", Config.get().getString(ConfigDefaults.DB_USER));
            hibProperties.put("hibernate.connection.password", Config.get().getString(ConfigDefaults.DB_PASSWORD));

            hibProperties.put("hibernate.connection.url", ConfigDefaults.get().getJdbcConnectionString());

            config.addProperties(hibProperties);
            // Force the use of our txn factory
            if (config.getProperty(Environment.TRANSACTION_STRATEGY) != null) {
                throw new IllegalArgumentException("The property " + Environment.TRANSACTION_STRATEGY
                        + " can not be set in a configuration file;" + " it is set to a fixed value by the code");
            }

            for (Iterator<String> i = hbms.iterator(); i.hasNext();) {
                String hbmFile = i.next();
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Adding resource " + hbmFile);
                }
                config.addResource(hbmFile);
            }
            if (configurators != null) {
                for (Iterator<Configurator> i = configurators.iterator(); i.hasNext();) {
                    Configurator c = i.next();
                    c.addConfig(config);
                }
            }

            // add empty varchar warning interceptor
            EmptyVarcharInterceptor interceptor = new EmptyVarcharInterceptor();
            interceptor.setAutoConvert(true);
            config.setInterceptor(interceptor);

            sessionFactory = config.buildSessionFactory();
        } catch (HibernateException e) {
            LOG.error("FATAL ERROR creating HibernateFactory", e);
        }
    }

    private SessionInfo threadSessionInfo() {
        return SESSION_TLS.get();
    }

    /**
     * Commit the transaction for the current session. This method or
     * {@link #rollbackTransaction}can only be called once per session.
     *
     * @throws HibernateException if the commit fails
     */
    public void commitTransaction() throws HibernateException {
        SessionInfo info = threadSessionInfo();
        if (info == null) {
            return;
        }
        if (info.getSession() == null) {
            // Session was never started
            return;
        }
        Transaction txn = info.getTransaction();
        if (txn != null) {
            txn.commit();
            info.setTransaction(null);
        }
    }

    /**
     * Roll the transaction for the current session back. This method or
     * {@link #commitTransaction}can only be called once per session.
     *
     * @throws HibernateException if the commit fails
     */
    public void rollbackTransaction() throws HibernateException {
        SessionInfo info = threadSessionInfo();
        if (info == null) {
            return;
        }
        if (info.getSession() == null) {
            return;
        }
        Transaction txn = info.getTransaction();
        if (txn != null) {
            txn.rollback();
            info.setTransaction(null);
        }
    }

    /**
     * Returns the Hibernate session stored in ThreadLocal storage. If not
     * present, creates a new one and stores it in ThreadLocal; creating the
     * session also begins a transaction implicitly.
     *
     * @return Session Session asked for
     */
    public Session getSession() {
        if (!isInitialized()) {
            initialize();
        }
        return getInternalSession();
    }

    private Session getInternalSession() {
        SessionInfo info = threadSessionInfo();
        if (info == null || info.getSession() == null) {
            try {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("YYY Opening Hibernate Session");
                }
                info = new SessionInfo(sessionFactory.openSession());
                // Automatically start a transaction
                info.setTransaction(info.getSession().beginTransaction());
            } catch (HibernateException e) {
                throw new HibernateRuntimeException("couldn't open session", e);
            }
            SESSION_TLS.set(info);
        }

        return info.getSession();

    }

    /**
     * Closes the Hibernate Session stored in ThreadLocal storage.
     */
    public void closeSession() {
        SessionInfo info = threadSessionInfo();
        if (info == null) {
            return;
        }
        Session session = info.getSession();
        try {
            Transaction txn = info.getTransaction();
            if (txn != null && !txn.wasCommitted() && !txn.wasRolledBack()) {
                try {
                    txn.commit();
                } catch (HibernateException e) {
                    txn.rollback();
                }
            }
        } catch (HibernateException e) {
            LOG.error(e);
        } finally {
            if (session != null) {
                try {
                    if (session.isOpen()) {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("YYY Closing Hibernate Session");
                        }
                        session.close();
                    }
                } catch (HibernateException e) {
                    throw new HibernateRuntimeException("couldn't close session");
                } finally {
                    SESSION_TLS.set(null);
                }
            } else {
                SESSION_TLS.set(null);
            }
        }
    }
}