001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package info.jtrac.config;
018:
019: import java.sql.Connection;
020: import java.sql.Statement;
021: import javax.sql.DataSource;
022: import org.apache.commons.dbcp.BasicDataSource;
023: import org.slf4j.Logger;
024: import org.slf4j.LoggerFactory;
025: import org.springframework.beans.factory.DisposableBean;
026: import org.springframework.beans.factory.FactoryBean;
027: import org.springframework.jdbc.datasource.SingleConnectionDataSource;
028: import org.springframework.jndi.JndiObjectFactoryBean;
029: import org.springframework.util.StringUtils;
030:
031: /**
032: * spring factory bean to conditionally create the right data source
033: * either embedded or apache dbcp or JNDI datasource
034: */
035: public class DataSourceFactoryBean implements FactoryBean,
036: DisposableBean {
037:
038: private final Logger logger = LoggerFactory.getLogger(getClass());
039:
040: private String driverClassName;
041: private String url;
042: private String username;
043: private String password;
044: private String validationQuery;
045: private String dataSourceJndiName;
046:
047: private DataSource dataSource;
048:
049: public void setDriverClassName(String driverClassName) {
050: this .driverClassName = driverClassName;
051: }
052:
053: public void setUrl(String url) {
054: this .url = url;
055: }
056:
057: public void setUsername(String username) {
058: this .username = username;
059: }
060:
061: public void setPassword(String password) {
062: this .password = password;
063: }
064:
065: public void setValidationQuery(String validationQuery) {
066: this .validationQuery = validationQuery;
067: }
068:
069: public void setDataSourceJndiName(String dataSourceJndiName) {
070: this .dataSourceJndiName = dataSourceJndiName;
071: }
072:
073: public Object getObject() throws Exception {
074: if (StringUtils.hasText(dataSourceJndiName)) {
075: logger
076: .info("JNDI datasource requested, looking up datasource from JNDI name: '"
077: + dataSourceJndiName + "'");
078: JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
079: factoryBean.setJndiName(dataSourceJndiName);
080: // "java:comp/env/" will be prefixed if the JNDI name doesn't already have it
081: factoryBean.setResourceRef(true);
082: // this step actually does the JNDI lookup
083: try {
084: factoryBean.afterPropertiesSet();
085: } catch (Exception e) {
086: logger.error("datasource init from JNDI failed : " + e);
087: logger.error("aborting application startup");
088: throw new RuntimeException(e);
089: }
090: dataSource = (DataSource) factoryBean.getObject();
091: } else if (url.startsWith("jdbc:hsqldb:file")) {
092: logger
093: .info("embedded HSQLDB mode detected, switching on spring single connection data source");
094: SingleConnectionDataSource ds = new SingleConnectionDataSource();
095: ds.setUrl(url);
096: ds.setDriverClassName(driverClassName);
097: ds.setUsername(username);
098: ds.setPassword(password);
099: ds.setSuppressClose(true);
100: dataSource = ds;
101: } else {
102: logger
103: .info("Not using embedded HSQLDB or JNDI datasource, switching on Apache DBCP data source connection pooling");
104: BasicDataSource ds = new BasicDataSource();
105: ds.setUrl(url);
106: ds.setDriverClassName(driverClassName);
107: ds.setUsername(username);
108: ds.setPassword(password);
109: ds.setValidationQuery(validationQuery);
110: ds.setTestOnBorrow(false);
111: ds.setTestWhileIdle(true);
112: ds.setTimeBetweenEvictionRunsMillis(600000);
113: dataSource = ds;
114: }
115: return dataSource;
116: }
117:
118: public Class getObjectType() {
119: return DataSource.class;
120: }
121:
122: public boolean isSingleton() {
123: return true;
124: }
125:
126: public void destroy() throws Exception {
127: if (dataSource instanceof SingleConnectionDataSource) {
128: logger
129: .info("attempting to shut down embedded HSQLDB database");
130: Connection con = dataSource.getConnection();
131: Statement stmt = con.createStatement();
132: stmt.executeUpdate("SHUTDOWN");
133: stmt.close();
134: con.close();
135: logger
136: .info("embedded HSQLDB database shut down successfully");
137: } else if (dataSource instanceof BasicDataSource) {
138: logger.info("attempting to close Apache DBCP data source");
139: ((BasicDataSource) dataSource).close();
140: logger.info("Apache DBCP data source closed successfully");
141: } else {
142: logger.info("context shutting down for JNDI datasource");
143: }
144: }
145:
146: }
|