Java tutorial
/** * Copyright (C) 2012 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.dashboard.database; import org.jboss.dashboard.database.hibernate.HibernateTxFragment; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Session; import javax.sql.DataSource; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.util.logging.Logger; /** * A data source implementation that bounds its connections to the underlying transaction. * <p>When a connection is requested it gets a connection from the pool and attach such connection * to the current transaction. When the transaction completes the data source * connection is automatically completed as well. */ public class ExternalDataSource implements DataSource { /** * Get an external data source instance. * @param name The name to assign to the datasource. * @param dsEntry The object containing the connection configuration for this datasource. */ public static ExternalDataSource lookup(String name, DataSourceEntry dsEntry) { ExternalDataSource ds = new ExternalDataSource(); ds.setName(name); ds.setDataSourceEntry(dsEntry); ds.setDisableAutoCommit(true); return ds; } protected static transient Log log = LogFactory.getLog(ExternalDataSource.class.getName()); protected String name; protected DataSourceEntry dataSourceEntry; protected transient Connection currentConnection; private PrintWriter printWriter = new PrintWriter(System.out); private int loginTimeOut = 0; private boolean disableAutoCommit; public ExternalDataSource() { this.name = null; this.dataSourceEntry = null; this.currentConnection = null; this.disableAutoCommit = true; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void setDataSourceEntry(DataSourceEntry dataSourceEntry) { this.dataSourceEntry = dataSourceEntry; } public DataSourceEntry getDataSourceEntry() { return dataSourceEntry; } public int getLoginTimeout() throws SQLException { return loginTimeOut; } public void setLoginTimeout(int seconds) throws SQLException { this.loginTimeOut = seconds; } public PrintWriter getLogWriter() throws SQLException { return printWriter; } public void setLogWriter(PrintWriter out) throws SQLException { this.printWriter = out; } public boolean isDisableAutoCommit() { return disableAutoCommit; } public void setDisableAutoCommit(boolean disableAutoCommit) { this.disableAutoCommit = disableAutoCommit; } public Connection getConnection(String username, String password) throws SQLException { return getConnection(); } public Connection getConnection() throws SQLException { if (currentConnection == null) initConnection(); return currentConnection; } public Logger getParentLogger() { return null; } protected void initConnection() { try { new HibernateTxFragment() { protected void txFragment(Session session) throws Exception { log.debug("Obtain data source connection: " + name); // Bug Fix: under some circumstances, the dataSourceEntry attribute became out of sync with the Hibernate session. dataSourceEntry = (DataSourceEntry) session.get(dataSourceEntry.getClass(), dataSourceEntry.getDbid()); Connection conn = dataSourceEntry.getConnection(); setAutoCommit(conn, !disableAutoCommit); currentConnection = conn; registerForCallbackNotifications(); } protected void beforeRollback() throws Exception { // Rollback asap. completeConnection(false); } protected void afterRollback() throws Exception { // Rollback if before commit fails. completeConnection(false); } protected void afterCommit() throws Exception { // Commit as late as possible. completeConnection(true); } }.execute(); } catch (Exception e) { throw new RuntimeException(e); } } protected void completeConnection(boolean commit) throws SQLException { if (currentConnection != null && !currentConnection.isClosed()) { if (!getAutoCommit(currentConnection)) { log.debug(commit ? "Commit" : "Rollback" + " data source connection: " + name); if (commit) currentConnection.commit(); else currentConnection.rollback(); } currentConnection.close(); } currentConnection = null; } protected boolean getAutoCommit(Connection conn) { try { return conn.getAutoCommit(); } catch (SQLException e) { // Ignore problems when trying to get autocommit. // In some environments (Presidencia - Informix) when trying to get autocommit an exception is thrown. log.debug("Can not get autocommit for datasource: " + name, e); return true; } } protected void setAutoCommit(Connection conn, boolean autocommit) { try { if (getAutoCommit(conn) != autocommit) { conn.setAutoCommit(autocommit); } } catch (SQLException e) { // Ignore problems when trying to change autocommit. // In some environments (Presidencia - Informix) when trying to set autocommit=true an exception is thrown. log.debug("Can not set autocommit for datasource: " + name, e); } } public boolean isWrapperFor(Class<?> c) { return false; } public <T> T unwrap(Class<T> c) { return null; } }