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.dao.jdbc.util;
016    
017    import com.liferay.portal.dao.orm.hibernate.PortletSessionFactoryImpl;
018    import com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl;
019    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
020    import com.liferay.portal.kernel.dao.jdbc.DataSourceFactoryUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
024    import com.liferay.portal.spring.hibernate.PortalHibernateConfiguration;
025    import com.liferay.portal.spring.hibernate.PortletHibernateConfiguration;
026    import com.liferay.portal.spring.jpa.LocalContainerEntityManagerFactoryBean;
027    import com.liferay.portal.util.PropsValues;
028    
029    import java.util.List;
030    import java.util.Properties;
031    
032    import javax.persistence.EntityManagerFactory;
033    
034    import javax.sql.DataSource;
035    
036    import org.hibernate.engine.SessionFactoryImplementor;
037    
038    import org.springframework.orm.hibernate3.HibernateTransactionManager;
039    import org.springframework.transaction.support.AbstractPlatformTransactionManager;
040    
041    /**
042     * @author Shuyang Zhou
043     */
044    public class DataSourceSwapper {
045    
046            public static void swapCounterDataSource(Properties properties)
047                    throws Exception {
048    
049                    if (_log.isInfoEnabled()) {
050                            _log.info("Create new counter data source");
051                    }
052    
053                    DataSource newDataSource = DataSourceFactoryUtil.initDataSource(
054                            properties);
055    
056                    DataSource oldDataSource =
057                            _counterDataSourceWrapper.getWrappedDataSource();
058    
059                    if (_log.isInfoEnabled()) {
060                            _log.info("Set new counter data source");
061                    }
062    
063                    _counterDataSourceWrapper.setWrappedDataSource(newDataSource);
064    
065                    if (_log.isInfoEnabled()) {
066                            _log.info("Destroy old counter data source");
067                    }
068    
069                    DataSourceFactoryUtil.destroyDataSource(oldDataSource);
070    
071                    if (PropsValues.PERSISTENCE_PROVIDER.equalsIgnoreCase("jpa")) {
072                            if (_log.isInfoEnabled()) {
073                                    _log.info("Reinitialize Hibernate for new counter data source");
074                            }
075    
076                            _reinitializeJPA("counterSessionFactory", newDataSource);
077                    }
078                    else {
079                            if (_log.isInfoEnabled()) {
080                                    _log.info("Reinitialize JPA for new counter data source");
081                            }
082    
083                            _reinitializeHibernate("counterSessionFactory", newDataSource);
084                    }
085            }
086    
087            public static void swapLiferayDataSource(Properties properties)
088                    throws Exception {
089    
090                    if (_log.isInfoEnabled()) {
091                            _log.info("Create new liferay data source");
092                    }
093    
094                    DataSource newDataSource = DataSourceFactoryUtil.initDataSource(
095                            properties);
096    
097                    DataSource oldDataSource =
098                            _liferayDataSourceWrapper.getWrappedDataSource();
099    
100                    if (_log.isInfoEnabled()) {
101                            _log.info("Set new liferay data source");
102                    }
103    
104                    _liferayDataSourceWrapper.setWrappedDataSource(newDataSource);
105    
106                    if (_log.isInfoEnabled()) {
107                            _log.info("Destroy old liferay data source");
108                    }
109    
110                    DataSourceFactoryUtil.destroyDataSource(oldDataSource);
111    
112                    if (PropsValues.PERSISTENCE_PROVIDER.equalsIgnoreCase("jpa")) {
113                            if (_log.isInfoEnabled()) {
114                                    _log.info("Reinitialize Hibernate for new liferay data source");
115                            }
116    
117                            _reinitializeJPA("liferaySessionFactory", newDataSource);
118                    }
119                    else {
120                            if (_log.isInfoEnabled()) {
121                                    _log.info("Reinitialize JPA for new liferay data source");
122                            }
123    
124                            _reinitializeHibernate("liferaySessionFactory", newDataSource);
125                    }
126    
127                    _reinitializePortletsHibernate(newDataSource);
128            }
129    
130            public void setCounterDataSourceWrapper(
131                    DataSourceWrapper counterDataSourceWrapper) {
132    
133                    _counterDataSourceWrapper = counterDataSourceWrapper;
134            }
135    
136            public void setLiferayDataSourceWrapper(
137                    DataSourceWrapper liferayDataSourceWrapper) {
138    
139                    _liferayDataSourceWrapper = liferayDataSourceWrapper;
140            }
141    
142            private static void _reinitializeHibernate(
143                            String name, DataSource dataSource)
144                    throws Exception {
145    
146                    PortalHibernateConfiguration portalHibernateConfiguration =
147                            new PortalHibernateConfiguration();
148    
149                    portalHibernateConfiguration.setDataSource(dataSource);
150    
151                    portalHibernateConfiguration.afterPropertiesSet();
152    
153                    SessionFactoryImplementor sessionFactoryImplementor =
154                            (SessionFactoryImplementor)portalHibernateConfiguration.getObject();
155    
156                    SessionFactoryImpl sessionFactoryImpl =
157                            (SessionFactoryImpl)PortalBeanLocatorUtil.locate(name);
158    
159                    sessionFactoryImpl.setSessionFactoryImplementor(
160                            sessionFactoryImplementor);
161    
162                    AbstractPlatformTransactionManager abstractPlatformTransactionManager =
163                            (AbstractPlatformTransactionManager)PortalBeanLocatorUtil.locate(
164                                    "liferayTransactionManager");
165    
166                    if (abstractPlatformTransactionManager instanceof
167                                    HibernateTransactionManager) {
168    
169                            HibernateTransactionManager hibernateTransactionManager =
170                                    (HibernateTransactionManager)abstractPlatformTransactionManager;
171    
172                            hibernateTransactionManager.setSessionFactory(
173                                    sessionFactoryImplementor);
174                    }
175                    else if (_log.isWarnEnabled()) {
176                            _log.warn(
177                                    "Unable to swap to session factory for " +
178                                            abstractPlatformTransactionManager.getClass() +
179                                                    " which may cause subsequent transaction failures");
180                    }
181            }
182    
183            private static void _reinitializeJPA(String name, DataSource dataSource)
184                    throws Exception {
185    
186                    LocalContainerEntityManagerFactoryBean
187                            localContainerEntityManagerFactoryBean =
188                                    new LocalContainerEntityManagerFactoryBean();
189    
190                    localContainerEntityManagerFactoryBean.setDataSource(dataSource);
191    
192                    localContainerEntityManagerFactoryBean.afterPropertiesSet();
193    
194                    EntityManagerFactory entityManagerFactory =
195                            localContainerEntityManagerFactoryBean.getObject();
196    
197                    com.liferay.portal.dao.orm.jpa.SessionFactoryImpl sessionFactoryImpl =
198                            (com.liferay.portal.dao.orm.jpa.SessionFactoryImpl)
199                                    PortalBeanLocatorUtil.locate(name);
200    
201                    sessionFactoryImpl.setEntityManagerFactory(entityManagerFactory);
202            }
203    
204            private static void _reinitializePortletsHibernate(DataSource newDataSource)
205                    throws Exception {
206    
207                    List<PortletSessionFactoryImpl> portletSessionFactoryImpls =
208                            SessionFactoryImpl.getPortletSessionFactories();
209    
210                    for (PortletSessionFactoryImpl portletSessionFactoryImpl :
211                                    portletSessionFactoryImpls) {
212    
213                            ClassLoader oldPortletClassLoader =
214                                    PortletClassLoaderUtil.getClassLoader();
215    
216                            ClassLoader portletClassLoader =
217                                    portletSessionFactoryImpl.getSessionFactoryClassLoader();
218    
219                            PortletClassLoaderUtil.setClassLoader(portletClassLoader);
220    
221                            Thread currentThread = Thread.currentThread();
222    
223                            ClassLoader oldContextClassLoader =
224                                    currentThread.getContextClassLoader();
225    
226                            currentThread.setContextClassLoader(portletClassLoader);
227    
228                            try {
229                                    PortletHibernateConfiguration portletHibernateConfiguration =
230                                            new PortletHibernateConfiguration();
231    
232                                    portletHibernateConfiguration.setDataSource(newDataSource);
233    
234                                    portletHibernateConfiguration.afterPropertiesSet();
235    
236                                    SessionFactoryImplementor sessionFactoryImplementor =
237                                            (SessionFactoryImplementor)
238                                                    portletHibernateConfiguration.getObject();
239    
240                                    portletSessionFactoryImpl.setSessionFactoryImplementor(
241                                            sessionFactoryImplementor);
242                            }
243                            finally {
244                                    PortletClassLoaderUtil.setClassLoader(oldPortletClassLoader);
245    
246                                    currentThread.setContextClassLoader(oldContextClassLoader);
247                            }
248                    }
249            }
250    
251            private static Log _log = LogFactoryUtil.getLog(DataSourceSwapper.class);
252    
253            private static DataSourceWrapper _counterDataSourceWrapper;
254            private static DataSourceWrapper _liferayDataSourceWrapper;
255    
256    }