001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.spring.hibernate;
016    
017    import com.liferay.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
023    import com.liferay.portal.kernel.util.Converter;
024    import com.liferay.portal.kernel.util.PreloadClassLoader;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.util.ClassLoaderUtil;
029    import com.liferay.portal.util.PropsUtil;
030    import com.liferay.portal.util.PropsValues;
031    
032    import java.io.InputStream;
033    
034    import java.net.URL;
035    
036    import java.util.Enumeration;
037    import java.util.HashMap;
038    import java.util.Map;
039    import java.util.Properties;
040    import java.util.WeakHashMap;
041    
042    import javassist.util.proxy.ProxyFactory;
043    
044    import org.hibernate.HibernateException;
045    import org.hibernate.SessionFactory;
046    import org.hibernate.cfg.Configuration;
047    import org.hibernate.cfg.Environment;
048    import org.hibernate.dialect.Dialect;
049    
050    import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
051    
052    /**
053     * @author Brian Wing Shun Chan
054     * @author Marcellus Tavares
055     * @author Shuyang Zhou
056     * @author Tomas Polesovsky
057     */
058    public class PortalHibernateConfiguration extends LocalSessionFactoryBean {
059    
060            @Override
061            public SessionFactory buildSessionFactory() throws Exception {
062                    setBeanClassLoader(getConfigurationClassLoader());
063    
064                    return super.buildSessionFactory();
065            }
066    
067            @Override
068            public void destroy() throws HibernateException {
069                    setBeanClassLoader(null);
070    
071                    super.destroy();
072            }
073    
074            public void setHibernateConfigurationConverter(
075                    Converter<String> hibernateConfigurationConverter) {
076    
077                    _hibernateConfigurationConverter = hibernateConfigurationConverter;
078            }
079    
080            protected static Map<String, Class<?>> getPreloadClassLoaderClasses() {
081                    try {
082                            Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
083    
084                            for (String className : _PRELOAD_CLASS_NAMES) {
085                                    ClassLoader portalClassLoader =
086                                            ClassLoaderUtil.getPortalClassLoader();
087    
088                                    Class<?> clazz = portalClassLoader.loadClass(className);
089    
090                                    classes.put(className, clazz);
091                            }
092    
093                            return classes;
094                    }
095                    catch (ClassNotFoundException cnfe) {
096                            throw new RuntimeException(cnfe);
097                    }
098            }
099    
100            protected Dialect determineDialect() {
101                    return DialectDetector.getDialect(getDataSource());
102            }
103    
104            protected ClassLoader getConfigurationClassLoader() {
105                    Class<?> clazz = getClass();
106    
107                    return clazz.getClassLoader();
108            }
109    
110            protected String[] getConfigurationResources() {
111                    return PropsUtil.getArray(PropsKeys.HIBERNATE_CONFIGS);
112            }
113    
114            @Override
115            protected Configuration newConfiguration() {
116                    Configuration configuration = new Configuration();
117    
118                    try {
119                            String[] resources = getConfigurationResources();
120    
121                            for (String resource : resources) {
122                                    try {
123                                            readResource(configuration, resource);
124                                    }
125                                    catch (Exception e2) {
126                                            if (_log.isWarnEnabled()) {
127                                                    _log.warn(e2, e2);
128                                            }
129                                    }
130                            }
131    
132                            Properties properties = PropsUtil.getProperties();
133    
134                            if (SPIUtil.isSPI()) {
135                                    properties.put(
136                                            "hibernate.cache.use_query_cache",
137                                            Boolean.FALSE.toString());
138                                    properties.put(
139                                            "hibernate.cache.use_second_level_cache",
140                                            Boolean.FALSE.toString());
141                            }
142    
143                            configuration.setProperties(properties);
144    
145                            if (Validator.isNull(PropsValues.HIBERNATE_DIALECT)) {
146                                    Dialect dialect = determineDialect();
147    
148                                    setDB(dialect);
149    
150                                    Class<?> clazz = dialect.getClass();
151    
152                                    configuration.setProperty("hibernate.dialect", clazz.getName());
153                            }
154    
155                            DB db = DBFactoryUtil.getDB();
156    
157                            String dbType = db.getType();
158    
159                            if (dbType.equals(DB.TYPE_HYPERSONIC)) {
160                                    //configuration.setProperty("hibernate.jdbc.batch_size", "0");
161                            }
162                    }
163                    catch (Exception e1) {
164                            _log.error(e1, e1);
165                    }
166    
167                    Properties hibernateProperties = getHibernateProperties();
168    
169                    if (hibernateProperties != null) {
170                            for (Map.Entry<Object, Object> entry :
171                                            hibernateProperties.entrySet()) {
172    
173                                    String key = (String)entry.getKey();
174                                    String value = (String)entry.getValue();
175    
176                                    configuration.setProperty(key, value);
177                            }
178                    }
179    
180                    return configuration;
181            }
182    
183            @Override
184            protected void postProcessConfiguration(Configuration configuration) {
185    
186                    // Make sure that the Hibernate settings from PropsUtil are set. See the
187                    // buildSessionFactory implementation in the LocalSessionFactoryBean
188                    // class to understand how Spring automates a lot of configuration for
189                    // Hibernate.
190    
191                    String connectionReleaseMode = PropsUtil.get(
192                            Environment.RELEASE_CONNECTIONS);
193    
194                    if (Validator.isNotNull(connectionReleaseMode)) {
195                            configuration.setProperty(
196                                    Environment.RELEASE_CONNECTIONS, connectionReleaseMode);
197                    }
198            }
199    
200            protected void readResource(
201                            Configuration configuration, InputStream inputStream)
202                    throws Exception {
203    
204                    if (inputStream == null) {
205                            return;
206                    }
207    
208                    if (_hibernateConfigurationConverter != null) {
209                            String configurationString = StringUtil.read(inputStream);
210    
211                            configurationString = _hibernateConfigurationConverter.convert(
212                                    configurationString);
213    
214                            inputStream = new UnsyncByteArrayInputStream(
215                                    configurationString.getBytes());
216                    }
217    
218                    configuration = configuration.addInputStream(inputStream);
219    
220                    inputStream.close();
221            }
222    
223            protected void readResource(Configuration configuration, String resource)
224                    throws Exception {
225    
226                    ClassLoader classLoader = getConfigurationClassLoader();
227    
228                    if (resource.startsWith("classpath*:")) {
229                            String name = resource.substring("classpath*:".length());
230    
231                            Enumeration<URL> enu = classLoader.getResources(name);
232    
233                            if (_log.isDebugEnabled() && !enu.hasMoreElements()) {
234                                    _log.debug("No resources found for " + name);
235                            }
236    
237                            while (enu.hasMoreElements()) {
238                                    URL url = enu.nextElement();
239    
240                                    InputStream inputStream = url.openStream();
241    
242                                    readResource(configuration, inputStream);
243                            }
244                    }
245                    else {
246                            InputStream inputStream = classLoader.getResourceAsStream(resource);
247    
248                            readResource(configuration, inputStream);
249                    }
250            }
251    
252            protected void setDB(Dialect dialect) {
253                    DBFactoryUtil.setDB(dialect);
254            }
255    
256            private static final String[] _PRELOAD_CLASS_NAMES =
257                    PropsValues.SPRING_HIBERNATE_CONFIGURATION_PROXY_FACTORY_PRELOAD_CLASSLOADER_CLASSES;
258    
259            private static Log _log = LogFactoryUtil.getLog(
260                    PortalHibernateConfiguration.class);
261    
262            private static Map<ProxyFactory, ClassLoader> _proxyFactoryClassLoaders =
263                    new WeakHashMap<ProxyFactory, ClassLoader>();
264    
265            static {
266                    ProxyFactory.classLoaderProvider =
267                            new ProxyFactory.ClassLoaderProvider() {
268    
269                                    @Override
270                                    public ClassLoader get(ProxyFactory proxyFactory) {
271                                            synchronized (_proxyFactoryClassLoaders) {
272                                                    ClassLoader classLoader = _proxyFactoryClassLoaders.get(
273                                                            proxyFactory);
274    
275                                                    if (classLoader != null) {
276                                                            return classLoader;
277                                                    }
278    
279                                                    classLoader = ClassLoaderUtil.getPortalClassLoader();
280    
281                                                    ClassLoader contextClassLoader =
282                                                            ClassLoaderUtil.getContextClassLoader();
283    
284                                                    if (classLoader != contextClassLoader) {
285                                                            classLoader = new PreloadClassLoader(
286                                                                    contextClassLoader,
287                                                                    getPreloadClassLoaderClasses());
288                                                    }
289    
290                                                    _proxyFactoryClassLoaders.put(
291                                                            proxyFactory, classLoader);
292    
293                                                    return classLoader;
294                                            }
295                                    }
296    
297                            };
298            }
299    
300            private Converter<String> _hibernateConfigurationConverter;
301    
302    }