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          Properties defaultProperties = PropsUtil.getProperties(
62              "jdbc.default.", true);
63  
64          PropertiesUtil.merge(defaultProperties, properties);
65  
66          properties = defaultProperties;
67  
68          String jndiName = properties.getProperty("jndi.name");
69  
70          if (Validator.isNotNull(jndiName)) {
71              try {
72                  return (DataSource)JNDIUtil.lookup(
73                      new InitialContext(), jndiName);
74              }
75              catch (Exception e) {
76                  _log.error("Unable to lookup " + jndiName, e);
77              }
78          }
79  
80          DataSource dataSource = null;
81  
82          String liferayPoolProvider =
83              PropsValues.JDBC_DEFAULT_LIFERAY_POOL_PROVIDER;
84  
85          if (liferayPoolProvider.equals("c3po")) {
86              dataSource = createDataSourceC3PO(properties);
87          }
88          else if (liferayPoolProvider.equals("dbcp")) {
89              dataSource = createDataSourceDBCP(properties);
90          }
91          else {
92              dataSource = createDataSourcePrimrose(properties);
93          }
94  
95          if (_log.isDebugEnabled()) {
96              _log.debug(
97                  "Created data source " + dataSource.getClass().getName());
98  
99              SortedProperties sortedProperties = new SortedProperties(
100                 properties);
101 
102             _log.debug("Properties for prefix " + _propertyPrefix);
103 
104             sortedProperties.list(System.out);
105         }
106 
107         return dataSource;
108     }
109 
110     public void destroyInstance(DataSource dataSource) throws Exception {
111         if (dataSource instanceof ComboPooledDataSource) {
112             ComboPooledDataSource comboPooledDataSource =
113                 (ComboPooledDataSource)dataSource;
114 
115             comboPooledDataSource.close();
116         }
117     }
118 
119     public Class<DataSource> getObjectType() {
120         return DataSource.class;
121     }
122 
123     public void setProperties(Properties properties) {
124         _properties = properties;
125     }
126 
127     public void setPropertyPrefix(String propertyPrefix) {
128         _propertyPrefix = propertyPrefix;
129     }
130 
131     public void setPropertyPrefixLookup(String propertyPrefixLookup) {
132         _propertyPrefix = PropsUtil.get(propertyPrefixLookup);
133     }
134 
135     protected DataSource createDataSourceC3PO(Properties properties)
136         throws Exception {
137 
138         ComboPooledDataSource comboPooledDataSource =
139             new ComboPooledDataSource();
140 
141         comboPooledDataSource.setIdentityToken(_propertyPrefix);
142 
143         Enumeration<String> enu =
144             (Enumeration<String>)properties.propertyNames();
145 
146         while (enu.hasMoreElements()) {
147             String key = enu.nextElement();
148 
149             String value = properties.getProperty(key);
150 
151             // Map org.apache.commons.dbcp.BasicDataSource to C3PO
152 
153             if (key.equalsIgnoreCase("driverClassName")) {
154                 key = "driverClass";
155             }
156             else if (key.equalsIgnoreCase("url")) {
157                 key = "jdbcUrl";
158             }
159             else if (key.equalsIgnoreCase("username")) {
160                 key = "user";
161             }
162 
163             // Ignore Liferay properties
164 
165             if (key.equalsIgnoreCase("jndi.name") ||
166                 key.equalsIgnoreCase("liferay.pool.provider")) {
167 
168                 continue;
169             }
170 
171             // Ignore DBCP properties
172 
173             if (key.equalsIgnoreCase("defaultTransactionIsolation") ||
174                 key.equalsIgnoreCase("maxActive") ||
175                 key.equalsIgnoreCase("minIdle") ||
176                 key.equalsIgnoreCase("removeAbandonedTimeout")) {
177 
178                 continue;
179             }
180 
181             // Ignore Primrose properties
182 
183             if (key.equalsIgnoreCase("base") ||
184                 key.equalsIgnoreCase("connectionTransactionIsolation") ||
185                 key.equalsIgnoreCase("idleTime") ||
186                 key.equalsIgnoreCase("numberOfConnectionsToInitializeWith")) {
187 
188                 continue;
189             }
190 
191             try {
192                 BeanUtil.setProperty(comboPooledDataSource, key, value);
193             }
194             catch (Exception e) {
195                 if (_log.isWarnEnabled()) {
196                     _log.warn(
197                         "Property " + key + " is not a valid C3PO property");
198                 }
199             }
200         }
201 
202         return comboPooledDataSource;
203     }
204 
205     protected DataSource createDataSourceDBCP(Properties properties)
206         throws Exception {
207 
208         return BasicDataSourceFactory.createDataSource(properties);
209     }
210 
211     protected DataSource createDataSourcePrimrose(Properties properties)
212         throws Exception {
213 
214         properties.setProperty("poolName", _propertyPrefix);
215 
216         Enumeration<String> enu =
217             (Enumeration<String>)properties.propertyNames();
218 
219         while (enu.hasMoreElements()) {
220             String key = enu.nextElement();
221 
222             String value = properties.getProperty(key);
223 
224             // Map org.apache.commons.dbcp.BasicDataSource to Primrose
225 
226             if (key.equalsIgnoreCase("driverClassName")) {
227                 key = "driverClass";
228             }
229             else if (key.equalsIgnoreCase("url")) {
230                 key = "driverURL";
231             }
232             else if (key.equalsIgnoreCase("username")) {
233                 key = "user";
234             }
235 
236             properties.setProperty(key, value);
237         }
238 
239         GenericDataSourceFactory genericDataSourceFactory =
240             new GenericDataSourceFactory();
241 
242         return genericDataSourceFactory.loadPool(_propertyPrefix, properties);
243     }
244 
245     private static Log _log = LogFactoryUtil.getLog(
246         DataSourceFactoryBean.class);
247 
248     private Properties _properties;
249     private String _propertyPrefix;
250 
251 }