1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
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 {
49  
50      public Object 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 JNDIUtil.lookup(new InitialContext(), jndiName);
73              }
74              catch (Exception e) {
75                  _log.error("Unable to lookup " + jndiName, e);
76              }
77          }
78  
79          DataSource dataSource = null;
80  
81          String liferayPoolProvider =
82              PropsValues.JDBC_DEFAULT_LIFERAY_POOL_PROVIDER;
83  
84          if (liferayPoolProvider.equals("c3po")) {
85              dataSource = createDataSourceC3PO(properties);
86          }
87          else if (liferayPoolProvider.equals("dbcp")) {
88              dataSource = createDataSourceDBCP(properties);
89          }
90          else {
91              dataSource = createDataSourcePrimrose(properties);
92          }
93  
94          if (_log.isDebugEnabled()) {
95              _log.debug(
96                  "Created data source " + dataSource.getClass().getName());
97  
98              SortedProperties sortedProperties = new SortedProperties(
99                  properties);
100 
101             _log.debug("Properties for prefix " + _propertyPrefix);
102 
103             sortedProperties.list(System.out);
104         }
105 
106         return dataSource;
107     }
108 
109     public void destroyInstance(Object dataSource) throws Exception {
110         if (dataSource instanceof ComboPooledDataSource) {
111             ComboPooledDataSource comboPooledDataSource =
112                 (ComboPooledDataSource)dataSource;
113 
114             comboPooledDataSource.close();
115         }
116     }
117 
118     public Class<?> getObjectType() {
119         return DataSource.class;
120     }
121 
122     public void setProperties(Properties properties) {
123         _properties = properties;
124     }
125 
126     public void setPropertyPrefix(String propertyPrefix) {
127         _propertyPrefix = propertyPrefix;
128     }
129 
130     public void setPropertyPrefixLookup(String propertyPrefixLookup) {
131         _propertyPrefix = PropsUtil.get(propertyPrefixLookup);
132     }
133 
134     protected DataSource createDataSourceC3PO(Properties properties)
135         throws Exception {
136 
137         ComboPooledDataSource comboPooledDataSource =
138             new ComboPooledDataSource();
139 
140         comboPooledDataSource.setIdentityToken(_propertyPrefix);
141 
142         Enumeration<String> enu =
143             (Enumeration<String>)properties.propertyNames();
144 
145         while (enu.hasMoreElements()) {
146             String key = enu.nextElement();
147 
148             String value = properties.getProperty(key);
149 
150             // Map org.apache.commons.dbcp.BasicDataSource to C3PO
151 
152             if (key.equalsIgnoreCase("driverClassName")) {
153                 key = "driverClass";
154             }
155             else if (key.equalsIgnoreCase("url")) {
156                 key = "jdbcUrl";
157             }
158             else if (key.equalsIgnoreCase("username")) {
159                 key = "user";
160             }
161 
162             // Ignore Liferay properties
163 
164             if (key.equalsIgnoreCase("jndi.name") ||
165                 key.equalsIgnoreCase("liferay.pool.provider")) {
166 
167                 continue;
168             }
169 
170             // Ignore DBCP properties
171 
172             if (key.equalsIgnoreCase("defaultTransactionIsolation") ||
173                 key.equalsIgnoreCase("maxActive") ||
174                 key.equalsIgnoreCase("minIdle") ||
175                 key.equalsIgnoreCase("removeAbandonedTimeout")) {
176 
177                 continue;
178             }
179 
180             // Ignore Primrose properties
181 
182             if (key.equalsIgnoreCase("base") ||
183                 key.equalsIgnoreCase("connectionTransactionIsolation") ||
184                 key.equalsIgnoreCase("idleTime") ||
185                 key.equalsIgnoreCase("numberOfConnectionsToInitializeWith")) {
186 
187                 continue;
188             }
189 
190             try {
191                 BeanUtil.setProperty(comboPooledDataSource, key, value);
192             }
193             catch (Exception e) {
194                 if (_log.isWarnEnabled()) {
195                     _log.warn(
196                         "Property " + key + " is not a valid C3PO property");
197                 }
198             }
199         }
200 
201         return comboPooledDataSource;
202     }
203 
204     protected DataSource createDataSourceDBCP(Properties properties)
205         throws Exception {
206 
207         return BasicDataSourceFactory.createDataSource(properties);
208     }
209 
210     protected DataSource createDataSourcePrimrose(Properties properties)
211         throws Exception {
212 
213         properties.setProperty("poolName", _propertyPrefix);
214 
215         Enumeration<String> enu =
216             (Enumeration<String>)properties.propertyNames();
217 
218         while (enu.hasMoreElements()) {
219             String key = enu.nextElement();
220 
221             String value = properties.getProperty(key);
222 
223             // Map org.apache.commons.dbcp.BasicDataSource to Primrose
224 
225             if (key.equalsIgnoreCase("driverClassName")) {
226                 key = "driverClass";
227             }
228             else if (key.equalsIgnoreCase("url")) {
229                 key = "driverURL";
230             }
231             else if (key.equalsIgnoreCase("username")) {
232                 key = "user";
233             }
234 
235             properties.setProperty(key, value);
236         }
237 
238         GenericDataSourceFactory genericDataSourceFactory =
239             new GenericDataSourceFactory();
240 
241         return genericDataSourceFactory.loadPool(_propertyPrefix, properties);
242     }
243 
244     private static Log _log = LogFactoryUtil.getLog(
245         DataSourceFactoryBean.class);
246 
247     private Properties _properties;
248     private String _propertyPrefix;
249 
250 }