FileDocCategorySizeDatePackage
BaseConnectionManager2.javaAPI DocJBoss 4.2.128205Fri Jul 13 21:01:18 BST 2007org.jboss.resource.connectionmanager

BaseConnectionManager2

public abstract class BaseConnectionManager2 extends org.jboss.system.ServiceMBeanSupport implements ConnectionListenerFactory, org.jboss.tm.TransactionTimeoutConfiguration, BaseConnectionManager2MBean, ConnectionCacheListener
The BaseConnectionManager2 is an abstract base class for JBoss ConnectionManager implementations. It includes functionality to obtain managed connections from a ManagedConnectionPool mbean, find the Subject from a SubjectSecurityDomain, and interact with the CachedConnectionManager for connections held over transaction and method boundaries. Important mbean references are to a ManagedConnectionPool supplier (typically a JBossManagedConnectionPool), and a RARDeployment representing the ManagedConnectionFactory.
author
David Jencks
author
Erwin Guib
author
Adrian Brock
author
Weston Price
version
$Revision: 57189 $

Fields Summary
private static final String
SECURITY_MGR_PATH
Note that this copy has a trailing / unlike the original in JaasSecurityManagerService.
public static final String
STOPPING_NOTIFICATION
protected ObjectName
managedConnectionPoolName
protected ManagedConnectionPool
poolingStrategy
protected String
jndiName
protected String
securityDomainJndiName
protected org.jboss.security.SubjectSecurityManager
securityDomain
protected ObjectName
jaasSecurityManagerService
protected ObjectName
ccmName
protected CachedConnectionManager
ccm
protected boolean
trace
Constructors Summary
public BaseConnectionManager2()
Default BaseConnectionManager2 managed constructor for use by subclass mbeans.

      super();
      trace = log.isTraceEnabled();
   
public BaseConnectionManager2(CachedConnectionManager ccm, ManagedConnectionPool poolingStrategy)
Creates a new BaseConnectionManager2 instance. for TESTING ONLY! not a managed operation.

param
ccm a CachedConnectionManager value
param
poolingStrategy a ManagedConnectionPool value

      super();
      this.ccm = ccm;
      this.poolingStrategy = poolingStrategy;
      trace = log.isTraceEnabled();
   
Methods Summary
public java.lang.ObjectallocateConnection(javax.resource.spi.ManagedConnectionFactory mcf, javax.resource.spi.ConnectionRequestInfo cri)

      if (poolingStrategy == null)
         throw new ResourceException(
               "You are trying to use a connection factory that has been shut down: ManagedConnectionFactory is null.");

      //it is an explicit spec requirement that equals be used for matching rather than ==.
      if (!poolingStrategy.getManagedConnectionFactory().equals(mcf))
         throw new ResourceException("Wrong ManagedConnectionFactory sent to allocateConnection!");

      // Pick a managed connection from the pool
      Subject subject = getSubject();
      ConnectionListener cl = getManagedConnection(subject, cri);

      // Tell each connection manager the managed connection is active
      reconnectManagedConnection(cl);

      // Ask the managed connection for a connection
      Object connection = null;
      try
      {
         connection = cl.getManagedConnection().getConnection(subject, cri);
      }
      catch (Throwable t)
      {
         managedConnectionDisconnected(cl);
         JBossResourceException.rethrowAsResourceException(
               "Unchecked throwable in ManagedConnection.getConnection() cl=" + cl, t);
      }

      // Associate managed connection with the connection
      registerAssociation(cl, connection);
      if (ccm != null)
         ccm.registerConnection(this, cl, connection, cri);
      return connection;
   
public voiddisconnect(java.util.Collection crs, java.util.Set unsharableResources)

      // if we have an unshareable connection do not remove the association
      // nothing to do
      if (unsharableResources.contains(jndiName))
      {
         log.trace("disconnect for unshareable connection: nothing to do");
         return;
      }

      Set cls = new HashSet();
      for (Iterator i = crs.iterator(); i.hasNext();)
      {
         ConnectionRecord cr = (ConnectionRecord) i.next();
         ConnectionListener cl = cr.cl;
         cr.setConnectionListener(null);
         unregisterAssociation(cl, cr.connection);
         if (!cls.contains(cl))
         {
            cls.add(cl);
         }
      }
      for (Iterator i = cls.iterator(); i.hasNext();)
         disconnectManagedConnection((ConnectionListener) i.next());
   
protected voiddisconnectManagedConnection(ConnectionListener cl)
Invoked when a managed connection is no longer associated

param
cl the managed connection

      try
      {
         managedConnectionDisconnected(cl);
      }
      catch (Throwable t)
      {
         log.warn("Unchecked throwable in managedConnectionDisconnected() cl=" + cl, t);
      }
   
public javax.management.ObjectNamegetCachedConnectionManager()

      return ccmName;
   
protected final CachedConnectionManagergetCcm()

      return ccm;
   
public intgetConnectionCount()

      return poolingStrategy.getConnectionCount();
   
public org.jboss.resource.connectionmanager.BaseConnectionManager2getInstance()

      return this;
   
public javax.management.ObjectNamegetJaasSecurityManagerService()

      return jaasSecurityManagerService;
   
public java.lang.StringgetJndiName()

      return jndiName;
   
public ConnectionListenergetManagedConnection(javax.security.auth.Subject subject, javax.resource.spi.ConnectionRequestInfo cri)
Public for use in testing pooling functionality by itself. called by both allocateConnection and reconnect.

param
subject a Subject value
param
cri a ConnectionRequestInfo value
return
a ManagedConnection value
exception
ResourceException if an error occurs

      return getManagedConnection(null, subject, cri);
   
protected ConnectionListenergetManagedConnection(javax.transaction.Transaction transaction, javax.security.auth.Subject subject, javax.resource.spi.ConnectionRequestInfo cri)
Get the managed connection from the pool

param
transaction the transaction for track by transaction
param
subject the subject
param
cri the ConnectionRequestInfo
return
a managed connection
exception
ResourceException if an error occurs

      return poolingStrategy.getConnection(transaction, subject, cri);
   
public javax.resource.spi.ManagedConnectionFactorygetManagedConnectionFactory()

      return poolingStrategy.getManagedConnectionFactory();
   
public javax.management.ObjectNamegetManagedConnectionPool()

      return managedConnectionPoolName;
   
public javax.management.MBeanNotificationInfo[]getNotificationInfo()

      // TODO: implement this javax.management.NotificationBroadcaster method
      return super.getNotificationInfo();
   
public ManagedConnectionPoolgetPoolingStrategy()
For testing

      return poolingStrategy;
   
public java.lang.StringgetSecurityDomainJndiName()

      return securityDomainJndiName;
   
private javax.security.auth.SubjectgetSubject()

      Subject subject = null;
      if (securityDomain != null)
      {
         /* Authenticate using the caller info and obtain a copy of the Subject
          state for use in establishing a secure connection. A copy must be
          obtained to avoid problems with multiple threads associated with
          the same principal changing the state of the resulting Subject.
          */
         Principal principal = GetPrincipalAction.getPrincipal();
         Object credential = GetCredentialAction.getCredential();
         subject = new Subject();
         if (securityDomain.isValid(principal, credential, subject) == false)
            throw new SecurityException("Invalid authentication attempt, principal=" + principal);
      }
      if (trace)
         log.trace("subject: " + subject);
      return subject;
   
public longgetTimeLeftBeforeTransactionTimeout(boolean errorRollback)

      return -1;
   
public javax.transaction.TransactionManagergetTransactionManagerInstance()

      return null;
   
public intgetTransactionTimeout()

      throw new NotImplementedException("NYI: getTransactionTimeout()");
   
public booleanisTransactional()

      return false;
   
protected voidmanagedConnectionDisconnected(ConnectionListener cl)
For polymorphism.

Do not invoke directly use disconnectManagedConnection which does the relevent exception handling

   
protected voidmanagedConnectionReconnected(ConnectionListener cl)
For polymorphism.

Do not invoke directly use reconnectManagedConnection which does the relevent exception handling

   
public voidreconnect(java.util.Collection conns, java.util.Set unsharableResources)

      // if we have an unshareable connection the association was not removed
      // nothing to do
      if (unsharableResources.contains(jndiName))
      {
         log.trace("reconnect for unshareable connection: nothing to do");
         return;
      }

      Map criToCLMap = new HashMap();
      for (Iterator i = conns.iterator(); i.hasNext();)
      {
         ConnectionRecord cr = (ConnectionRecord) i.next();
         if (cr.cl != null)
         {
            //This might well be an error.
            log.warn("reconnecting a connection handle that still has a managedConnection! "
                  + cr.cl.getManagedConnection() + " " + cr.connection);
         }
         ConnectionListener cl = (ConnectionListener) criToCLMap.get(cr.cri);
         if (cl == null)
         {
            cl = getManagedConnection(getSubject(), cr.cri);
            criToCLMap.put(cr.cri, cl);
            //only call once per managed connection, when we get it.
            reconnectManagedConnection(cl);
         }

         cl.getManagedConnection().associateConnection(cr.connection);
         registerAssociation(cl, cr.connection);
         cr.setConnectionListener(cl);
      }
      criToCLMap.clear();//not needed logically, might help the gc.
   
protected voidreconnectManagedConnection(ConnectionListener cl)
Invoked to reassociate a managed connection

param
cl the managed connection

      try
      {
         //WRONG METHOD NAME!!
         managedConnectionReconnected(cl);
      }
      catch (Throwable t)
      {
         disconnectManagedConnection(cl);
         JBossResourceException.rethrowAsResourceException("Unchecked throwable in managedConnectionReconnected() cl="
               + cl, t);
      }
   
private voidregisterAssociation(ConnectionListener cl, java.lang.Object c)

      cl.registerConnection(c);
   
protected static voidrethrowAsResourceException(java.lang.String message, java.lang.Throwable t)
Rethrow a throwable as resource exception

deprecated
use JBossResourceException.rethrowAsResourceException


                 
           
   
      JBossResourceException.rethrowAsResourceException(message, t);
   
public voidreturnManagedConnection(ConnectionListener cl, boolean kill)

      ManagedConnectionPool localStrategy = cl.getManagedConnectionPool();
      if (localStrategy != poolingStrategy)
         kill = true;

      try
      {
         if (kill == false && cl.getState() == ConnectionListener.NORMAL)
            cl.tidyup();
      }
      catch (Throwable t)
      {
         log.warn("Error during tidyup " + cl, t);
         kill = true;
      }
      
      try
      {
         localStrategy.returnConnection(cl, kill);
      }
      catch (ResourceException re)
      {
         // We can receive notification of an error on the connection
         // before it has been assigned to the pool. Reduce the noise for
         // these errors
         if (kill)
            log.debug("resourceException killing connection (error retrieving from pool?)", re);
         else
            log.warn("resourceException returning connection: " + cl.getManagedConnection(), re);
      }
   
public voidsetCachedConnectionManager(javax.management.ObjectName ccmName)

      this.ccmName = ccmName;
   
public voidsetJaasSecurityManagerService(javax.management.ObjectName jaasSecurityManagerService)

      this.jaasSecurityManagerService = jaasSecurityManagerService;
   
public voidsetJndiName(java.lang.String jndiName)

      this.jndiName = jndiName;
   
public voidsetManagedConnectionPool(javax.management.ObjectName newManagedConnectionPool)

      this.managedConnectionPoolName = newManagedConnectionPool;
   
public voidsetSecurityDomainJndiName(java.lang.String securityDomainJndiName)

      if (securityDomainJndiName != null && securityDomainJndiName.startsWith(SECURITY_MGR_PATH))
      {
         securityDomainJndiName = securityDomainJndiName.substring(SECURITY_MGR_PATH.length());
         log.warn("WARNING: UPDATE YOUR SecurityDomainJndiName! REMOVE " + SECURITY_MGR_PATH);
      }
      this.securityDomainJndiName = securityDomainJndiName;
   
protected voidstartService()

      try
      {
         ccm = (CachedConnectionManager) server.getAttribute(ccmName, "Instance");
      }
      catch (Exception e)
      {
         JMXExceptionDecoder.rethrow(e);
      }

      if (ccm == null)
         throw new DeploymentException("cached ConnectionManager not found: " + ccmName);

      if (securityDomainJndiName != null && jaasSecurityManagerService == null)
         throw new DeploymentException("You must supply both securityDomainJndiName and jaasSecurityManagerService to use container managed security");

      if (securityDomainJndiName != null)
         securityDomain = (SubjectSecurityManager) new InitialContext().lookup(SECURITY_MGR_PATH
               + securityDomainJndiName);

      if (managedConnectionPoolName == null)
         throw new DeploymentException("managedConnectionPool not set!");
      try
      {
         poolingStrategy = (ManagedConnectionPool) server.getAttribute(managedConnectionPoolName,
               "ManagedConnectionPool");
      }
      catch (Exception e)
      {
         JMXExceptionDecoder.rethrow(e);
      }

      poolingStrategy.setConnectionListenerFactory(this);

      // Give it somewhere to tell people things
      String categoryName = poolingStrategy.getManagedConnectionFactory().getClass().getName() + "." + jndiName;
      Logger log = Logger.getLogger(categoryName);
      PrintWriter logWriter = new LoggerPluginWriter(log.getLoggerPlugin());
      try
      {
         poolingStrategy.getManagedConnectionFactory().setLogWriter(logWriter);
      }
      catch (ResourceException re)
      {
         log.warn("Unable to set log writer '" + logWriter + "' on " + "managed connection factory", re);
         log.warn("Linked exception:", re.getLinkedException());
      }
      
      if (poolingStrategy instanceof PreFillPoolSupport)
      {
                  
         PreFillPoolSupport prefill = (PreFillPoolSupport) poolingStrategy;
         
         if(prefill.shouldPreFill()){

            prefill.prefill();
            
         }
         
      }
   
   
protected voidstopService()

      //notify the login modules the mcf is going away, they need to look it up again later.
      sendNotification(new Notification(STOPPING_NOTIFICATION, getServiceName(), getNextNotificationSequenceNumber()));
      if (jaasSecurityManagerService != null && securityDomainJndiName != null)
         server.invoke(jaasSecurityManagerService, "flushAuthenticationCache", new Object[] { securityDomainJndiName }, new String[] { String.class.getName() });

      poolingStrategy.setConnectionListenerFactory(null);

      poolingStrategy = null;
      securityDomain = null;
      ccm = null;
   
public voidtransactionStarted(java.util.Collection conns)

      //reimplement in subclasses
   
protected voidunregisterAssociation(ConnectionListener cl, java.lang.Object c)

      cl.unregisterConnection(c);