001
014
015 package com.liferay.portal.dao.jdbc;
016
017 import com.liferay.portal.dao.jdbc.util.DataSourceWrapper;
018 import com.liferay.portal.kernel.configuration.Filter;
019 import com.liferay.portal.kernel.dao.jdbc.DataSourceFactory;
020 import com.liferay.portal.kernel.jndi.JNDIUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
024 import com.liferay.portal.kernel.util.FileUtil;
025 import com.liferay.portal.kernel.util.HttpUtil;
026 import com.liferay.portal.kernel.util.PropertiesUtil;
027 import com.liferay.portal.kernel.util.PropsKeys;
028 import com.liferay.portal.kernel.util.ServerDetector;
029 import com.liferay.portal.kernel.util.SortedProperties;
030 import com.liferay.portal.kernel.util.StringUtil;
031 import com.liferay.portal.kernel.util.Validator;
032 import com.liferay.portal.util.FileImpl;
033 import com.liferay.portal.util.HttpImpl;
034 import com.liferay.portal.util.JarUtil;
035 import com.liferay.portal.util.PropsUtil;
036 import com.liferay.portal.util.PropsValues;
037
038 import com.mchange.v2.c3p0.ComboPooledDataSource;
039
040 import java.lang.management.ManagementFactory;
041
042 import java.util.Enumeration;
043 import java.util.Map;
044 import java.util.Properties;
045
046 import javax.management.MBeanServer;
047 import javax.management.ObjectName;
048
049 import javax.naming.Context;
050 import javax.naming.InitialContext;
051
052 import javax.sql.DataSource;
053
054 import jodd.bean.BeanUtil;
055
056 import org.apache.commons.dbcp.BasicDataSourceFactory;
057 import org.apache.tomcat.jdbc.pool.PoolProperties;
058 import org.apache.tomcat.jdbc.pool.jmx.ConnectionPool;
059
060
064 @DoPrivileged
065 public class DataSourceFactoryImpl implements DataSourceFactory {
066
067 @Override
068 public void destroyDataSource(DataSource dataSource) throws Exception {
069 while (dataSource instanceof DataSourceWrapper) {
070 DataSourceWrapper dataSourceWrapper = (DataSourceWrapper)dataSource;
071
072 dataSource = dataSourceWrapper.getWrappedDataSource();
073 }
074
075 if (dataSource instanceof ComboPooledDataSource) {
076 ComboPooledDataSource comboPooledDataSource =
077 (ComboPooledDataSource)dataSource;
078
079 comboPooledDataSource.close();
080 }
081 else if (dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource) {
082 org.apache.tomcat.jdbc.pool.DataSource tomcatDataSource =
083 (org.apache.tomcat.jdbc.pool.DataSource)dataSource;
084
085 tomcatDataSource.close();
086 }
087 }
088
089 @Override
090 public DataSource initDataSource(Properties properties) throws Exception {
091 Properties defaultProperties = PropsUtil.getProperties(
092 "jdbc.default.", true);
093
094 PropertiesUtil.merge(defaultProperties, properties);
095
096 properties = defaultProperties;
097
098 String jndiName = properties.getProperty("jndi.name");
099
100 if (Validator.isNotNull(jndiName)) {
101 try {
102 Properties jndiEnvironmentProperties = PropsUtil.getProperties(
103 PropsKeys.JNDI_ENVIRONMENT, true);
104
105 Context context = new InitialContext(jndiEnvironmentProperties);
106
107 return (DataSource)JNDIUtil.lookup(context, jndiName);
108 }
109 catch (Exception e) {
110 _log.error("Unable to lookup " + jndiName, e);
111 }
112 }
113
114 if (_log.isDebugEnabled()) {
115 _log.debug("Data source properties:\n");
116
117 SortedProperties sortedProperties = new SortedProperties(
118 properties);
119
120 _log.debug(PropertiesUtil.toString(sortedProperties));
121 }
122
123 testClassForName(properties);
124
125 DataSource dataSource = null;
126
127 String liferayPoolProvider =
128 PropsValues.JDBC_DEFAULT_LIFERAY_POOL_PROVIDER;
129
130 if (StringUtil.equalsIgnoreCase(liferayPoolProvider, "c3p0") ||
131 StringUtil.equalsIgnoreCase(liferayPoolProvider, "c3po")) {
132
133 if (_log.isDebugEnabled()) {
134 _log.debug("Initializing C3P0 data source");
135 }
136
137 dataSource = initDataSourceC3PO(properties);
138 }
139 else if (StringUtil.equalsIgnoreCase(liferayPoolProvider, "dbcp")) {
140 if (_log.isDebugEnabled()) {
141 _log.debug("Initializing DBCP data source");
142 }
143
144 dataSource = initDataSourceDBCP(properties);
145 }
146 else {
147 if (_log.isDebugEnabled()) {
148 _log.debug("Initializing Tomcat data source");
149 }
150
151 dataSource = initDataSourceTomcat(properties);
152 }
153
154 if (_log.isDebugEnabled()) {
155 _log.debug("Created data source " + dataSource.getClass());
156 }
157
158 return _pacl.getDataSource(dataSource);
159 }
160
161 @Override
162 public DataSource initDataSource(
163 String driverClassName, String url, String userName,
164 String password, String jndiName)
165 throws Exception {
166
167 Properties properties = new Properties();
168
169 properties.setProperty("driverClassName", driverClassName);
170 properties.setProperty("url", url);
171 properties.setProperty("username", userName);
172 properties.setProperty("password", password);
173 properties.setProperty("jndi.name", jndiName);
174
175 return initDataSource(properties);
176 }
177
178 public static interface PACL {
179
180 public DataSource getDataSource(DataSource dataSource);
181
182 }
183
184 protected DataSource initDataSourceC3PO(Properties properties)
185 throws Exception {
186
187 ComboPooledDataSource comboPooledDataSource =
188 new ComboPooledDataSource();
189
190 String identityToken = StringUtil.randomString();
191
192 comboPooledDataSource.setIdentityToken(identityToken);
193
194 Enumeration<String> enu =
195 (Enumeration<String>)properties.propertyNames();
196
197 while (enu.hasMoreElements()) {
198 String key = enu.nextElement();
199 String value = properties.getProperty(key);
200
201
202
203 if (StringUtil.equalsIgnoreCase(key, "driverClassName")) {
204 key = "driverClass";
205 }
206 else if (StringUtil.equalsIgnoreCase(key, "url")) {
207 key = "jdbcUrl";
208 }
209 else if (StringUtil.equalsIgnoreCase(key, "username")) {
210 key = "user";
211 }
212
213
214
215 if (isPropertyLiferay(key)) {
216 continue;
217 }
218
219
220
221 if (isPropertyDBCP(key)) {
222 continue;
223 }
224
225
226
227 if (isPropertyTomcat(key)) {
228 continue;
229 }
230
231 try {
232 BeanUtil.setProperty(comboPooledDataSource, key, value);
233 }
234 catch (Exception e) {
235 if (_log.isWarnEnabled()) {
236 _log.warn(
237 "Property " + key + " is not a valid C3PO property");
238 }
239 }
240 }
241
242 return comboPooledDataSource;
243 }
244
245 protected DataSource initDataSourceDBCP(Properties properties)
246 throws Exception {
247
248 return BasicDataSourceFactory.createDataSource(properties);
249 }
250
251 protected DataSource initDataSourceTomcat(Properties properties)
252 throws Exception {
253
254 PoolProperties poolProperties = new PoolProperties();
255
256 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
257 String key = (String)entry.getKey();
258 String value = (String)entry.getValue();
259
260
261
262 if (isPropertyLiferay(key)) {
263 continue;
264 }
265
266
267
268 if (isPropertyC3PO(key)) {
269 continue;
270 }
271
272 try {
273 BeanUtil.setProperty(poolProperties, key, value);
274 }
275 catch (Exception e) {
276 if (_log.isWarnEnabled()) {
277 _log.warn(
278 "Property " + key + " is not a valid Tomcat JDBC " +
279 "Connection Pool property");
280 }
281 }
282 }
283
284 String poolName = StringUtil.randomString();
285
286 poolProperties.setName(poolName);
287
288 org.apache.tomcat.jdbc.pool.DataSource dataSource =
289 new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
290
291 if (poolProperties.isJmxEnabled()) {
292 org.apache.tomcat.jdbc.pool.ConnectionPool jdbcConnectionPool =
293 dataSource.createPool();
294
295 ConnectionPool jmxConnectionPool = jdbcConnectionPool.getJmxPool();
296
297 MBeanServer mBeanServer =
298 ManagementFactory.getPlatformMBeanServer();
299
300 ObjectName objectName = new ObjectName(
301 _TOMCAT_JDBC_POOL_OBJECT_NAME_PREFIX + poolName);
302
303 mBeanServer.registerMBean(jmxConnectionPool, objectName);
304 }
305
306 return dataSource;
307 }
308
309 protected boolean isPropertyC3PO(String key) {
310 if (StringUtil.equalsIgnoreCase(key, "acquireIncrement") ||
311 StringUtil.equalsIgnoreCase(key, "acquireRetryAttempts") ||
312 StringUtil.equalsIgnoreCase(key, "acquireRetryDelay") ||
313 StringUtil.equalsIgnoreCase(key, "connectionCustomizerClassName") ||
314 StringUtil.equalsIgnoreCase(key, "idleConnectionTestPeriod") ||
315 StringUtil.equalsIgnoreCase(key, "initialPoolSize") ||
316 StringUtil.equalsIgnoreCase(key, "maxIdleTime") ||
317 StringUtil.equalsIgnoreCase(key, "maxPoolSize") ||
318 StringUtil.equalsIgnoreCase(key, "minPoolSize") ||
319 StringUtil.equalsIgnoreCase(key, "numHelperThreads") ||
320 StringUtil.equalsIgnoreCase(key, "preferredTestQuery")) {
321
322 return true;
323 }
324
325 return false;
326 }
327
328 protected boolean isPropertyDBCP(String key) {
329 if (StringUtil.equalsIgnoreCase(key, "defaultTransactionIsolation") ||
330 StringUtil.equalsIgnoreCase(key, "maxActive") ||
331 StringUtil.equalsIgnoreCase(key, "minIdle") ||
332 StringUtil.equalsIgnoreCase(key, "removeAbandonedTimeout")) {
333
334 return true;
335 }
336
337 return false;
338 }
339
340 protected boolean isPropertyLiferay(String key) {
341 if (StringUtil.equalsIgnoreCase(key, "jndi.name") ||
342 StringUtil.equalsIgnoreCase(key, "liferay.pool.provider")) {
343
344 return true;
345 }
346
347 return false;
348 }
349
350 protected boolean isPropertyTomcat(String key) {
351 if (StringUtil.equalsIgnoreCase(key, "fairQueue") ||
352 StringUtil.equalsIgnoreCase(key, "jdbcInterceptors") ||
353 StringUtil.equalsIgnoreCase(key, "jmxEnabled") ||
354 StringUtil.equalsIgnoreCase(key, "timeBetweenEvictionRunsMillis") ||
355 StringUtil.equalsIgnoreCase(key, "useEquals")) {
356
357 return true;
358 }
359
360 return false;
361 }
362
363 protected void testClassForName(Properties properties) throws Exception {
364 String driverClassName = properties.getProperty("driverClassName");
365
366 try {
367 Class.forName(driverClassName);
368 }
369 catch (ClassNotFoundException cnfe) {
370 if (!ServerDetector.isGeronimo() && !ServerDetector.isJetty() &&
371 !ServerDetector.isTomcat()) {
372
373 throw cnfe;
374 }
375
376 String url = PropsUtil.get(
377 PropsKeys.SETUP_DATABASE_JAR_URL, new Filter(driverClassName));
378 String name = PropsUtil.get(
379 PropsKeys.SETUP_DATABASE_JAR_NAME, new Filter(driverClassName));
380
381 if (Validator.isNull(url) || Validator.isNull(name)) {
382 throw cnfe;
383 }
384
385 if (HttpUtil.getHttp() == null) {
386 HttpUtil httpUtil = new HttpUtil();
387
388 httpUtil.setHttp(new HttpImpl());
389 }
390
391 if (FileUtil.getFile() == null) {
392 FileUtil fileUtil = new FileUtil();
393
394 fileUtil.setFile(new FileImpl());
395 }
396
397 JarUtil.downloadAndInstallJar(true, url, name, null);
398 }
399 }
400
401 private static final String _TOMCAT_JDBC_POOL_OBJECT_NAME_PREFIX =
402 "TomcatJDBCPool:type=ConnectionPool,name=";
403
404 private static Log _log = LogFactoryUtil.getLog(
405 DataSourceFactoryImpl.class);
406
407 private static PACL _pacl = new NoPACL();
408
409 private static class NoPACL implements PACL {
410
411 @Override
412 public DataSource getDataSource(DataSource dataSource) {
413 return dataSource;
414 }
415
416 }
417
418 }