org.unitime.commons.hibernate.util.HibernateUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.commons.hibernate.util.HibernateUtil.java

Source

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you 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.unitime.commons.hibernate.util;

import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.naming.spi.NamingManager;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.MappingException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.ConfigHelper;
import org.hibernate.mapping.Formula;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.IntegerType;
import org.unitime.commons.LocalContext;
import org.unitime.commons.hibernate.connection.DisposableConnectionProvider;
import org.unitime.commons.hibernate.id.UniqueIdGenerator;
import org.unitime.timetable.ApplicationProperties;
import org.unitime.timetable.defaults.ApplicationProperty;
import org.unitime.timetable.model.base._BaseRootDAO;
import org.unitime.timetable.model.dao._RootDAO;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

/**
 * @author Tomas Muller
 */
public class HibernateUtil {
    private static Log sLog = LogFactory.getLog(HibernateUtil.class);
    private static SessionFactory sSessionFactory = null;

    private static void setProperty(org.w3c.dom.Document document, String name, String value) {
        if (value == null) {
            removeProperty(document, name);
        } else {
            org.w3c.dom.Element hibConfiguration = (org.w3c.dom.Element) document
                    .getElementsByTagName("hibernate-configuration").item(0);
            org.w3c.dom.Element sessionFactoryConfig = (org.w3c.dom.Element) hibConfiguration
                    .getElementsByTagName("session-factory").item(0);
            NodeList properties = sessionFactoryConfig.getElementsByTagName("property");
            for (int i = 0; i < properties.getLength(); i++) {
                org.w3c.dom.Element property = (org.w3c.dom.Element) properties.item(i);
                if (name.equals(property.getAttribute("name"))) {
                    Text text = (Text) property.getFirstChild();
                    if (text == null) {
                        property.appendChild(document.createTextNode(value));
                    } else {
                        text.setData(value);
                    }
                    return;
                }
            }
            org.w3c.dom.Element property = document.createElement("property");
            property.setAttribute("name", name);
            property.appendChild(document.createTextNode(value));
            sessionFactoryConfig.appendChild(property);
        }
    }

    private static void removeProperty(org.w3c.dom.Document document, String name) {
        org.w3c.dom.Element hibConfiguration = (org.w3c.dom.Element) document
                .getElementsByTagName("hibernate-configuration").item(0);
        org.w3c.dom.Element sessionFactoryConfig = (org.w3c.dom.Element) hibConfiguration
                .getElementsByTagName("session-factory").item(0);
        org.w3c.dom.NodeList properties = sessionFactoryConfig.getElementsByTagName("property");
        for (int i = 0; i < properties.getLength(); i++) {
            org.w3c.dom.Element property = (org.w3c.dom.Element) properties.item(i);
            if (name.equals(property.getAttribute("name"))) {
                sessionFactoryConfig.removeChild(property);
                return;
            }
        }
    }

    public static void configureHibernate(String connectionUrl) throws Exception {
        Properties properties = ApplicationProperties.getProperties();
        properties.setProperty("connection.url", connectionUrl);
        configureHibernate(properties);
    }

    public static String getProperty(Properties properties, String name) {
        String value = properties.getProperty(name);
        if (value != null) {
            sLog.debug("   -- " + name + "=" + value);
            return value;
        }
        sLog.debug("   -- using application properties for " + name);
        value = ApplicationProperties.getProperty(name);
        sLog.debug("     -- " + name + "=" + value);
        return value;
    }

    public static void fixSchemaInFormulas(Configuration cfg) {
        cfg.buildMappings();
        String schema = cfg.getProperty("default_schema");
        if (schema != null) {
            for (Iterator i = cfg.getClassMappings(); i.hasNext();) {
                PersistentClass pc = (PersistentClass) i.next();
                for (Iterator j = pc.getPropertyIterator(); j.hasNext();) {
                    Property p = (Property) j.next();
                    for (Iterator k = p.getColumnIterator(); k.hasNext();) {
                        Selectable c = (Selectable) k.next();
                        if (c instanceof Formula) {
                            Formula f = (Formula) c;
                            if (f.getFormula() != null && f.getFormula().indexOf("%SCHEMA%") >= 0) {
                                f.setFormula(f.getFormula().replaceAll("%SCHEMA%", schema));
                                sLog.debug("Schema updated in " + pc.getClassName() + "." + p.getName() + " to "
                                        + f.getFormula());
                            }
                        }
                    }
                }
            }
        }
    }

    public static void configureHibernate(Properties properties) throws Exception {
        if (sSessionFactory != null) {
            sSessionFactory.close();
            sSessionFactory = null;
        }

        if (!NamingManager.hasInitialContextFactoryBuilder())
            NamingManager.setInitialContextFactoryBuilder(new LocalContext(null));

        sLog.info("Connecting to " + getProperty(properties, "connection.url"));
        ClassLoader classLoader = HibernateUtil.class.getClassLoader();
        sLog.debug("  -- class loader retrieved");

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        sLog.debug("  -- document factory created");
        DocumentBuilder builder = factory.newDocumentBuilder();
        builder.setEntityResolver(new EntityResolver() {
            public InputSource resolveEntity(String publicId, String systemId) {
                if (publicId.equals("-//Hibernate/Hibernate Mapping DTD 3.0//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Mapping DTD//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD 3.0//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                }
                return null;
            }
        });
        sLog.debug("  -- document builder created");
        Document document = builder.parse(classLoader.getResource("hibernate.cfg.xml").openStream());
        sLog.debug("  -- hibernate.cfg.xml parsed");

        String dialect = getProperty(properties, "dialect");
        if (dialect != null)
            setProperty(document, "dialect", dialect);

        String idgen = getProperty(properties, "tmtbl.uniqueid.generator");
        if (idgen != null)
            setProperty(document, "tmtbl.uniqueid.generator", idgen);

        if (ApplicationProperty.HibernateClusterEnabled.isFalse())
            setProperty(document, "net.sf.ehcache.configurationResourceName", "ehcache-nocluster.xml");

        // Remove second level cache
        setProperty(document, "hibernate.cache.use_second_level_cache", "false");
        setProperty(document, "hibernate.cache.use_query_cache", "false");
        removeProperty(document, "hibernate.cache.region.factory_class");

        for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
            String name = (String) e.nextElement();
            if (name.startsWith("hibernate.") || name.startsWith("connection.")
                    || name.startsWith("tmtbl.hibernate.")) {
                String value = properties.getProperty(name);
                if ("NULL".equals(value))
                    removeProperty(document, name);
                else
                    setProperty(document, name, value);
                if (!name.equals("connection.password"))
                    sLog.debug("  -- set " + name + ": " + value);
                else
                    sLog.debug("  -- set " + name + ": *****");
            }
        }

        String default_schema = getProperty(properties, "default_schema");
        if (default_schema != null)
            setProperty(document, "default_schema", default_schema);

        sLog.debug("  -- hibernate.cfg.xml altered");

        Configuration cfg = new Configuration();
        sLog.debug("  -- configuration object created");

        cfg.setEntityResolver(new EntityResolver() {
            public InputSource resolveEntity(String publicId, String systemId) {
                if (publicId.equals("-//Hibernate/Hibernate Mapping DTD 3.0//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Mapping DTD//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD 3.0//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD//EN")) {
                    return new InputSource(HibernateUtil.class.getClassLoader()
                            .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                }
                return null;
            }
        });
        sLog.debug("  -- added entity resolver");

        cfg.configure(document);
        sLog.debug("  -- hibernate configured");

        fixSchemaInFormulas(cfg);

        UniqueIdGenerator.configure(cfg);

        (new _BaseRootDAO() {
            void setConf(Configuration cfg) {
                _BaseRootDAO.sConfiguration = cfg;
            }

            protected Class getReferenceClass() {
                return null;
            }
        }).setConf(cfg);
        sLog.debug("  -- configuration set to _BaseRootDAO");

        sSessionFactory = cfg.buildSessionFactory();
        sLog.debug("  -- session factory created");

        (new _BaseRootDAO() {
            void setSF(SessionFactory fact) {
                _BaseRootDAO.sSessionFactory = fact;
            }

            protected Class getReferenceClass() {
                return null;
            }
        }).setSF(sSessionFactory);
        sLog.debug("  -- session factory set to _BaseRootDAO");

        addBitwiseOperationsToDialect();
        sLog.debug("  -- bitwise operation added to the dialect if needed");

        DatabaseUpdate.update();
    }

    public static void closeHibernate() {
        if (sSessionFactory != null) {
            if (sSessionFactory instanceof SessionFactoryImpl) {
                ConnectionProvider cp = ((SessionFactoryImpl) sSessionFactory).getConnectionProvider();
                if (cp instanceof DisposableConnectionProvider) {
                    try {
                        ((DisposableConnectionProvider) cp).destroy();
                    } catch (Exception e) {
                        sLog.error("Failed to destroy connection provider: " + e.getMessage());
                    }
                }
            }
            sSessionFactory.close();
            sSessionFactory = null;
        }
    }

    public static void configureHibernateFromRootDAO(String cfgName, Configuration cfg) {
        try {
            EntityResolver entityResolver = new EntityResolver() {
                public InputSource resolveEntity(String publicId, String systemId) {
                    if (publicId.equals("-//Hibernate/Hibernate Mapping DTD 3.0//EN")) {
                        return new InputSource(HibernateUtil.class.getClassLoader()
                                .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                    } else if (publicId.equals("-//Hibernate/Hibernate Mapping DTD//EN")) {
                        return new InputSource(HibernateUtil.class.getClassLoader()
                                .getResourceAsStream("org/hibernate/hibernate-mapping-3.0.dtd"));
                    } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD 3.0//EN")) {
                        return new InputSource(HibernateUtil.class.getClassLoader()
                                .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                    } else if (publicId.equals("-//Hibernate/Hibernate Configuration DTD//EN")) {
                        return new InputSource(HibernateUtil.class.getClassLoader()
                                .getResourceAsStream("org/hibernate/hibernate-configuration-3.0.dtd"));
                    }
                    return null;
                }
            };

            cfg.setEntityResolver(entityResolver);
            sLog.debug("  -- added entity resolver");

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            sLog.debug("  -- document factory created");
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver(entityResolver);
            sLog.debug("  -- document builder created");
            Document document = builder
                    .parse(ConfigHelper.getConfigStream(cfgName == null ? "hibernate.cfg.xml" : cfgName));

            String dialect = ApplicationProperty.DatabaseDialect.value();
            if (dialect != null)
                setProperty(document, "dialect", dialect);

            String default_schema = ApplicationProperty.DatabaseSchema.value();
            if (default_schema != null)
                setProperty(document, "default_schema", default_schema);

            String idgen = ApplicationProperty.DatabaseUniqueIdGenerator.value();
            if (idgen != null)
                setProperty(document, "tmtbl.uniqueid.generator", idgen);

            if (ApplicationProperty.HibernateClusterEnabled.isFalse())
                setProperty(document, "net.sf.ehcache.configurationResourceName", "ehcache-nocluster.xml");

            for (Enumeration e = ApplicationProperties.getProperties().propertyNames(); e.hasMoreElements();) {
                String name = (String) e.nextElement();
                if (name.startsWith("hibernate.") || name.startsWith("connection.")
                        || name.startsWith("tmtbl.hibernate.")) {
                    String value = ApplicationProperties.getProperty(name);
                    if ("NULL".equals(value))
                        removeProperty(document, name);
                    else
                        setProperty(document, name, value);
                    if (!name.equals("connection.password"))
                        sLog.debug("  -- set " + name + ": " + value);
                    else
                        sLog.debug("  -- set " + name + ": *****");
                }
            }

            cfg.configure(document);
            sLog.debug("  -- hibernate configured");

            HibernateUtil.fixSchemaInFormulas(cfg);
            sLog.debug("  -- %SCHEMA% in formulas changed to " + cfg.getProperty("default_schema"));

            UniqueIdGenerator.configure(cfg);
            sLog.debug("  -- UniquId generator configured");
        } catch (Exception e) {
            sLog.error("Unable to configure hibernate, reason: " + e.getMessage(), e);
        }
    }

    private static String sConnectionUrl = null;

    public static String getConnectionUrl() {
        if (sConnectionUrl == null) {
            try {
                SessionImplementor session = (SessionImplementor) new _RootDAO().getSession();
                Connection connection = session.getJdbcConnectionAccess().obtainConnection();
                sConnectionUrl = connection.getMetaData().getURL();
                session.getJdbcConnectionAccess().releaseConnection(connection);
            } catch (Exception e) {
                sLog.error("Unable to get connection string, reason: " + e.getMessage(), e);
            }
        }
        return sConnectionUrl;
    }

    public static String getDatabaseName() {
        String schema = _RootDAO.getConfiguration().getProperty("default_schema");
        String url = getConnectionUrl();
        if (url == null)
            return "N/A";
        if (url.startsWith("jdbc:oracle:")) {
            return schema + "@" + url.substring(1 + url.lastIndexOf(':'));
        }
        return schema;
    }

    public static void clearCache() {
        clearCache(null, true);
    }

    public static void clearCache(Class persistentClass) {
        clearCache(persistentClass, false);
    }

    public static void clearCache(Class persistentClass, boolean evictQueries) {
        _RootDAO dao = new _RootDAO();
        org.hibernate.Session hibSession = dao.getSession();
        SessionFactory hibSessionFactory = hibSession.getSessionFactory();
        if (persistentClass == null) {
            for (Iterator i = hibSessionFactory.getAllClassMetadata().entrySet().iterator(); i.hasNext();) {
                Map.Entry entry = (Map.Entry) i.next();
                String className = (String) entry.getKey();
                ClassMetadata classMetadata = (ClassMetadata) entry.getValue();
                try {
                    hibSessionFactory.getCache().evictEntityRegion(Class.forName(className));
                    for (int j = 0; j < classMetadata.getPropertyNames().length; j++) {
                        if (classMetadata.getPropertyTypes()[j].isCollectionType()) {
                            try {
                                hibSessionFactory.getCache().evictCollectionRegion(
                                        className + "." + classMetadata.getPropertyNames()[j]);
                            } catch (MappingException e) {
                            }
                        }
                    }
                } catch (ClassNotFoundException e) {
                }
            }
            hibSessionFactory.getCache().evictEntityRegions();
            hibSessionFactory.getCache().evictCollectionRegions();
        } else {
            ClassMetadata classMetadata = hibSessionFactory.getClassMetadata(persistentClass);
            hibSessionFactory.getCache().evictEntityRegion(persistentClass);
            if (classMetadata != null) {
                for (int j = 0; j < classMetadata.getPropertyNames().length; j++) {
                    if (classMetadata.getPropertyTypes()[j].isCollectionType()) {
                        try {
                            hibSessionFactory.getCache().evictCollectionRegion(persistentClass.getClass().getName()
                                    + "." + classMetadata.getPropertyNames()[j]);
                        } catch (MappingException e) {
                        }
                    }
                }
            }
        }
        if (evictQueries) {
            hibSessionFactory.getCache().evictQueryRegions();
            hibSessionFactory.getCache().evictDefaultQueryRegion();
        }
    }

    public static Class<?> getDialect() {
        try {
            return Class.forName(_RootDAO.getConfiguration().getProperty("dialect"));
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    public static boolean isMySQL() {
        return MySQLDialect.class.isAssignableFrom(getDialect());
    }

    public static boolean isOracle() {
        return Oracle8iDialect.class.isAssignableFrom(getDialect());
    }

    public static String addDate(String dateSQL, String incrementSQL) {
        if (isMySQL())
            return "adddate(" + dateSQL + "," + incrementSQL + ")";
        else
            return dateSQL + (incrementSQL.startsWith("+") || incrementSQL.startsWith("-") ? "" : "+")
                    + incrementSQL;
    }

    public static String dayOfWeek(String field) {
        if (isOracle())
            return "to_char(" + field + ",'D')";
        else
            return "dayofweek(" + field + ")";
    }

    public static String date(Date date) {
        if (isOracle())
            return "to_date('" + new SimpleDateFormat("yyyy-MM-dd").format(date) + "', 'YYYY-MM-DD')";
        else
            return "str_to_date('" + new SimpleDateFormat("yyyy-MM-dd").format(date) + "', '%Y-%m-%d')";
    }

    public static void addBitwiseOperationsToDialect() {
        SessionFactoryImplementor hibSessionFactory = (SessionFactoryImplementor) new _RootDAO().getSession()
                .getSessionFactory();
        Dialect dialect = hibSessionFactory.getDialect();
        if (!dialect.getFunctions().containsKey("bit_and")) {
            if (isOracle())
                dialect.getFunctions().put("bit_and", new StandardSQLFunction("bitand", IntegerType.INSTANCE));
            else
                dialect.getFunctions().put("bit_and", new SQLFunctionTemplate(IntegerType.INSTANCE, "?1 & ?2"));
        }
    }
}