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