gt:             Throwable ex = ((TeiidSQLException)e).getCause();
context: /*
   * JBoss, Home of Professional Open Source.
   * See the COPYRIGHT.txt file distributed with this work for information
   * regarding copyright ownership.  Some portions may be licensed
   * to Red Hat, Inc. under one or more contributor license agreements.
   * 
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   * 
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   * 
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301 USA.
   */
  
  package org.teiid.jdbc;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  import java.sql.Connection;
  import java.sql.SQLException;
  import java.util.Collections;
  import java.util.IdentityHashMap;
  import java.util.Iterator;
  import java.util.Set;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  import javax.sql.ConnectionEvent;
  import javax.sql.ConnectionEventListener;
  import javax.sql.StatementEventListener;
  import javax.sql.XAConnection;
  import javax.transaction.xa.XAException;
  import javax.transaction.xa.XAResource;
  import javax.transaction.xa.Xid;
  
  import org.teiid.client.security.InvalidSessionException;
  import org.teiid.client.util.ExceptionUtil;
  import org.teiid.client.xa.XATransactionException;
  import org.teiid.client.xa.XidImpl;
  import org.teiid.net.CommunicationException;
  import org.teiid.net.ServerConnection;
  import org.teiid.net.socket.SingleInstanceCommunicationException;
  
  /**
   * Implementation of XAConnection.
   */
  public class XAConnectionImpl implements XAConnection, XAResource {
  	
      private final class CloseInterceptor implements
                                          InvocationHandler {
          
          private ConnectionImpl proxiedConnection;
          
          CloseInterceptor(ConnectionImpl connection) {
              this.proxiedConnection = connection; 
          }
  
          public Object invoke(Object proxy,
                               Method method,
                               Object[] args) throws Throwable {
              if ("close".equals(method.getName())) {  //$NON-NLS-1$
                  close();
                  return null;
              }
              
              try {
  				return method.invoke(this.proxiedConnection, args);
  			} catch (InvocationTargetException e) {
  				Exception ex = ExceptionUtil.getExceptionOfType(e, InvalidSessionException.class);
  				if (ex == null) {
  					ex = ExceptionUtil.getExceptionOfType(e, CommunicationException.class);
  					if (ex instanceof SingleInstanceCommunicationException) {
  						ServerConnection sc = proxiedConnection.getServerConnection();
  						if (!sc.isOpen(ServerConnection.PING_INTERVAL)) {
  							ex = null;
  						}
  					}
  				}
  				if (ex != null) {
  					SQLException se = null;
  					if (e.getCause() instanceof SQLException) {
  						se = (SQLException)e.getCause();
  					} else {
  						se = TeiidSQLException.create(e.getCause());
  					}
  					notifyListener(se);
  				} 
  				throw e.getTargetException();
  			}
          }
  
  		void close() {
  			this.proxiedConnection.recycleConnection(loadBalance);
  			XAConnectionImpl.this.notifyListener(null);
  		}
      }
  
  	private static Logger logger = Logger.getLogger("org.teiid.jdbc"); //$NON-NLS-1$
  
  	private int timeOut;
      private Set<ConnectionEventListener> listeners;
  	private ConnectionImpl connection;
  	private CloseInterceptor handler;
      private boolean isClosed;
      private boolean loadBalance = true;
          
  	public XAConnectionImpl(ConnectionImpl conn){
  	    this.connection = conn;
  	}
  	
  	public void setLoadBalance(boolean loadBalance) {
  		this.loadBalance = loadBalance;
  	}
  		
  	public Connection getConnection() throws SQLException{
          ConnectionImpl conn = getConnectionImpl();
  		if (handler != null) {
  			handler.close();
  		}
  		handler = new CloseInterceptor(conn);
  		Connection result = (Connection)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {Connection.class}, handler);
  		return result;
  	}
  	
  	ConnectionImpl getConnectionImpl() throws SQLException {
  	    if(isClosed){
              throw new SQLException(JDBCPlugin.Util.getString("MMXAConnection.connection_is_closed")); //$NON-NLS-1$
          }
          
          return connection;
  	}
  	    
  	public synchronized void addConnectionEventListener(ConnectionEventListener listener){
  		if(listeners == null){
  			listeners = Collections.newSetFromMap(new IdentityHashMap<ConnectionEventListener, Boolean>());
  		}
  		this.listeners.add(listener);
  	}
  	
  	public synchronized void removeConnectionEventListener(ConnectionEventListener listener){
  		if(listeners == null){
  			return;
  		}
  		this.listeners.remove(listener);
  	}
  	
  	public XAResource getXAResource() throws SQLException{
  		return this;
  	}
  	
  	public void close()throws SQLException{		
  		if(connection != null && !connection.isClosed()){
  			connection.close();			
  		}
          isClosed = true;
  	}
  	
  	/**
  	 * Notify listeners, if there is any, about the connection status.
  	 * If e is null, the connection is properly closed.
  	 * @param e
  	 */
  	protected synchronized void notifyListener(SQLException e){
  		if(listeners != null && !listeners.isEmpty()){
  			Iterator<ConnectionEventListener> iter = listeners.iterator();
  			while(iter.hasNext()){
  				ConnectionEventListener listener = iter.next();
  				if(e == null){
  					//no exception
  					listener.connectionClosed(new ConnectionEvent(this));
  				}else{
  					//exception occurred
  					listener.connectionErrorOccurred(new ConnectionEvent(this, e));	
  				}
  			}
  		}	
  	}
  
  	public void addStatementEventListener(StatementEventListener arg0) {
  	}
  
  	public void removeStatementEventListener(StatementEventListener arg0) {
  	}
  	
  	public void commit(Xid xid, boolean onePhase) throws XAException {
      	XidImpl mmXid = getMMXid(xid);
  		try{
  			getMMConnection().commitTransaction(mmXid, onePhase); 	
  		}catch(SQLException e){
  			String logMsg = JDBCPlugin.Util.getString("MMXAResource.FailedCommitTXN", xid, onePhase ? "true":"false"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  			throw handleError(e, logMsg);
  		}
      }
  
      private XAException handleError(Exception e,String logMsg) {
          logger.log(Level.SEVERE, logMsg, e);
  
          if(e instanceof TeiidSQLException){
  