[jboss-cvs] JBossAS SVN: r70798 - in projects/ejb3/branches/cluster-dev: cache-jbc2 and 12 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Mar 12 23:27:01 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-03-12 23:27:01 -0400 (Wed, 12 Mar 2008)
New Revision: 70798

Added:
   projects/ejb3/branches/cluster-dev/cache-jbc2/
   projects/ejb3/branches/cluster-dev/cache-jbc2/pom.xml
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUAlgorithm.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUPolicy.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ContextInUseException.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStoreSource.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/java/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/resources/
   projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/resources/log4j.xml
Log:
[EJBTHREE-1026] Initial checkin of JBC2 stuff


Property changes on: projects/ejb3/branches/cluster-dev/cache-jbc2
___________________________________________________________________
Name: svn:ignore
   + .settings
eclipse-target
target
.classpath
.project


Added: projects/ejb3/branches/cluster-dev/cache-jbc2/pom.xml
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/pom.xml	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/pom.xml	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  vi:ts=2:sw=2:expandtab:
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <!-- Define Parent -->
+  <parent>
+    <groupId>org.jboss.ejb3</groupId>
+    <artifactId>jboss-ejb3-build</artifactId>
+    <version>0.13.0-SNAPSHOT</version>
+    <relativePath>../build/pom.xml</relativePath>
+  </parent>
+
+  <!-- Maven POM Model Version -->
+  <modelVersion>4.0.0</modelVersion>
+
+  <!-- Artifact Information -->
+  <groupId>org.jboss.ejb3</groupId>
+  <artifactId>jboss-ejb3-cache-jbc2</artifactId>
+  <version>0.14.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  <name>JBoss EJB 3.0 JBoss Cache Integration</name>
+  <url>http://labs.jboss.com/jbossejb3/</url>
+  <description>The Java EJB 3.0 JBoss Cache Integration classes</description>
+
+  <properties>
+    <version.org.jboss.cache_jbosscache-core>2.1.0-SNAPSHOT</version.org.jboss.cache_jbosscache-core>
+  </properties>
+
+  <dependencies>
+
+    <!-- EJB3 Cache -->
+    <dependency>
+      <groupId>org.jboss.ejb3</groupId>
+      <artifactId>jboss-ejb3-cache</artifactId>
+      <version>0.14.0-SNAPSHOT</version>
+    </dependency>
+
+    <!-- JBoss Cache -->
+    <dependency>
+      <groupId>org.jboss.cache</groupId>
+      <artifactId>jbosscache-core</artifactId>
+      <version>${version.org.jboss.cache_jbosscache-core}</version>
+    </dependency>
+
+    <!-- JUnit -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+</project>

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUAlgorithm.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUAlgorithm.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUAlgorithm.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,106 @@
+/*
+ * 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.ejb3.cache.impl.backing.jbc2;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.eviction.EvictionPolicy;
+import org.jboss.cache.eviction.LRUAlgorithm;
+import org.jboss.cache.lock.TimeoutException;
+import org.jboss.logging.Logger;
+
+/**
+ * LRUAlgorithm subclass that doesn't log an error if it catches
+ * {@link ContextInUseException}.
+ * 
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class AbortableLRUAlgorithm extends LRUAlgorithm
+{
+   private static final Logger log = Logger.getLogger(AbortableLRUAlgorithm.class);
+   
+   public AbortableLRUAlgorithm()
+   {
+      super();
+   }
+   
+   /**
+    * Evict a node from cache.
+    *
+    * @param fqn node corresponds to this fqn
+    * @return True if successful
+    */
+   protected boolean evictCacheNode(Fqn fqn)
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("Attempting to evict cache node with fqn of " + fqn);
+      }
+      
+      EvictionPolicy policy = region.getEvictionPolicy();
+      try
+      {
+         policy.evict(fqn);
+      }
+      catch (ContextInUseException e)
+      {
+         // Don't log it at any alarming level
+         if (log.isTraceEnabled())
+            log.trace("Eviction of " + fqn + " aborted as bean is in use");
+         return false;
+      }
+      catch (TimeoutException e)
+      {
+         log.warn("Eviction of " + fqn + " timed out, retrying later");
+         log.debug(e, e);
+         return false;
+      }
+      catch (RuntimeException e)
+      {
+         Throwable cause = e.getCause();
+         if (cause instanceof ContextInUseException)
+         {
+            // Don't log it at any alarming level
+            if (log.isTraceEnabled())
+               log.trace("Eviction of " + fqn + " aborted as bean is in use");
+            return false;            
+         }
+         log.error("Eviction of " + fqn + " failed", e);
+         return false;
+      }
+      catch (Exception e)
+      {
+         log.error("Eviction of " + fqn + " failed", e);
+         return false;
+      }
+
+      if (log.isTraceEnabled())
+      {
+         log.trace("Eviction of cache node with fqn of " + fqn + " successful");
+      }
+
+      return true;
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUPolicy.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUPolicy.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/AbortableLRUPolicy.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,42 @@
+/*
+ * 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.ejb3.cache.impl.backing.jbc2;
+
+import org.jboss.cache.eviction.LRUPolicy;
+
+/**
+ * LRUPolicy subclass with an algorithm that doesn't error log
+ * {@link ContextInUseException}.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class AbortableLRUPolicy extends LRUPolicy
+{
+   public AbortableLRUPolicy()
+   {
+      super();
+      algorithm = new AbortableLRUAlgorithm();
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ClusteredCacheListener.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,153 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.ejb3.cache.impl.backing.jbc2;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeActivated;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodePassivated;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.annotation.NodeVisited;
+import org.jboss.cache.notifications.event.NodeActivatedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodePassivatedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+import org.jboss.cache.notifications.event.NodeVisitedEvent;
+
+/**
+ * Single {@link CacheListener} that handles event Fqn parsing and then
+ * delegates to a handler that has registered for the region.  Intent is
+ * to do the region-matching work once here, rather than having multiple 
+ * listeners registered with the cache.
+ *  
+ * @author Brian Stansberry
+ */
+ at CacheListener
+public class ClusteredCacheListener
+{
+   public static interface RegionHandler
+   {
+      void nodeVisited(OwnedItem ownedItem, NodeVisitedEvent event);
+      void nodeModified(OwnedItem ownedItem, NodeModifiedEvent event);
+      void nodeRemoved(OwnedItem ownedItem, NodeRemovedEvent event);
+      void nodeActivated(OwnedItem ownedItem, NodeActivatedEvent event);
+      void nodePassivated(OwnedItem ownedItem, NodePassivatedEvent event);
+   }
+   
+   private final Map<Fqn, RegionHandler> handlers = new ConcurrentHashMap<Fqn, RegionHandler>();
+   private final boolean checkBuddy;
+   
+   public ClusteredCacheListener(boolean checkBuddy)
+   {
+      this.checkBuddy= checkBuddy;
+   }
+   
+   public void addRegionHandler(Fqn region, RegionHandler handler)
+   {
+      handlers.put(region, handler);
+   }
+   
+   public boolean removeRegionHandler(Fqn region)
+   {
+      handlers.remove(region);
+      return handlers.size() > 0;
+   }
+   
+   private RegionHandler getRegionHandler(OwnedItem oi)
+   {
+      return (oi == null ? null : handlers.get(oi.getRegion()));
+   }
+   
+   @NodeVisited
+   public void nodeVisited(NodeVisitedEvent event)
+   {
+      if (event.isPre())
+         return;
+      
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      RegionHandler handler = getRegionHandler(oi);
+      if (handler != null)
+      {
+         handler.nodeVisited(oi, event);
+      }
+   }
+   
+   @NodeModified
+   public void nodeModified(NodeModifiedEvent event)
+   {
+      if (event.isPre() || NodeModifiedEvent.ModificationType.REMOVE_DATA == event.getModificationType())
+         return;
+      
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      RegionHandler handler = getRegionHandler(oi);
+      if (handler != null)
+      {
+         handler.nodeModified(oi, event);
+      }
+   }
+   
+   @NodeRemoved
+   public void nodeRemoved(NodeRemovedEvent event)
+   {
+      // Here we only want pre as that's what lets us get the removed data
+      if (!event.isPre())
+         return; 
+      
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      RegionHandler handler = getRegionHandler(oi);
+      if (handler != null)
+      {
+         handler.nodeRemoved(oi, event);
+      }
+   }
+   
+   @NodeActivated
+   public void nodeActivated(NodeActivatedEvent event)
+   {
+      if(event.isPre()) return; 
+      
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      RegionHandler handler = getRegionHandler(oi);
+      if (handler != null)
+      {
+         handler.nodeActivated(oi, event);
+      }
+   }
+
+   @NodePassivated
+   public void nodePassivated(NodePassivatedEvent event)
+   {
+      if(event.isPre()) return;
+      
+      OwnedItem oi = OwnedItem.getOwnedItem(event.getFqn(), checkBuddy);
+      RegionHandler handler = getRegionHandler(oi);
+      if (handler != null)
+      {
+         handler.nodePassivated(oi, event);
+      }
+   }
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ContextInUseException.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ContextInUseException.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/ContextInUseException.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,56 @@
+/*
+ * 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.ejb3.cache.impl.backing.jbc2;
+
+/**
+ * Exception thrown by JBCIntegratedObjectStore if an attempt is made
+ * to passivate a bean that is currently in use.
+ * 
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1.1 $
+ */
+public class ContextInUseException extends RuntimeException
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 7731424431763921352L;
+
+   /**
+    * Create a new ContextInUseException.
+    * 
+    */
+   public ContextInUseException()
+   {
+      super();
+   }
+
+   /**
+    * Create a new ContextInUseException.
+    * 
+    * @param message
+    */
+   public ContextInUseException(String message)
+   {
+      super(message);
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStore.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,566 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.ejb3.cache.impl.backing.jbc2;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.Region;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.cache.config.BuddyReplicationConfig;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.notifications.event.NodeActivatedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodePassivatedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+import org.jboss.cache.notifications.event.NodeVisitedEvent;
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.BackingCacheEntry;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.impl.AbstractPassivatingIntegratedObjectStore;
+import org.jboss.logging.Logger;
+import org.jboss.util.id.GUID;
+
+/**
+ * JBoss Cache-based implementation of {@link PassivatingIntegratedObjectStore}.
+ * 
+ * @author Brian Stansberry
+ */
+public class JBCIntegratedObjectStore<C extends CacheItem, T extends BackingCacheEntry<C>>
+   extends AbstractPassivatingIntegratedObjectStore<C, T>
+{
+   public static final String FQN_BASE = "sfsb";
+   
+   private static final String KEY = "item";
+   
+   private static final ThreadLocal removedItem = new ThreadLocal();
+   
+   /** Depth of fqn element where we store the id. */ 
+   static final int FQN_SIZE = 4; // depth of fqn that we store the session in.
+   private static final int DEFAULT_BUCKET_COUNT = 100;
+
+   private static final String[] DEFAULT_HASH_BUCKETS = new String[DEFAULT_BUCKET_COUNT];
+
+   static
+   {
+      for (int i = 0; i < DEFAULT_HASH_BUCKETS.length; i++)
+      {
+         DEFAULT_HASH_BUCKETS[i] = String.valueOf(i);
+      }
+   }
+   
+   /** The underlying JBC instance */
+   private Cache<Object, T> jbc;
+
+   /** Qualifier used to scope our Fqns */
+   private final Object keyBase;
+
+   private Fqn<Object> cacheNode;
+   private Region region;
+   private ClusteredCacheListener listener;
+   private RegionHandlerImpl regionHandler;
+
+   public static long MarkInUseWaitTime = 15000;
+
+   private final ThreadLocal<Boolean> localActivity = new ThreadLocal<Boolean>();
+   private final Logger log;
+   private String[] hashBuckets = DEFAULT_HASH_BUCKETS;
+   private int createCount = 0;
+   private int passivatedCount = 0;
+   private int removeCount = 0;
+   private boolean usingBuddyRepl;
+   private boolean trackVisits;
+   
+   private final ConcurrentMap<OwnedItem, Long> inMemoryItems;
+   private final ConcurrentMap<OwnedItem, Long> passivatedItems;
+   
+   public JBCIntegratedObjectStore(Cache jbc, 
+                                   CacheConfig cacheConfig, 
+                                   Object keyBase,
+                                   String name,
+                                   boolean forGroups)
+   {     
+      super(cacheConfig, name, forGroups);
+      
+      assert jbc != null : "jbc is null";
+      assert keyBase != null : "keyBase is null";
+      
+      this.jbc = jbc;
+      this.keyBase = keyBase;
+
+      this.log = Logger.getLogger(getClass().getName() + "." + name);
+      this.cacheNode = new Fqn<Object>(new Object[] { FQN_BASE, this.keyBase });
+      BuddyReplicationConfig brc = jbc.getConfiguration().getBuddyReplicationConfig();
+      this.usingBuddyRepl = brc != null && brc.isEnabled();
+      
+      this.inMemoryItems = new ConcurrentHashMap<OwnedItem, Long>();
+      this.passivatedItems = new ConcurrentHashMap<OwnedItem, Long>();
+   }
+
+//   private EvictionPolicyConfig getEvictionPolicyConfig()
+//   {
+//      LRUConfiguration epc = new LRUConfiguration();
+//      // Override the standard policy class
+//      epc.setEvictionPolicyClass(AbortableLRUPolicy.class.getName());
+//      epc.setTimeToLiveSeconds((int) getIdleTimeSeconds());
+//      epc.setMaxNodes(getMaxSize());
+//      return epc;
+//   }
+
+   public boolean isClustered()
+   {
+      return jbc.getConfiguration().getCacheMode() != Configuration.CacheMode.LOCAL;
+   }
+
+   public T get(Object key)
+   {
+      T entry = null;
+      Fqn<Object> id = getFqn(key, false);
+      Boolean active = localActivity.get();
+      try
+      {
+         localActivity.set(Boolean.TRUE);
+         // If need be, gravitate
+         if (usingBuddyRepl)
+         {
+            jbc.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
+         }
+         entry = (T) jbc.get(id, KEY);
+      }
+      catch (CacheException e)
+      {
+         RuntimeException re = convertToRuntimeException(e);
+         throw re;
+      }
+      finally
+      {
+         localActivity.set(active);
+      }
+
+      if(log.isTraceEnabled())
+      {
+         log.trace("get: retrieved bean with cache id " +id.toString());
+      }
+
+      return entry;
+   }
+
+   public void insert(T entry)
+   {
+      try
+      {
+         putInCache(entry);
+      }
+      catch (CacheException e)
+      {
+         RuntimeException re = convertToRuntimeException(e);
+         throw re;
+      }
+   }
+
+   public void passivate(T entry)
+   {
+      Fqn<Object> id = getFqn(entry.getId(), false);
+      jbc.evict(id);
+   }
+
+   public T remove(Object key)
+   {
+      Fqn<Object> id = getFqn(key, false);
+      try
+      {
+         if(log.isTraceEnabled())
+         {
+            log.trace("remove: cache id " +id.toString());
+         }
+         
+         if (usingBuddyRepl)
+         {
+            jbc.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
+         }
+         jbc.removeNode(id);
+
+         // Hack! Our cache listener has access to the removed node's data map
+         // so it passes the removed item to us via a thread local.
+         // Otherwise we'd have to do a remove(id, KEY) followed by removeNode(id)
+         T removed = (T) removedItem.get();
+         removedItem.set(null);
+         
+         ++removeCount;
+         
+         return removed;
+      }
+      catch (CacheException e)
+      {
+         RuntimeException re = convertToRuntimeException(e);
+         throw re;
+      }
+   }
+
+   public void update(T entry)
+   {
+      try
+      {
+         putInCache(entry);
+      }
+      catch (CacheException e)
+      {
+         RuntimeException re = convertToRuntimeException(e);
+         throw re;
+      }
+   }
+
+   public void start()
+   {      
+      region = jbc.getRegion(cacheNode, true);
+      // Try to create an eviction region per ejb
+      // BES 2008/03/12 No, let's handle passivation ourselves
+      // since JBC doesn't properly track the buddy-backup region
+//      EvictionPolicyConfig epc = getEvictionPolicyConfig();
+//      region.setEvictionPolicy(epc);
+
+      // JBCACHE-1136.  There's no reason to have state in an inactive region
+      cleanBeanRegion();
+
+      // Transfer over the state for the region
+      region.registerContextClassLoader(Thread.currentThread().getContextClassLoader());
+      region.activate();
+      
+      // register to listen for cache events
+
+      for (Object listener : jbc.getCacheListeners())
+      {
+         if (listener instanceof ClusteredCacheListener)
+         {
+            this.listener = (ClusteredCacheListener) listener;
+            break;
+         }
+      }
+      if (listener == null)
+      {
+         listener = new ClusteredCacheListener(usingBuddyRepl);
+         jbc.addCacheListener(listener);
+      }
+      
+      regionHandler = new RegionHandlerImpl();
+      listener.addRegionHandler(cacheNode, regionHandler);
+      
+      initializeTrackingMaps();
+      
+      super.start();
+   }
+
+   private void initializeTrackingMaps()
+   {      
+      // First the main tree
+      Node<Object, T> parent = jbc.getNode(cacheNode);
+      analyzeRegionContent(parent);
+     
+      // Now any buddy regions
+      if (usingBuddyRepl)
+      {
+         Node<Object, T> bbRoot = jbc.getNode(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
+         if (bbRoot != null)
+         {
+            for (Node<Object, T> bbRegion : bbRoot.getChildren())
+            {
+               Node<Object, T> ourPart = bbRegion.getChild(cacheNode);
+               if (ourPart != null)
+               {
+                  analyzeRegionContent(ourPart);
+               }
+            }
+         }
+      }
+      
+      // Now, we know any node visits will be from users, so
+      // lets start monitoring them
+      trackVisits = true;
+   }
+
+   private void analyzeRegionContent(Node<Object, T> parent)
+   {
+      for (int i = 0; i < hashBuckets.length; i++)
+      {
+         Node<Object, T> bucket = parent.getChild(hashBuckets[i]);
+         if (bucket == null)
+            continue;
+         Set<Object> childrenNames = bucket.getChildrenNames();
+         for (Object name : childrenNames)
+         {
+            Node<Object, T> child = bucket.getChild(name);
+            if (child == null)
+               continue;
+            T entry = (T) child.get(KEY);
+            if (entry != null)
+            {
+               OwnedItem oi = OwnedItem.getOwnedItem(child.getFqn(), usingBuddyRepl);
+               if (entry.isPrePassivated())
+               {
+                  jbc.evict(child.getFqn()); // we'll get a listener event for this
+               }
+               else
+               {
+                  long lastUsed = (entry.getLastUsed() == 0) ? System.currentTimeMillis() : entry.getLastUsed();
+                  // Use putIfAbsent so we don't overwrite listener events
+                  inMemoryItems.putIfAbsent(oi, lastUsed);
+               }
+            }
+         }
+      }
+   }
+   
+   public void stop()
+   {
+      // FIXME get the proper ordering vis-a-vis stopping the timeout runner
+      
+      if (jbc != null)
+      {
+         // Remove the listener
+         if (listener != null && regionHandler != null && listener.removeRegionHandler(cacheNode))
+            jbc.removeCacheListener(listener);
+
+         // Remove locally. We do this to clean up the persistent store,
+         // which is not affected by the inactivateRegion call below.
+         cleanBeanRegion();
+
+         try {
+            // Remove locally. We do this to clean up the persistent store,
+            // which is not affected by the region.deactivate call below.
+            jbc.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+            jbc.removeNode(cacheNode);
+         }
+         catch (CacheException e)
+         {
+            log.error("stop(): can't remove bean from the underlying distributed cache");
+         }
+
+         if (region != null)
+         {
+            region.deactivate();
+            region.unregisterContextClassLoader();
+
+            jbc.removeRegion(region.getFqn());
+            // Clear any queues
+            region.resetEvictionQueues();
+            region = null;
+         }
+      }
+      
+      inMemoryItems.clear();
+      passivatedItems.clear();
+      
+      super.stop();
+   }
+
+   public int getCacheSize()
+   {
+      int count = 0;
+      try
+      {
+         Set<Object> children = null;
+         for (int i = 0; i < hashBuckets.length; i++)
+         {
+            Node<Object, T> node = jbc.getRoot().getChild(new Fqn<Object>(cacheNode, hashBuckets[i]));
+            if (node != null)
+            {
+               children = node.getChildrenNames();
+               count += (children == null ? 0 : children.size());
+            }
+         }
+         count = count - passivatedCount;
+      }
+      catch (CacheException e)
+      {
+         log.error("Caught exception calculating cache size", e);
+         count = -1;
+      }
+      return count;
+   }
+
+   public int getTotalSize()
+   {
+      return inMemoryItems.size() + passivatedItems.size();
+   }
+
+   public int getCreateCount()
+   {
+       return createCount;
+   }
+
+   public int getPassivatedCount()
+   {
+       return passivatedItems.size();
+   }
+
+   public int getRemoveCount()
+   {
+      return removeCount;
+   }
+
+   public int getAvailableCount()
+   {
+      return -1;
+   }
+
+   public int getCurrentSize()
+   {
+      return inMemoryItems.size();
+   }
+
+   @Override
+   protected void runExpiration()
+   {
+      throw new UnsupportedOperationException("implement me");
+   }
+
+   @Override
+   protected void runPassivation()
+   {
+      throw new UnsupportedOperationException("implement me");      
+   }
+
+   private Fqn<Object> getFqn(Object id, boolean regionRelative)
+   {
+      String beanId = id.toString();
+      int index;
+      if (id instanceof GUID)
+      {
+         index = (id.hashCode()& 0x7FFFFFFF) % hashBuckets.length;
+      }
+      else
+      {
+         index = (beanId.hashCode()& 0x7FFFFFFF) % hashBuckets.length;
+      }
+
+      if (regionRelative)
+         return new Fqn<Object>( new Object[] {hashBuckets[index], beanId} );
+      else
+         return new Fqn<Object>(cacheNode, hashBuckets[index], beanId);
+   }
+
+   /**
+    * Creates a RuntimeException, but doesn't pass CacheException as the cause
+    * as it is a type that likely doesn't exist on a client.
+    * Instead creates a RuntimeException with the original exception's
+    * stack trace.
+    */
+   private RuntimeException convertToRuntimeException(CacheException e)
+   {
+      RuntimeException re = new RuntimeException(e.getClass().getName() + " " + e.getMessage());
+      re.setStackTrace(e.getStackTrace());
+      return re;
+   }
+
+   private void cleanBeanRegion()
+   {
+      try {
+         // Remove locally.
+         jbc.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+         jbc.removeNode(cacheNode);
+      }
+      catch (CacheException e)
+      {
+         log.error("Can't clean region " + cacheNode + " in the underlying distributed cache", e);
+      }
+   }
+
+   private void putInCache(T entry)
+   {
+      Boolean active = localActivity.get();
+      try
+      {
+         localActivity.set(Boolean.TRUE);
+         jbc.put(getFqn(entry.getId(), false), KEY, entry);
+      }
+      finally
+      {
+         localActivity.set(active);
+      }
+   }
+
+   /**
+    * A CacheListener that allows us to get notifications of passivations and
+    * activations and thus notify the cached StatefulBeanContext.
+    */
+   public class RegionHandlerImpl implements ClusteredCacheListener.RegionHandler
+   {
+      public void nodeVisited(OwnedItem oi, NodeVisitedEvent event)
+      {
+         if (trackVisits)
+            inMemoryItems.put(oi, System.currentTimeMillis());         
+      }
+      
+      public void nodeModified(OwnedItem oi, NodeModifiedEvent event)
+      {
+         T entry = (T) event.getData().get(KEY);
+         if (entry != null)
+         {
+            long lastUsed = entry.getLastUsed();
+            lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
+            inMemoryItems.put(oi, lastUsed);
+         }       
+      }
+      
+      public void nodeRemoved(OwnedItem oi, NodeRemovedEvent event)
+      {
+         inMemoryItems.remove(oi);
+         passivatedItems.remove(oi);
+         
+         // Hack! We have access to the data map here; so pass the removed
+         // item to our remove() method via a thread local
+         removedItem.set(event.getData().get(KEY));
+      }
+      
+      public void nodeActivated(OwnedItem oi, NodeActivatedEvent event)
+      {
+         T entry = (T) event.getData().get(KEY);
+         if (entry != null)
+         {
+            long lastUsed = entry.getLastUsed();
+            lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
+            inMemoryItems.put(oi, lastUsed);
+            passivatedItems.remove(oi);
+         }        
+      }
+
+      public void nodePassivated(OwnedItem oi, NodePassivatedEvent event)
+      {
+         T entry = (T) event.getData().get(KEY);
+         if (entry != null)
+         {
+            long lastUsed = entry.getLastUsed();
+            lastUsed = (lastUsed == 0 ? System.currentTimeMillis() : lastUsed);
+            passivatedItems.put(oi, lastUsed);
+            inMemoryItems.remove(oi);
+         } 
+      }
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStoreSource.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStoreSource.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/JBCIntegratedObjectStoreSource.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.ejb3.cache.impl.backing.jbc2;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheManager;
+import org.jboss.ejb3.annotation.CacheConfig;
+import org.jboss.ejb3.cache.CacheItem;
+import org.jboss.ejb3.cache.spi.IntegratedObjectStoreSource;
+import org.jboss.ejb3.cache.spi.PassivatingIntegratedObjectStore;
+import org.jboss.ejb3.cache.spi.SynchronizationCoordinator;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupImpl;
+import org.jboss.ejb3.cache.spi.impl.SerializationGroupMember;
+
+/**
+ * {@link IntegratedObjectStoreSource} that provides instances of
+ * {@link JBCIntegratedObjectStore}.
+ * 
+ * @author Brian Stansberry
+ */
+public class JBCIntegratedObjectStoreSource<T extends CacheItem> 
+   implements IntegratedObjectStoreSource<T>
+{
+   private CacheManager cacheManager;
+   
+   public PassivatingIntegratedObjectStore<T, SerializationGroupImpl<T>>  createGroupIntegratedObjectStore(String containerName,
+         String cacheConfigName, CacheConfig cacheConfig, TransactionManager transactionManager, SynchronizationCoordinator synchronizationCoordinator)
+   {
+      Cache<Object, Object> jbc = getJBossCache(cacheConfigName);
+      
+      String keyBaseSuffix = (containerName == null || containerName.length() == 0) ? "" : "-" + containerName;
+      String keyBase = "GroupCache" + keyBaseSuffix;
+      return new JBCIntegratedObjectStore<T, SerializationGroupImpl<T>>(jbc, cacheConfig, keyBase, keyBase, true);
+   }
+
+   public PassivatingIntegratedObjectStore<T, SerializationGroupMember<T>>  createIntegratedObjectStore(String containerName, String cacheConfigName,
+         CacheConfig cacheConfig, TransactionManager transactionManager, SynchronizationCoordinator synchronizationCoordinator)
+   {
+      Cache<Object, Object> jbc = getJBossCache(cacheConfigName);
+      
+      return new JBCIntegratedObjectStore<T, SerializationGroupMember<T>>(jbc, cacheConfig, containerName, containerName, false);
+   }
+
+   public CacheManager getCacheManager()
+   {
+      return cacheManager;
+   }
+
+   public void setCacheManager(CacheManager cacheManager)
+   {
+      this.cacheManager = cacheManager;
+   }
+   
+   private Cache<Object, Object> getJBossCache(String cacheConfigName)
+   {
+      if (cacheManager == null)
+         throw new IllegalStateException("CacheManager not installed");
+      
+      try
+      {
+         return cacheManager.getCache(cacheConfigName, true);
+      }
+      catch (RuntimeException re)
+      {
+         throw re;
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException("Unable to get cache " + cacheConfigName, e);
+      }
+   }
+
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/main/java/org/jboss/ejb3/cache/impl/backing/jbc2/OwnedItem.java	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, 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.ejb3.cache.impl.backing.jbc2;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.buddyreplication.BuddyManager;
+import org.jboss.ejb3.cache.CacheItem;
+
+/**
+ * Encapsulates the identifier for a {@link CacheItem} as well as information
+ * about what node logical "owns" it.
+ * 
+ * @author Brian Stansberry
+ */
+public class OwnedItem
+{
+   private static final int FQN_SIZE = JBCIntegratedObjectStore.FQN_SIZE;
+   private static final int KEY_INDEX = FQN_SIZE - 1;
+   private static final int OWNER_INDEX = 1;
+   private static final int BR_FQN_SIZE = FQN_SIZE + OWNER_INDEX + 1;
+   private static final int BR_KEY_INDEX = BR_FQN_SIZE - 1;
+   
+   private final String owner;
+   private final Object id;
+   private final Fqn region;
+   
+   /**
+    * Generates an OwnedItem from the given Fqn if the Fqn is a logical
+    * child of <code>base</code>
+    * 
+    * @param fqn  the Fqn
+    * @param base the base Fqn
+    * @param checkBuddy <code>true</code> if it is possible that <code>fqn</code>
+    *                   belongs to a {@link BuddyManager#BUDDY_BACKUP_SUBTREE_FQN buddy-backup subtree}
+    *                   
+    * @return an OwnedItem or <code>null</code> if <code>fqn</code> is not a
+    *         logical child of <code>base</code>
+    */
+   @SuppressWarnings("unchecked")
+   public static OwnedItem getOwnedItem(Fqn fqn, boolean checkBuddy)
+   {
+      int size = fqn.size();
+      if (size < FQN_SIZE)
+         return null;
+      
+      String owner = null;
+      Object key = null;
+      Fqn region = null;
+      
+      boolean buddy = checkBuddy && fqn.get(0).equals(BuddyManager.BUDDY_BACKUP_SUBTREE);
+      if (buddy)
+      { 
+         if (size == BR_FQN_SIZE)
+         {
+            key = fqn.get(BR_KEY_INDEX);
+            owner = (String) fqn.get(OWNER_INDEX);
+            region = fqn.getSubFqn(OWNER_INDEX, BR_KEY_INDEX);
+         }
+      }
+      else if (size == FQN_SIZE)
+      {
+         region = fqn.getParent();
+         key = fqn.get(KEY_INDEX);
+      }
+      
+      return (key == null ? null : new OwnedItem(owner, key, region));
+   }
+   
+   public OwnedItem(String owner, Object id, Fqn region)
+   {
+      assert id != null : "id is null";
+      assert region != null : "region is null";
+      
+      this.owner = owner;
+      this.id = id;
+      this.region = region;
+   }
+   
+   /**
+    * Gets the logical "owner" of the item.  A value of <code>null</code>
+    * means either there is no logical owner or this process is the owner.
+    * (Basically it means the item is stored in the main area of a JBoss CAche
+    * tree, not in a named buddy-backup region.)
+    * 
+    * @return
+    */
+   public String getOwner()
+   {
+      return owner;
+   }
+
+   /**
+    * Gets the item's unique identifier.
+    */
+   public Object getId()
+   {
+      return id;
+   }
+   
+   /**
+    * Gets the base Fqn for the region where the item is cached.
+    */
+   public Fqn getRegion()
+   {
+      return region;
+   }
+   
+   public Fqn getFullFqn()
+   {
+      if (owner != null)
+      {
+         Fqn ownerFqn = new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, owner);
+         Fqn base = new Fqn(ownerFqn, region);
+         return new Fqn(base, id);
+      }
+      else
+      {
+         return new Fqn(region, id);
+      }
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      
+      if (obj instanceof OwnedItem)
+      {
+         OwnedItem other = (OwnedItem) obj;
+         return (id.equals(other.id) && safeEquals(owner, other.owner));
+      }
+      return false;
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      int result = 17;
+      result += 31 * id.hashCode();
+      result += 31 * (owner == null ? 0 : owner.hashCode());
+      return result;
+   }
+   
+   @Override
+   public String toString()
+   {
+      return new StringBuilder(getClass().getName())
+                               .append("[id=")
+                               .append(id)
+                               .append(",owner=")
+                               .append(owner)
+                               .append(",region=")
+                               .append(region)
+                               .append("]")
+                               .toString();
+   }
+   
+   private static boolean safeEquals(Object a, Object b)
+   {
+      return (a == b || (a != null && a.equals(b)));
+   }
+   
+}

Added: projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/resources/log4j.xml
===================================================================
--- projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/resources/log4j.xml	                        (rev 0)
+++ projects/ejb3/branches/cluster-dev/cache-jbc2/src/test/resources/log4j.xml	2008-03-13 03:27:01 UTC (rev 70798)
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  Log4j Configuration                                                  -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<!-- $Id: log4j.xml 65339 2007-09-12 16:21:48Z wolfc $ -->
+
+<!--
+   | For more configuration infromation and examples see the Jakarta Log4j
+   | owebsite: http://jakarta.apache.org/log4j
+ -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+  <!-- ================================= -->
+  <!-- Preserve messages in a local file -->
+  <!-- ================================= -->
+
+  <!-- A time/date based rolling appender -->
+  <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
+    <param name="File" value="target/test.log"/>
+    <param name="Append" value="false"/>
+
+    <!-- Rollover at midnight each day -->
+    <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+
+    <!-- Rollover at the top of each hour
+    <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
+    -->
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <!-- The default pattern: Date Priority [Category] Message\n -->
+      <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+
+      <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
+      <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
+       -->
+    </layout>	    
+  </appender>
+
+  <!-- A size based file rolling appender
+  <appender name="FILE" class="org.jboss.logging.appender.RollingFileAppender">
+    <param name="File" value="${jboss.server.home.dir}/log/server.log"/>
+    <param name="Append" value="false"/>
+    <param name="MaxFileSize" value="500KB"/>
+    <param name="MaxBackupIndex" value="1"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+    </layout>	    
+  </appender>
+  -->
+
+  <!-- ============================== -->
+  <!-- Append messages to the console -->
+  <!-- ============================== -->
+
+  <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+    <!--param name="Threshold" value="FATAL"/-->
+    <param name="Target" value="System.out"/>
+
+    <layout class="org.apache.log4j.PatternLayout">
+      <!-- The default pattern: Date Priority [Category] Message\n -->
+      <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+    </layout>
+  </appender>
+
+
+  <!-- ====================== -->
+  <!-- More Appender examples -->
+  <!-- ====================== -->
+
+  <!-- Buffer events and log them asynchronously
+  <appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
+    <appender-ref ref="FILE"/>
+    <appender-ref ref="CONSOLE"/>
+  </appender>
+  -->
+
+  <!-- EMail events to an administrator
+  <appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
+    <param name="Threshold" value="ERROR"/>
+    <param name="To" value="admin at myhost.domain.com"/>
+    <param name="From" value="nobody at myhost.domain.com"/>
+    <param name="Subject" value="JBoss Sever Errors"/>
+    <param name="SMTPHost" value="localhost"/>
+    <param name="BufferSize" value="10"/>
+  </appender>
+  -->
+
+  <!-- Syslog events
+  <appender name="SYSLOG" class="org.apache.log4j.net.SyslogAppender">
+    <param name="Facility" value="LOCAL7"/>
+    <param name="FacilityPrinting" value="true"/>
+    <param name="SyslogHost" value="localhost"/>
+  </appender>
+  -->
+
+  <!-- Log events to JMS (requires a topic to be created)
+  <appender name="JMS" class="org.apache.log4j.net.JMSAppender">
+    <param name="Threshold" value="ERROR"/>
+    <param name="TopicConnectionFactoryBindingName" value="java:/ConnectionFactory"/>
+    <param name="TopicBindingName" value="topic/MyErrorsTopic"/>
+  </appender>
+  -->
+
+  <!-- ================ -->
+  <!-- Limit categories -->
+  <!-- ================ -->
+
+  <!-- Limit JBoss categories to INFO -->
+  <category name="org.jboss">
+    <priority value="INFO" class="org.jboss.logging.XLevel"/>
+  </category>
+
+  <!-- Increase the priority threshold for the DefaultDS category
+  <category name="DefaultDS">
+    <priority value="FATAL"/>
+  </category>
+  -->
+
+  <!-- Decrease the priority threshold for the org.jboss.varia category
+  <category name="org.jboss.varia">
+    <priority value="DEBUG"/>
+  </category>
+  -->
+
+  <!--
+     | An example of enabling the custom TRACE level priority that is used
+     | by the JBoss internals to diagnose low level details. This example
+     | turns on TRACE level msgs for the org.jboss.ejb.plugins package and its
+     | subpackages. This will produce A LOT of logging output.
+  <category name="org.jboss.system">
+    <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+  </category>
+  -->
+
+  <category name="org.jboss.security">
+    <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+  </category>
+
+  <category name="org.jboss.tm">
+    <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+  </category>
+  
+  <category name="org.jboss.ejb3">
+    <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+  </category>
+  
+  <!-- ======================= -->
+  <!-- Setup the Root category -->
+  <!-- ======================= -->
+
+  <root>
+    <appender-ref ref="CONSOLE"/>
+    <appender-ref ref="FILE"/>
+  </root>
+  
+</log4j:configuration>




More information about the jboss-cvs-commits mailing list