/*
* Use of this J2EE Connectors Sample Source Code file is governed by
* the following modified BSD license:
*
* Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* -Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduct the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR LIABILITIES
* SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE, MODIFICATION
* OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
package com.sun.connector.blackbox;
import javax.resource.*;
import javax.resource.spi.*;
import javax.resource.spi.security.PasswordCredential;
import javax.resource.spi.IllegalStateException;
import javax.resource.spi.SecurityException;
import javax.resource.NotSupportedException;
import javax.transaction.xa.XAResource;
import java.io.*;
import java.util.*;
import javax.security.auth.Subject;
import javax.sql.PooledConnection;
import javax.sql.XAConnection;
import java.sql.SQLException;
import java.sql.Connection;
/**
* @author Tony Ng
*/
public class JdbcManagedConnection implements ManagedConnection {
private XAConnection xacon;
private Connection con;
private JdbcConnectionEventListener jdbcListener;
private PasswordCredential passCred;
private ManagedConnectionFactory mcf;
private PrintWriter logWriter;
private boolean supportsXA;
private boolean supportsLocalTx;
private boolean destroyed;
private Set connectionSet; // set of JdbcConnection
JdbcManagedConnection(ManagedConnectionFactory mcf,
PasswordCredential passCred,
XAConnection xacon,
Connection con,
boolean supportsXA,
boolean supportsLocalTx) {
this.mcf = mcf;
this.passCred = passCred;
this.xacon = xacon;
this.con = con;
this.supportsXA = supportsXA;
this.supportsLocalTx = supportsLocalTx;
connectionSet = new HashSet();
jdbcListener = new JdbcConnectionEventListener(this);
if (xacon != null) {
xacon.addConnectionEventListener(jdbcListener);
}
}
// XXX should throw better exception
private void throwResourceException(SQLException ex)
throws ResourceException {
ResourceException re =
new ResourceException("SQLException: " + ex.getMessage());
re.setLinkedException(ex);
throw re;
}
public Object getConnection(Subject subject,
ConnectionRequestInfo connectionRequestInfo)
throws ResourceException {
PasswordCredential pc =
Util.getPasswordCredential(mcf, subject, connectionRequestInfo);
if (!Util.isPasswordCredentialEqual(pc, passCred)) {
throw new SecurityException("Principal does not match. Reauthentication not supported");
}
checkIfDestroyed();
JdbcConnection jdbcCon =
new JdbcConnection(this, this.supportsLocalTx);
addJdbcConnection(jdbcCon);
return jdbcCon;
}
public void destroy() throws ResourceException {
try {
if (destroyed) return;
destroyed = true;
Iterator it = connectionSet.iterator();
while (it.hasNext()) {
JdbcConnection jdbcCon = (JdbcConnection) it.next();
jdbcCon.invalidate();
}
connectionSet.clear();
con.close();
if (xacon != null) xacon.close();
} catch (SQLException ex) {
throwResourceException(ex);
}
}
public void cleanup() throws ResourceException {
try {
checkIfDestroyed();
Iterator it = connectionSet.iterator();
while (it.hasNext()) {
JdbcConnection jdbcCon = (JdbcConnection) it.next();
jdbcCon.invalidate();
}
connectionSet.clear();
if (xacon != null) {
con.close();
con = xacon.getConnection();
} else {
con.setAutoCommit(true);
}
} catch (SQLException ex) {
throwResourceException(ex);
}
}
public void associateConnection(Object connection)
throws ResourceException {
checkIfDestroyed();
if (connection instanceof JdbcConnection) {
JdbcConnection jdbcCon = (JdbcConnection) connection;
jdbcCon.associateConnection(this);
} else {
throw new IllegalStateException("Invalid connection object: " +
connection);
}
}
public void addConnectionEventListener(ConnectionEventListener listener) {
jdbcListener.addConnectorListener(listener);
}
public void removeConnectionEventListener
(ConnectionEventListener listener) {
jdbcListener.removeConnectorListener(listener);
}
public XAResource getXAResource() throws ResourceException {
if (!supportsXA) {
throw new NotSupportedException("XA transaction not supported");
}
try {
checkIfDestroyed();
return xacon.getXAResource();
} catch (SQLException ex) {
throwResourceException(ex);
return null;
}
}
public LocalTransaction getLocalTransaction() throws ResourceException {
if (!supportsLocalTx) {
throw new NotSupportedException("Local transaction not supported");
} else {
checkIfDestroyed();
return new LocalTransactionImpl(this);
}
}
public ManagedConnectionMetaData getMetaData() throws ResourceException {
checkIfDestroyed();
return new MetaDataImpl(this);
}
public void setLogWriter(PrintWriter out) throws ResourceException {
this.logWriter = out;
}
public PrintWriter getLogWriter() throws ResourceException {
return logWriter;
}
Connection getJdbcConnection() throws ResourceException {
checkIfDestroyed();
return con;
}
boolean isDestroyed() {
return destroyed;
}
PasswordCredential getPasswordCredential() {
return passCred;
}
void sendEvent(int eventType, Exception ex) {
jdbcListener.sendEvent(eventType, ex, null);
}
void sendEvent(int eventType, Exception ex, Object connectionHandle) {
jdbcListener.sendEvent(eventType, ex, connectionHandle);
}
void removeJdbcConnection(JdbcConnection jdbcCon) {
connectionSet.remove(jdbcCon);
}
void addJdbcConnection(JdbcConnection jdbcCon) {
connectionSet.add(jdbcCon);
}
private void checkIfDestroyed() throws ResourceException {
if (destroyed) {
throw new IllegalStateException("Managed connection is closed");
}
}
ManagedConnectionFactory getManagedConnectionFactory() {
return mcf;
}
}