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