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