001    /**
002     * Copyright (c) 2000-2010 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.kernel.jndi.JNDIUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.PropertiesUtil;
021    import com.liferay.portal.kernel.util.SortedProperties;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.portal.util.PropsUtil;
024    import com.liferay.portal.util.PropsValues;
025    
026    import com.mchange.v2.c3p0.ComboPooledDataSource;
027    
028    import java.util.Enumeration;
029    import java.util.Properties;
030    
031    import javax.naming.InitialContext;
032    
033    import javax.sql.DataSource;
034    
035    import jodd.bean.BeanUtil;
036    
037    import org.apache.commons.dbcp.BasicDataSourceFactory;
038    
039    import org.springframework.beans.factory.config.AbstractFactoryBean;
040    
041    import uk.org.primrose.pool.datasource.GenericDataSourceFactory;
042    
043    /**
044     * @author Brian Wing Shun Chan
045     */
046    public class DataSourceFactoryBean extends AbstractFactoryBean<DataSource> {
047    
048            public DataSource createInstance() throws Exception {
049                    Properties properties = _properties;
050    
051                    if (properties == null) {
052                            properties = PropsUtil.getProperties(_propertyPrefix, true);
053                    }
054                    else {
055                            properties = PropertiesUtil.getProperties(
056                                    properties, _propertyPrefix, true);
057                    }
058    
059                    Properties defaultProperties = PropsUtil.getProperties(
060                            "jdbc.default.", true);
061    
062                    PropertiesUtil.merge(defaultProperties, properties);
063    
064                    properties = defaultProperties;
065    
066                    String jndiName = properties.getProperty("jndi.name");
067    
068                    if (Validator.isNotNull(jndiName)) {
069                            try {
070                                    return (DataSource)JNDIUtil.lookup(
071                                            new InitialContext(), jndiName);
072                            }
073                            catch (Exception e) {
074                                    _log.error("Unable to lookup " + jndiName, e);
075                            }
076                    }
077    
078                    DataSource dataSource = null;
079    
080                    String liferayPoolProvider =
081                            PropsValues.JDBC_DEFAULT_LIFERAY_POOL_PROVIDER;
082    
083                    if (liferayPoolProvider.equals("c3po")) {
084                            dataSource = createDataSourceC3PO(properties);
085                    }
086                    else if (liferayPoolProvider.equals("dbcp")) {
087                            dataSource = createDataSourceDBCP(properties);
088                    }
089                    else {
090                            dataSource = createDataSourcePrimrose(properties);
091                    }
092    
093                    if (_log.isDebugEnabled()) {
094                            _log.debug(
095                                    "Created data source " + dataSource.getClass().getName());
096    
097                            SortedProperties sortedProperties = new SortedProperties(
098                                    properties);
099    
100                            _log.debug("Properties for prefix " + _propertyPrefix);
101    
102                            sortedProperties.list(System.out);
103                    }
104    
105                    return dataSource;
106            }
107    
108            public void destroyInstance(DataSource dataSource) throws Exception {
109                    if (dataSource instanceof ComboPooledDataSource) {
110                            ComboPooledDataSource comboPooledDataSource =
111                                    (ComboPooledDataSource)dataSource;
112    
113                            comboPooledDataSource.close();
114                    }
115            }
116    
117            public Class<DataSource> getObjectType() {
118                    return DataSource.class;
119            }
120    
121            public void setProperties(Properties properties) {
122                    _properties = properties;
123            }
124    
125            public void setPropertyPrefix(String propertyPrefix) {
126                    _propertyPrefix = propertyPrefix;
127            }
128    
129            public void setPropertyPrefixLookup(String propertyPrefixLookup) {
130                    _propertyPrefix = PropsUtil.get(propertyPrefixLookup);
131            }
132    
133            protected DataSource createDataSourceC3PO(Properties properties)
134                    throws Exception {
135    
136                    ComboPooledDataSource comboPooledDataSource =
137                            new ComboPooledDataSource();
138    
139                    comboPooledDataSource.setIdentityToken(_propertyPrefix);
140    
141                    Enumeration<String> enu =
142                            (Enumeration<String>)properties.propertyNames();
143    
144                    while (enu.hasMoreElements()) {
145                            String key = enu.nextElement();
146    
147                            String value = properties.getProperty(key);
148    
149                            // Map org.apache.commons.dbcp.BasicDataSource to C3PO
150    
151                            if (key.equalsIgnoreCase("driverClassName")) {
152                                    key = "driverClass";
153                            }
154                            else if (key.equalsIgnoreCase("url")) {
155                                    key = "jdbcUrl";
156                            }
157                            else if (key.equalsIgnoreCase("username")) {
158                                    key = "user";
159                            }
160    
161                            // Ignore Liferay properties
162    
163                            if (key.equalsIgnoreCase("jndi.name") ||
164                                    key.equalsIgnoreCase("liferay.pool.provider")) {
165    
166                                    continue;
167                            }
168    
169                            // Ignore DBCP properties
170    
171                            if (key.equalsIgnoreCase("defaultTransactionIsolation") ||
172                                    key.equalsIgnoreCase("maxActive") ||
173                                    key.equalsIgnoreCase("minIdle") ||
174                                    key.equalsIgnoreCase("removeAbandonedTimeout")) {
175    
176                                    continue;
177                            }
178    
179                            // Ignore Primrose properties
180    
181                            if (key.equalsIgnoreCase("base") ||
182                                    key.equalsIgnoreCase("connectionTransactionIsolation") ||
183                                    key.equalsIgnoreCase("idleTime") ||
184                                    key.equalsIgnoreCase("numberOfConnectionsToInitializeWith")) {
185    
186                                    continue;
187                            }
188    
189                            try {
190                                    BeanUtil.setProperty(comboPooledDataSource, key, value);
191                            }
192                            catch (Exception e) {
193                                    if (_log.isWarnEnabled()) {
194                                            _log.warn(
195                                                    "Property " + key + " is not a valid C3PO property");
196                                    }
197                            }
198                    }
199    
200                    return comboPooledDataSource;
201            }
202    
203            protected DataSource createDataSourceDBCP(Properties properties)
204                    throws Exception {
205    
206                    return BasicDataSourceFactory.createDataSource(properties);
207            }
208    
209            protected DataSource createDataSourcePrimrose(Properties properties)
210                    throws Exception {
211    
212                    properties.setProperty("poolName", _propertyPrefix);
213    
214                    Enumeration<String> enu =
215                            (Enumeration<String>)properties.propertyNames();
216    
217                    while (enu.hasMoreElements()) {
218                            String key = enu.nextElement();
219    
220                            String value = properties.getProperty(key);
221    
222                            // Map org.apache.commons.dbcp.BasicDataSource to Primrose
223    
224                            if (key.equalsIgnoreCase("driverClassName")) {
225                                    key = "driverClass";
226                            }
227                            else if (key.equalsIgnoreCase("url")) {
228                                    key = "driverURL";
229                            }
230                            else if (key.equalsIgnoreCase("username")) {
231                                    key = "user";
232                            }
233    
234                            properties.setProperty(key, value);
235                    }
236    
237                    GenericDataSourceFactory genericDataSourceFactory =
238                            new GenericDataSourceFactory();
239    
240                    return genericDataSourceFactory.loadPool(_propertyPrefix, properties);
241            }
242    
243            private static Log _log = LogFactoryUtil.getLog(
244                    DataSourceFactoryBean.class);
245    
246            private Properties _properties;
247            private String _propertyPrefix;
248    
249    }