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