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.Validator;
031 import com.liferay.portal.util.FileImpl;
032 import com.liferay.portal.util.HttpImpl;
033 import com.liferay.portal.util.JarUtil;
034 import com.liferay.portal.util.PropsUtil;
035 import com.liferay.portal.util.PropsValues;
036 import com.liferay.util.PwdGenerator;
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 (liferayPoolProvider.equalsIgnoreCase("c3p0") ||
131 liferayPoolProvider.equalsIgnoreCase("c3po")) {
132
133 if (_log.isDebugEnabled()) {
134 _log.debug("Initializing C3P0 data source");
135 }
136
137 dataSource = initDataSourceC3PO(properties);
138 }
139 else if (liferayPoolProvider.equalsIgnoreCase("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 protected DataSource initDataSourceC3PO(Properties properties)
179 throws Exception {
180
181 ComboPooledDataSource comboPooledDataSource =
182 new ComboPooledDataSource();
183
184 String identityToken = PwdGenerator.getPassword(PwdGenerator.KEY2, 8);
185
186 comboPooledDataSource.setIdentityToken(identityToken);
187
188 Enumeration<String> enu =
189 (Enumeration<String>)properties.propertyNames();
190
191 while (enu.hasMoreElements()) {
192 String key = enu.nextElement();
193 String value = properties.getProperty(key);
194
195
196
197 if (key.equalsIgnoreCase("driverClassName")) {
198 key = "driverClass";
199 }
200 else if (key.equalsIgnoreCase("url")) {
201 key = "jdbcUrl";
202 }
203 else if (key.equalsIgnoreCase("username")) {
204 key = "user";
205 }
206
207
208
209 if (isPropertyLiferay(key)) {
210 continue;
211 }
212
213
214
215 if (isPropertyDBCP(key)) {
216 continue;
217 }
218
219
220
221 if (isPropertyTomcat(key)) {
222 continue;
223 }
224
225 try {
226 BeanUtil.setProperty(comboPooledDataSource, key, value);
227 }
228 catch (Exception e) {
229 if (_log.isWarnEnabled()) {
230 _log.warn(
231 "Property " + key + " is not a valid C3PO property");
232 }
233 }
234 }
235
236 return comboPooledDataSource;
237 }
238
239 protected DataSource initDataSourceDBCP(Properties properties)
240 throws Exception {
241
242 return BasicDataSourceFactory.createDataSource(properties);
243 }
244
245 protected DataSource initDataSourceTomcat(Properties properties)
246 throws Exception {
247
248 PoolProperties poolProperties = new PoolProperties();
249
250 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
251 String key = (String)entry.getKey();
252 String value = (String)entry.getValue();
253
254
255
256 if (isPropertyLiferay(key)) {
257 continue;
258 }
259
260
261
262 if (isPropertyC3PO(key)) {
263 continue;
264 }
265
266 try {
267 BeanUtil.setProperty(poolProperties, key, value);
268 }
269 catch (Exception e) {
270 if (_log.isWarnEnabled()) {
271 _log.warn(
272 "Property " + key + " is not a valid Tomcat JDBC " +
273 "Connection Pool property");
274 }
275 }
276 }
277
278 String poolName = PwdGenerator.getPassword(PwdGenerator.KEY2, 8);
279
280 poolProperties.setName(poolName);
281
282 org.apache.tomcat.jdbc.pool.DataSource dataSource =
283 new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
284
285 if (poolProperties.isJmxEnabled()) {
286 org.apache.tomcat.jdbc.pool.ConnectionPool jdbcConnectionPool =
287 dataSource.createPool();
288
289 ConnectionPool jmxConnectionPool = jdbcConnectionPool.getJmxPool();
290
291 MBeanServer mBeanServer =
292 ManagementFactory.getPlatformMBeanServer();
293
294 ObjectName objectName = new ObjectName(
295 _TOMCAT_JDBC_POOL_OBJECT_NAME_PREFIX + poolName);
296
297 mBeanServer.registerMBean(jmxConnectionPool, objectName);
298 }
299
300 return dataSource;
301 }
302
303 protected boolean isPropertyC3PO(String key) {
304 if (key.equalsIgnoreCase("acquireIncrement") ||
305 key.equalsIgnoreCase("acquireRetryAttempts") ||
306 key.equalsIgnoreCase("acquireRetryDelay") ||
307 key.equalsIgnoreCase("connectionCustomizerClassName") ||
308 key.equalsIgnoreCase("idleConnectionTestPeriod") ||
309 key.equalsIgnoreCase("maxIdleTime") ||
310 key.equalsIgnoreCase("maxPoolSize") ||
311 key.equalsIgnoreCase("minPoolSize") ||
312 key.equalsIgnoreCase("numHelperThreads") ||
313 key.equalsIgnoreCase("preferredTestQuery")) {
314
315 return true;
316 }
317 else {
318 return false;
319 }
320 }
321
322 protected boolean isPropertyDBCP(String key) {
323 if (key.equalsIgnoreCase("defaultTransactionIsolation") ||
324 key.equalsIgnoreCase("maxActive") ||
325 key.equalsIgnoreCase("minIdle") ||
326 key.equalsIgnoreCase("removeAbandonedTimeout")) {
327
328 return true;
329 }
330 else {
331 return false;
332 }
333 }
334
335 protected boolean isPropertyLiferay(String key) {
336 if (key.equalsIgnoreCase("jndi.name") ||
337 key.equalsIgnoreCase("liferay.pool.provider")) {
338
339 return true;
340 }
341 else {
342 return false;
343 }
344 }
345
346 protected boolean isPropertyTomcat(String key) {
347 if (key.equalsIgnoreCase("fairQueue") ||
348 key.equalsIgnoreCase("jdbcInterceptors") ||
349 key.equalsIgnoreCase("jmxEnabled") ||
350 key.equalsIgnoreCase("timeBetweenEvictionRunsMillis") ||
351 key.equalsIgnoreCase("useEquals")) {
352
353 return true;
354 }
355 else {
356 return false;
357 }
358 }
359
360 protected void testClassForName(Properties properties) throws Exception {
361 String driverClassName = properties.getProperty("driverClassName");
362
363 try {
364 Class.forName(driverClassName);
365 }
366 catch (ClassNotFoundException cnfe) {
367 if (!ServerDetector.isGeronimo() && !ServerDetector.isJetty() &&
368 !ServerDetector.isTomcat()) {
369
370 throw cnfe;
371 }
372
373 String url = PropsUtil.get(
374 PropsKeys.SETUP_DATABASE_JAR_URL, new Filter(driverClassName));
375 String name = PropsUtil.get(
376 PropsKeys.SETUP_DATABASE_JAR_NAME, new Filter(driverClassName));
377
378 if (Validator.isNull(url) || Validator.isNull(name)) {
379 throw cnfe;
380 }
381
382 if (HttpUtil.getHttp() == null) {
383 HttpUtil httpUtil = new HttpUtil();
384
385 httpUtil.setHttp(new HttpImpl());
386 }
387
388 if (FileUtil.getFile() == null) {
389 FileUtil fileUtil = new FileUtil();
390
391 fileUtil.setFile(new FileImpl());
392 }
393
394 JarUtil.downloadAndInstallJar(true, url, name, null);
395 }
396 }
397
398 private static final String _TOMCAT_JDBC_POOL_OBJECT_NAME_PREFIX =
399 "TomcatJDBCPool:type=ConnectionPool,name=";
400
401 private static Log _log = LogFactoryUtil.getLog(
402 DataSourceFactoryImpl.class);
403
404 private static PACL _pacl = new NoPACL();
405
406 private static class NoPACL implements PACL {
407
408 @Override
409 public DataSource getDataSource(DataSource dataSource) {
410 return dataSource;
411 }
412
413 }
414
415 public static interface PACL {
416
417 public DataSource getDataSource(DataSource dataSource);
418
419 }
420
421 }