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