1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.dao.jdbc.util;
16  
17  import com.liferay.portal.kernel.jndi.JNDIUtil;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.util.PropertiesUtil;
21  import com.liferay.portal.kernel.util.SortedProperties;
22  import com.liferay.portal.kernel.util.Validator;
23  import com.liferay.portal.util.PropsUtil;
24  import com.liferay.portal.util.PropsValues;
25  
26  import com.mchange.v2.c3p0.ComboPooledDataSource;
27  
28  import java.util.Enumeration;
29  import java.util.Properties;
30  
31  import javax.naming.InitialContext;
32  
33  import javax.sql.DataSource;
34  
35  import jodd.bean.BeanUtil;
36  
37  import org.apache.commons.dbcp.BasicDataSourceFactory;
38  
39  import org.springframework.beans.factory.config.AbstractFactoryBean;
40  
41  import uk.org.primrose.pool.datasource.GenericDataSourceFactory;
42  
43  /**
44   * <a href="DataSourceFactoryBean.java.html"><b><i>View Source</i></b></a>
45   *
46   * @author Brian Wing Shun Chan
47   */
48  public class DataSourceFactoryBean extends AbstractFactoryBean<DataSource> {
49  
50      public DataSource createInstance() throws Exception {
51          Properties properties = _properties;
52  
53          if (properties == null) {
54              properties = PropsUtil.getProperties(_propertyPrefix, true);
55          }
56          else {
57              properties = PropertiesUtil.getProperties(
58                  properties, _propertyPrefix, true);
59          }
60  
61          String jndiName = properties.getProperty("jndi.name");
62  
63          if (Validator.isNotNull(jndiName)) {
64              try {
65                  return (DataSource)JNDIUtil.lookup(
66                      new InitialContext(), jndiName);
67              }
68              catch (Exception e) {
69                  _log.error("Unable to lookup " + jndiName, e);
70              }
71          }
72  
73          DataSource dataSource = null;
74  
75          String liferayPoolProvider =
76              PropsValues.JDBC_DEFAULT_LIFERAY_POOL_PROVIDER;
77  
78          if (liferayPoolProvider.equals("c3po")) {
79              dataSource = createDataSourceC3PO(properties);
80          }
81          else if (liferayPoolProvider.equals("dbcp")) {
82              dataSource = createDataSourceDBCP(properties);
83          }
84          else {
85              dataSource = createDataSourcePrimrose(properties);
86          }
87  
88          if (_log.isDebugEnabled()) {
89              _log.debug(
90                  "Created data source " + dataSource.getClass().getName());
91  
92              SortedProperties sortedProperties = new SortedProperties(
93                  properties);
94  
95              _log.debug("Properties for prefix " + _propertyPrefix);
96  
97              sortedProperties.list(System.out);
98          }
99  
100         return dataSource;
101     }
102 
103     public void destroyInstance(DataSource dataSource) throws Exception {
104         if (dataSource instanceof ComboPooledDataSource) {
105             ComboPooledDataSource comboPooledDataSource =
106                 (ComboPooledDataSource)dataSource;
107 
108             comboPooledDataSource.close();
109         }
110     }
111 
112     public Class<DataSource> getObjectType() {
113         return DataSource.class;
114     }
115 
116     public void setProperties(Properties properties) {
117         _properties = properties;
118     }
119 
120     public void setPropertyPrefix(String propertyPrefix) {
121         _propertyPrefix = propertyPrefix;
122     }
123 
124     public void setPropertyPrefixLookup(String propertyPrefixLookup) {
125         _propertyPrefix = PropsUtil.get(propertyPrefixLookup);
126     }
127 
128     protected DataSource createDataSourceC3PO(Properties properties)
129         throws Exception {
130 
131         ComboPooledDataSource comboPooledDataSource =
132             new ComboPooledDataSource();
133 
134         comboPooledDataSource.setIdentityToken(_propertyPrefix);
135 
136         Enumeration<String> enu =
137             (Enumeration<String>)properties.propertyNames();
138 
139         while (enu.hasMoreElements()) {
140             String key = enu.nextElement();
141 
142             String value = properties.getProperty(key);
143 
144             // Map org.apache.commons.dbcp.BasicDataSource to C3PO
145 
146             if (key.equalsIgnoreCase("driverClassName")) {
147                 key = "driverClass";
148             }
149             else if (key.equalsIgnoreCase("url")) {
150                 key = "jdbcUrl";
151             }
152             else if (key.equalsIgnoreCase("username")) {
153                 key = "user";
154             }
155 
156             // Ignore Liferay properties
157 
158             if (key.equalsIgnoreCase("jndi.name") ||
159                 key.equalsIgnoreCase("liferay.pool.provider")) {
160 
161                 continue;
162             }
163 
164             // Ignore DBCP properties
165 
166             if (key.equalsIgnoreCase("defaultTransactionIsolation") ||
167                 key.equalsIgnoreCase("maxActive") ||
168                 key.equalsIgnoreCase("minIdle")) {
169 
170                 continue;
171             }
172 
173             // Ignore Primrose properties
174 
175             if (key.equalsIgnoreCase("base") ||
176                 key.equalsIgnoreCase("connectionTransactionIsolation") ||
177                 key.equalsIgnoreCase("idleTime") ||
178                 key.equalsIgnoreCase("numberOfConnectionsToInitializeWith")) {
179 
180                 continue;
181             }
182 
183             try {
184                 BeanUtil.setProperty(comboPooledDataSource, key, value);
185             }
186             catch (Exception e) {
187                 if (_log.isWarnEnabled()) {
188                     _log.warn(
189                         "Property " + key + " is not a valid C3PO property");
190                 }
191             }
192         }
193 
194         return comboPooledDataSource;
195     }
196 
197     protected DataSource createDataSourceDBCP(Properties properties)
198         throws Exception {
199 
200         return BasicDataSourceFactory.createDataSource(properties);
201     }
202 
203     protected DataSource createDataSourcePrimrose(Properties properties)
204         throws Exception {
205 
206         properties.setProperty("poolName", _propertyPrefix);
207 
208         Enumeration<String> enu =
209             (Enumeration<String>)properties.propertyNames();
210 
211         while (enu.hasMoreElements()) {
212             String key = enu.nextElement();
213 
214             String value = properties.getProperty(key);
215 
216             // Map org.apache.commons.dbcp.BasicDataSource to Primrose
217 
218             if (key.equalsIgnoreCase("driverClassName")) {
219                 key = "driverClass";
220             }
221             else if (key.equalsIgnoreCase("url")) {
222                 key = "driverURL";
223             }
224             else if (key.equalsIgnoreCase("username")) {
225                 key = "user";
226             }
227 
228             properties.setProperty(key, value);
229         }
230 
231         GenericDataSourceFactory genericDataSourceFactory =
232             new GenericDataSourceFactory();
233 
234         return genericDataSourceFactory.loadPool(_propertyPrefix, properties);
235     }
236 
237     private static Log _log = LogFactoryUtil.getLog(
238         DataSourceFactoryBean.class);
239 
240     private Properties _properties;
241     private String _propertyPrefix;
242 
243 }