Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2006, Red Hat Middleware LLC, 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 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 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 GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General 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.jboss.resource.connectionmanager;
 
 import java.util.Map;
 import java.util.Set;
 
 
The CachedConnectionManager mbean manages associations between meta-aware objects (those accessed through interceptor chains) and connection handles, and between user transactions and connection handles. Normally there should only be one such mbean. It is called by CachedConnectionInterceptor, UserTransaction, and all BaseConnectionManager2 instances.

Author(s):
David Jencks
Erwin Guib
Adrian Brock
Version:
$Revision: 81820 $
 
 public class CachedConnectionManager
         extends ServiceMBeanSupport
         UserTransactionListener,
         ComponentStack,
 {
    private boolean specCompliant;
 
    protected boolean trace;
    
    private boolean debug;
 
    protected boolean error;
 
    private TransactionManager tm;

   
ThreadLocal that holds current calling meta-programming aware object, used in case someone is idiotic enough to cache a connection between invocations.and want the spec required behavior of it getting hooked up to an appropriate ManagedConnection on each method invocation.
 
    private final ThreadLocal currentObjects = new ThreadLocal();

   
The variable objectToConnectionManagerMap holds the map of meta-aware object to set of connections it holds, used by the idiot spec compliant behavior.
 
    private final Map objectToConnectionManagerMap = new HashMap();

   
Connection stacktraces
 
    private Map connectionStackTraces = new WeakHashMap();

   
Default CachedConnectionManager managed constructor for mbeans. Remember that this mbean should be a singleton.

Jmx.managed:
constructor
   {
      super();
       = .isTraceEnabled();
   }
   public boolean isSpecCompliant()
   {
      return ;
   }
   public void setSpecCompliant(boolean specCompliant)
   {
      if (specCompliant)
         .warn("THE SpecCompliant ATTRIBUTE IS MISNAMED SEE http://jira.jboss.com/jira/browse/JBAS-1662");
      this. = specCompliant;
   }
   public boolean isDebug()
   {
      return ;
   }
   public void setDebug(boolean value)
   {
      this. = value;
   }
   public boolean isError()
   {
      return ;
   }
   public void setError(boolean value)
   {
      this. = value;
   }
   {
      return ;
   }
   {
      this. = tm;
      // FIXME we should be injecting onto the synchronizer directly
      if (tm != null)
         TransactionSynchronizer.setTransactionManager(tm);
   }
   {
      return this;
   }
   public int getInUseConnections()
   {
      synchronized ()
      {
         return .size();
      }
   }
   public Map listInUseConnections()
   {
      synchronized ()
      {
         HashMap result = new HashMap();
         for (Iterator i = .entrySet().iterator(); i.hasNext();)
         {
            Map.Entry entry = (Map.Entryi.next();
            Throwable stackTrace = (Throwableentry.getValue();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(baos);
            stackTrace.printStackTrace(ps);
            result.put(entry.getKey().toString(), baos.toString());
         }
         return result;
      }
   }
   //Object registration for meta-aware objects (i.e. this is called by interceptors)

   
Describe pushMetaAwareObject method here.

Parameters:
rawKey an Object value
unsharableResources the unsharable resources
Throws:
javax.resource.ResourceException if an error occurs
See also:
org.jboss.jca.spi.ComponentStack.pushMetaAwareObject(java.lang.Object,java.util.Set)
   public void pushMetaAwareObject(final Object rawKeySet unsharableResources)
           throws ResourceException
   {
      LinkedList stack = (LinkedList.get();
      if (stack == null)
      {
         if ()
            .trace("new stack for key: " + Strings.defaultToString(rawKey));
         stack = new LinkedList();
         .set(stack);
      } // end of if ()
      else
      {
         if ()
            .trace("old stack for key: " + Strings.defaultToString(rawKey));
         //At one time I attempted to recycle connections held over method calls.
         //This caused problems if the other method call started a new transaction.
         //To assure optimal use of connections, close them before calling out.
      } // end of else
      //check for reentrancy, reconnect if not reentrant.
      //wrap key to be based on == rather than equals
      KeyConnectionAssociation key = new KeyConnectionAssociation(rawKey);
      if ( && !stack.contains(key))
      {
         reconnect(keyunsharableResources);
      }
      stack.addLast(key);
   }

   
Describe popMetaAwareObject method here.

   public void popMetaAwareObject(Set unsharableResources)
           throws ResourceException
   {
      LinkedList stack = (LinkedList.get();
      if ()
         .trace("popped object: " + Strings.defaultToString(oldKey));
      if ()
      {
         if (!stack.contains(oldKey))
         {
            disconnect(oldKeyunsharableResources);
         } // end of if ()
      }
      else if ()
      {
         if (closeAll(oldKey.getCMToConnectionsMap()) && )
            throw new ResourceException("Some connections were not closed, see the log for the allocation stacktraces");
      }
      //At one time I attempted to recycle connections held over method calls.
      //This caused problems if the other method call started a new transaction.
      //To assure optimal use of connections, close them before calling out.
   }
   {
      LinkedList stack = (LinkedList.get();
      if (stack == null)
         return null;
      if (!stack.isEmpty())
         return (KeyConnectionAssociationstack.getLast();
      else
         return null;
   }
   //ConnectionRegistration -- called by ConnectionCacheListeners (normally ConnectionManagers)
   {
      if ()
      {
         synchronized ()
         {
            .put(connectionnew Throwable("STACKTRACE"));
         }
      }
      if ()
         .trace("registering connection from " + cm + ", connection : " + connection + ", key: " + key);
      if (key == null)
         return//not participating properly in this management scheme.
      ConnectionRecord cr = new ConnectionRecord(clconnectioncri);
      Map cmToConnectionsMap = key.getCMToConnectionsMap();
      Collection conns = (CollectioncmToConnectionsMap.get(cm);
      if (conns == null)
      {
         conns = new ArrayList();
         cmToConnectionsMap.put(cmconns);
      }
      conns.add(cr);
   }
   {
      if ()
      {
         if (cas != null)
            cas.remove(c);
         synchronized ()
         {
            .remove(c);
         }
      }
      if ()
         .trace("unregistering connection from " + cm + ", object: " + c + ", key: " + key);
      if (key == null)
         return//not participating properly in this management scheme.
      Map cmToConnectionsMap = key.getCMToConnectionsMap();
      Collection conns = (CollectioncmToConnectionsMap.get(cm);
      if (conns == null)
         return// Can happen if connections are "passed" between contexts
      for (Iterator i = conns.iterator(); i.hasNext();)
      {
         if (((ConnectionRecordi.next()). == c)
         {
            i.remove();
            return;
         }
      }
      throw new IllegalStateException("Trying to return an unknown connection2! " + c);
   }
   //called by UserTransaction after starting a transaction
   public void userTransactionStarted()
           throws SystemException
   {
      if ()
         .trace("user tx started, key: " + key);
      if (key == null)
         return//not participating properly in this management scheme.
      Map cmToConnectionsMap = key.getCMToConnectionsMap();
      Iterator cmToConnectionsMapIterator = cmToConnectionsMap.entrySet().iterator();
      while (cmToConnectionsMapIterator.hasNext())
      {
         Map.Entry cmToConnectionsMapEntry = (Map.Entry)cmToConnectionsMapIterator.next();
         ConnectionCacheListener cm = (ConnectionCacheListenercmToConnectionsMapEntry.getKey();
         Collection conns = (CollectioncmToConnectionsMapEntry.getValue();
         cm.transactionStarted(conns);
      }
   }

   
The reconnect method gets the cmToConnectionsMap from objectToConnectionManagerMap, copies it to the key, and reconnects all the connections in it.

Parameters:
key a KeyConnectionAssociation value
unsharableResources a Set value
Throws:
javax.resource.ResourceException if an error occurs
   private void reconnect(KeyConnectionAssociation keySet unsharableResources)
           throws ResourceException
   {
      Map cmToConnectionsMap = null;
      synchronized ()
      {
         cmToConnectionsMap = (Map.get(key);
         if (cmToConnectionsMap == null)
            return;
      }
      key.setCMToConnectionsMap(cmToConnectionsMap);
      Iterator cmToConnectionsMapIterator = cmToConnectionsMap.entrySet().iterator();
      while (cmToConnectionsMapIterator.hasNext())
      {
         Map.Entry cmToConnectionsMapEntry = (Map.Entry)cmToConnectionsMapIterator.next();
         ConnectionCacheListener cm = (ConnectionCacheListenercmToConnectionsMapEntry.getKey();
         Collection conns = (CollectioncmToConnectionsMapEntry.getValue();
         cm.reconnect(connsunsharableResources);
      }
   }
   private void disconnect(KeyConnectionAssociation keySet unsharableResources)
           throws ResourceException
   {
      Map cmToConnectionsMap = key.getCMToConnectionsMap();
      if (!cmToConnectionsMap.isEmpty())
      {
         synchronized ()
         {
            .put(keycmToConnectionsMap);
         }
         Iterator cmToConnectionsMapIterator = cmToConnectionsMap.entrySet().iterator();
         while (cmToConnectionsMapIterator.hasNext())
         {
            Map.Entry cmToConnectionsMapEntry = (Map.Entry)cmToConnectionsMapIterator.next();
            ConnectionCacheListener cm = (ConnectionCacheListenercmToConnectionsMapEntry.getKey();
            Collection conns = (CollectioncmToConnectionsMapEntry.getValue();
            cm.disconnect(connsunsharableResources);
         }
      }
   }
   private boolean closeAll(Map cmToConnectionsMap)
   {
      if ( == false)
         return false;
      boolean unclosed = false;
      Collection connections = cmToConnectionsMap.values();
      if (connections.size() != 0)
      {
         for (Iterator i = connections.iterator(); i.hasNext();)
         {
            Collection conns = (Collectioni.next();
            for (Iterator j = conns.iterator(); j.hasNext();)
            {
               Object c = ((ConnectionRecordj.next()).;
               CloseConnectionSynchronization cas = getCloseConnectionSynchronization(true);
               if (cas == null)
               {
                  unclosed = true;
                  closeConnection(c);
               }
               else
                  cas.add(c);
            }
         }
      }
      
      return unclosed;
   }

   
Describe unregisterConnectionCacheListener method here. This is a shutdown method called by a connection manager. It will remove all reference to that connection manager from the cache, so cached connections from that manager will never be recoverable. Possibly this method should not exist.

Parameters:
cm a ConnectionCacheListener value
   {
      if ()
         .trace("unregisterConnectionCacheListener: " + cm);
      synchronized ()
      {
         for (Iterator i = .values().iterator(); i.hasNext();)
         {
            Map cmToConnectionsMap = (Mapi.next();
            if (cmToConnectionsMap != null)
               cmToConnectionsMap.remove(cm);
         }
      }
   }

   
The class KeyConnectionAssociation wraps objects so they may be used in hashmaps based on their object identity rather than equals implementation. Used for keys.
   private final static class KeyConnectionAssociation
   {
      //key
      private final Object o;
      //map of cm to list of connections for that cm.
      private Map cmToConnectionsMap;
      KeyConnectionAssociation(final Object o)
      {
         this. = o;
      }
      public boolean equals(Object other)
      {
         return (other instanceof KeyConnectionAssociation) &&  == ((KeyConnectionAssociationother).;
      }
      public String toString()
      {
         return Strings.defaultToString();
      }
      
      public int hashCode()
      {
         return System.identityHashCode();
      }
      public void setCMToConnectionsMap(Map cmToConnectionsMap)
      {
         this. = cmToConnectionsMap;
      }
      public Map getCMToConnectionsMap()
      {
         if ( == null)
         {
             = new HashMap();
         } // end of if ()
         return ;
      }
   }
   private void closeConnection(Object c)
   {
      try
      {
         Throwable e;
         synchronized ()
         {
            e = (Throwable.remove(c);
         }
         Method m = c.getClass().getMethod("close"new Class[]{});
         try
         {
            if (e != null)
               .info("Closing a connection for you.  Please close them yourself: " + ce);
            else
               .info("Closing a connection for you.  Please close them yourself: " + c);
            m.invoke(cnew Object[]{});
         }
         catch (Throwable t)
         {
            .info("Throwable trying to close a connection for you, please close it yourself"t);
         }
      }
      catch (NoSuchMethodException nsme)
      {
         .info("Could not find a close method on alleged connection objects.  Please close your own connections.");
      }
   }
   private CloseConnectionSynchronization getCloseConnectionSynchronization(boolean createIfNotFound)
   {
      try
      {
         Transaction tx = null;
         if ( != null)
            tx = .getTransaction();
         if (tx != null)
         {
            TransactionSynchronizer.lock(tx);
            try
            {
               CloseConnectionSynchronization cas = (CloseConnectionSynchronization) TransactionSynchronizer.getCCMSynchronization(tx);
               if (cas == null && createIfNotFound && TxUtils.isActive(tx))
               {
                  cas = new CloseConnectionSynchronization();
                  TransactionSynchronizer.registerCCMSynchronization(txcas);
               }
               return cas;
            }
            finally
            {
               TransactionSynchronizer.unlock(tx);
            }
         }
      }
      catch (Throwable t)
      {
         .debug("Unable to synchronize with transaction"t);
      }
      return null;
   }
   private class CloseConnectionSynchronization implements Synchronization
   {
      HashSet connections = new HashSet();
      boolean closing = false;
      public CloseConnectionSynchronization()
      {
      }
      public synchronized void add(Object c)
      {
         if ()
            return;
         .add(c);
      }
      public synchronized void remove(Object c)
      {
         if ()
            return;
         .remove(c);
      }
      public void beforeCompletion()
      {
      }
      public void afterCompletion(int status)
      {
         synchronized (this)
         {
             = true;
         }
         for (Iterator i = .iterator(); i.hasNext();)
            closeConnection(i.next());
         .clear(); // Help the GC
      }
   }
New to GrepCode? Check out our FAQ X