/* * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.etk.component.database.impl; import org.etk.common.exception.ObjectNotFoundException; import org.etk.common.logging.Logger; import org.etk.common.utils.PrivilegedSystemHelper; import org.etk.common.utils.SecurityHelper; import org.etk.component.database.HibernateService; import org.etk.component.database.ObjectQuery; import org.etk.kernel.cache.CacheService; import org.etk.kernel.container.KernelContainer; import org.etk.kernel.container.component.ComponentPlugin; import org.etk.kernel.container.component.ComponentRequestLifecycle; import org.etk.kernel.container.xml.InitParams; import org.etk.kernel.container.xml.PropertiesParam; import org.etk.kernel.container.xml.Property; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.resolver.DialectFactory; import org.hibernate.tool.hbm2ddl.SchemaUpdate; import java.io.Serializable; import java.net.URL; import java.security.PrivilegedAction; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Properties; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; /** * Created by The eXo Platform SAS . * * @author Tuan Nguyen tuan08@users.sourceforge.net Date: Jun 14, 2003 * @author dhodnett $Id: HibernateServiceImpl.java,v 1.3 2004/10/30 02:27:52 * tuan08 Exp $ */ public class HibernateServiceImpl implements HibernateService, ComponentRequestLifecycle { public static final String AUTO_DIALECT = "AUTO"; private ThreadLocal<Session> threadLocal_; private static Logger log_ = Logger.getLogger(HibernateServiceImpl.class); private HibernateConfigurationImpl conf_; private SessionFactory sessionFactory_; private HashSet<String> mappings_ = new HashSet<String>(); @SuppressWarnings("unchecked") public HibernateServiceImpl(InitParams initParams, CacheService cacheService) { threadLocal_ = new ThreadLocal<Session>(); PropertiesParam param = initParams.getPropertiesParam("hibernate.properties"); final HibernateSettingsFactory settingsFactory = new HibernateSettingsFactory(new ExoCacheProvider(cacheService)); conf_ = SecurityHelper.doPrivilegedAction(new PrivilegedAction<HibernateConfigurationImpl>() { public HibernateConfigurationImpl run() { return new HibernateConfigurationImpl(settingsFactory); } }); Iterator properties = param.getPropertyIterator(); while (properties.hasNext()) { Property p = (Property) properties.next(); // String name = p.getName(); String value = p.getValue(); // Julien: Don't remove that unless you know what you are doing if (name.equals("hibernate.dialect") && !value.equalsIgnoreCase(AUTO_DIALECT)) { Package pkg = Dialect.class.getPackage(); String dialect = value.substring(22); value = pkg.getName() + "." + dialect; // 22 is the length of // "org.hibernate.dialect" log_.info("Using dialect " + dialect); } // conf_.setProperty(name, value); } // Replace the potential "java.io.tmpdir" variable in the connection URL String connectionURL = conf_.getProperty("hibernate.connection.url"); if (connectionURL != null) { connectionURL = connectionURL.replace("${java.io.tmpdir}", PrivilegedSystemHelper.getProperty("java.io.tmpdir")); conf_.setProperty("hibernate.connection.url", connectionURL); } // Auto-detect dialect if "hibernate.dialect" is set as AUTO or is not set. String dialect = conf_.getProperty("hibernate.dialect"); if (dialect == null || dialect.equalsIgnoreCase(AUTO_DIALECT)) { // detect dialect and replace parameter Connection connection = null; try { // check is there is data source String dataSourceName = conf_.getProperty("hibernate.connection.datasource"); if (dataSourceName != null) { // detect dialect by data source DataSource dataSource; try { dataSource = (DataSource) new InitialContext().lookup(dataSourceName); if (dataSource == null) { log_.error("DataSource is configured but not finded.", new Exception()); } else { connection = dataSource.getConnection(); Dialect d = DialectFactory.buildDialect(new Properties(), connection); conf_.setProperty("hibernate.dialect", d.getClass().getName()); } } catch (NamingException e) { log_.error(e.getMessage(), e); } } else { String url = conf_.getProperty("hibernate.connection.url"); if (url != null) { // detect dialect by url try { // load driver class Class.forName(conf_.getProperty("hibernate.connection.driver_class")).newInstance(); } catch (InstantiationException e) { log_.error(e.getMessage(), e); } catch (IllegalAccessException e) { log_.error(e.getMessage(), e); } catch (ClassNotFoundException e) { log_.error(e.getMessage(), e); } String dbUserName = conf_.getProperty("hibernate.connection.username"); String dbPassword = conf_.getProperty("hibernate.connection.password"); connection = dbUserName != null ? DriverManager.getConnection(url, dbUserName, dbPassword) : DriverManager.getConnection(url); Dialect d = DialectFactory.buildDialect(new Properties(), connection); conf_.setProperty("hibernate.dialect", d.getClass().getName()); } else { Exception e = new Exception("Any data source is not configured!"); log_.error(e.getMessage(), e); } } } catch (SQLException e) { log_.error(e.getMessage(), e); } finally { if (connection != null) { try { connection.close(); } catch (SQLException e) { log_.error(e.getMessage(), e); } } } } } public void addPlugin(ComponentPlugin plugin) { if (plugin instanceof AddHibernateMappingPlugin) { AddHibernateMappingPlugin impl = (AddHibernateMappingPlugin) plugin; try { List path = impl.getMapping(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (path != null) { for (int i = 0; i < path.size(); i++) { String relativePath = (String) path.get(i); if (!mappings_.contains(relativePath)) { mappings_.add(relativePath); URL url = cl.getResource(relativePath); log_.info("Adding Hibernate Mapping: " + relativePath); log_.info("URL XML file: " + url); conf_.addURL(url); } } } // Annotations List<String> annotations = impl.getAnnotations(); if (annotations != null) { for (String annotation : annotations) { Class clazz = cl.loadClass(annotation); conf_.addAnnotatedClass(clazz); } } } catch (Exception ex) { log_.error(ex.getLocalizedMessage(), ex); } } } public ComponentPlugin removePlugin(String name) { return null; } public Collection getPlugins() { return null; } public Configuration getHibernateConfiguration() { return conf_; } /** * @return the SessionFactory */ public SessionFactory getSessionFactory() { if (sessionFactory_ == null) { sessionFactory_ = SecurityHelper.doPrivilegedAction(new PrivilegedAction<SessionFactory>() { public SessionFactory run() { SessionFactory factory = conf_.buildSessionFactory(); new SchemaUpdate(conf_).execute(false, true); return factory; } }); } return sessionFactory_; } public Session openSession() { Session currentSession = threadLocal_.get(); if (currentSession == null) { if (log_.isDebugEnabled()) log_.debug("open new hibernate session in openSession()"); currentSession = getSessionFactory().openSession(); threadLocal_.set(currentSession); } return currentSession; } public Session openNewSession() { Session currentSession = threadLocal_.get(); if (currentSession != null) { closeSession(currentSession); } currentSession = getSessionFactory().openSession(); threadLocal_.set(currentSession); return currentSession; } public void closeSession(Session session) { if (session == null) return; try { session.close(); if (log_.isDebugEnabled()) log_.debug("close hibernate session in openSession(Session session)"); } catch (Throwable t) { log_.error("Error closing hibernate session : " + t.getMessage(), t); } threadLocal_.set(null); } final public void closeSession() { Session s = threadLocal_.get(); if (s != null) s.close(); threadLocal_.set(null); } public Object findExactOne(Session session, String query, String id) throws Exception { Object res = session.createQuery(query).setString(0, id).uniqueResult(); if (res == null) { throw new ObjectNotFoundException("Cannot find the object with id: " + id); } return res; } public Object findOne(Session session, String query, String id) throws Exception { List l = session.createQuery(query).setString(0, id).list(); if (l.size() == 0) { return null; } else if (l.size() > 1) { throw new Exception("Expect only one object but found" + l.size()); } else { return l.get(0); } } public Object findOne(Class clazz, Serializable id) throws Exception { Session session = openSession(); Object obj = session.get(clazz, id); return obj; } public Object findOne(ObjectQuery q) throws Exception { Session session = openSession(); List l = session.createQuery(q.getHibernateQuery()).list(); if (l.size() == 0) { return null; } else if (l.size() > 1) { throw new Exception("Expect only one object but found" + l.size()); } else { return l.get(0); } } public Object create(Object obj) throws Exception { Session session = openSession(); session.save(obj); session.flush(); return obj; } public Object update(Object obj) throws Exception { Session session = openSession(); session.update(obj); session.flush(); return obj; } public Object save(Object obj) throws Exception { Session session = openSession(); session.merge(obj); session.flush(); return obj; } public Object remove(Object obj) throws Exception { Session session = openSession(); session.delete(obj); session.flush(); return obj; } public Object remove(Class clazz, Serializable id) throws Exception { Session session = openSession(); Object obj = session.get(clazz, id); session.delete(obj); session.flush(); return obj; } public Object remove(Session session, Class clazz, Serializable id) throws Exception { Object obj = session.get(clazz, id); session.delete(obj); return obj; } public void startRequest(KernelContainer container) { } public void endRequest(KernelContainer container) { closeSession(); } }