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.security.pacl.PACLClassLoaderUtil;
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                                            PACLClassLoaderUtil.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                            inputStream.close();
200    
201                            configurationString = _hibernateConfigurationConverter.convert(
202                                    configurationString);
203    
204                            inputStream = new UnsyncByteArrayInputStream(
205                                    configurationString.getBytes());
206                    }
207    
208                    configuration = configuration.addInputStream(inputStream);
209    
210                    inputStream.close();
211            }
212    
213            protected void readResource(Configuration configuration, String resource)
214                    throws Exception {
215    
216                    ClassLoader classLoader = getConfigurationClassLoader();
217    
218                    if (resource.startsWith("classpath*:")) {
219                            String name = resource.substring("classpath*:".length());
220    
221                            Enumeration<URL> enu = classLoader.getResources(name);
222    
223                            if (_log.isDebugEnabled() && !enu.hasMoreElements()) {
224                                    _log.debug("No resources found for " + name);
225                            }
226    
227                            while (enu.hasMoreElements()) {
228                                    URL url = enu.nextElement();
229    
230                                    InputStream inputStream = url.openStream();
231    
232                                    readResource(configuration, inputStream);
233                            }
234                    }
235                    else {
236                            InputStream inputStream = classLoader.getResourceAsStream(resource);
237    
238                            readResource(configuration, inputStream);
239                    }
240            }
241    
242            protected void setDB(Dialect dialect) {
243                    DBFactoryUtil.setDB(dialect);
244            }
245    
246            private static final String[] _PRELOAD_CLASS_NAMES =
247                    PropsValues.SPRING_HIBERNATE_CONFIGURATION_PROXY_FACTORY_PRELOAD_CLASSLOADER_CLASSES;
248    
249            private static Log _log = LogFactoryUtil.getLog(
250                    PortalHibernateConfiguration.class);
251    
252            private static Map<ProxyFactory, ClassLoader> _proxyFactoryClassLoaders =
253                    new WeakHashMap<ProxyFactory, ClassLoader>();
254    
255            static {
256                    ProxyFactory.classLoaderProvider =
257                            new ProxyFactory.ClassLoaderProvider() {
258    
259                                    public ClassLoader get(ProxyFactory proxyFactory) {
260                                            synchronized (_proxyFactoryClassLoaders) {
261                                                    ClassLoader classLoader = _proxyFactoryClassLoaders.get(
262                                                            proxyFactory);
263    
264                                                    if (classLoader != null) {
265                                                            return classLoader;
266                                                    }
267    
268                                                    classLoader =
269                                                            PACLClassLoaderUtil.getPortalClassLoader();
270    
271                                                    ClassLoader contextClassLoader =
272                                                            PACLClassLoaderUtil.getContextClassLoader();
273    
274                                                    if (classLoader != contextClassLoader) {
275                                                            classLoader = new PreloadClassLoader(
276                                                                    contextClassLoader,
277                                                                    getPreloadClassLoaderClasses());
278                                                    }
279    
280                                                    _proxyFactoryClassLoaders.put(
281                                                            proxyFactory, classLoader);
282    
283                                                    return classLoader;
284                                            }
285                                    }
286    
287                            };
288            }
289    
290            private Converter<String> _hibernateConfigurationConverter;
291    
292    }