001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.beans.factory.BeanFactory;
041    import org.springframework.beans.factory.BeanFactoryAware;
042    import org.springframework.orm.hibernate3.HibernateTransactionManager;
043    import org.springframework.transaction.support.AbstractPlatformTransactionManager;
044    
045    /**
046     * @author Shuyang Zhou
047     */
048    public class DataSourceSwapper implements BeanFactoryAware {
049    
050            public static void swapCounterDataSource(Properties properties)
051                    throws Exception {
052    
053                    if (_log.isInfoEnabled()) {
054                            _log.info("Create new counter data source");
055                    }
056    
057                    DataSource newDataSource = DataSourceFactoryUtil.initDataSource(
058                            properties);
059    
060                    DataSource oldDataSource =
061                            _counterDataSourceWrapper.getWrappedDataSource();
062    
063                    if (_log.isInfoEnabled()) {
064                            _log.info("Set new counter data source");
065                    }
066    
067                    _counterDataSourceWrapper.setWrappedDataSource(newDataSource);
068    
069                    if (_log.isInfoEnabled()) {
070                            _log.info("Destroy old counter data source");
071                    }
072    
073                    DataSourceFactoryUtil.destroyDataSource(oldDataSource);
074    
075                    if (StringUtil.equalsIgnoreCase(
076                                    PropsValues.PERSISTENCE_PROVIDER, "jpa")) {
077    
078                            if (_log.isInfoEnabled()) {
079                                    _log.info("Reinitialize Hibernate for new counter data source");
080                            }
081    
082                            _reinitializeJPA("counterSessionFactory", newDataSource);
083                    }
084                    else {
085                            if (_log.isInfoEnabled()) {
086                                    _log.info("Reinitialize JPA for new counter data source");
087                            }
088    
089                            _reinitializeHibernate("counterSessionFactory", newDataSource);
090                    }
091            }
092    
093            public static void swapLiferayDataSource(Properties properties)
094                    throws Exception {
095    
096                    if (_log.isInfoEnabled()) {
097                            _log.info("Create new liferay data source");
098                    }
099    
100                    DataSource newDataSource = DataSourceFactoryUtil.initDataSource(
101                            properties);
102    
103                    DataSource oldDataSource =
104                            _liferayDataSourceWrapper.getWrappedDataSource();
105    
106                    if (_log.isInfoEnabled()) {
107                            _log.info("Set new liferay data source");
108                    }
109    
110                    _liferayDataSourceWrapper.setWrappedDataSource(newDataSource);
111    
112                    if (_log.isInfoEnabled()) {
113                            _log.info("Destroy old liferay data source");
114                    }
115    
116                    DataSourceFactoryUtil.destroyDataSource(oldDataSource);
117    
118                    if (StringUtil.equalsIgnoreCase(
119                                    PropsValues.PERSISTENCE_PROVIDER, "jpa")) {
120    
121                            if (_log.isInfoEnabled()) {
122                                    _log.info("Reinitialize Hibernate for new liferay data source");
123                            }
124    
125                            _reinitializeJPA("liferaySessionFactory", newDataSource);
126                    }
127                    else {
128                            if (_log.isInfoEnabled()) {
129                                    _log.info("Reinitialize JPA for new liferay data source");
130                            }
131    
132                            _reinitializeHibernate("liferaySessionFactory", newDataSource);
133                    }
134    
135                    _reinitializePortletsHibernate(newDataSource);
136            }
137    
138            @Override
139            public void setBeanFactory(BeanFactory beanFactory) {
140                    _beanFactory = beanFactory;
141            }
142    
143            public void setCounterDataSourceWrapper(
144                    DataSourceWrapper counterDataSourceWrapper) {
145    
146                    _counterDataSourceWrapper = counterDataSourceWrapper;
147            }
148    
149            public void setLiferayDataSourceWrapper(
150                    DataSourceWrapper liferayDataSourceWrapper) {
151    
152                    _liferayDataSourceWrapper = liferayDataSourceWrapper;
153            }
154    
155            private static void _reinitializeHibernate(
156                            String name, DataSource dataSource)
157                    throws Exception {
158    
159                    PortalHibernateConfiguration portalHibernateConfiguration =
160                            new PortalHibernateConfiguration();
161    
162                    portalHibernateConfiguration.setBeanFactory(_beanFactory);
163                    portalHibernateConfiguration.setDataSource(dataSource);
164    
165                    portalHibernateConfiguration.afterPropertiesSet();
166    
167                    SessionFactoryImplementor sessionFactoryImplementor =
168                            (SessionFactoryImplementor)portalHibernateConfiguration.getObject();
169    
170                    SessionFactoryImpl sessionFactoryImpl =
171                            (SessionFactoryImpl)PortalBeanLocatorUtil.locate(name);
172    
173                    sessionFactoryImpl.setSessionFactoryImplementor(
174                            sessionFactoryImplementor);
175    
176                    AbstractPlatformTransactionManager abstractPlatformTransactionManager =
177                            (AbstractPlatformTransactionManager)PortalBeanLocatorUtil.locate(
178                                    "liferayTransactionManager");
179    
180                    if (abstractPlatformTransactionManager instanceof
181                                    HibernateTransactionManager) {
182    
183                            HibernateTransactionManager hibernateTransactionManager =
184                                    (HibernateTransactionManager)abstractPlatformTransactionManager;
185    
186                            hibernateTransactionManager.setSessionFactory(
187                                    sessionFactoryImplementor);
188                    }
189                    else if (_log.isWarnEnabled()) {
190                            _log.warn(
191                                    "Unable to swap to session factory for " +
192                                            abstractPlatformTransactionManager.getClass() +
193                                                    " which may cause subsequent transaction failures");
194                    }
195            }
196    
197            private static void _reinitializeJPA(String name, DataSource dataSource)
198                    throws Exception {
199    
200                    LocalContainerEntityManagerFactoryBean
201                            localContainerEntityManagerFactoryBean =
202                                    new LocalContainerEntityManagerFactoryBean();
203    
204                    localContainerEntityManagerFactoryBean.setDataSource(dataSource);
205    
206                    localContainerEntityManagerFactoryBean.afterPropertiesSet();
207    
208                    EntityManagerFactory entityManagerFactory =
209                            localContainerEntityManagerFactoryBean.getObject();
210    
211                    com.liferay.portal.dao.orm.jpa.SessionFactoryImpl sessionFactoryImpl =
212                            (com.liferay.portal.dao.orm.jpa.SessionFactoryImpl)
213                                    PortalBeanLocatorUtil.locate(name);
214    
215                    sessionFactoryImpl.setEntityManagerFactory(entityManagerFactory);
216            }
217    
218            private static void _reinitializePortletsHibernate(DataSource newDataSource)
219                    throws Exception {
220    
221                    List<PortletSessionFactoryImpl> portletSessionFactoryImpls =
222                            SessionFactoryImpl.getPortletSessionFactories();
223    
224                    for (PortletSessionFactoryImpl portletSessionFactoryImpl :
225                                    portletSessionFactoryImpls) {
226    
227                            ClassLoader classLoader = PortletClassLoaderUtil.getClassLoader();
228                            ClassLoader contextClassLoader =
229                                    ClassLoaderUtil.getContextClassLoader();
230    
231                            try {
232                                    ClassLoader sessionFactoryClassLoader =
233                                            portletSessionFactoryImpl.getSessionFactoryClassLoader();
234    
235                                    PortletClassLoaderUtil.setClassLoader(
236                                            sessionFactoryClassLoader);
237                                    ClassLoaderUtil.setContextClassLoader(
238                                            sessionFactoryClassLoader);
239    
240                                    PortletHibernateConfiguration portletHibernateConfiguration =
241                                            new PortletHibernateConfiguration();
242    
243                                    portletHibernateConfiguration.setDataSource(newDataSource);
244    
245                                    portletHibernateConfiguration.afterPropertiesSet();
246    
247                                    SessionFactoryImplementor sessionFactoryImplementor =
248                                            (SessionFactoryImplementor)
249                                                    portletHibernateConfiguration.getObject();
250    
251                                    portletSessionFactoryImpl.setSessionFactoryImplementor(
252                                            sessionFactoryImplementor);
253                            }
254                            finally {
255                                    PortletClassLoaderUtil.setClassLoader(classLoader);
256                                    ClassLoaderUtil.setContextClassLoader(contextClassLoader);
257                            }
258                    }
259            }
260    
261            private static Log _log = LogFactoryUtil.getLog(DataSourceSwapper.class);
262    
263            private static BeanFactory _beanFactory;
264            private static DataSourceWrapper _counterDataSourceWrapper;
265            private static DataSourceWrapper _liferayDataSourceWrapper;
266    
267    }