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