AbstractConnectionListener.java
/*
* IronJacamar, a Java EE Connector Architecture implementation
* Copyright 2015, Red Hat Inc, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the Eclipse Public License 1.0 as
* published by the Free Software Foundation.
*
* This software 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 Eclipse
* Public License for more details.
*
* You should have received a copy of the Eclipse Public License
* along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.ironjacamar.core.connectionmanager.listener;
import org.ironjacamar.common.api.metadata.common.FlushStrategy;
import org.ironjacamar.core.CoreBundle;
import org.ironjacamar.core.CoreLogger;
import org.ironjacamar.core.api.connectionmanager.pool.FlushMode;
import org.ironjacamar.core.connectionmanager.ConnectionManager;
import org.ironjacamar.core.connectionmanager.Credential;
import org.ironjacamar.core.connectionmanager.pool.ManagedConnectionPool;
import org.ironjacamar.core.spi.transaction.ConnectableResourceListener;
import org.ironjacamar.core.tracer.Tracer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ManagedConnection;
import org.jboss.logging.Logger;
import org.jboss.logging.Messages;
/**
* The abstract connection listener
*
* @author <a href="jesper.pedersen@ironjacamar.org">Jesper Pedersen</a>
*/
public abstract class AbstractConnectionListener implements ConnectionListener, ConnectableResourceListener
{
/**
* The core Logger
*/
private static CoreLogger log = Logger
.getMessageLogger(CoreLogger.class, AbstractConnectionListener.class.getName());
/** The bundle */
private static CoreBundle bundle = Messages.getBundle(CoreBundle.class);
/** The connection manager */
protected ConnectionManager cm;
/** The managed connection */
private ManagedConnection mc;
/** The managed connection pool*/
private ManagedConnectionPool mcp;
/** The credential */
private Credential credential;
/** The state */
private AtomicInteger state;
/** Connection handles */
protected CopyOnWriteArraySet<Object> connectionHandles;
/** Connection traces */
protected Map<Object, Exception> connectionTraces;
/** Last validated timestamp */
private long validated;
/** Last fromPool timestamp */
private long fromPool;
/** Last toPool timestamp */
private long toPool;
/** Flush strategy **/
private FlushStrategy flushStrategy;
/**
* Constructor
* @param cm The connection manager
* @param mc The managed connection
* @param credential The credential
* @param mcp The ManagedConnectionPool
* @param flushStrategy The FlushStrategy
*/
public AbstractConnectionListener(ConnectionManager cm, ManagedConnection mc, Credential credential,
ManagedConnectionPool mcp, FlushStrategy flushStrategy)
{
this.cm = cm;
this.mc = mc;
this.mcp = mcp;
this.flushStrategy = flushStrategy;
this.credential = credential;
this.state = new AtomicInteger(FREE);
this.connectionHandles = new CopyOnWriteArraySet<Object>();
if (cm.getConnectionManagerConfiguration().isTracking() != null &&
cm.getConnectionManagerConfiguration().isTracking().booleanValue())
this.connectionTraces = new HashMap<Object, Exception>();
long timestamp = System.currentTimeMillis();
this.validated = timestamp;
this.fromPool = timestamp;
this.toPool = timestamp;
mc.addConnectionEventListener(this);
}
/**
* {@inheritDoc}
*/
public boolean changeState(int currentState, int newState)
{
return state.compareAndSet(currentState, newState);
}
/**
* {@inheritDoc}
*/
public int getState()
{
return state.get();
}
/**
* {@inheritDoc}
*/
public void setState(int state)
{
this.state.set(state);
}
/**
* {@inheritDoc}
*/
public Credential getCredential()
{
return credential;
}
/**
* {@inheritDoc}
*/
public void connectionClosed(ConnectionEvent event)
{
Object connection = event.getConnectionHandle();
removeConnection(connection);
if (cm.getCachedConnectionManager() != null)
{
cm.getCachedConnectionManager().unregisterConnection(cm, this, connection);
}
if (connectionHandles.isEmpty() && !isEnlisted())
cm.returnConnectionListener(this, false);
}
/**
* {@inheritDoc}
*/
public void connectionErrorOccurred(ConnectionEvent event)
{
if (getState() == IN_USE)
{
if (event != null)
{
Exception cause = event.getException();
if (cause == null)
{
cause = new Exception(bundle.noExceptionWasReported());
}
log.connectionErrorOccurred(this, cause);
}
else
{
Exception cause = new Exception(bundle.noExceptionWasReported());
log.unknownConnectionErrorOccurred(this, cause);
}
}
Object connection = event.getConnectionHandle();
removeConnection(connection);
if (cm.getCachedConnectionManager() != null)
{
cm.getCachedConnectionManager().unregisterConnection(cm, this, connection);
}
if (cm.getCachedConnectionManager() != null)
{
for (Object c : connectionHandles)
cm.getCachedConnectionManager().unregisterConnection(cm, this, c);
}
clearConnections();
if (event != null && event.getSource() != getManagedConnection())
{
log.notifiedErrorDifferentManagedConnection();
}
haltCatchFire();
cm.returnConnectionListener(this, true);
if (flushStrategy == FlushStrategy.FAILING_CONNECTION_ONLY)
{
mcp.prefill();
}
else if (flushStrategy == FlushStrategy.INVALID_IDLE_CONNECTIONS)
{
mcp.flush(FlushMode.INVALID);
}
else if (flushStrategy == FlushStrategy.IDLE_CONNECTIONS)
{
mcp.flush(FlushMode.IDLE);
}
else if (flushStrategy == FlushStrategy.GRACEFULLY)
{
mcp.flush(FlushMode.GRACEFULLY);
}
else if (flushStrategy == FlushStrategy.ENTIRE_POOL)
{
mcp.flush(FlushMode.ALL);
}
else if (flushStrategy == FlushStrategy.ALL_INVALID_IDLE_CONNECTIONS)
{
cm.getPool().flush(FlushMode.INVALID);
}
else if (flushStrategy == FlushStrategy.ALL_IDLE_CONNECTIONS)
{
cm.getPool().flush(FlushMode.IDLE);
}
else if (flushStrategy == FlushStrategy.ALL_GRACEFULLY)
{
cm.getPool().flush(FlushMode.GRACEFULLY);
}
else if (flushStrategy == FlushStrategy.ALL_CONNECTIONS)
{
cm.getPool().flush(FlushMode.ALL);
}
}
/**
* {@inheritDoc}
*/
public void localTransactionStarted(ConnectionEvent event)
{
}
/**
* {@inheritDoc}
*/
public void localTransactionCommitted(ConnectionEvent event)
{
}
/**
* {@inheritDoc}
*/
public void localTransactionRolledback(ConnectionEvent event)
{
}
/**
* {@inheritDoc}
*/
public ManagedConnection getManagedConnection()
{
return mc;
}
/**
* {@inheritDoc}
*/
public ManagedConnectionPool getManagedConnectionPool()
{
return mcp;
}
/**
* {@inheritDoc}
*/
public Object getConnection() throws ResourceException
{
Object result = mc.getConnection(credential.getSubject(), credential.getConnectionRequestInfo());
addConnection(result);
return result;
}
/**
* {@inheritDoc}
*/
public Set<Object> getConnections()
{
return connectionHandles;
}
/**
* {@inheritDoc}
*/
public boolean addConnection(Object c)
{
if (Tracer.isEnabled())
Tracer.getConnection(cm.getPool().getConfiguration().getId(), mcp, this, c);
if (connectionTraces != null)
connectionTraces.put(c, new Exception());
return connectionHandles.add(c);
}
/**
* {@inheritDoc}
*/
public boolean removeConnection(Object c)
{
if (Tracer.isEnabled())
Tracer.returnConnection(cm.getPool().getConfiguration().getId(), mcp, this, c);
if (connectionTraces != null)
connectionTraces.remove(c);
return connectionHandles.remove(c);
}
/**
* {@inheritDoc}
*/
public void clearConnections()
{
if (Tracer.isEnabled())
{
for (Object c : connectionHandles)
Tracer.returnConnection(cm.getPool().getConfiguration().getId(), mcp, this, c);
}
if (connectionTraces != null)
connectionTraces.clear();
connectionHandles.clear();
}
/**
* {@inheritDoc}
*/
public long getValidated()
{
return validated;
}
/**
* {@inheritDoc}
*/
public void validated()
{
validated = System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
public long getFromPool()
{
return fromPool;
}
/**
* {@inheritDoc}
*/
public void fromPool()
{
fromPool = System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
public long getToPool()
{
return toPool;
}
/**
* {@inheritDoc}
*/
public void toPool() throws ResourceException
{
toPool = System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
public void handleCreated(Object h)
{
addConnection(h);
}
/**
* {@inheritDoc}
*/
public void handleClosed(Object h)
{
// This is never called
removeConnection(h);
}
/**
* Halt and Catch Fire
*/
void haltCatchFire()
{
// Do nothing by default
}
/**
* {@inheritDoc}
*/
public int compareTo(Object o)
{
return 0;
}
}