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