[jbosscache-commits] JBoss Cache SVN: r6109 - in pojo/tags: 2.2.0.CR1 and 9 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Fri Jun 27 18:03:18 EDT 2008


Author: jason.greene at jboss.com
Date: 2008-06-27 18:03:17 -0400 (Fri, 27 Jun 2008)
New Revision: 6109

Added:
   pojo/tags/2.2.0.CR1/
   pojo/tags/2.2.0.CR1/pom.xml
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java
   pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java
Removed:
   pojo/tags/2.2.0.CR1/pom.xml
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Attach.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/CheckIdValidity.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Detach.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Find.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Reentrant.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Tx.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/TxUndo.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckIdInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckNonSerializableInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/MethodReentrancyStopperInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoBeginInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoEventInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoFailedTxMockupInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxLockInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoSynchronizationInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/StaticFieldInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java
   pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java
   pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java
   pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java
Log:
Tag 2.2.0.CR1


Copied: pojo/tags/2.2.0.CR1 (from rev 6047, pojo/trunk)

Deleted: pojo/tags/2.2.0.CR1/pom.xml
===================================================================
--- pojo/trunk/pom.xml	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/pom.xml	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,337 +0,0 @@
-<?xml version="1.0"?>
-<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/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <properties>
-    <jbosscache-pojo-version>2.2.0-SNAPSHOT</jbosscache-pojo-version>
-    <jbosscache-core-version>2.2.0.CR4</jbosscache-core-version>
-    <jboss.aop.version>2.0.0-SNAPSHOT</jboss.aop.version>
-  </properties>
-  <parent>
-    <groupId>org.jboss.cache</groupId>
-    <artifactId>jbosscache-common-parent</artifactId>
-    <version>1.1</version>
-  </parent>
-  <groupId>org.jboss.cache</groupId>
-  <artifactId>jbosscache-pojo</artifactId>
-  <version>${jbosscache-pojo-version}</version>
-  <name>JBoss Cache - POJO Edition</name>
-  <description>JBoss Cache - POJO Edition</description>
-  <packaging>jar</packaging>
-  <dependencies>
-    <dependency>
-      <groupId>org.jboss.aop</groupId>
-      <artifactId>jboss-aop</artifactId>
-      <version>${jboss.aop.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jboss.cache</groupId>
-      <artifactId>jbosscache-core</artifactId>
-      <version>${jbosscache-core-version}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jboss.cache</groupId>
-      <artifactId>jbosscache-core</artifactId>
-      <version>${jbosscache-core-version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-      <version>1.0.4</version>
-    </dependency>
-    <dependency>
-       <groupId>net.jcip</groupId>
-       <artifactId>jcip-annotations</artifactId>
-       <version>1.0</version>
-       <optional>true</optional>
-    </dependency>
-  </dependencies>
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <executions>
-          <execution>
-            <phase>package</phase>
-            <goals>
-              <goal>javadoc</goal>
-            </goals>
-            <configuration>
-              <aggregate>${jbosscache.reports.aggregate}</aggregate>
-              <links>
-                <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
-                <link>http://java.sun.com/javaee/5/docs/api/</link>
-                <link>http://labs.jboss.org/file-access/default/members/jbosscache/freezone/docs/2.1.0.GA/apidocs/</link>
-              </links>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    <plugin>
-        <artifactId>maven-assembly-plugin</artifactId>
-        <version>2.2-beta-1</version>
-        <executions>
-          <execution>
-            <id>assemble</id>
-            <phase>install</phase>
-            <goals>
-              <goal>attached</goal>
-            </goals>
-            <configuration>
-              <descriptors>
-                <descriptor>assembly/bin.xml</descriptor>
-                <descriptor>assembly/doc.xml</descriptor>
-                <descriptor>assembly/all.xml</descriptor>
-              </descriptors>
-              <finalName>${artifactId}-${jbosscache-pojo-version}</finalName>
-              <outputDirectory>target/distribution</outputDirectory>
-              <workDirectory>target/assembly/work</workDirectory>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.3</version>
-        <configuration>
-          <systemProperties>
-            <property>
-              <name>bind.address</name>
-              <value>127.0.0.1</value>
-            </property>
-            <property>
-              <name>java.net.preferIPv4Stack</name>
-              <value>true</value>
-            </property>
-            <property>
-              <name>jgroups.stack</name>
-              <value>udp</value>
-            </property>
-          </systemProperties>
-          <groups>functional</groups>
-          <forkMode>always</forkMode>
-          <argLine>-Djboss.aop.path=${basedir}/src/main/resources/META-INF/pojocache-aop.xml -javaagent:${settings.localRepository}/org/jboss/aop/jboss-aop/${jboss.aop.version}/jboss-aop-${jboss.aop.version}.jar</argLine>
-          <!-- Warning, this does not work right on 2.4-SNAPSHOT, (see SUREFIRE-349) -->
-          <!-- This seems to fail in some cases on 2.3 as well, disable for now -->
-          <useSystemClassLoader>true</useSystemClassLoader>
-          <redirectTestOutputToFile>false</redirectTestOutputToFile>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.jboss.maven.plugins</groupId>
-        <artifactId>maven-jbossaop-plugin</artifactId>
-        <version>1.0.0-SNAPSHOT</version>
-        <!-- HACK: AOP project and plugin has broken deps -->
-        <dependencies>    
-          <dependency>
-            <groupId>commons-logging</groupId>
-            <artifactId>commons-logging</artifactId>
-            <version>1.0.4</version>
-          </dependency>
-          <dependency>
-            <groupId>org.jboss.cache</groupId>
-            <artifactId>jbosscache-core</artifactId>
-            <version>${jbosscache-core-version}</version>
-          </dependency>
-          <dependency>
-            <groupId>org.jboss.aop</groupId>
-            <artifactId>jboss-aop</artifactId>
-            <version>${jboss.aop.version}</version>
-          </dependency>
-        </dependencies> 
-        <executions>
-          <execution>
-            <id>aopc</id>
-            <phase>compile</phase>
-            <goals>
-              <goal>compile</goal>
-            </goals>
-            <configuration>
-              <verbose>false</verbose>
-              <aoppaths>
-              <aoppath>${basedir}/src/main/resources/META-INF/pojocache-aop.xml</aoppath>
-              </aoppaths>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-      <!-- the docbook generation plugin for the user guide -->
-      <plugin>
-        <groupId>org.jboss.maven.plugins</groupId>
-        <artifactId>maven-jdocbook-plugin</artifactId>
-        <version>2.0.0</version>
-        <extensions>true</extensions>
-        <dependencies>
-            <dependency>
-               <groupId>org.jboss</groupId>
-               <artifactId>jbossorg-docbook-xslt</artifactId>
-               <version>1.0.0</version>
-            </dependency>
-            <dependency>
-               <groupId>org.jboss</groupId>
-               <artifactId>jbossorg-jdocbook-style</artifactId>
-               <version>1.0.0</version>
-               <type>jdocbook-style</type>
-            </dependency>
-           <dependency>
-                  <groupId>com.uwyn</groupId>
-                  <artifactId>jhighlight</artifactId>
-                  <version>1.0</version>
-              </dependency>
-              <dependency>
-                  <groupId>de.java2html</groupId>
-                  <artifactId>java2html</artifactId>
-                  <version>5.0</version>
-              </dependency>
-              <dependency>
-                  <groupId>org.richfaces.docs</groupId>
-                  <artifactId>highlight</artifactId>
-                  <version>3.1.4.GA</version>
-              </dependency>
-         </dependencies>
-        <executions>
-
-          <!-- The User Guide-->
-          <execution>
-            <id>userguide_en</id>
-            <phase>package</phase>
-            <goals>
-              <goal>resources</goal>
-              <goal>generate</goal>
-            </goals>
-            <configuration>
-              <sourceDocumentName>master.xml</sourceDocumentName>
-              <sourceDirectory>${basedir}/src/main/docbook/userguide/en</sourceDirectory>
-              <imageResource>
-                <directory>${basedir}/src/main/docbook/images</directory>
-              </imageResource>
-              <cssResource>
-                <directory>${basedir}/src/main/docbook/css</directory>
-              </cssResource>
-              <targetDirectory>${basedir}/target/docbook/userguide_en</targetDirectory>
-              <formats>
-                <format>
-                  <formatName>pdf</formatName>
-				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
-                  <finalName>userguide_en.pdf</finalName>
-                </format>
-				<format>
-                	<formatName>html</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-				<format>
-					<formatName>html_single</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-			  </formats>
-              <options>
-                <xincludeSupported>false</xincludeSupported>
-              </options>
-            </configuration>
-          </execution>
-
-          <!-- The Tutorial -->
-          <execution>
-            <id>tutorial_en</id>
-            <phase>package</phase>
-            <goals>
-              <goal>resources</goal>
-              <goal>generate</goal>
-            </goals>
-            <configuration>
-              <sourceDocumentName>master.xml</sourceDocumentName>
-              <sourceDirectory>${basedir}/src/main/docbook/tutorial/en</sourceDirectory>
-              <imageResource>
-                <directory>${basedir}/src/main/docbook/images</directory>
-              </imageResource>
-              <cssResource>
-                <directory>${basedir}/src/main/docbook/css</directory>
-              </cssResource>
-              <targetDirectory>${basedir}/target/docbook/tutorial_en</targetDirectory>
-              <formats>
-                <format>
-                  <formatName>pdf</formatName>
-				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
-                  <finalName>tutorial_en.pdf</finalName>
-                </format>
-				<format>
-                	<formatName>html</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-				<format>
-					<formatName>html_single</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-              </formats>
-              <options>
-                <xincludeSupported>false</xincludeSupported>
-              </options>
-            </configuration>
-          </execution>
-
-          <!-- the FAQs -->
-          <execution>
-            <id>faq_en</id>
-            <phase>package</phase>
-            <goals>
-              <goal>resources</goal>
-              <goal>generate</goal>
-            </goals>
-            <configuration>
-              <sourceDocumentName>master.xml</sourceDocumentName>
-              <sourceDirectory>${basedir}/src/main/docbook/faq/en</sourceDirectory>
-              <imageResource>
-                <directory>${basedir}/src/main/docbook/images</directory>
-              </imageResource>
-              <cssResource>
-                <directory>${basedir}/src/main/docbook/css</directory>
-              </cssResource>
-              <targetDirectory>${basedir}/target/docbook/faq_en</targetDirectory>
-              <formats>
-                <format>
-                  <formatName>pdf</formatName>
-				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
-                  <finalName>faq_en.pdf</finalName>
-                </format>
-				<format>
-                	<formatName>html</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-				<format>
-					<formatName>html_single</formatName>
-				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
-				    <finalName>index.html</finalName>
-				</format>
-              </formats>
-              <options>
-                <xincludeSupported>false</xincludeSupported>
-              </options>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-  <!-- basic JBoss repository so that the common parent POM in jbosscache-support can be found -->
-  <repositories>
-    <repository>
-      <id>snapshots.jboss.org</id>
-      <url>http://snapshots.jboss.org/maven2</url>
-    </repository>
-    <repository>
-      <id>repository.jboss.org</id>
-      <url>http://repository.jboss.org/maven2</url>
-    </repository>
-  </repositories>
-</project>

Copied: pojo/tags/2.2.0.CR1/pom.xml (from rev 6108, pojo/trunk/pom.xml)
===================================================================
--- pojo/tags/2.2.0.CR1/pom.xml	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/pom.xml	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,299 @@
+<?xml version="1.0"?>
+<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/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <properties>
+    <jbosscache-pojo-version>2.2.0.CR1</jbosscache-pojo-version>
+    <jbosscache-core-version>2.2.0.CR5</jbosscache-core-version>
+    <jboss.aop.version>2.0.0.CR14</jboss.aop.version>
+  </properties>
+  <parent>
+    <groupId>org.jboss.cache</groupId>
+    <artifactId>jbosscache-common-parent</artifactId>
+    <version>1.1</version>
+  </parent>
+  <groupId>org.jboss.cache</groupId>
+  <artifactId>jbosscache-pojo</artifactId>
+  <version>${jbosscache-pojo-version}</version>
+  <name>JBoss Cache - POJO Edition</name>
+  <description>JBoss Cache - POJO Edition</description>
+  <packaging>jar</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.jboss.aop</groupId>
+      <artifactId>jboss-aop</artifactId>
+      <version>${jboss.aop.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.cache</groupId>
+      <artifactId>jbosscache-core</artifactId>
+      <version>${jbosscache-core-version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.cache</groupId>
+      <artifactId>jbosscache-core</artifactId>
+      <version>${jbosscache-core-version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+      <version>1.0.4</version>
+    </dependency>
+    <dependency>
+       <groupId>net.jcip</groupId>
+       <artifactId>jcip-annotations</artifactId>
+       <version>1.0</version>
+       <optional>true</optional>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>javadoc</goal>
+            </goals>
+            <configuration>
+              <aggregate>${jbosscache.reports.aggregate}</aggregate>
+              <links>
+                <link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
+                <link>http://java.sun.com/javaee/5/docs/api/</link>
+                <link>http://labs.jboss.org/file-access/default/members/jbosscache/freezone/docs/2.1.0.GA/apidocs/</link>
+              </links>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <version>2.2-beta-1</version>
+        <executions>
+          <execution>
+            <id>assemble</id>
+            <phase>install</phase>
+            <goals>
+              <goal>attached</goal>
+            </goals>
+            <configuration>
+              <descriptors>
+                <descriptor>assembly/bin.xml</descriptor>
+                <descriptor>assembly/doc.xml</descriptor>
+                <descriptor>assembly/all.xml</descriptor>
+              </descriptors>
+              <finalName>${artifactId}-${jbosscache-pojo-version}</finalName>
+              <outputDirectory>target/distribution</outputDirectory>
+              <workDirectory>target/assembly/work</workDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.3</version>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>bind.address</name>
+              <value>127.0.0.1</value>
+            </property>
+            <property>
+              <name>java.net.preferIPv4Stack</name>
+              <value>true</value>
+            </property>
+            <property>
+              <name>jgroups.stack</name>
+              <value>udp</value>
+            </property>
+          </systemProperties>
+          <groups>functional</groups>
+          <forkMode>always</forkMode>
+          <argLine>-Djboss.aop.path=${basedir}/src/main/resources/META-INF/pojocache-aop.xml -javaagent:${settings.localRepository}/org/jboss/aop/jboss-aop/${jboss.aop.version}/jboss-aop-${jboss.aop.version}.jar</argLine>
+          <!-- Warning, this does not work right on 2.4-SNAPSHOT, (see SUREFIRE-349) -->
+          <!-- This seems to fail in some cases on 2.3 as well, disable for now -->
+          <useSystemClassLoader>true</useSystemClassLoader>
+          <redirectTestOutputToFile>false</redirectTestOutputToFile>
+        </configuration>
+      </plugin>
+      <!-- the docbook generation plugin for the user guide -->
+      <plugin>
+        <groupId>org.jboss.maven.plugins</groupId>
+        <artifactId>maven-jdocbook-plugin</artifactId>
+        <version>2.0.0</version>
+        <extensions>true</extensions>
+        <dependencies>
+            <dependency>
+               <groupId>org.jboss</groupId>
+               <artifactId>jbossorg-docbook-xslt</artifactId>
+               <version>1.0.0</version>
+            </dependency>
+            <dependency>
+               <groupId>org.jboss</groupId>
+               <artifactId>jbossorg-jdocbook-style</artifactId>
+               <version>1.0.0</version>
+               <type>jdocbook-style</type>
+            </dependency>
+           <dependency>
+                  <groupId>com.uwyn</groupId>
+                  <artifactId>jhighlight</artifactId>
+                  <version>1.0</version>
+              </dependency>
+              <dependency>
+                  <groupId>de.java2html</groupId>
+                  <artifactId>java2html</artifactId>
+                  <version>5.0</version>
+              </dependency>
+              <dependency>
+                  <groupId>org.richfaces.docs</groupId>
+                  <artifactId>highlight</artifactId>
+                  <version>3.1.4.GA</version>
+              </dependency>
+         </dependencies>
+        <executions>
+
+          <!-- The User Guide-->
+          <execution>
+            <id>userguide_en</id>
+            <phase>package</phase>
+            <goals>
+              <goal>resources</goal>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <sourceDocumentName>master.xml</sourceDocumentName>
+              <sourceDirectory>${basedir}/src/main/docbook/userguide/en</sourceDirectory>
+              <imageResource>
+                <directory>${basedir}/src/main/docbook/images</directory>
+              </imageResource>
+              <cssResource>
+                <directory>${basedir}/src/main/docbook/css</directory>
+              </cssResource>
+              <targetDirectory>${basedir}/target/docbook/userguide_en</targetDirectory>
+              <formats>
+                <format>
+                  <formatName>pdf</formatName>
+				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
+                  <finalName>userguide_en.pdf</finalName>
+                </format>
+				<format>
+                	<formatName>html</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+				<format>
+					<formatName>html_single</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+			  </formats>
+              <options>
+                <xincludeSupported>false</xincludeSupported>
+              </options>
+            </configuration>
+          </execution>
+
+          <!-- The Tutorial -->
+          <execution>
+            <id>tutorial_en</id>
+            <phase>package</phase>
+            <goals>
+              <goal>resources</goal>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <sourceDocumentName>master.xml</sourceDocumentName>
+              <sourceDirectory>${basedir}/src/main/docbook/tutorial/en</sourceDirectory>
+              <imageResource>
+                <directory>${basedir}/src/main/docbook/images</directory>
+              </imageResource>
+              <cssResource>
+                <directory>${basedir}/src/main/docbook/css</directory>
+              </cssResource>
+              <targetDirectory>${basedir}/target/docbook/tutorial_en</targetDirectory>
+              <formats>
+                <format>
+                  <formatName>pdf</formatName>
+				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
+                  <finalName>tutorial_en.pdf</finalName>
+                </format>
+				<format>
+                	<formatName>html</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+				<format>
+					<formatName>html_single</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+              </formats>
+              <options>
+                <xincludeSupported>false</xincludeSupported>
+              </options>
+            </configuration>
+          </execution>
+
+          <!-- the FAQs -->
+          <execution>
+            <id>faq_en</id>
+            <phase>package</phase>
+            <goals>
+              <goal>resources</goal>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <sourceDocumentName>master.xml</sourceDocumentName>
+              <sourceDirectory>${basedir}/src/main/docbook/faq/en</sourceDirectory>
+              <imageResource>
+                <directory>${basedir}/src/main/docbook/images</directory>
+              </imageResource>
+              <cssResource>
+                <directory>${basedir}/src/main/docbook/css</directory>
+              </cssResource>
+              <targetDirectory>${basedir}/target/docbook/faq_en</targetDirectory>
+              <formats>
+                <format>
+                  <formatName>pdf</formatName>
+				  <stylesheetResource>classpath:/xslt/org/jboss/main-pdf.xsl</stylesheetResource>
+                  <finalName>faq_en.pdf</finalName>
+                </format>
+				<format>
+                	<formatName>html</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/main-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+				<format>
+					<formatName>html_single</formatName>
+				    <stylesheetResource>classpath:/xslt/org/jboss/nochunk-html.xsl</stylesheetResource>
+				    <finalName>index.html</finalName>
+				</format>
+              </formats>
+              <options>
+                <xincludeSupported>false</xincludeSupported>
+              </options>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <!-- basic JBoss repository so that the common parent POM in jbosscache-support can be found -->
+  <repositories>
+    <repository>
+      <id>snapshots.jboss.org</id>
+      <url>http://snapshots.jboss.org/maven2</url>
+    </repository>
+    <repository>
+      <id>repository.jboss.org</id>
+      <url>http://repository.jboss.org/maven2</url>
+    </repository>
+  </repositories>
+</project>

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Attach.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/Attach.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Attach.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one checks for tx.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface Attach
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/CheckIdValidity.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/CheckIdValidity.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/CheckIdValidity.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one to check id validity.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface CheckIdValidity
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Detach.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/Detach.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Detach.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one checks for tx.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface Detach
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Find.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/Find.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Find.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one checks for tx.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface Find
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Reentrant.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/Reentrant.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Reentrant.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,26 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annoataion that wraps the Prepare annotation of JBossAop.
- *
- * @author Ben Wang
- *         Date: Jan 22, 2006
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.TYPE)
-public @interface Reentrant
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Tx.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/Tx.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/Tx.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one checks for tx.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface Tx
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/TxUndo.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/annotation/TxUndo.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/annotation/TxUndo.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,25 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation for PojoCache interceptor stack. This one annotates method to provide rollback operation.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at Retention(RetentionPolicy.RUNTIME)
- at Target(ElementType.METHOD)
-public @interface TxUndo
-{
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,188 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.collection;
-
-import org.jboss.cache.pojo.annotation.Reentrant;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Abstract class for CachedList.
- *
- * @author Scott Marlow
- */
-
- at Reentrant
-abstract class CachedListAbstract implements List
-{
-   public void clear()
-   {
-      // TODO Can use optimization here
-      for (int i = size() - 1; i >= 0; i--)
-      {
-         remove(i);
-      }
-   }
-
-   public boolean isEmpty()
-   {
-      return size() == 0;
-   }
-
-   public Object[] toArray()
-   {
-      Object[] objs = new Object[size()];
-      for (int i = 0; i < size(); i++)
-      {
-         objs[i] = get(i);
-      }
-      return objs;
-   }
-
-   public Object[] toArray(Object a[])
-   {
-      int actualLength = size();
-      if (actualLength > a.length)  // need to allocate a larger array
-         a = new Object[actualLength];
-      int looper;
-      for (looper = 0; looper < actualLength; looper++)
-      {
-         a[looper] = get(looper);
-      }
-      for (; looper < a.length; looper++)
-         a[looper] = null; // if the array is larger than needed, set extra slots to null
-      return a;
-   }
-
-   public boolean add(Object o)
-   {
-      add(size(), o);
-      return true;
-   }
-
-   public boolean contains(Object o)
-   {
-      if (indexOf(o) != -1) return true;
-      return false;
-   }
-
-   public boolean remove(Object o)
-   {
-      int i = indexOf(o);
-      if (i == -1)
-         return false;
-
-      remove(i);
-      return true;
-   }
-
-   public boolean addAll(int index, Collection c)
-   {
-      if (c.size() == 0)
-         return false;
-      // should optimize this
-      for (Object o : c)
-      {
-         add(index++, o);
-      }
-      return true;
-   }
-
-   public boolean addAll(Collection c)
-   {
-      if (c.size() == 0)
-         return false;
-      for (Object o : c)
-      {
-         add(o);
-      }
-      return true;
-   }
-
-   public boolean containsAll(Collection c)
-   {
-      for (Object aC : c)
-      {
-         if (!contains(aC))
-         {
-            return false;
-         }
-      }
-      return true;
-   }
-
-   public boolean removeAll(Collection c)
-   {
-      for (Object o : c)
-      {
-         remove(o);
-      }
-      return true;
-   }
-
-   public int hashCode()
-   {
-      int result = 1;
-      for (int i = 0; i < size(); i++)
-      {
-         Object o = get(i);
-         result = 31 * result + (o == null ? 0 : o.hashCode());
-      }
-      return result;
-   }
-
-   public boolean equals(Object object)
-   {
-      if (object == this)
-         return true;
-      if (object == null || !(object instanceof List))
-         return false;
-      List list = (List) object;
-      if (size() != list.size())
-         return false;
-      for (int i = 0; i < list.size(); i++)
-      {
-         Object value1 = get(i);
-         Object value2 = list.get(i);
-         if ((value1 == null && value2 != null) ||
-                 (value1 != null && !(value1.equals(value2))))
-            return false;
-      }
-      return true;
-   }
-
-   public String toString()
-   {
-      StringBuffer buf = new StringBuffer();
-      int size = size();
-      for (int i = 0; i < size; i++)
-      {
-         Object key = get(i);
-         buf.append("[").append(key).append("]");
-         if (i <= size) buf.append(", ");
-      }
-
-      return buf.toString();
-   }
-
-   public boolean retainAll(Collection c)
-   {
-      boolean changedAnything = false;
-      Iterator iter = iterator();
-      while (iter.hasNext())
-      {
-         if (!c.contains(iter.next()))
-         {
-            iter.remove();
-            changedAnything = true;
-         }
-      }
-      return changedAnything;
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListAbstract.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,184 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Abstract class for CachedList.
+ *
+ * @author Scott Marlow
+ */
+abstract class CachedListAbstract implements List
+{
+   public void clear()
+   {
+      // TODO Can use optimization here
+      for (int i = size() - 1; i >= 0; i--)
+      {
+         remove(i);
+      }
+   }
+
+   public boolean isEmpty()
+   {
+      return size() == 0;
+   }
+
+   public Object[] toArray()
+   {
+      Object[] objs = new Object[size()];
+      for (int i = 0; i < size(); i++)
+      {
+         objs[i] = get(i);
+      }
+      return objs;
+   }
+
+   public Object[] toArray(Object a[])
+   {
+      int actualLength = size();
+      if (actualLength > a.length)  // need to allocate a larger array
+         a = new Object[actualLength];
+      int looper;
+      for (looper = 0; looper < actualLength; looper++)
+      {
+         a[looper] = get(looper);
+      }
+      for (; looper < a.length; looper++)
+         a[looper] = null; // if the array is larger than needed, set extra slots to null
+      return a;
+   }
+
+   public boolean add(Object o)
+   {
+      add(size(), o);
+      return true;
+   }
+
+   public boolean contains(Object o)
+   {
+      if (indexOf(o) != -1) return true;
+      return false;
+   }
+
+   public boolean remove(Object o)
+   {
+      int i = indexOf(o);
+      if (i == -1)
+         return false;
+
+      remove(i);
+      return true;
+   }
+
+   public boolean addAll(int index, Collection c)
+   {
+      if (c.size() == 0)
+         return false;
+      // should optimize this
+      for (Object o : c)
+      {
+         add(index++, o);
+      }
+      return true;
+   }
+
+   public boolean addAll(Collection c)
+   {
+      if (c.size() == 0)
+         return false;
+      for (Object o : c)
+      {
+         add(o);
+      }
+      return true;
+   }
+
+   public boolean containsAll(Collection c)
+   {
+      for (Object aC : c)
+      {
+         if (!contains(aC))
+         {
+            return false;
+         }
+      }
+      return true;
+   }
+
+   public boolean removeAll(Collection c)
+   {
+      for (Object o : c)
+      {
+         remove(o);
+      }
+      return true;
+   }
+
+   public int hashCode()
+   {
+      int result = 1;
+      for (int i = 0; i < size(); i++)
+      {
+         Object o = get(i);
+         result = 31 * result + (o == null ? 0 : o.hashCode());
+      }
+      return result;
+   }
+
+   public boolean equals(Object object)
+   {
+      if (object == this)
+         return true;
+      if (object == null || !(object instanceof List))
+         return false;
+      List list = (List) object;
+      if (size() != list.size())
+         return false;
+      for (int i = 0; i < list.size(); i++)
+      {
+         Object value1 = get(i);
+         Object value2 = list.get(i);
+         if ((value1 == null && value2 != null) ||
+                 (value1 != null && !(value1.equals(value2))))
+            return false;
+      }
+      return true;
+   }
+
+   public String toString()
+   {
+      StringBuffer buf = new StringBuffer();
+      int size = size();
+      for (int i = 0; i < size; i++)
+      {
+         Object key = get(i);
+         buf.append("[").append(key).append("]");
+         if (i <= size) buf.append(", ");
+      }
+
+      return buf.toString();
+   }
+
+   public boolean retainAll(Collection c)
+   {
+      boolean changedAnything = false;
+      Iterator iter = iterator();
+      while (iter.hasNext())
+      {
+         if (!c.contains(iter.next()))
+         {
+            iter.remove();
+            changedAnything = true;
+         }
+      }
+      return changedAnything;
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,528 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.collection;
-
-import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
-
-import java.io.ObjectStreamException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.util.AopUtil;
-import org.jboss.cache.pojo.util.CacheApiUtil;
-import org.jboss.cache.pojo.util.Null;
-
-/**
- * List implementation that uses cache as a backend store.
- *
- * @author Ben Wang
- * @author Scott Marlow
- */
-public class CachedListImpl extends CachedListAbstract
-{
-   private static Log log_ = LogFactory.getLog(CachedListImpl.class.getName());
-   private Cache<Object, Object> cache;
-   private PojoCacheImpl pojoCache;
-   private AbstractCollectionInterceptor interceptor;
-
-   public CachedListImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
-   {
-      this.pojoCache = cache;
-      this.cache = pojoCache.getCache();
-      this.interceptor = interceptor;
-   }
-
-   private Fqn getFqn()
-   {
-      return interceptor.getFqn();
-   }
-
-   // implementation of the java.util.List interface
-
-   private Set<Node> getNodeChildren()
-   {
-      return CacheApiUtil.getNodeChildren(cache, getFqn());
-   }
-
-   /**
-    * Serialize a normal ArrayList
-    */
-   private Object XwriteReplace() throws ObjectStreamException
-   {
-      log_.warn("writeReplace(): this calss is not suppored to be serialized." +
-              " Will substitue with a normal ArryList");
-
-      ArrayList toSerialize = new ArrayList();
-      toSerialize.addAll(this);
-      return toSerialize;
-   }
-
-   public Object get(int index)
-   {
-      checkIndex();
-      return Null.toNullValue(pojoCache.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
-   }
-
-   private static void checkIndex()
-   {
-      // TODO This is too expensive now to check it everytime from the cache (potentially twice).
-      // It is showing up in the JProfiler. So I am disabling it now.
-      return;
-/*
-      if(size() == 0) return; // No need to check here.
-      if( i < 0 || i >= size() ) {
-         throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " +i
-         + " but size is " +size());
-      } */
-   }
-
-   public int size()
-   {
-      Set<Node> children = getNodeChildren();
-      return children == null ? 0 : children.size();
-   }
-
-   public Object set(int index, Object element)
-   {
-      if (index != 0)
-         checkIndex(); // Since index can be size().
-      return Null.toNullValue(attach(index, element, "SET"));
-   }
-
-   public void add(int index, Object element)
-   {
-      if (index != 0)
-         checkIndex(); // Since index can be size().
-      for (int i = size(); i > index; i--)
-      {
-         Object obj = detach(i - 1);
-         attach(i, obj);
-      }
-      attach(index, element, "ADD");
-   }
-
-   private Object attach(int i, Object obj)
-   {
-      return attach(i, obj, null);
-   }
-
-   private Object attach(int i, Object obj, String operation)
-   {
-      Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
-      Object o = pojoCache.attach(fqn, Null.toNullObject(obj));
-      if (operation != null)
-         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
-
-      return o;
-   }
-
-   private Object detach(int i)
-   {
-      return detach(i, null);
-   }
-
-   private Object detach(int i, String operation)
-   {
-      Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
-      if (operation != null)
-         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
-      return pojoCache.detach(fqn);
-   }
-
-   public int indexOf(Object o)
-   {
-      int size = size();
-      if (o == null)
-      {
-         for (int i = 0; i < size; i++)
-         {
-            if (null == get(i))
-               return i;
-         }
-      } else
-      {
-         for (int i = 0; i < size; i++)
-         {
-            if (o.equals(get(i)))
-               return i;
-         }
-      }
-      return -1;
-   }
-
-   public int lastIndexOf(Object o)
-   {
-      if (o == null)
-      {
-         for (int i = size() - 1; i >= 0; i--)
-         {
-            if (null == get(i))
-               return i;
-         }
-      } else
-      {
-         for (int i = size() - 1; i >= 0; i--)
-         {
-            if (o.equals(get(i)))
-               return i;
-         }
-      }
-      return -1;
-   }
-
-   public Object remove(int index)
-   {
-      checkIndex();
-      // Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
-      int size = size();
-      Object result = Null.toNullValue(detach(index, "REMOVE"));
-      if (size == (index + 1))
-      {
-         return result; // We are the last one.
-      }
-      for (int i = index; i < size - 1; i++)
-      {
-         Object obj = detach(i + 1);
-         attach(i, obj);
-      }
-      return result;
-   }
-
-   public Iterator iterator()
-   {
-      // TODO: check for concurrent modification
-      return new Iterator()
-      {
-         // Need to share this
-         int current = -1;
-         int size = size();
-
-         public boolean hasNext()
-         {
-            if (size == 0) return false;
-            if (current > size)
-               throw new NoSuchElementException("CachedSetImpl.iterator.hasNext(). " +
-                       " Cursor position " + current + " is greater than the size " + size());
-
-            return current < size - 1;
-         }
-
-         public Object next()
-         {
-            if (current == size)
-               throw new NoSuchElementException("CachedSetImpl.iterator.next(). " +
-                       " Cursor position " + current + " is greater than the size " + size());
-
-            return Null.toNullValue(pojoCache.getObject(AopUtil.constructFqn(getFqn(), IntegerCache.toString(++current))));
-         }
-
-         public void remove()
-         {
-            // TODO Need optimization here since set does not care about index
-            if (size == 0) return;
-            if (current == size)
-               throw new IllegalStateException("CachedSetImpl.iterator.remove(). " +
-                       " Cursor position " + current + " is greater than the size " + size);
-            if (current < (size - 1))
-            {
-               // Need to reshuffle the items.
-               Object last = detach(current, "REMOVE");
-               for (int i = current + 1; i < size; i++)
-               {
-                  last = detach(i);
-                  attach(i - 1, last);
-               }
-            } else
-            { // we are the last index.
-               // Need to move back the cursor.
-               detach(current, "REMOVE");
-            }
-            current--;
-            size--;
-         }
-      };
-   }
-
-   public List subList(int fromIndex, int toIndex)
-   {
-      if (fromIndex < 0)
-         throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-      if (toIndex > size())
-         throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
-      if (fromIndex > toIndex)
-         throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
-      if (fromIndex == toIndex)            // request for empty list?
-         return new LinkedList();
-      return new MyCachedSubListImpl(this, fromIndex, toIndex);
-   }
-
-   public ListIterator listIterator()
-   {
-      return new MyListIterator(this, 0);
-   }
-
-   public ListIterator listIterator(int index)
-   {
-      return new MyListIterator(this, index);
-   }
-
-   static class MyListIterator implements ListIterator
-   {
-      int index = 0;
-      List list_;
-
-      public MyListIterator(List list, int index)
-      {
-         list_ = list;
-         if (index < 0 || index > list_.size())
-         {
-            throw new IndexOutOfBoundsException("CachedListImpl: MyListIterator construction. " +
-                    " Index is out of bound : " + index);
-         }
-         this.index = index;
-      }
-
-      public int nextIndex()
-      {
-         return index;
-      }
-
-      public int previousIndex()
-      {
-         return index - 1;
-      }
-
-      public void remove()
-      {
-         int size = list_.size();
-         if (size == 0) return;
-         if (previousIndex() == size)
-            throw new IllegalStateException("CachedSetImpl.MyListIterator.remove(). " +
-                    " Cursor position " + index + " is greater than the size " + size);
-         if (previousIndex() < (size))
-         {
-            list_.remove(previousIndex());
-            index--;
-         }
-      }
-
-      public boolean hasNext()
-      {
-         return (index < list_.size());
-      }
-
-      public boolean hasPrevious()
-      {
-         return (index != 0);
-      }
-
-      public Object next()
-      {
-         if (index == list_.size())
-            throw new NoSuchElementException();
-
-         index++;
-         return list_.get(index - 1);  // pass zero relative index
-      }
-
-      public Object previous()
-      {
-         if (index == 0)
-            throw new NoSuchElementException();
-
-         index--;
-         return list_.get(index);
-      }
-
-      public void add(Object o)
-      {
-         int size = list_.size();
-         if (size == 0) return;
-
-         if (previousIndex() == size)
-            throw new IllegalStateException("CachedSetImpl.MyListIterator.add(). " +
-                    " Cursor position " + index + " is greater than the size " + size);
-         if (previousIndex() < (size))
-         {
-            list_.add(previousIndex(), o);
-         }
-      }
-
-      public void set(Object o)
-      {
-         int size = list_.size();
-         if (size == 0) return;
-
-         if (previousIndex() == size)
-            throw new IllegalStateException("CachedSetImpl.MyListIterator.set(). " +
-                    " Cursor position " + index + " is greater than the size " + size);
-         if (previousIndex() < (size))
-         {
-            list_.set(previousIndex(), o);
-         }
-      }
-   }
-
-   static public class MyCachedSubListImpl extends CachedListAbstract implements List
-   {
-
-      private List backStore_;
-      private int fromIndex_;
-      private int toIndex_;
-
-      MyCachedSubListImpl(List backStore, int fromIndex, int toIndex)
-      {
-         backStore_ = backStore;
-         fromIndex_ = fromIndex;
-         toIndex_ = toIndex;
-      }
-
-      public int size()
-      {
-         int size = backStore_.size();
-         if (size > toIndex_)
-            size = toIndex_;
-         size -= fromIndex_;     // subtract number of items ignored at the start of list
-         return size;
-      }
-
-      public Iterator iterator()
-      {
-         // TODO: check for concurrent modification
-         return new Iterator()
-         {
-            int current = -1;
-            Iterator iter_ = initializeIter();
-
-            private Iterator initializeIter()
-            {
-               Iterator iter = backStore_.iterator();
-               for (int looper = 0; looper < fromIndex_; looper++)
-                  if (iter.hasNext())      // skip past to where we need to start from
-                     iter.next();
-               return iter;
-            }
-
-            public boolean hasNext()
-            {
-               int size = size();
-               if (size == 0) return false;
-               if (current > size)
-                  throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.hasNext(). " +
-                          " Cursor position " + current + " is greater than the size " + size());
-
-               return current < size() - 1;
-            }
-
-            public Object next()
-            {
-               if (current == size())
-                  throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.next(). " +
-                          " Cursor position " + current + " is greater than the size " + size());
-               current++;
-               return iter_.next();
-            }
-
-            public void remove()
-            {
-               iter_.remove();
-               current--;
-            }
-         };
-
-      }
-
-      public Object get(int index)
-      {
-         checkIndex(index);
-         return backStore_.get(index + fromIndex_);
-      }
-
-      public Object set(int index, Object element)
-      {
-         checkIndex(index);
-         return backStore_.set(index + fromIndex_, element);
-      }
-
-      public void add(int index, Object element)
-      {
-         backStore_.add(index + fromIndex_, element);
-      }
-
-      public Object remove(int index)
-      {
-         return backStore_.remove(index + fromIndex_);
-      }
-
-      public int indexOf(Object o)
-      {
-         int index = backStore_.indexOf(o);
-         if (index < fromIndex_ || index >= toIndex_)
-            index = -1;
-         else
-            index -= fromIndex_;    // convert to be relative to our from/to range
-         return index;
-      }
-
-      public int lastIndexOf(Object o)
-      {
-         int index = backStore_.lastIndexOf(o);
-         if (index < fromIndex_ || index >= toIndex_)
-            index = -1;
-         else
-            index -= fromIndex_;    // convert to be relative to our from/to range
-         return index;
-      }
-
-      public ListIterator listIterator()
-      {
-         return new MyListIterator(this, 0);
-      }
-
-      public ListIterator listIterator(int index)
-      {
-         return new MyListIterator(this, index);
-      }
-
-      public List subList(int fromIndex, int toIndex)
-      {
-         if (fromIndex < 0)
-            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
-         if (toIndex > size())
-            throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
-         if (fromIndex > toIndex)
-            throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
-         if (fromIndex == toIndex)            // request for empty list?
-            return new LinkedList();
-         return new MyCachedSubListImpl(this, fromIndex, toIndex);
-      }
-
-      private void checkIndex(int i)
-      {
-         if (size() == 0) return; // No need to check here.
-         if (i < 0 || i >= size())
-         {
-            throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " + i
-                    + " but size is " + size());
-         }
-      }
-
-   }
-
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedListImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,544 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.collection;
+
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
+
+import java.io.ObjectStreamException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.util.AopUtil;
+import org.jboss.cache.pojo.util.CacheApiUtil;
+import org.jboss.cache.pojo.util.Null;
+
+/**
+ * List implementation that uses cache as a backend store.
+ *
+ * @author Ben Wang
+ * @author Scott Marlow
+ */
+public class CachedListImpl extends CachedListAbstract
+{
+   private static Log log_ = LogFactory.getLog(CachedListImpl.class.getName());
+   private Cache<Object, Object> cache;
+   private PojoCacheImpl pojoCache;
+   private AbstractCollectionInterceptor interceptor;
+
+   public CachedListImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
+   {
+      this.pojoCache = cache;
+      this.cache = pojoCache.getCache();
+      this.interceptor = interceptor;
+   }
+
+   private Fqn getFqn()
+   {
+      return interceptor.getFqn();
+   }
+
+   // implementation of the java.util.List interface
+
+   private Set<Node> getNodeChildren()
+   {
+      return CacheApiUtil.getNodeChildren(cache, getFqn());
+   }
+
+   /**
+    * Serialize a normal ArrayList
+    */
+   private Object XwriteReplace() throws ObjectStreamException
+   {
+      log_.warn("writeReplace(): this calss is not suppored to be serialized." +
+              " Will substitue with a normal ArryList");
+
+      ArrayList toSerialize = new ArrayList();
+      toSerialize.addAll(this);
+      return toSerialize;
+   }
+
+   public Object get(int index)
+   {
+      checkIndex();
+      return Null.toNullValue(pojoCache.find(AopUtil.constructFqn(getFqn(), IntegerCache.toString(index))));
+   }
+
+   private static void checkIndex()
+   {
+      // TODO This is too expensive now to check it everytime from the cache (potentially twice).
+      // It is showing up in the JProfiler. So I am disabling it now.
+      return;
+/*
+      if(size() == 0) return; // No need to check here.
+      if( i < 0 || i >= size() ) {
+         throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " +i
+         + " but size is " +size());
+      } */
+   }
+
+   public int size()
+   {
+      Set<Node> children = getNodeChildren();
+      return children == null ? 0 : children.size();
+   }
+
+   public Object set(int index, Object element)
+   {
+      if (index != 0)
+         checkIndex(); // Since index can be size().
+      return Null.toNullValue(attach(index, element, "SET"));
+   }
+
+   public void add(int index, Object element)
+   {
+      if (index != 0)
+         checkIndex(); // Since index can be size().
+      for (int i = size(); i > index; i--)
+      {
+         Object obj = detach(i - 1);
+         attach(i, obj);
+      }
+      attach(index, element, "ADD");
+   }
+
+   private Object attach(int i, Object obj)
+   {
+      return attach(i, obj, null);
+   }
+
+   private Object attach(int i, Object obj, String operation)
+   {
+      Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
+      Object o = pojoCache.attach(fqn, Null.toNullObject(obj));
+      if (operation != null)
+         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
+
+      return o;
+   }
+
+   private Object detach(int i)
+   {
+      return detach(i, null);
+   }
+
+   private Object detach(int i, String operation)
+   {
+      Fqn fqn = AopUtil.constructFqn(getFqn(), IntegerCache.toString(i));
+      if (operation != null)
+         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, operation);
+      return pojoCache.detach(fqn);
+   }
+
+   public int indexOf(Object o)
+   {
+      int size = size();
+      if (o == null)
+      {
+         for (int i = 0; i < size; i++)
+         {
+            if (null == get(i))
+               return i;
+         }
+      } else
+      {
+         for (int i = 0; i < size; i++)
+         {
+            if (o.equals(get(i)))
+               return i;
+         }
+      }
+      return -1;
+   }
+
+   public int lastIndexOf(Object o)
+   {
+      if (o == null)
+      {
+         for (int i = size() - 1; i >= 0; i--)
+         {
+            if (null == get(i))
+               return i;
+         }
+      } else
+      {
+         for (int i = size() - 1; i >= 0; i--)
+         {
+            if (o.equals(get(i)))
+               return i;
+         }
+      }
+      return -1;
+   }
+
+   public Object remove(int index)
+   {
+      checkIndex();
+      // Object result = cache.removeObject(((Fqn) fqn.clone()).add(new Integer(index)));
+      int size = size();
+      Object result = Null.toNullValue(detach(index, "REMOVE"));
+      if (size == (index + 1))
+      {
+         return result; // We are the last one.
+      }
+      for (int i = index; i < size - 1; i++)
+      {
+         Object obj = detach(i + 1);
+         attach(i, obj);
+      }
+      return result;
+   }
+
+   public Iterator iterator()
+   {
+      // TODO: check for concurrent modification
+      return new Iterator()
+      {
+         // Need to share this
+         int current = -1;
+         int size = size();
+
+         public boolean hasNext()
+         {
+            if (size == 0) return false;
+            if (current > size)
+               throw new NoSuchElementException("CachedSetImpl.iterator.hasNext(). " +
+                       " Cursor position " + current + " is greater than the size " + size());
+
+            return current < size - 1;
+         }
+
+         public Object next()
+         {
+            if (current == size)
+               throw new NoSuchElementException("CachedSetImpl.iterator.next(). " +
+                       " Cursor position " + current + " is greater than the size " + size());
+
+            return Null.toNullValue(pojoCache.find(AopUtil.constructFqn(getFqn(), IntegerCache.toString(++current))));
+         }
+
+         public void remove()
+         {
+            // TODO Need optimization here since set does not care about index
+            if (size == 0) return;
+            if (current == size)
+               throw new IllegalStateException("CachedSetImpl.iterator.remove(). " +
+                       " Cursor position " + current + " is greater than the size " + size);
+            if (current < (size - 1))
+            {
+               // Need to reshuffle the items.
+               Object last = detach(current, "REMOVE");
+               for (int i = current + 1; i < size; i++)
+               {
+                  last = detach(i);
+                  attach(i - 1, last);
+               }
+            } else
+            { // we are the last index.
+               // Need to move back the cursor.
+               detach(current, "REMOVE");
+            }
+            current--;
+            size--;
+         }
+      };
+   }
+
+   public List subList(int fromIndex, int toIndex)
+   {
+      if (fromIndex < 0)
+         throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+      if (toIndex > size())
+         throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
+      if (fromIndex > toIndex)
+         throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
+      if (fromIndex == toIndex)            // request for empty list?
+         return new LinkedList();
+      return new MyCachedSubListImpl(this, fromIndex, toIndex);
+   }
+
+   public ListIterator listIterator()
+   {
+      return new MyListIterator(this, 0);
+   }
+
+   public ListIterator listIterator(int index)
+   {
+      return new MyListIterator(this, index);
+   }
+
+   public String toString()
+   {
+      StringBuffer buf = new StringBuffer();
+      int size = size();
+      for (int i = 0; i < size; i++)
+      {
+         Object key = get(i);
+         if (key == interceptor.getBoundProxy())
+            key = "(this list)";
+         buf.append("[").append(key).append("]");
+         if (i <= size) buf.append(", ");
+      }
+
+      return buf.toString();
+   }
+
+   static class MyListIterator implements ListIterator
+   {
+      int index = 0;
+      List list_;
+
+      public MyListIterator(List list, int index)
+      {
+         list_ = list;
+         if (index < 0 || index > list_.size())
+         {
+            throw new IndexOutOfBoundsException("CachedListImpl: MyListIterator construction. " +
+                    " Index is out of bound : " + index);
+         }
+         this.index = index;
+      }
+
+      public int nextIndex()
+      {
+         return index;
+      }
+
+      public int previousIndex()
+      {
+         return index - 1;
+      }
+
+      public void remove()
+      {
+         int size = list_.size();
+         if (size == 0) return;
+         if (previousIndex() == size)
+            throw new IllegalStateException("CachedSetImpl.MyListIterator.remove(). " +
+                    " Cursor position " + index + " is greater than the size " + size);
+         if (previousIndex() < (size))
+         {
+            list_.remove(previousIndex());
+            index--;
+         }
+      }
+
+      public boolean hasNext()
+      {
+         return (index < list_.size());
+      }
+
+      public boolean hasPrevious()
+      {
+         return (index != 0);
+      }
+
+      public Object next()
+      {
+         if (index == list_.size())
+            throw new NoSuchElementException();
+
+         index++;
+         return list_.get(index - 1);  // pass zero relative index
+      }
+
+      public Object previous()
+      {
+         if (index == 0)
+            throw new NoSuchElementException();
+
+         index--;
+         return list_.get(index);
+      }
+
+      public void add(Object o)
+      {
+         int size = list_.size();
+         if (size == 0) return;
+
+         if (previousIndex() == size)
+            throw new IllegalStateException("CachedSetImpl.MyListIterator.add(). " +
+                    " Cursor position " + index + " is greater than the size " + size);
+         if (previousIndex() < (size))
+         {
+            list_.add(previousIndex(), o);
+         }
+      }
+
+      public void set(Object o)
+      {
+         int size = list_.size();
+         if (size == 0) return;
+
+         if (previousIndex() == size)
+            throw new IllegalStateException("CachedSetImpl.MyListIterator.set(). " +
+                    " Cursor position " + index + " is greater than the size " + size);
+         if (previousIndex() < (size))
+         {
+            list_.set(previousIndex(), o);
+         }
+      }
+   }
+
+   static public class MyCachedSubListImpl extends CachedListAbstract implements List
+   {
+
+      private List backStore_;
+      private int fromIndex_;
+      private int toIndex_;
+
+      MyCachedSubListImpl(List backStore, int fromIndex, int toIndex)
+      {
+         backStore_ = backStore;
+         fromIndex_ = fromIndex;
+         toIndex_ = toIndex;
+      }
+
+      public int size()
+      {
+         int size = backStore_.size();
+         if (size > toIndex_)
+            size = toIndex_;
+         size -= fromIndex_;     // subtract number of items ignored at the start of list
+         return size;
+      }
+
+      public Iterator iterator()
+      {
+         // TODO: check for concurrent modification
+         return new Iterator()
+         {
+            int current = -1;
+            Iterator iter_ = initializeIter();
+
+            private Iterator initializeIter()
+            {
+               Iterator iter = backStore_.iterator();
+               for (int looper = 0; looper < fromIndex_; looper++)
+                  if (iter.hasNext())      // skip past to where we need to start from
+                     iter.next();
+               return iter;
+            }
+
+            public boolean hasNext()
+            {
+               int size = size();
+               if (size == 0) return false;
+               if (current > size)
+                  throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.hasNext(). " +
+                          " Cursor position " + current + " is greater than the size " + size());
+
+               return current < size() - 1;
+            }
+
+            public Object next()
+            {
+               if (current == size())
+                  throw new IllegalStateException("CachedSetImpl.MyCachedSubListImpl.iterator.next(). " +
+                          " Cursor position " + current + " is greater than the size " + size());
+               current++;
+               return iter_.next();
+            }
+
+            public void remove()
+            {
+               iter_.remove();
+               current--;
+            }
+         };
+
+      }
+
+      public Object get(int index)
+      {
+         checkIndex(index);
+         return backStore_.get(index + fromIndex_);
+      }
+
+      public Object set(int index, Object element)
+      {
+         checkIndex(index);
+         return backStore_.set(index + fromIndex_, element);
+      }
+
+      public void add(int index, Object element)
+      {
+         backStore_.add(index + fromIndex_, element);
+      }
+
+      public Object remove(int index)
+      {
+         return backStore_.remove(index + fromIndex_);
+      }
+
+      public int indexOf(Object o)
+      {
+         int index = backStore_.indexOf(o);
+         if (index < fromIndex_ || index >= toIndex_)
+            index = -1;
+         else
+            index -= fromIndex_;    // convert to be relative to our from/to range
+         return index;
+      }
+
+      public int lastIndexOf(Object o)
+      {
+         int index = backStore_.lastIndexOf(o);
+         if (index < fromIndex_ || index >= toIndex_)
+            index = -1;
+         else
+            index -= fromIndex_;    // convert to be relative to our from/to range
+         return index;
+      }
+
+      public ListIterator listIterator()
+      {
+         return new MyListIterator(this, 0);
+      }
+
+      public ListIterator listIterator(int index)
+      {
+         return new MyListIterator(this, index);
+      }
+
+      public List subList(int fromIndex, int toIndex)
+      {
+         if (fromIndex < 0)
+            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+         if (toIndex > size())
+            throw new IndexOutOfBoundsException("toIndex = " + toIndex + " but size() =" + size());
+         if (fromIndex > toIndex)
+            throw new IllegalArgumentException("fromIndex (" + fromIndex + ") must be less than toIndex(" + toIndex + ")");
+         if (fromIndex == toIndex)            // request for empty list?
+            return new LinkedList();
+         return new MyCachedSubListImpl(this, fromIndex, toIndex);
+      }
+
+      private void checkIndex(int i)
+      {
+         if (size() == 0) return; // No need to check here.
+         if (i < 0 || i >= size())
+         {
+            throw new IndexOutOfBoundsException("Index out of bound at CachedListImpl(). Index is " + i
+                    + " but size is " + size());
+         }
+      }
+
+   }
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,403 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.collection;
-
-import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
-
-import java.io.Serializable;
-import java.util.AbstractCollection;
-import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.aop.Advised;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.annotation.Reentrant;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.util.CacheApiUtil;
-import org.jboss.cache.pojo.util.Null;
-
-/**
- * Map that uses cache as a backend store.
- *
- * @author Ben Wang
- * @author Scott Marlow
- */
- at Reentrant
-public class CachedMapImpl implements Map
-{
-   private PojoCacheImpl pojoCache;
-   private Cache<Object, Object> cache;
-   private AbstractCollectionInterceptor interceptor;
-
-   public CachedMapImpl(PojoCacheImpl pCache, AbstractCollectionInterceptor interceptor)
-   {
-      this.pojoCache = pCache;
-      this.cache = pojoCache.getCache();
-      this.interceptor = interceptor;
-   }
-
-   private static Fqn constructFqn(Fqn baseFqn, Object relative)
-   {
-      if (!(relative instanceof Serializable) && !(relative instanceof Advised))
-      {
-         throw new PojoCacheException("Non-serializable for " + relative.getClass().getName());
-      }
-
-      return new Fqn(baseFqn, relative);
-   }
-
-   private Fqn getFqn()
-   {
-      return interceptor.getFqn();
-   }
-
-   private Object attach(Object key, Object value)
-   {
-      Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
-      Object o = pojoCache.attach(fqn, Null.toNullObject(value));
-      pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "PUT");
-
-      return o;
-   }
-
-   private Object detach(Object key)
-   {
-      Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
-      pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
-
-      return pojoCache.detach(fqn);
-   }
-
-   // implementation of the java.util.Map interface
-
-   private Set<Node> getNodeChildren()
-   {
-      return CacheApiUtil.getNodeChildren(cache, getFqn());
-   }
-
-   public Object get(Object key)
-   {
-      return Null.toNullValue(pojoCache.getObject(constructFqn(getFqn(), Null.toNullKeyObject(key))));
-   }
-
-   public Object put(Object key, Object value)
-   {
-      return attach(key, value);
-   }
-
-   public void putAll(Map map)
-   {
-      for (Iterator i = map.entrySet().iterator(); i.hasNext();)
-      {
-         Map.Entry entry = (Map.Entry) i.next();
-         put(entry.getKey(), entry.getValue());
-      }
-   }
-
-   public Object remove(Object key)
-   {
-      return detach(key);
-   }
-
-   public void clear()
-   {
-      // Need to clone first to avoid CME
-      ArrayList list = new ArrayList(keySet());
-      for (int i = 0; i < list.size(); i++)
-      {
-         remove(list.get(i));
-      }
-   }
-
-   public int size()
-   {
-      Set<Node> children = getNodeChildren();
-      return children == null ? 0 : children.size();
-   }
-
-   public boolean isEmpty()
-   {
-      return size() == 0;
-   }
-
-   public boolean containsKey(Object object)
-   {
-      Set<Node> children = getNodeChildren();
-      if (children == null) return false;
-      for (Object n : children)
-      {
-         if (((Node) n).getFqn().getLastElement().equals(Null.toNullKeyObject(object))) return true;
-      }
-
-      return false;
-   }
-
-   public boolean containsValue(Object object)
-   {
-      return values().contains(Null.toNullObject(object));
-   }
-
-   public Set entrySet()
-   {
-      final CachedMapImpl map = this;
-
-      return new AbstractSet()
-      {
-
-         public int size()
-         {
-            Set<Node> children = getNodeChildren();
-            return children == null ? 0 : children.size();
-         }
-
-         public Iterator iterator()
-         {
-            Set<Node> children = getNodeChildren();
-            final Iterator i =
-                    children == null
-                            ? Collections.EMPTY_LIST.iterator()
-                            : children.iterator();
-            return new Iterator()
-            {
-               Object lastKey; // for remove
-
-               public boolean hasNext()
-               {
-                  return i.hasNext();
-               }
-
-               public Object next()
-               {
-                  return new Entry(lastKey = ((Node) i.next()).getFqn().getLastElement());
-               }
-
-               public void remove()
-               {
-                  map.remove(lastKey);
-               }
-            };
-         }
-      };
-   }
-
-   public Collection values()
-   {
-      final CachedMapImpl map = this;
-
-      return new AbstractCollection()
-      {
-
-         public int size()
-         {
-            Set<Node> children = getNodeChildren();
-            return children == null ? 0 : children.size();
-         }
-
-         public void clear()
-         {
-            map.clear();
-         }
-
-         public Iterator iterator()
-         {
-            Set<Node> children = getNodeChildren();
-            final Iterator i =
-                    children == null
-                            ? Collections.EMPTY_LIST.iterator()
-                            : children.iterator();
-
-            return new Iterator()
-            {
-               Object lastKey; // for remove
-
-               public boolean hasNext()
-               {
-                  return i.hasNext();
-               }
-
-               public Object next()
-               {
-                  Fqn f = ((Node) i.next()).getFqn();
-                  lastKey = f.getLastElement();
-                  return Null.toNullValue(pojoCache.getObject(f));
-               }
-
-               public void remove()
-               {
-                  Object key = lastKey;
-                  if (key != null)  // convert from internal Null form to actual null if needed
-                     key = Null.toNullKeyValue(key);
-                  map.remove(key);
-               }
-            };
-         }
-      };
-   }
-
-   public Set keySet()
-   {
-      final CachedMapImpl map = this;
-
-      return new AbstractSet()
-      {
-
-         public int size()
-         {
-            Set<Node> children = getNodeChildren();
-            return children == null ? 0 : children.size();
-         }
-
-         public Iterator iterator()
-         {
-            Set<Node> children = getNodeChildren();
-            final Iterator i =
-                    children == null
-                            ? Collections.EMPTY_LIST.iterator()
-                            : children.iterator();
-
-            return new Iterator()
-            {
-               Object lastKey; // for remove
-
-               public boolean hasNext()
-               {
-                  return i.hasNext();
-               }
-
-               public Object next()
-               {
-                  lastKey = ((Node) i.next()).getFqn().getLastElement();
-                  return Null.toNullKeyValue(lastKey);
-
-               }
-
-               public void remove()
-               {
-                  Object key = lastKey;
-                  if (key != null)  // convert from internal Null form to actual null if needed
-                     key = Null.toNullKeyValue(key);
-                  map.remove(key);
-               }
-            };
-
-         }
-      };
-   }
-
-   public int hashCode()
-   {
-      int result = 0;
-      for (Iterator i = entrySet().iterator(); i.hasNext();)
-      {
-         result += i.next().hashCode();
-      }
-      return result;
-   }
-
-   public boolean equals(Object object)
-   {
-      if (object == this)
-         return true;
-      if (object == null || !(object instanceof Map))
-         return false;
-      Map map = (Map) object;
-      if (size() != map.size())
-         return false;
-      for (Iterator i = entrySet().iterator(); i.hasNext();)
-      {
-         Entry entry = (Entry) i.next();
-         Object value = entry.getValue();
-         Object key = entry.getKey();
-         if (value == null)
-         {
-            if (!(map.get(key) == null && map.containsKey(key)))
-            {
-               return false;
-            }
-         } else
-         {
-            if (!value.equals(map.get(key)))
-               return false;
-         }
-      }
-      return true;
-   }
-
-   public String toString()
-   {
-      StringBuffer buf = new StringBuffer();
-      Set set = keySet();
-      for (Iterator it = set.iterator(); it.hasNext();)
-      {
-         Object key = it.next();
-         buf.append("[").append(key).append(", ").append(get(key)).append("]");
-         if (it.hasNext()) buf.append(", ");
-      }
-
-      return buf.toString();
-   }
-
-   class Entry implements Map.Entry
-   {
-
-      Object key;
-
-      public Entry(Object key)
-      {
-         this.key = key;
-      }
-
-      public Object getKey()
-      {
-         return Null.toNullValue(key);
-      }
-
-      public Object getValue()
-      {
-         return Null.toNullValue(pojoCache.getObject(constructFqn(getFqn(), key)));
-      }
-
-      public Object setValue(Object value)
-      {
-         return attach(key, value);
-      }
-
-      public int hashCode()
-      {
-         Object value = getValue();
-         return ((key == null) ? 0 : key.hashCode())
-                 ^ ((value == null) ? 0 : value.hashCode());
-      }
-
-      public boolean equals(Object obj)
-      {
-         if (!(obj instanceof Entry))
-            return false;
-         Entry entry = (Entry) obj;
-         Object value = getValue();
-         return (
-                 key == null
-                         ? entry.getKey() == null
-                         : key.equals(entry.getKey()))
-                 && (value == null
-                 ? entry.getValue() == null
-                 : value.equals(entry.getValue()));
-      }
-   }
-
-
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedMapImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,406 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.collection;
+
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
+
+import java.io.Serializable;
+import java.util.AbstractCollection;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.aop.Advised;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.util.CacheApiUtil;
+import org.jboss.cache.pojo.util.Null;
+
+/**
+ * Map that uses cache as a backend store.
+ *
+ * @author Ben Wang
+ * @author Scott Marlow
+ */
+public class CachedMapImpl implements Map
+{
+   private PojoCacheImpl pojoCache;
+   private Cache<Object, Object> cache;
+   private AbstractCollectionInterceptor interceptor;
+
+   public CachedMapImpl(PojoCacheImpl pCache, AbstractCollectionInterceptor interceptor)
+   {
+      this.pojoCache = pCache;
+      this.cache = pojoCache.getCache();
+      this.interceptor = interceptor;
+   }
+
+   private static Fqn constructFqn(Fqn baseFqn, Object relative)
+   {
+      if (!(relative instanceof Serializable) && !(relative instanceof Advised))
+      {
+         throw new PojoCacheException("Non-serializable for " + relative.getClass().getName());
+      }
+
+      return new Fqn(baseFqn, relative);
+   }
+
+   private Fqn getFqn()
+   {
+      return interceptor.getFqn();
+   }
+
+   private Object attach(Object key, Object value)
+   {
+      Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
+      Object o = pojoCache.attach(fqn, Null.toNullObject(value));
+      pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "PUT");
+
+      return o;
+   }
+
+   private Object detach(Object key)
+   {
+      Fqn fqn = constructFqn(getFqn(), Null.toNullKeyObject(key));
+      pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
+
+      return pojoCache.detach(fqn);
+   }
+
+   // implementation of the java.util.Map interface
+
+   private Set<Node> getNodeChildren()
+   {
+      return CacheApiUtil.getNodeChildren(cache, getFqn());
+   }
+
+   public Object get(Object key)
+   {
+      return Null.toNullValue(pojoCache.find(constructFqn(getFqn(), Null.toNullKeyObject(key))));
+   }
+
+   public Object put(Object key, Object value)
+   {
+      return attach(key, value);
+   }
+
+   public void putAll(Map map)
+   {
+      for (Iterator i = map.entrySet().iterator(); i.hasNext();)
+      {
+         Map.Entry entry = (Map.Entry) i.next();
+         put(entry.getKey(), entry.getValue());
+      }
+   }
+
+   public Object remove(Object key)
+   {
+      return detach(key);
+   }
+
+   public void clear()
+   {
+      // Need to clone first to avoid CME
+      ArrayList list = new ArrayList(keySet());
+      for (int i = 0; i < list.size(); i++)
+      {
+         remove(list.get(i));
+      }
+   }
+
+   public int size()
+   {
+      Set<Node> children = getNodeChildren();
+      return children == null ? 0 : children.size();
+   }
+
+   public boolean isEmpty()
+   {
+      return size() == 0;
+   }
+
+   public boolean containsKey(Object object)
+   {
+      Set<Node> children = getNodeChildren();
+      if (children == null) return false;
+      for (Object n : children)
+      {
+         if (((Node) n).getFqn().getLastElement().equals(Null.toNullKeyObject(object))) return true;
+      }
+
+      return false;
+   }
+
+   public boolean containsValue(Object object)
+   {
+      return values().contains(Null.toNullObject(object));
+   }
+
+   public Set entrySet()
+   {
+      final CachedMapImpl map = this;
+
+      return new AbstractSet()
+      {
+
+         public int size()
+         {
+            Set<Node> children = getNodeChildren();
+            return children == null ? 0 : children.size();
+         }
+
+         public Iterator iterator()
+         {
+            Set<Node> children = getNodeChildren();
+            final Iterator i =
+                    children == null
+                            ? Collections.EMPTY_LIST.iterator()
+                            : children.iterator();
+            return new Iterator()
+            {
+               Object lastKey; // for remove
+
+               public boolean hasNext()
+               {
+                  return i.hasNext();
+               }
+
+               public Object next()
+               {
+                  return new Entry(lastKey = ((Node) i.next()).getFqn().getLastElement());
+               }
+
+               public void remove()
+               {
+                  map.remove(lastKey);
+               }
+            };
+         }
+      };
+   }
+
+   public Collection values()
+   {
+      final CachedMapImpl map = this;
+
+      return new AbstractCollection()
+      {
+
+         public int size()
+         {
+            Set<Node> children = getNodeChildren();
+            return children == null ? 0 : children.size();
+         }
+
+         public void clear()
+         {
+            map.clear();
+         }
+
+         public Iterator iterator()
+         {
+            Set<Node> children = getNodeChildren();
+            final Iterator i =
+                    children == null
+                            ? Collections.EMPTY_LIST.iterator()
+                            : children.iterator();
+
+            return new Iterator()
+            {
+               Object lastKey; // for remove
+
+               public boolean hasNext()
+               {
+                  return i.hasNext();
+               }
+
+               public Object next()
+               {
+                  Fqn f = ((Node) i.next()).getFqn();
+                  lastKey = f.getLastElement();
+                  return Null.toNullValue(pojoCache.find(f));
+               }
+
+               public void remove()
+               {
+                  Object key = lastKey;
+                  if (key != null)  // convert from internal Null form to actual null if needed
+                     key = Null.toNullKeyValue(key);
+                  map.remove(key);
+               }
+            };
+         }
+      };
+   }
+
+   public Set keySet()
+   {
+      final CachedMapImpl map = this;
+
+      return new AbstractSet()
+      {
+
+         public int size()
+         {
+            Set<Node> children = getNodeChildren();
+            return children == null ? 0 : children.size();
+         }
+
+         public Iterator iterator()
+         {
+            Set<Node> children = getNodeChildren();
+            final Iterator i =
+                    children == null
+                            ? Collections.EMPTY_LIST.iterator()
+                            : children.iterator();
+
+            return new Iterator()
+            {
+               Object lastKey; // for remove
+
+               public boolean hasNext()
+               {
+                  return i.hasNext();
+               }
+
+               public Object next()
+               {
+                  lastKey = ((Node) i.next()).getFqn().getLastElement();
+                  return Null.toNullKeyValue(lastKey);
+
+               }
+
+               public void remove()
+               {
+                  Object key = lastKey;
+                  if (key != null)  // convert from internal Null form to actual null if needed
+                     key = Null.toNullKeyValue(key);
+                  map.remove(key);
+               }
+            };
+
+         }
+      };
+   }
+
+   public int hashCode()
+   {
+      int result = 0;
+      for (Iterator i = entrySet().iterator(); i.hasNext();)
+      {
+         result += i.next().hashCode();
+      }
+      return result;
+   }
+
+   public boolean equals(Object object)
+   {
+      if (object == this)
+         return true;
+      if (object == null || !(object instanceof Map))
+         return false;
+      Map map = (Map) object;
+      if (size() != map.size())
+         return false;
+      for (Iterator i = entrySet().iterator(); i.hasNext();)
+      {
+         Entry entry = (Entry) i.next();
+         Object value = entry.getValue();
+         Object key = entry.getKey();
+         if (value == null)
+         {
+            if (!(map.get(key) == null && map.containsKey(key)))
+            {
+               return false;
+            }
+         } else
+         {
+            if (!value.equals(map.get(key)))
+               return false;
+         }
+      }
+      return true;
+   }
+
+   public String toString()
+   {
+      StringBuffer buf = new StringBuffer();
+      Set set = keySet();
+      for (Iterator it = set.iterator(); it.hasNext();)
+      {
+         Object key = it.next();
+         Object value = get(key);
+         if (key == interceptor.getBoundProxy())
+            key = "(this map)";
+         if (value == interceptor.getBoundProxy())
+            value = "(this map)";
+
+         buf.append("[").append(key).append(", ").append(value).append("]");
+         if (it.hasNext()) buf.append(", ");
+      }
+
+      return buf.toString();
+   }
+
+   class Entry implements Map.Entry
+   {
+
+      Object key;
+
+      public Entry(Object key)
+      {
+         this.key = key;
+      }
+
+      public Object getKey()
+      {
+         return Null.toNullValue(key);
+      }
+
+      public Object getValue()
+      {
+         return Null.toNullValue(pojoCache.find(constructFqn(getFqn(), key)));
+      }
+
+      public Object setValue(Object value)
+      {
+         return attach(key, value);
+      }
+
+      public int hashCode()
+      {
+         Object value = getValue();
+         return ((key == null) ? 0 : key.hashCode())
+                 ^ ((value == null) ? 0 : value.hashCode());
+      }
+
+      public boolean equals(Object obj)
+      {
+         if (!(obj instanceof Entry))
+            return false;
+         Entry entry = (Entry) obj;
+         Object value = getValue();
+         return (
+                 key == null
+                         ? entry.getKey() == null
+                         : key.equals(entry.getKey()))
+                 && (value == null
+                 ? entry.getValue() == null
+                 : value.equals(entry.getValue()));
+      }
+   }
+
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,71 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt 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.cache.pojo.collection;
-
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.impl.ArrayInterceptable;
-import org.jboss.cache.pojo.impl.InternalConstant;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.util.AopUtil;
-import org.jboss.cache.pojo.util.Null;
-
-/**
- * A CachedObjectArray is used to back arrays with a component type that extends Object.
- * It currently maps each array element to a cache Node, to support fine-grained locking.
- *
- * @author Jason T. Greene
- */
-public class CachedObjectArray extends CachedArray
-{
-   // Used to indicate that the source of the element is an interceptable array
-   // so that multi-dimensional arrays can be handled properly
-   private static ArrayInterceptable arraySource = new ArrayInterceptable() {};
-
-   protected CachedObjectArray(Fqn<?> fqn, Class<?> type, PojoCacheImpl cache)
-   {
-      super(fqn, type, cache);
-   }
-
-   public void set(int index, Object element)
-   {
-      Fqn<?> fqn = AopUtil.constructFqn(this.fqn, IntegerCache.toString(index));
-
-      cache.attach(fqn, Null.toNullObject(element), null, arraySource);
-      cache.getCache().put(fqn, InternalConstant.POJOCACHE_OPERATION, "SET");
-   }
-
-   public Object get(int index)
-   {
-      Fqn<?> fqn = AopUtil.constructFqn(this.fqn, IntegerCache.toString(index));
-
-      return Null.toNullValue(cache.getObject(fqn, null, arraySource));
-   }
-
-   public void destroy()
-   {
-      // Detach all children to ensure reference cleanup
-      for (int i = 0; i < length(); i++)
-         cache.detach(AopUtil.constructFqn(this.fqn, IntegerCache.toString(i)), null, arraySource);
-
-      super.destroy();
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedObjectArray.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,71 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt 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.cache.pojo.collection;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.impl.ArrayInterceptable;
+import org.jboss.cache.pojo.impl.InternalConstant;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.util.AopUtil;
+import org.jboss.cache.pojo.util.Null;
+
+/**
+ * A CachedObjectArray is used to back arrays with a component type that extends Object.
+ * It currently maps each array element to a cache Node, to support fine-grained locking.
+ *
+ * @author Jason T. Greene
+ */
+public class CachedObjectArray extends CachedArray
+{
+   // Used to indicate that the source of the element is an interceptable array
+   // so that multi-dimensional arrays can be handled properly
+   private static ArrayInterceptable arraySource = new ArrayInterceptable() {};
+
+   protected CachedObjectArray(Fqn<?> fqn, Class<?> type, PojoCacheImpl cache)
+   {
+      super(fqn, type, cache);
+   }
+
+   public void set(int index, Object element)
+   {
+      Fqn<?> fqn = AopUtil.constructFqn(this.fqn, IntegerCache.toString(index));
+
+      cache.attach(fqn, Null.toNullObject(element), null, arraySource);
+      cache.getCache().put(fqn, InternalConstant.POJOCACHE_OPERATION, "SET");
+   }
+
+   public Object get(int index)
+   {
+      Fqn<?> fqn = AopUtil.constructFqn(this.fqn, IntegerCache.toString(index));
+
+      return Null.toNullValue(cache.find(fqn, null, arraySource));
+   }
+
+   public void destroy()
+   {
+      // Detach all children to ensure reference cleanup
+      for (int i = 0; i < length(); i++)
+         cache.detach(AopUtil.constructFqn(this.fqn, IntegerCache.toString(i)), null, arraySource);
+
+      super.destroy();
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,292 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.collection;
-
-import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
-
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.NodeSPI;
-import org.jboss.cache.pojo.annotation.Reentrant;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.util.AopUtil;
-import org.jboss.cache.pojo.util.CacheApiUtil;
-import org.jboss.cache.pojo.util.Null;
-
-/**
- * Set implementation that uses a cache as an underlying backend store.
- * Set data is stored in children nodes named based on the attached Object's hash code
- * in hexidecimal string form.
- * If there are conflicts between two Objects with the same hash code, then a
- * counter (upper 32 bits of 64) is used.
- *
- * @author Ben Wang
- * @author Scott Marlow
- * @author Jussi Pyorre
- */
- at Reentrant
-public class CachedSetImpl extends AbstractSet
-{
-   private PojoCacheImpl pojoCache;
-   private Cache<Object, Object> cache;
-   private AbstractCollectionInterceptor interceptor;
-
-   public CachedSetImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
-   {
-      this.pojoCache = cache;
-      this.cache = pojoCache.getCache();
-      this.interceptor = interceptor;
-   }
-
-   private Set<Node> getNodeChildren()
-   {
-      return CacheApiUtil.getNodeChildren(cache, getFqn());
-   }
-
-   private Fqn getFqn()
-   {
-      // Cannot cache this as this can be reset
-      return interceptor.getFqn();
-   }
-
-   // java.util.Set implementation
-
-   public boolean add(Object o)
-   {
-      o = Null.toNullObject(o);
-      int hashCode = o.hashCode();
-      int size = size();
-      for (int i = 0; i < size + 1; i++)
-      {
-         Object key = toLong(hashCode, i);
-         Object o2 = getNoUnmask(key);
-         if (o2 == null)
-         {
-            attach(key, o, true);
-            return true;
-         }
-         if (o.equals(o2))
-         {
-            return false;
-         }
-      }
-      // should never reach here
-      throw new CacheException();
-   }
-
-   public void clear()
-   {
-      Set<Node> children = getNodeChildren();
-      for (Node n : children)
-      {
-         pojoCache.detach(n.getFqn());
-      }
-   }
-
-   public boolean contains(Object o)
-   {
-      o = Null.toNullObject(o);
-      int hashCode = o.hashCode();
-      int size = size();
-      for (int i = 0; i < size; i++)
-      {
-         Object key = toLong(hashCode, i);
-         Object o2 = getNoUnmask(key);
-         if (o2 == null)
-         {
-            return false;
-         }
-         if (o.equals(o2))
-         {
-            return true;
-         }
-      }
-      return false;
-   }
-
-   public Iterator iterator()
-   {
-      Node node = cache.getRoot().getChild(getFqn());
-      if (node == null)
-      {
-         return Collections.EMPTY_SET.iterator();
-      }
-      return new IteratorImpl(node);
-   }
-
-   public boolean remove(Object o)
-   {
-      o = Null.toNullObject(o);
-      int hashCode = o.hashCode();
-      int size = size();
-      boolean removed = false;
-      Object oldkey = null;
-      for (int i = 0; i < size; i++)
-      {
-         Object key = toLong(hashCode, i);
-         Object o2 = getNoUnmask(key);
-         if (o2 == null)
-         {
-            break;
-         }
-         if (removed)
-         {
-            // move o2 to old key
-            detach(key);
-            attach(oldkey, o2);
-         }
-         if (o.equals(o2))
-         {
-            detach(key, true);
-            removed = true;
-         }
-         oldkey = key;
-      }
-      return removed;
-   }
-
-   public int size()
-   {
-      Set<Node> children = getNodeChildren();
-      return (children == null) ? 0 : children.size();
-   }
-
-   public String toString()
-   {
-      StringBuffer buf = new StringBuffer();
-      for (Iterator it = iterator(); it.hasNext();)
-      {
-         Object key = it.next();
-         buf.append("[").append(key).append("]");
-         if (it.hasNext()) buf.append(", ");
-      }
-
-      return buf.toString();
-   }
-
-   /**
-    * Return a long with "count" as the high 32 bits.
-    * TODO should be able to use java.lang.Long, but some CacheLoader don't
-    * support non-String keys
-    */
-   private String toLong(long hashCode, long count)
-   {
-      long key = (hashCode & 0xFFFFL) | (count << 32);
-      return Long.toHexString(key);
-   }
-
-
-   private Object attach(Object key, Object pojo)
-   {
-      return attach(key, pojo, false);
-   }
-
-   private Object attach(Object key, Object pojo, boolean add)
-   {
-      Fqn fqn = AopUtil.constructFqn(getFqn(), key);
-      Object o = pojoCache.attach(fqn, pojo);
-      if (add)
-         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "ADD");
-
-      return o;
-   }
-
-   private Object detach(Object key)
-   {
-      return detach(key, false);
-   }
-
-   private Object detach(Object key, boolean remove)
-   {
-      Fqn fqn = AopUtil.constructFqn(getFqn(), key);
-      if (remove)
-         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
-
-      return pojoCache.detach(fqn);
-   }
-
-   private Object getNoUnmask(Object key)
-   {
-      return pojoCache.getObject(AopUtil.constructFqn(getFqn(), key));
-   }
-
-   public int hashCode()
-   {
-      int result = super.hashCode();
-      result = 29 * result + cache.hashCode();
-      result = 29 * result + interceptor.hashCode();
-      return result;
-   }
-
-   public boolean equals(Object o)
-   {
-      if (o == this)
-      {
-         return true;
-      }
-
-      try
-      {
-         return super.equals(o);
-      }
-      catch (ClassCastException e)
-      {
-         return false;
-      }
-      catch (NullPointerException unused)
-      {
-         return false;
-      }
-   }
-
-   private class IteratorImpl implements Iterator
-   {
-      private Iterator<NodeSPI> iterator;
-
-      private Node node;
-      private Object o;
-
-      private IteratorImpl(Node node)
-      {
-         Collection<NodeSPI> children = new HashSet<NodeSPI>(((NodeSPI) node).getChildrenDirect());
-         iterator = children.iterator();
-      }
-
-      public boolean hasNext()
-      {
-         return iterator.hasNext();
-      }
-
-      public Object next()
-      {
-         node = iterator.next();
-         o = Null.toNullValue(pojoCache.getObject(node.getFqn()));
-         return o;
-      }
-
-      public void remove() throws IllegalStateException
-      {
-         if (node == null)
-         {
-            throw new IllegalStateException();
-         }
-         CachedSetImpl.this.remove(o);
-      }
-
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CachedSetImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,291 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.collection;
+
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.util.AopUtil;
+import org.jboss.cache.pojo.util.CacheApiUtil;
+import org.jboss.cache.pojo.util.Null;
+
+/**
+ * Set implementation that uses a cache as an underlying backend store.
+ * Set data is stored in children nodes named based on the attached Object's hash code
+ * in hexidecimal string form.
+ * If there are conflicts between two Objects with the same hash code, then a
+ * counter (upper 32 bits of 64) is used.
+ *
+ * @author Ben Wang
+ * @author Scott Marlow
+ * @author Jussi Pyorre
+ */
+public class CachedSetImpl extends AbstractSet
+{
+   private PojoCacheImpl pojoCache;
+   private Cache<Object, Object> cache;
+   private AbstractCollectionInterceptor interceptor;
+
+   public CachedSetImpl(PojoCacheImpl cache, AbstractCollectionInterceptor interceptor)
+   {
+      this.pojoCache = cache;
+      this.cache = pojoCache.getCache();
+      this.interceptor = interceptor;
+   }
+
+   private Set<Node> getNodeChildren()
+   {
+      return CacheApiUtil.getNodeChildren(cache, getFqn());
+   }
+
+   private Fqn getFqn()
+   {
+      // Cannot cache this as this can be reset
+      return interceptor.getFqn();
+   }
+
+   // java.util.Set implementation
+
+   public boolean add(Object o)
+   {
+      o = Null.toNullObject(o);
+      int hashCode = o.hashCode();
+      int size = size();
+      for (int i = 0; i < size + 1; i++)
+      {
+         Object key = toLong(hashCode, i);
+         Object o2 = getNoUnmask(key);
+         if (o2 == null)
+         {
+            attach(key, o, true);
+            return true;
+         }
+         if (o.equals(o2))
+         {
+            return false;
+         }
+      }
+      // should never reach here
+      throw new CacheException();
+   }
+
+   public void clear()
+   {
+      Set<Node> children = getNodeChildren();
+      for (Node n : children)
+      {
+         pojoCache.detach(n.getFqn());
+      }
+   }
+
+   public boolean contains(Object o)
+   {
+      o = Null.toNullObject(o);
+      int hashCode = o.hashCode();
+      int size = size();
+      for (int i = 0; i < size; i++)
+      {
+         Object key = toLong(hashCode, i);
+         Object o2 = getNoUnmask(key);
+         if (o2 == null)
+         {
+            return false;
+         }
+         if (o.equals(o2))
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   public Iterator iterator()
+   {
+      Node node = cache.getRoot().getChild(getFqn());
+      if (node == null)
+      {
+         return Collections.EMPTY_SET.iterator();
+      }
+      return new IteratorImpl(node);
+   }
+
+   public boolean remove(Object o)
+   {
+      o = Null.toNullObject(o);
+      int hashCode = o.hashCode();
+      int size = size();
+      boolean removed = false;
+      Object oldkey = null;
+      for (int i = 0; i < size; i++)
+      {
+         Object key = toLong(hashCode, i);
+         Object o2 = getNoUnmask(key);
+         if (o2 == null)
+         {
+            break;
+         }
+         if (removed)
+         {
+            // move o2 to old key
+            detach(key);
+            attach(oldkey, o2);
+         }
+         if (o.equals(o2))
+         {
+            detach(key, true);
+            removed = true;
+         }
+         oldkey = key;
+      }
+      return removed;
+   }
+
+   public int size()
+   {
+      Set<Node> children = getNodeChildren();
+      return (children == null) ? 0 : children.size();
+   }
+
+   public String toString()
+   {
+      StringBuffer buf = new StringBuffer();
+      for (Iterator it = iterator(); it.hasNext();)
+      {
+         Object key = it.next();
+         if (key == interceptor.getBoundProxy())
+            key = "(this set)";
+         buf.append("[").append(key).append("]");
+         if (it.hasNext()) buf.append(", ");
+      }
+
+      return buf.toString();
+   }
+
+   /**
+    * Return a long with "count" as the high 32 bits.
+    * TODO should be able to use java.lang.Long, but some CacheLoader don't
+    * support non-String keys
+    */
+   private String toLong(long hashCode, long count)
+   {
+      long key = (hashCode & 0xFFFFL) | (count << 32);
+      return Long.toHexString(key);
+   }
+
+
+   private Object attach(Object key, Object pojo)
+   {
+      return attach(key, pojo, false);
+   }
+
+   private Object attach(Object key, Object pojo, boolean add)
+   {
+      Fqn fqn = AopUtil.constructFqn(getFqn(), key);
+      Object o = pojoCache.attach(fqn, pojo);
+      if (add)
+         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "ADD");
+
+      return o;
+   }
+
+   private Object detach(Object key)
+   {
+      return detach(key, false);
+   }
+
+   private Object detach(Object key, boolean remove)
+   {
+      Fqn fqn = AopUtil.constructFqn(getFqn(), key);
+      if (remove)
+         pojoCache.getCache().put(fqn, POJOCACHE_OPERATION, "REMOVE");
+
+      return pojoCache.detach(fqn);
+   }
+
+   private Object getNoUnmask(Object key)
+   {
+      return pojoCache.find(AopUtil.constructFqn(getFqn(), key));
+   }
+
+   public int hashCode()
+   {
+      int result = super.hashCode();
+      result = 29 * result + cache.hashCode();
+      result = 29 * result + interceptor.hashCode();
+      return result;
+   }
+
+   public boolean equals(Object o)
+   {
+      if (o == this)
+      {
+         return true;
+      }
+
+      try
+      {
+         return super.equals(o);
+      }
+      catch (ClassCastException e)
+      {
+         return false;
+      }
+      catch (NullPointerException unused)
+      {
+         return false;
+      }
+   }
+
+   private class IteratorImpl implements Iterator
+   {
+      private Iterator<NodeSPI> iterator;
+
+      private Node node;
+      private Object o;
+
+      private IteratorImpl(Node node)
+      {
+         Collection<NodeSPI> children = new HashSet<NodeSPI>(((NodeSPI) node).getChildrenDirect());
+         iterator = children.iterator();
+      }
+
+      public boolean hasNext()
+      {
+         return iterator.hasNext();
+      }
+
+      public Object next()
+      {
+         node = iterator.next();
+         o = Null.toNullValue(pojoCache.find(node.getFqn()));
+         return o;
+      }
+
+      public void remove() throws IllegalStateException
+      {
+         if (node == null)
+         {
+            throw new IllegalStateException();
+         }
+         CachedSetImpl.this.remove(o);
+      }
+
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,210 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.collection;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.AspectManager;
-import org.jboss.aop.InstanceAdvisor;
-import org.jboss.aop.advice.AdviceBinding;
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.aop.pointcut.ast.ParseException;
-import org.jboss.aop.proxy.ClassProxy;
-import org.jboss.aop.proxy.ClassProxyFactory;
-import org.jboss.aop.util.MethodHashing;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CachedListInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CachedMapInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CachedSetInterceptor;
-import org.jboss.cache.pojo.util.AopUtil;
-
-/**
- * CollectionInterceptorUtil contains helper methods for the interceptors of
- * the different collection types.
- *
- * @author <a href="mailto:harald at gliebe.de">Harald Gliebe</a>
- * @author Ben Wang
- */
-public class CollectionInterceptorUtil
-{
-   private static Log log = LogFactory.getLog(CollectionInterceptorUtil.class.getName());
-
-   private static ClassProxy createProxy(Class clazz, AbstractCollectionInterceptor interceptor)
-           throws Exception
-   {
-      ClassProxy result = ClassProxyFactory.newInstance(clazz, null, true);
-      InstanceAdvisor advisor = result._getInstanceAdvisor();
-      advisor.appendInterceptor(interceptor);
-
-      return result;
-   }
-
-   public static ClassProxy createMapProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Map obj) throws Exception
-   {
-      return CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache, fqn, clazz, obj));
-   }
-
-   public static ClassProxy createListProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, List obj) throws Exception
-   {
-      return CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache, fqn, clazz, obj));
-   }
-
-   public static ClassProxy createSetProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Set obj) throws Exception
-   {
-      return CollectionInterceptorUtil.createProxy(clazz, new CachedSetInterceptor(cache, fqn, clazz, obj));
-   }
-
-   public static AbstractCollectionInterceptor getInterceptor(ClassProxy proxy)
-   {
-      InstanceAdvisor advisor = proxy._getInstanceAdvisor();
-      return (AbstractCollectionInterceptor) AopUtil.findCollectionInterceptor(advisor);
-   }
-
-   public static Map getMethodMap(Class clazz)
-   {
-      Map result = ClassProxyFactory.getMethodMap(clazz.getName());
-      if (result == null)
-      {
-         try
-         {
-            ClassProxyFactory.newInstance(clazz);
-         }
-         catch (Exception e)
-         {
-            throw new PojoCacheException(e);
-         }
-         result = ClassProxyFactory.getMethodMap(clazz.getName());
-      }
-      return result;
-   }
-
-   public static Map getManagedMethods(Class clazz)
-   {
-      Method tostring = null;
-      try
-      {
-         tostring = Object.class.getDeclaredMethod("toString", new Class[0]);
-      }
-      catch (NoSuchMethodException e)
-      {
-         throw new PojoCacheException(e);
-      }
-
-      Map managedMethods = new HashMap();
-      try
-      {
-         Method[] methods = clazz.getDeclaredMethods();
-         for (int i = 0; i < methods.length; i++)
-         {
-            long hash = MethodHashing.methodHash(methods[i]);
-            managedMethods.put(hash, methods[i]);
-         }
-         // Add toString to ManagedMethod
-         long hash = MethodHashing.methodHash(tostring);
-         managedMethods.put(hash, tostring);
-      }
-      catch (Exception ignored)
-      {
-         log.trace(ignored, ignored);
-      }
-      return managedMethods;
-   }
-
-   private static boolean skipVerify(Method method)
-   {
-      String name = method.getName();
-      Class<?>[] types = method.getParameterTypes();
-      if ("toString".equals(name) && types.length == 0)
-         return true;
-
-      return false;
-   }
-
-   public static Object invoke(Invocation invocation,
-                               AbstractCollectionInterceptor interceptor,
-                               Object impl,
-                               Map methodMap, Map managedMethods)
-           throws Throwable
-   {
-
-      try
-      {
-         if (invocation instanceof MethodInvocation)
-         {
-            MethodInvocation methodInvocation = (MethodInvocation) invocation;
-            Long methodHash = methodInvocation.getMethodHash();
-            Method method = (Method) managedMethods.get(methodHash);
-            if (log.isTraceEnabled() && method != null)
-            {
-               log.trace("invoke(): method intercepted " + method.getName());
-            }
-
-            if (writeReplaceInvocation(methodInvocation)) {
-               if (!skipVerify(methodInvocation.getMethod()))
-                  interceptor.verifyAttached(impl);
-
-               return interceptor.getSerializationCopy();
-            }
-
-            Object[] args = methodInvocation.getArguments();
-            if (method != null)
-            {
-               if (!skipVerify(method))
-                  interceptor.verifyAttached(impl);
-
-               return method.invoke(impl, args);
-            } else
-            {
-               method = methodInvocation.getMethod();
-               if (method == null)
-               {
-                  method = (Method) methodMap.get(methodHash);
-               }
-
-               if (log.isTraceEnabled())
-                  log.trace("invoke(): non-managed method: " + method.toString());
-               Object target = methodInvocation.getTargetObject();
-               if (target == null)
-               {
-                  throw new PojoCacheException("CollectionInterceptorUtil.invoke(): targetObject is null." +
-                          " Can't invoke " + method.toString());
-               }
-               return method.invoke(target, args);
-               //            return method.invoke(interceptor, args);
-            }
-         }
-      }
-      catch (InvocationTargetException e)
-      {
-         if (e.getCause() != null)
-            throw e.getCause();
-         else if (e.getTargetException() != null)
-            throw e.getTargetException();
-         throw e;
-      }
-
-      return invocation.invokeNext();
-   }
-
-   private static boolean writeReplaceInvocation(MethodInvocation methodInvocation)
-   {
-      Method method = methodInvocation.getMethod();
-      return "writeReplace".equals(method.getName()) && method.getParameterTypes().length == 0;
-   }
-
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/collection/CollectionInterceptorUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,211 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.collection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.AspectManager;
+import org.jboss.aop.InstanceAdvisor;
+import org.jboss.aop.advice.AdviceBinding;
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.aop.pointcut.ast.ParseException;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.aop.proxy.ClassProxyFactory;
+import org.jboss.aop.util.MethodHashing;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.CachedListInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.CachedMapInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.CachedSetInterceptor;
+import org.jboss.cache.pojo.util.AopUtil;
+
+/**
+ * CollectionInterceptorUtil contains helper methods for the interceptors of
+ * the different collection types.
+ *
+ * @author <a href="mailto:harald at gliebe.de">Harald Gliebe</a>
+ * @author Ben Wang
+ */
+public class CollectionInterceptorUtil
+{
+   private static Log log = LogFactory.getLog(CollectionInterceptorUtil.class.getName());
+
+   private static ClassProxy createProxy(Class clazz, AbstractCollectionInterceptor interceptor)
+           throws Exception
+   {
+      ClassProxy result = ClassProxyFactory.newInstance(clazz, null, true);
+      InstanceAdvisor advisor = result._getInstanceAdvisor();
+      advisor.appendInterceptor(interceptor);
+      interceptor.setBoundProxy(result);
+
+      return result;
+   }
+
+   public static ClassProxy createMapProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Map obj) throws Exception
+   {
+      return CollectionInterceptorUtil.createProxy(clazz, new CachedMapInterceptor(cache, fqn, clazz, obj));
+   }
+
+   public static ClassProxy createListProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, List obj) throws Exception
+   {
+      return CollectionInterceptorUtil.createProxy(clazz, new CachedListInterceptor(cache, fqn, clazz, obj));
+   }
+
+   public static ClassProxy createSetProxy(PojoCacheImpl cache, Fqn fqn, Class clazz, Set obj) throws Exception
+   {
+      return CollectionInterceptorUtil.createProxy(clazz, new CachedSetInterceptor(cache, fqn, clazz, obj));
+   }
+
+   public static AbstractCollectionInterceptor getInterceptor(ClassProxy proxy)
+   {
+      InstanceAdvisor advisor = proxy._getInstanceAdvisor();
+      return (AbstractCollectionInterceptor) AopUtil.findCollectionInterceptor(advisor);
+   }
+
+   public static Map getMethodMap(Class clazz)
+   {
+      Map result = ClassProxyFactory.getMethodMap(clazz.getName());
+      if (result == null)
+      {
+         try
+         {
+            ClassProxyFactory.newInstance(clazz);
+         }
+         catch (Exception e)
+         {
+            throw new PojoCacheException(e);
+         }
+         result = ClassProxyFactory.getMethodMap(clazz.getName());
+      }
+      return result;
+   }
+
+   public static Map getManagedMethods(Class clazz)
+   {
+      Method tostring = null;
+      try
+      {
+         tostring = Object.class.getDeclaredMethod("toString", new Class[0]);
+      }
+      catch (NoSuchMethodException e)
+      {
+         throw new PojoCacheException(e);
+      }
+
+      Map managedMethods = new HashMap();
+      try
+      {
+         Method[] methods = clazz.getDeclaredMethods();
+         for (int i = 0; i < methods.length; i++)
+         {
+            long hash = MethodHashing.methodHash(methods[i]);
+            managedMethods.put(hash, methods[i]);
+         }
+         // Add toString to ManagedMethod
+         long hash = MethodHashing.methodHash(tostring);
+         managedMethods.put(hash, tostring);
+      }
+      catch (Exception ignored)
+      {
+         log.trace(ignored, ignored);
+      }
+      return managedMethods;
+   }
+
+   private static boolean skipVerify(Method method)
+   {
+      String name = method.getName();
+      Class<?>[] types = method.getParameterTypes();
+      if ("toString".equals(name) && types.length == 0)
+         return true;
+
+      return false;
+   }
+
+   public static Object invoke(Invocation invocation,
+                               AbstractCollectionInterceptor interceptor,
+                               Object impl,
+                               Map methodMap, Map managedMethods)
+           throws Throwable
+   {
+
+      try
+      {
+         if (invocation instanceof MethodInvocation)
+         {
+            MethodInvocation methodInvocation = (MethodInvocation) invocation;
+            Long methodHash = methodInvocation.getMethodHash();
+            Method method = (Method) managedMethods.get(methodHash);
+            if (log.isTraceEnabled() && method != null)
+            {
+               log.trace("invoke(): method intercepted " + method.getName());
+            }
+
+            if (writeReplaceInvocation(methodInvocation)) {
+               if (!skipVerify(methodInvocation.getMethod()))
+                  interceptor.verifyAttached(impl);
+
+               return interceptor.getSerializationCopy();
+            }
+
+            Object[] args = methodInvocation.getArguments();
+            if (method != null)
+            {
+               if (!skipVerify(method))
+                  interceptor.verifyAttached(impl);
+
+               return method.invoke(impl, args);
+            } else
+            {
+               method = methodInvocation.getMethod();
+               if (method == null)
+               {
+                  method = (Method) methodMap.get(methodHash);
+               }
+
+               if (log.isTraceEnabled())
+                  log.trace("invoke(): non-managed method: " + method.toString());
+               Object target = methodInvocation.getTargetObject();
+               if (target == null)
+               {
+                  throw new PojoCacheException("CollectionInterceptorUtil.invoke(): targetObject is null." +
+                          " Can't invoke " + method.toString());
+               }
+               return method.invoke(target, args);
+               //            return method.invoke(interceptor, args);
+            }
+         }
+      }
+      catch (InvocationTargetException e)
+      {
+         if (e.getCause() != null)
+            throw e.getCause();
+         else if (e.getTargetException() != null)
+            throw e.getTargetException();
+         throw e;
+      }
+
+      return invocation.invokeNext();
+   }
+
+   private static boolean writeReplaceInvocation(MethodInvocation methodInvocation)
+   {
+      Method method = methodInvocation.getMethod();
+      return "writeReplace".equals(method.getName()) && method.getParameterTypes().length == 0;
+   }
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,257 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt 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.cache.pojo.impl;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.Advised;
-import org.jboss.aop.ClassInstanceAdvisor;
-import org.jboss.aop.InstanceAdvisor;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
-import org.jboss.cache.pojo.memory.FieldPersistentReference;
-import org.jboss.cache.pojo.util.AopUtil;
-import org.jboss.cache.pojo.util.Instantiator;
-import org.jboss.cache.pojo.util.ObjectUtil;
-
-/**
- * Handling the advised pojo operations. No consideration of object graph here.
- *
- * @author Ben Wang
- *         Date: Aug 4, 2005
- * @version $Id$
- */
-class AdvisedPojoHandler extends AbstractHandler
-{
-   private final Log log = LogFactory.getLog(AdvisedPojoHandler.class);
-   private Cache<Object, Object> cache_;
-   private PojoCacheImpl pCache_;
-   private PojoUtil util_;
-
-   public AdvisedPojoHandler(PojoCacheImpl pCache, InternalHelper internal,
-                             PojoUtil util)
-   {
-      pCache_ = pCache;
-      cache_ = pCache_.getCache();
-      util_ = util;
-   }
-
-   @Override
-   protected Fqn<?> getFqn(Object obj)
-   {
-      if (obj instanceof Advised)
-      {
-         InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
-         if (advisor == null)
-            throw new PojoCacheException("_putObject(): InstanceAdvisor is null for: " + obj);
-
-         // Step Check for cross references
-         BaseInterceptor interceptor = AopUtil.findCacheInterceptor(advisor);
-         if (interceptor != null)
-            return interceptor.getFqn();
-      }
-
-      return null;
-   }
-
-   @Override
-   protected Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance) throws CacheException
-   {
-      CachedType type = pCache_.getCachedType(clazz);
-      Object obj = Instantiator.newInstance(clazz);
-
-      // Eager initialize final fields, since these may not be intercepted
-
-      try
-      {
-         for (FieldPersistentReference ref : type.getFinalFields())
-         {
-            Field field = ref.getField();
-            Object result;
-
-            if (CachedType.isSimpleAttribute(field))
-               result = cache_.get(fqn, field.getName());
-            else
-               result = pCache_.getObject(fqn, field.getName(), obj);
-
-            field.set(obj, result);
-         }
-      }
-      catch (Exception e)
-      {
-         log.warn("Could not initialize final fields on object: " + ObjectUtil.identityString(obj));
-      }
-
-      InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
-      CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
-      interceptor.setAopInstance(pojoInstance);
-      util_.attachInterceptor(obj, advisor, interceptor);
-      return obj;
-   }
-
-   @Override
-   protected void put(Fqn<?> fqn, Fqn<?> referencingFqn, Object obj) throws CacheException
-   {
-      CachedType type = pCache_.getCachedType(obj.getClass());
-      // We have a clean slate then.
-      InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
-      // TODO workaround for deserialiased objects
-      if (advisor == null)
-      {
-         advisor = new ClassInstanceAdvisor(obj);
-         ((Advised) obj)._setInstanceAdvisor(advisor);
-      }
-
-      // Let's do batch update via Map instead
-      Map map = new HashMap();
-      // Always initialize the ref count so we can mark this as an AopNode.
-      PojoInstance pojoInstance = InternalHelper.initializeAopInstance(referencingFqn);
-      map.put(PojoInstance.KEY, pojoInstance);
-      pojoInstance.setPojoClass(type.getType());
-      // we will do it recursively.
-      // Map of sub-objects that are non-primitive
-      Map subPojoMap = new HashMap();
-
-      for (Iterator i = type.getFields().iterator(); i.hasNext();)
-      {
-         Field field = (Field) (((FieldPersistentReference) i.next())).get();
-         Object value = null;
-         try
-         {
-            value = field.get(obj);
-         }
-         catch (IllegalAccessException e)
-         {
-            throw new CacheException("field access failed", e);
-         }
-
-         // we simply treat field that has @Serializable as a primitive type.
-         if (CachedType.isSimpleAttribute(field))
-         {
-            // switched using batch update
-            map.put(field.getName(), value);
-         }
-         else
-         {
-            subPojoMap.put(field, value);
-         }
-      }
-
-      // Use option to skip locking since we have parent lock already.
-//      cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
-
-      cache_.getRoot().addChild(fqn).putAll(map);
-
-      // Insert interceptor after PojoInstance has been written to the cache
-      // This prevents JBCACHE-1078 with pessimistic locking, optimistic is still a problem
-      CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
-      interceptor.setAopInstance(pojoInstance);
-      util_.attachInterceptor(obj, advisor, interceptor);
-
-//      cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(false);
-      // This is in-memory operation only
-      InternalHelper.setPojo(pojoInstance, obj);
-
-      for (Object o : subPojoMap.keySet())
-      {
-         Field field = (Field) o;
-         Object value = subPojoMap.get(field);
-         if (value == null) continue; // really no need to map the POJO.
-         pCache_.attach(fqn, value, field.getName(), obj);
-         // If it is Collection classes, we replace it with dynamic proxy.
-         // But we will have to ignore it if value is null
-         if (value instanceof Map || value instanceof List || value instanceof Set)
-         {
-            Object newValue = pCache_.getObject(fqn, field.getName(), obj);
-            util_.inMemorySubstitution(obj, field, newValue);
-         }
-      }
-
-      // Need to make sure this is behind put such that obj.toString is done correctly.
-      if (log.isDebugEnabled())
-      {
-         log.debug("internalPut(): inserting with fqn: " + fqn);
-      }
-   }
-
-   @Override
-   protected Object remove(Fqn<?> fqn, Fqn<?> referencingFqn, Object result) throws CacheException
-   {
-      CachedType type = pCache_.getCachedType(result.getClass());
-      InstanceAdvisor advisor = ((Advised) result)._getInstanceAdvisor();
-      for (Iterator i = type.getFields().iterator(); i.hasNext();)
-      {
-         Field field = (Field) (((FieldPersistentReference) i.next())).get();
-         Object value = null;
-
-         if (! CachedType.isSimpleAttribute(field))
-         {
-            value = pCache_.detach(fqn, field.getName(), result);
-
-            // Check for Collection. If it is, we need to reset the original reference.
-            if ((value instanceof Map || value instanceof List || value instanceof Set))
-            {
-               // If this Collection class, we are returning the original value already
-               util_.inMemorySubstitution(result, field, value);
-            }
-         }
-         else
-         {
-            // Update last known field state
-            value = cache_.get(fqn,  field.getName());
-            util_.inMemorySubstitution(result, field, value);
-         }
-      }
-
-      cache_.removeNode(fqn);
-      // Determine if we want to keep the interceptor for later use.
-      CacheFieldInterceptor interceptor = (CacheFieldInterceptor) AopUtil.findCacheInterceptor(advisor);
-      // Remember to remove the interceptor from in-memory object but make sure it belongs to me first.
-      if (interceptor != null)
-      {
-         if (log.isDebugEnabled())
-         {
-            log.debug("regularRemoveObject(): removed cache interceptor fqn: " + fqn + " interceptor: " + interceptor);
-         }
-         util_.detachInterceptor(advisor, interceptor);
-      }
-
-      return result;
-   }
-
-   @Override
-   protected boolean handles(Class<?> clazz)
-   {
-      return Advised.class.isAssignableFrom(clazz);
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,257 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt 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.cache.pojo.impl;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.Advised;
+import org.jboss.aop.ClassInstanceAdvisor;
+import org.jboss.aop.InstanceAdvisor;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
+import org.jboss.cache.pojo.memory.FieldPersistentReference;
+import org.jboss.cache.pojo.util.AopUtil;
+import org.jboss.cache.pojo.util.Instantiator;
+import org.jboss.cache.pojo.util.ObjectUtil;
+
+/**
+ * Handling the advised pojo operations. No consideration of object graph here.
+ *
+ * @author Ben Wang
+ *         Date: Aug 4, 2005
+ * @version $Id$
+ */
+class AdvisedPojoHandler extends AbstractHandler
+{
+   private final Log log = LogFactory.getLog(AdvisedPojoHandler.class);
+   private Cache<Object, Object> cache_;
+   private PojoCacheImpl pCache_;
+   private PojoUtil util_;
+
+   public AdvisedPojoHandler(PojoCacheImpl pCache, InternalHelper internal,
+                             PojoUtil util)
+   {
+      pCache_ = pCache;
+      cache_ = pCache_.getCache();
+      util_ = util;
+   }
+
+   @Override
+   protected Fqn<?> getFqn(Object obj)
+   {
+      if (obj instanceof Advised)
+      {
+         InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
+         if (advisor == null)
+            throw new PojoCacheException("_putObject(): InstanceAdvisor is null for: " + obj);
+
+         // Step Check for cross references
+         BaseInterceptor interceptor = AopUtil.findCacheInterceptor(advisor);
+         if (interceptor != null)
+            return interceptor.getFqn();
+      }
+
+      return null;
+   }
+
+   @Override
+   protected Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance) throws CacheException
+   {
+      CachedType type = pCache_.getCachedType(clazz);
+      Object obj = Instantiator.newInstance(clazz);
+
+      // Eager initialize final fields, since these may not be intercepted
+
+      try
+      {
+         for (FieldPersistentReference ref : type.getFinalFields())
+         {
+            Field field = ref.getField();
+            Object result;
+
+            if (CachedType.isSimpleAttribute(field))
+               result = cache_.get(fqn, field.getName());
+            else
+               result = pCache_.find(fqn, field.getName(), obj);
+
+            field.set(obj, result);
+         }
+      }
+      catch (Exception e)
+      {
+         log.warn("Could not initialize final fields on object: " + ObjectUtil.identityString(obj));
+      }
+
+      InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
+      CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
+      interceptor.setAopInstance(pojoInstance);
+      util_.attachInterceptor(obj, advisor, interceptor);
+      return obj;
+   }
+
+   @Override
+   protected void put(Fqn<?> fqn, Fqn<?> referencingFqn, Object obj) throws CacheException
+   {
+      CachedType type = pCache_.getCachedType(obj.getClass());
+      // We have a clean slate then.
+      InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
+      // TODO workaround for deserialiased objects
+      if (advisor == null)
+      {
+         advisor = new ClassInstanceAdvisor(obj);
+         ((Advised) obj)._setInstanceAdvisor(advisor);
+      }
+
+      // Let's do batch update via Map instead
+      Map map = new HashMap();
+      // Always initialize the ref count so we can mark this as an AopNode.
+      PojoInstance pojoInstance = InternalHelper.initializeAopInstance(referencingFqn);
+      map.put(PojoInstance.KEY, pojoInstance);
+      pojoInstance.setPojoClass(type.getType());
+      // we will do it recursively.
+      // Map of sub-objects that are non-primitive
+      Map subPojoMap = new HashMap();
+
+      for (Iterator i = type.getFields().iterator(); i.hasNext();)
+      {
+         Field field = (Field) (((FieldPersistentReference) i.next())).get();
+         Object value = null;
+         try
+         {
+            value = field.get(obj);
+         }
+         catch (IllegalAccessException e)
+         {
+            throw new CacheException("field access failed", e);
+         }
+
+         // we simply treat field that has @Serializable as a primitive type.
+         if (CachedType.isSimpleAttribute(field))
+         {
+            // switched using batch update
+            map.put(field.getName(), value);
+         }
+         else
+         {
+            subPojoMap.put(field, value);
+         }
+      }
+
+      // Use option to skip locking since we have parent lock already.
+//      cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
+
+      cache_.getRoot().addChild(fqn).putAll(map);
+
+      // Insert interceptor after PojoInstance has been written to the cache
+      // This prevents JBCACHE-1078 with pessimistic locking, optimistic is still a problem
+      CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
+      interceptor.setAopInstance(pojoInstance);
+      util_.attachInterceptor(obj, advisor, interceptor);
+
+//      cache_.getInvocationContext().getOptionOverrides().setSuppressLocking(false);
+      // This is in-memory operation only
+      InternalHelper.setPojo(pojoInstance, obj);
+
+      for (Object o : subPojoMap.keySet())
+      {
+         Field field = (Field) o;
+         Object value = subPojoMap.get(field);
+         if (value == null) continue; // really no need to map the POJO.
+         pCache_.attach(fqn, value, field.getName(), obj);
+         // If it is Collection classes, we replace it with dynamic proxy.
+         // But we will have to ignore it if value is null
+         if (value instanceof Map || value instanceof List || value instanceof Set)
+         {
+            Object newValue = pCache_.find(fqn, field.getName(), obj);
+            util_.inMemorySubstitution(obj, field, newValue);
+         }
+      }
+
+      // Need to make sure this is behind put such that obj.toString is done correctly.
+      if (log.isDebugEnabled())
+      {
+         log.debug("internalPut(): inserting with fqn: " + fqn);
+      }
+   }
+
+   @Override
+   protected Object remove(Fqn<?> fqn, Fqn<?> referencingFqn, Object result) throws CacheException
+   {
+      CachedType type = pCache_.getCachedType(result.getClass());
+      InstanceAdvisor advisor = ((Advised) result)._getInstanceAdvisor();
+      for (Iterator i = type.getFields().iterator(); i.hasNext();)
+      {
+         Field field = (Field) (((FieldPersistentReference) i.next())).get();
+         Object value = null;
+
+         if (! CachedType.isSimpleAttribute(field))
+         {
+            value = pCache_.detach(fqn, field.getName(), result);
+
+            // Check for Collection. If it is, we need to reset the original reference.
+            if ((value instanceof Map || value instanceof List || value instanceof Set))
+            {
+               // If this Collection class, we are returning the original value already
+               util_.inMemorySubstitution(result, field, value);
+            }
+         }
+         else
+         {
+            // Update last known field state
+            value = cache_.get(fqn,  field.getName());
+            util_.inMemorySubstitution(result, field, value);
+         }
+      }
+
+      cache_.removeNode(fqn);
+      // Determine if we want to keep the interceptor for later use.
+      CacheFieldInterceptor interceptor = (CacheFieldInterceptor) AopUtil.findCacheInterceptor(advisor);
+      // Remember to remove the interceptor from in-memory object but make sure it belongs to me first.
+      if (interceptor != null)
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("regularRemoveObject(): removed cache interceptor fqn: " + fqn + " interceptor: " + interceptor);
+         }
+         util_.detachInterceptor(advisor, interceptor);
+      }
+
+      return result;
+   }
+
+   @Override
+   protected boolean handles(Class<?> clazz)
+   {
+      return Advised.class.isAssignableFrom(clazz);
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,293 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt 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.cache.pojo.impl;
-
-import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_COMPLETED;
-import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_REGISTERED;
-import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
-import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_STATUS;
-
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import javax.transaction.Transaction;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.notifications.annotation.CacheListener;
-import org.jboss.cache.notifications.annotation.NodeModified;
-import org.jboss.cache.notifications.annotation.TransactionCompleted;
-import org.jboss.cache.notifications.annotation.TransactionRegistered;
-import org.jboss.cache.notifications.event.NodeModifiedEvent;
-import org.jboss.cache.notifications.event.TransactionalEvent;
-import org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.interceptors.PojoTxLockInterceptor;
-import org.jboss.cache.pojo.notification.NotificationContext;
-import org.jboss.cache.pojo.notification.event.ArrayModifiedEvent;
-import org.jboss.cache.pojo.notification.event.AttachedEvent;
-import org.jboss.cache.pojo.notification.event.DetachedEvent;
-import org.jboss.cache.pojo.notification.event.Event;
-import org.jboss.cache.pojo.notification.event.FieldModifiedEvent;
-import org.jboss.cache.pojo.notification.event.ListModifiedEvent;
-import org.jboss.cache.pojo.notification.event.MapModifiedEvent;
-import org.jboss.cache.pojo.notification.event.SetModifiedEvent;
-import org.jboss.cache.pojo.notification.event.TransactionCompletedEvent;
-import org.jboss.cache.pojo.notification.event.TransactionRegisteredEvent;
-
-// $Id$
-
-/**
- * Adapts the core cache listener API into the POJO listener API.
- *
- * @author Jason T. Greene
- */
- at CacheListener
-public class CacheListenerAdaptor
-{
-   private static final HashSet<String> internalKeys = new HashSet<String>();
-   private static final Log log = LogFactory.getLog(CacheListenerAdaptor.class);
-
-   static
-   {
-      internalKeys.add(POJOCACHE_STATUS);
-      internalKeys.add(POJOCACHE_OPERATION);
-      internalKeys.add(PojoInstance.KEY);
-      internalKeys.add(PojoReference.KEY);
-      internalKeys.add(PojoTxLockInterceptor.LOCK_KEY);
-   }
-
-   private PojoCacheImpl cache;
-   private NotificationDispatcher dispatcher = new NotificationDispatcher();
-
-   public CacheListenerAdaptor(PojoCacheImpl cache)
-   {
-      this.cache = cache;
-   }
-
-   public PojoCache getPojoCache()
-   {
-      return this.cache;
-   }
-
-   private FieldModifiedEvent createModifyEvent(NotificationContext context, Fqn fqn, String key, Object value, boolean local)
-   {
-      if (value instanceof PojoReference)
-         value = cache.find(((PojoReference) value).getFqn().toString());
-
-      Object o = cache.find(fqn.toString());
-      // Detached
-      if (o == null)
-         return null;
-
-      Field f;
-      try
-      {
-         f = o.getClass().getDeclaredField(key);
-      }
-      catch (NoSuchFieldException e)
-      {
-         if (log.isWarnEnabled())
-            log.warn("Could not get field " + key + " on class " + o.getClass());
-         return null;
-      }
-
-      return new FieldModifiedEvent(context, o, f, value, local);
-   }
-
-   private NotificationContext createContext(final TransactionalEvent event)
-   {
-      return new NotificationContext()
-      {
-
-         public PojoCache getPojoCache()
-         {
-            return CacheListenerAdaptor.this.getPojoCache();
-         }
-
-         public Transaction getTransaction()
-         {
-            return event.getTransaction();
-         }
-      };
-   }
-
-   private void sendNotification(Event notification, Set<NotificationDispatcher.Entry> listeners)
-   {
-      if (notification == null)
-         return;
-
-      if (listeners == null)
-         dispatcher.dispatch(notification);
-      else
-         dispatcher.dispatch(notification, listeners);
-   }
-
-   @TransactionCompleted
-   @TransactionRegistered
-   public void handleTransaction(TransactionalEvent event)
-   {
-      if (event.getType() == TRANSACTION_COMPLETED)
-      {
-         boolean successful = ((org.jboss.cache.notifications.event.TransactionCompletedEvent) event).isSuccessful();
-         sendNotification(new TransactionCompletedEvent(createContext(event), successful, event.isOriginLocal()), null);
-      }
-      else if (event.getType() == TRANSACTION_REGISTERED)
-      {
-         sendNotification(new TransactionRegisteredEvent(createContext(event), event.isOriginLocal()), null);
-      }
-   }
-
-   @NodeModified
-   public void nodeModified(NodeModifiedEvent event)
-   {
-      Map<Object, Object> data = event.getData();
-      boolean pre = event.isPre();
-      Fqn fqn = event.getFqn();
-      ModificationType modType = event.getModificationType();
-      boolean isLocal = event.isOriginLocal();
-
-      if (pre)
-         return;
-
-      //System.out.println(fqn + " " + modType + " " + data);
-
-      // If we are filtering, don't load as much as possible
-      Set<NotificationDispatcher.Entry> matched = null;
-      if (dispatcher.hasFilters())
-      {
-         matched = matchListeners(fqn);
-         if (matched != null && matched.isEmpty())
-            return;
-      }
-
-      if (modType == ModificationType.PUT_DATA)
-      {
-         if ("ATTACHED".equals(data.get(POJOCACHE_STATUS)))
-         {
-            Object o = cache.find(fqn.toString());
-            sendNotification(new AttachedEvent(createContext(event), o, isLocal), matched);
-         }
-         else if ("DETACHING".equals(data.get(POJOCACHE_STATUS)))
-         {
-            Object o = cache.find(fqn.toString());
-            sendNotification(new DetachedEvent(createContext(event), o, isLocal), matched);
-         }
-         else if (data.containsKey(POJOCACHE_OPERATION))
-         {
-            Object collection = cache.find(fqn.getParent().toString());
-            if (collection instanceof List)
-            {
-               int i = Integer.parseInt(fqn.getLastElementAsString());
-               ListModifiedEvent.Operation operation = ListModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
-               Object value = cache.find(fqn.toString());
-               sendNotification(new ListModifiedEvent(createContext(event), (List) collection, operation, i, value, isLocal), matched);
-            }
-            else if (collection instanceof Set)
-            {
-               SetModifiedEvent.Operation operation = SetModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
-               Object value = cache.find(fqn.toString());
-               sendNotification(new SetModifiedEvent(createContext(event), (Set) collection, operation, value, isLocal), matched);
-            }
-            else if (collection instanceof Map)
-            {
-               MapModifiedEvent.Operation operation = MapModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
-               Object value = cache.find(fqn.toString());
-               sendNotification(new MapModifiedEvent(createContext(event), (Map) collection, operation, fqn.getLastElement(), value, isLocal), matched);
-            }
-            else if (collection instanceof Object[]) {
-               int i = Integer.parseInt(fqn.getLastElementAsString());
-               Object value = cache.find(fqn.toString());
-               sendNotification(new ArrayModifiedEvent(createContext(event), collection, i, value, isLocal), matched);
-            }
-         }
-         else if ("ATTACHED".equals(cache.getCache().get(fqn, POJOCACHE_STATUS)))
-         {
-            for (Map.Entry entry : data.entrySet())
-            {
-               String key = entry.getKey().toString();
-               Object value = entry.getValue();
-
-               if (internalKeys.contains(key))
-                  continue;
-
-               sendNotification(createModifyEvent(createContext(event), fqn, key, value, isLocal), matched);
-            }
-         }
-      }
-      else if (modType == ModificationType.REMOVE_DATA)
-      {
-         for (Map.Entry entry : data.entrySet())
-         {
-            String key = entry.getKey().toString();
-            if (internalKeys.contains(key))
-               continue;
-
-            sendNotification(createModifyEvent(createContext(event), fqn, key, null, isLocal), matched);
-         }
-      }
-   }
-
-   private Set<NotificationDispatcher.Entry> matchListeners(Fqn fqn)
-   {
-      PojoInstance instance = (PojoInstance) cache.getCache().get(fqn, PojoInstance.KEY);
-      if (instance != null)
-         return dispatcher.getListenerEntries(instance.getReferences());
-
-      return null;
-   }
-
-   public boolean isEmpty()
-   {
-      return dispatcher.isEmpty();
-   }
-
-   public Collection<Object> getListeners()
-   {
-      return dispatcher.getListeners();
-   }
-
-   public void addListener(Object listener)
-   {
-      dispatcher.add(listener);
-   }
-
-   public void addListener(Object listener, Pattern pattern)
-   {
-      if (pattern == null)
-         dispatcher.add(listener);
-      else
-         dispatcher.add(listener, pattern);
-   }
-
-   public void removeListener(Object listener)
-   {
-      dispatcher.remove(listener);
-   }
-}
\ No newline at end of file

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/CacheListenerAdaptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,293 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.cache.pojo.impl;
+
+import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_COMPLETED;
+import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_REGISTERED;
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_OPERATION;
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_STATUS;
+import static org.jboss.cache.pojo.impl.InternalConstant.POJOCACHE_LOCK;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.transaction.Transaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.TransactionCompleted;
+import org.jboss.cache.notifications.annotation.TransactionRegistered;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.TransactionalEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.notification.NotificationContext;
+import org.jboss.cache.pojo.notification.event.ArrayModifiedEvent;
+import org.jboss.cache.pojo.notification.event.AttachedEvent;
+import org.jboss.cache.pojo.notification.event.DetachedEvent;
+import org.jboss.cache.pojo.notification.event.Event;
+import org.jboss.cache.pojo.notification.event.FieldModifiedEvent;
+import org.jboss.cache.pojo.notification.event.ListModifiedEvent;
+import org.jboss.cache.pojo.notification.event.MapModifiedEvent;
+import org.jboss.cache.pojo.notification.event.SetModifiedEvent;
+import org.jboss.cache.pojo.notification.event.TransactionCompletedEvent;
+import org.jboss.cache.pojo.notification.event.TransactionRegisteredEvent;
+
+// $Id$
+
+/**
+ * Adapts the core cache listener API into the POJO listener API.
+ *
+ * @author Jason T. Greene
+ */
+ at CacheListener
+public class CacheListenerAdaptor
+{
+   private static final HashSet<String> internalKeys = new HashSet<String>();
+   private static final Log log = LogFactory.getLog(CacheListenerAdaptor.class);
+
+   static
+   {
+      internalKeys.add(POJOCACHE_STATUS);
+      internalKeys.add(POJOCACHE_OPERATION);
+      internalKeys.add(PojoInstance.KEY);
+      internalKeys.add(PojoReference.KEY);
+      internalKeys.add(POJOCACHE_LOCK);
+   }
+
+   private PojoCacheImpl cache;
+   private NotificationDispatcher dispatcher = new NotificationDispatcher();
+
+   public CacheListenerAdaptor(PojoCacheImpl cache)
+   {
+      this.cache = cache;
+   }
+
+   public PojoCache getPojoCache()
+   {
+      return this.cache;
+   }
+
+   private FieldModifiedEvent createModifyEvent(NotificationContext context, Fqn fqn, String key, Object value, boolean local)
+   {
+      if (value instanceof PojoReference)
+         value = cache.find(((PojoReference) value).getFqn().toString());
+
+      Object o = cache.find(fqn.toString());
+      // Detached
+      if (o == null)
+         return null;
+
+      Field f;
+      try
+      {
+         f = o.getClass().getDeclaredField(key);
+      }
+      catch (NoSuchFieldException e)
+      {
+         if (log.isWarnEnabled())
+            log.warn("Could not get field " + key + " on class " + o.getClass());
+         return null;
+      }
+
+      return new FieldModifiedEvent(context, o, f, value, local);
+   }
+
+   private NotificationContext createContext(final TransactionalEvent event)
+   {
+      return new NotificationContext()
+      {
+
+         public PojoCache getPojoCache()
+         {
+            return CacheListenerAdaptor.this.getPojoCache();
+         }
+
+         public Transaction getTransaction()
+         {
+            return event.getTransaction();
+         }
+      };
+   }
+
+   private void sendNotification(Event notification, Set<NotificationDispatcher.Entry> listeners)
+   {
+      if (notification == null)
+         return;
+
+      if (listeners == null)
+         dispatcher.dispatch(notification);
+      else
+         dispatcher.dispatch(notification, listeners);
+   }
+
+   @TransactionCompleted
+   @TransactionRegistered
+   public void handleTransaction(TransactionalEvent event)
+   {
+      if (event.getType() == TRANSACTION_COMPLETED)
+      {
+         boolean successful = ((org.jboss.cache.notifications.event.TransactionCompletedEvent) event).isSuccessful();
+         sendNotification(new TransactionCompletedEvent(createContext(event), successful, event.isOriginLocal()), null);
+      }
+      else if (event.getType() == TRANSACTION_REGISTERED)
+      {
+         sendNotification(new TransactionRegisteredEvent(createContext(event), event.isOriginLocal()), null);
+      }
+   }
+
+   @NodeModified
+   public void nodeModified(NodeModifiedEvent event)
+   {
+      Map<Object, Object> data = event.getData();
+      boolean pre = event.isPre();
+      Fqn fqn = event.getFqn();
+      ModificationType modType = event.getModificationType();
+      boolean isLocal = event.isOriginLocal();
+
+      if (pre)
+         return;
+
+      //System.out.println(fqn + " " + modType + " " + data);
+
+      // If we are filtering, don't load as much as possible
+      Set<NotificationDispatcher.Entry> matched = null;
+      if (dispatcher.hasFilters())
+      {
+         matched = matchListeners(fqn);
+         if (matched != null && matched.isEmpty())
+            return;
+      }
+
+      if (modType == ModificationType.PUT_DATA)
+      {
+         if ("ATTACHED".equals(data.get(POJOCACHE_STATUS)))
+         {
+            Object o = cache.find(fqn.toString());
+            sendNotification(new AttachedEvent(createContext(event), o, isLocal), matched);
+         }
+         else if ("DETACHING".equals(data.get(POJOCACHE_STATUS)))
+         {
+            Object o = cache.find(fqn.toString());
+            sendNotification(new DetachedEvent(createContext(event), o, isLocal), matched);
+         }
+         else if (data.containsKey(POJOCACHE_OPERATION))
+         {
+            Object collection = cache.find(fqn.getParent().toString());
+            if (collection instanceof List)
+            {
+               int i = Integer.parseInt(fqn.getLastElementAsString());
+               ListModifiedEvent.Operation operation = ListModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
+               Object value = cache.find(fqn.toString());
+               sendNotification(new ListModifiedEvent(createContext(event), (List) collection, operation, i, value, isLocal), matched);
+            }
+            else if (collection instanceof Set)
+            {
+               SetModifiedEvent.Operation operation = SetModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
+               Object value = cache.find(fqn.toString());
+               sendNotification(new SetModifiedEvent(createContext(event), (Set) collection, operation, value, isLocal), matched);
+            }
+            else if (collection instanceof Map)
+            {
+               MapModifiedEvent.Operation operation = MapModifiedEvent.Operation.valueOf(data.get(POJOCACHE_OPERATION).toString());
+               Object value = cache.find(fqn.toString());
+               sendNotification(new MapModifiedEvent(createContext(event), (Map) collection, operation, fqn.getLastElement(), value, isLocal), matched);
+            }
+            else if (collection instanceof Object[]) {
+               int i = Integer.parseInt(fqn.getLastElementAsString());
+               Object value = cache.find(fqn.toString());
+               sendNotification(new ArrayModifiedEvent(createContext(event), collection, i, value, isLocal), matched);
+            }
+         }
+         else if ("ATTACHED".equals(cache.getCache().get(fqn, POJOCACHE_STATUS)))
+         {
+            for (Map.Entry entry : data.entrySet())
+            {
+               String key = entry.getKey().toString();
+               Object value = entry.getValue();
+
+               if (internalKeys.contains(key))
+                  continue;
+
+               sendNotification(createModifyEvent(createContext(event), fqn, key, value, isLocal), matched);
+            }
+         }
+      }
+      else if (modType == ModificationType.REMOVE_DATA)
+      {
+         for (Map.Entry entry : data.entrySet())
+         {
+            String key = entry.getKey().toString();
+            if (internalKeys.contains(key))
+               continue;
+
+            sendNotification(createModifyEvent(createContext(event), fqn, key, null, isLocal), matched);
+         }
+      }
+   }
+
+   private Set<NotificationDispatcher.Entry> matchListeners(Fqn fqn)
+   {
+      PojoInstance instance = (PojoInstance) cache.getCache().get(fqn, PojoInstance.KEY);
+      if (instance != null)
+         return dispatcher.getListenerEntries(instance.getReferences());
+
+      return null;
+   }
+
+   public boolean isEmpty()
+   {
+      return dispatcher.isEmpty();
+   }
+
+   public Collection<Object> getListeners()
+   {
+      return dispatcher.getListeners();
+   }
+
+   public void addListener(Object listener)
+   {
+      dispatcher.add(listener);
+   }
+
+   public void addListener(Object listener, Pattern pattern)
+   {
+      if (pattern == null)
+         dispatcher.add(listener);
+      else
+         dispatcher.add(listener, pattern);
+   }
+
+   public void removeListener(Object listener)
+   {
+      dispatcher.remove(listener);
+   }
+}
\ No newline at end of file

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,31 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.impl;
-
-import org.jboss.cache.Fqn;
-
-/**
- * Internal helper class to handle internal cache sotre, that is, the portion that is not part of
- * user's data.
- *
- * @author Ben Wang
- */
-public class InternalConstant
-{
-   public static final String CLASS_INTERNAL = "__jboss:internal:class__";
-   public static final String SERIALIZED = "__SERIALIZED__";
-   public static final String JBOSS_INTERNAL_STRING = "__JBossInternal__";
-   public static final String JBOSS_INTERNAL_ID_SEP_STRING = "_ID_";
-   public static final Fqn<String> JBOSS_INTERNAL = new Fqn<String>(JBOSS_INTERNAL_STRING);
-   public static final Fqn<String> JBOSS_INTERNAL_ID_SEP = new Fqn<String>(JBOSS_INTERNAL_ID_SEP_STRING);
-   public static final Fqn<String> JBOSS_INTERNAL_MAP = new Fqn<String>(InternalConstant.JBOSS_INTERNAL, "__RefMap__");
-   public static final String JBOSS_INTERNAL_STATIC = "__jboss:static__";
-   public static final String POJOCACHE_KEY_PREFIX = "POJOCache.";
-   public static final String POJOCACHE_STATUS = POJOCACHE_KEY_PREFIX + "Status";
-   public static final String POJOCACHE_OPERATION = POJOCACHE_KEY_PREFIX + "Operation";
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalConstant.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.impl;
+
+import org.jboss.cache.Fqn;
+
+/**
+ * Internal helper class to handle internal cache sotre, that is, the portion that is not part of
+ * user's data.
+ *
+ * @author Ben Wang
+ */
+public class InternalConstant
+{
+   public static final String CLASS_INTERNAL = "__jboss:internal:class__";
+   public static final String SERIALIZED = "__SERIALIZED__";
+   public static final String JBOSS_INTERNAL_STRING = "__JBossInternal__";
+   public static final String JBOSS_INTERNAL_ID_SEP_STRING = "_ID_";
+   public static final Fqn<String> JBOSS_INTERNAL = new Fqn<String>(JBOSS_INTERNAL_STRING);
+   public static final Fqn<String> JBOSS_INTERNAL_ID_SEP = new Fqn<String>(JBOSS_INTERNAL_ID_SEP_STRING);
+   public static final Fqn<String> JBOSS_INTERNAL_MAP = new Fqn<String>(InternalConstant.JBOSS_INTERNAL, "__RefMap__");
+   public static final String JBOSS_INTERNAL_STATIC = "__jboss:static__";
+   public static final String POJOCACHE_KEY_PREFIX = "POJOCache.";
+   public static final String POJOCACHE_STATUS = POJOCACHE_KEY_PREFIX + "Status";
+   public static final String POJOCACHE_OPERATION = POJOCACHE_KEY_PREFIX + "Operation";
+   public static final String POJOCACHE_LOCK = POJOCACHE_KEY_PREFIX + "LOCK";
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,377 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.impl;
-
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.util.ObjectUtil;
-
-/**
- * Internal helper class to handle internal cache sotre, that is, the portion that is not part of
- * user's data.
- *
- * @author Ben Wang
- */
-public class InternalHelper
-{
-   private static  Log log = LogFactory.getLog(InternalHelper.class.getName());
-
-   private Cache<Object, Object> cache;
-   private PojoCache pcache;
-
-   InternalHelper(PojoCache pcache)
-   {
-      this.cache = pcache.getCache();
-      this.pcache = pcache;
-   }
-
-   PojoInstance getPojoInstance(Fqn fqn) throws CacheException
-   {
-      return (PojoInstance) get(fqn, PojoInstance.KEY, true);
-   }
-
-   PojoReference getPojoReference(Fqn fqn, String field) throws CacheException
-   {
-      if (field == null)
-         field = PojoReference.KEY;
-
-      return (PojoReference) get(fqn, field, true);
-   }
-
-   PojoReference getPojoReference(Fqn fqn) throws CacheException
-   {
-      return getPojoReference(fqn, null);
-   }
-
-
-   static PojoInstance initializeAopInstance(Fqn sourceFqn)
-   {
-      PojoInstance pojoInstance = new PojoInstance();
-
-      pojoInstance.incrementRefCount(sourceFqn);
-      return pojoInstance;
-   }
-
-   /**
-    * Increment reference count for the pojo. Note that this is not thread safe or atomic.
-    */
-   int incrementRefCount(Fqn originalFqn, Fqn referencingFqn) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(originalFqn);
-      if (pojoInstance == null)
-         throw new PojoCacheException("InternalDelegate.incrementRefCount(): null pojoReference for fqn: " + originalFqn);
-
-      int count = pojoInstance.incrementRefCount(referencingFqn);
-      // need to update it.
-      put(originalFqn, PojoInstance.KEY, pojoInstance);
-      return count;
-   }
-
-   /**
-    * Has a delegate method so we can use the switch.
-    */
-
-   Object get(Fqn fqn, Object key) throws CacheException
-   {
-      return get(fqn, key, false);
-   }
-
-   private Object get(Fqn fqn, Object key, boolean gravitate) throws CacheException
-   {
-      // Only gravitate when we have to and only when the user has enabled it
-      if (gravitate && pcache.getThreadContext().isGravitationEnabled())
-      {
-         cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
-         Object obj = cache.get(fqn, key);
-         cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(false);
-         return obj;
-      }
-
-      return cache.get(fqn, key);
-   }
-
-   private void put(Fqn fqn, Object key, Object value) throws CacheException
-   {
-      cache.put(fqn, key, value);
-   }
-
-   void put(Fqn fqn, Map map) throws CacheException
-   {
-      cache.put(fqn, map);
-   }
-
-
-   /**
-    * decrement reference count for the pojo. Note that this is not thread safe or atomic.
-    */
-   int decrementRefCount(Fqn originalFqn, Fqn referencingFqn) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(originalFqn);
-      if (pojoInstance == null)
-         throw new PojoCacheException("InternalDelegate.decrementRefCount(): null pojoReference.");
-
-      int count = pojoInstance.decrementRefCount(referencingFqn);
-
-      if (count < -1)  // can't dip below -1
-         throw new PojoCacheException("InternalDelegate.decrementRefCount(): null pojoReference.");
-
-      // need to update it.
-      put(originalFqn, PojoInstance.KEY, pojoInstance);
-      return count;
-   }
-
-   static boolean isReferenced(PojoInstance pojoInstance)
-   {
-      // If ref counter is greater than 0, we fqn is being referenced.
-      return (pojoInstance.getRefCount() > 0);
-   }
-
-   int getRefCount(Fqn fqn) throws CacheException
-   {
-      return getPojoInstance(fqn).getRefCount();
-   }
-
-   String XgetRefFqn(Fqn fqn) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(fqn);
-      return getRefFqn(pojoInstance);
-   }
-
-   String getRefFqn(PojoInstance pojoInstance) throws CacheException
-   {
-      if (pojoInstance == null)
-         return null;
-
-      String aliasFqn = pojoInstance.getInternalFqn();
-
-      if (aliasFqn == null || aliasFqn.length() == 0) return null;
-
-      return getRefFqnFromAlias(aliasFqn);
-   }
-
-   void setRefFqn(Fqn fqn, String internalFqn) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(fqn);
-      if (pojoInstance == null)
-         pojoInstance = new PojoInstance();
-
-      pojoInstance.setInternalFqn(internalFqn);
-      put(fqn, PojoInstance.KEY, pojoInstance);
-   }
-
-   void removeRefFqn(Fqn fqn) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(fqn);
-      if (pojoInstance == null)
-         throw new PojoCacheException("InternalDelegate.getInternalFqn(): null pojoReference.");
-
-      pojoInstance.removeInternalFqn();
-      put(fqn, PojoInstance.KEY, pojoInstance);
-   }
-
-   Object getPojo(Fqn fqn, String field) throws CacheException
-   {
-      PojoReference pojoReference = getPojoReference(fqn, field);
-      Fqn realFqn = null;
-      if (pojoReference != null)
-      {
-         // This is outward facing node
-         realFqn = pojoReference.getFqn();
-      }
-      else
-      {
-         // If we are looking for a field then there must be a reference
-         if (field != null)
-            return null;
-
-         // This is the internal node.
-         realFqn = fqn;
-      }
-
-      PojoInstance pojoInstance = getPojoInstance(realFqn);
-      if (pojoInstance == null)
-         return null;
-
-      return pojoInstance.get();
-   }
-
-   void setPojo(Fqn fqn, Object pojo) throws CacheException
-   {
-      PojoInstance pojoInstance = getPojoInstance(fqn);
-      if (pojoInstance == null)
-      {
-         pojoInstance = new PojoInstance();
-         put(fqn, PojoInstance.KEY, pojoInstance);
-      }
-
-      pojoInstance.set(pojo);
-      // No need to do a cache put since pojo is transient anyway.
-   }
-
-   static boolean isMultipleReferenced(PojoInstance pojoInstance)
-   {
-      if (pojoInstance.getRefCount() > (PojoInstance.INITIAL_COUNTER_VALUE + 1)) return true;
-
-      return false;
-   }
-
-   static void setPojo(PojoInstance pojoInstance, Object pojo)
-   {
-      // No need to do a cache put since pojo is transient anyway.
-      pojoInstance.set(pojo);
-   }
-
-   void setPojo(Fqn fqn, Object pojo, PojoInstance pojoInstance) throws CacheException
-   {
-      if (pojoInstance == null)
-      {
-         pojoInstance = new PojoInstance();
-         put(fqn, PojoInstance.KEY, pojoInstance);
-      }
-
-      pojoInstance.set(pojo);
-      // No need to do a cache put since pojo is transient anyway.
-   }
-
-   void putPojoReference(Fqn fqn, PojoReference pojoReference) throws CacheException
-   {
-      putPojoReference(fqn, pojoReference, PojoReference.KEY);
-   }
-
-   void putPojoReference(Fqn fqn, PojoReference pojoReference, String field) throws CacheException
-   {
-      if (field == null)
-         field = PojoReference.KEY;
-
-      put(fqn, field, pojoReference);
-   }
-
-   void putAopClazz(Fqn fqn, Class clazz) throws CacheException
-   {
-      put(fqn, InternalConstant.CLASS_INTERNAL, clazz);
-   }
-
-   /**
-    * We store the class name in string and put it in map instead of directly putting
-    * it into cache for optimization.
-    */
-   static void putAopClazz(Class clazz, Map map)
-   {
-      map.put(InternalConstant.CLASS_INTERNAL, clazz);
-   }
-
-   Class peekAopClazz(Fqn fqn) throws CacheException
-   {
-      return (Class) get(fqn, InternalConstant.CLASS_INTERNAL);
-   }
-
-   void removeInternalAttributes(Fqn fqn) throws CacheException
-   {
-      cache.remove(fqn, PojoInstance.KEY);
-      cache.remove(fqn, InternalConstant.CLASS_INTERNAL);
-   }
-
-   void cleanUp(Fqn fqn, String field) throws CacheException
-   {
-      if (field != null)
-      {
-         cache.remove(fqn, field);
-         return;
-      }
-
-      // We can't do a brute force remove anymore?
-      if (cache.getRoot().getChild(fqn).getChildren().size() == 0)
-      {
-         // remove everything
-         cache.removeNode(fqn);
-//         cache_.getRoot().getChild(fqn).clearData();
-//         removeNodeWithoutInterceptor(fqn);
-      }
-      else
-      {
-         // Assume everything here is all PojoCache data for optimization
-         cache.getRoot().getChild(fqn).clearData();
-         if (log.isTraceEnabled())
-         {
-            log.trace("cleanup(): fqn: " + fqn + " is not empty. That means it has sub-pojos. Will not remove node");
-         }
-      }
-   }
-
-   String createIndirectFqn(String fqn) throws CacheException
-   {
-      String indirectFqn = getIndirectFqn(fqn);
-      Fqn internalFqn = getInternalFqn(fqn);
-      put(internalFqn, indirectFqn, fqn);
-      return indirectFqn;
-   }
-
-   private Fqn getInternalFqn(String fqn)
-   {
-      if (fqn == null || fqn.length() == 0)
-         throw new IllegalStateException("InternalDelegate.getInternalFqn(). fqn is either null or empty!");
-
-      String indirectFqn = getIndirectFqn(fqn);
-      return new Fqn(InternalConstant.JBOSS_INTERNAL_MAP, indirectFqn);
-//      return JBOSS_INTERNAL_MAP;
-   }
-
-   static String getIndirectFqn(String fqn)
-   {
-      // TODO This is not unique. Will need to come up with a better one in the future.
-      return ObjectUtil.getIndirectFqn(fqn);
-   }
-
-   void removeIndirectFqn(String oldFqn) throws CacheException
-   {
-      String indirectFqn = getIndirectFqn(oldFqn);
-      cache.remove(getInternalFqn(oldFqn), indirectFqn);
-   }
-
-   void setIndirectFqn(String oldFqn, String newFqn) throws CacheException
-   {
-      String indirectFqn = getIndirectFqn(oldFqn);
-      Fqn tmpFqn = getInternalFqn(oldFqn);
-      put(tmpFqn, indirectFqn, newFqn);
-   }
-
-   void updateIndirectFqn(Fqn originalFqn, Fqn newFqn) throws CacheException
-   {
-      put(getInternalFqn(originalFqn.toString()), getIndirectFqn(originalFqn.toString()), newFqn.toString());
-   }
-
-   private String getRefFqnFromAlias(String aliasFqn) throws CacheException
-   {
-      return (String) get(getInternalFqn(aliasFqn), aliasFqn, true);
-   }
-
-   Fqn getNextFqnInLine(Fqn currentFqn) throws CacheException
-   {
-      PojoInstance ai = getPojoInstance(currentFqn);
-      return ai.getAndRemoveFirstFqnInList();
-   }
-
-   /**
-    * Test if this internal node.
-    *
-    * @param fqn
-    */
-   public static boolean isInternalNode(Fqn fqn)
-   {
-      // we ignore all the node events corresponding to JBOSS_INTERNAL
-      if (fqn.isChildOrEquals(InternalConstant.JBOSS_INTERNAL)) return true;
-
-      return false;
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/InternalHelper.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,416 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.impl;
+
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.lock.UpgradeException;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.util.ObjectUtil;
+
+/**
+ * Internal helper class to handle internal cache sotre, that is, the portion that is not part of
+ * user's data.
+ *
+ * @author Ben Wang
+ */
+public class InternalHelper
+{
+   private static  Log log = LogFactory.getLog(InternalHelper.class.getName());
+
+   private Cache<Object, Object> cache;
+   private PojoCache pcache;
+
+   InternalHelper(PojoCache pcache)
+   {
+      this.cache = pcache.getCache();
+      this.pcache = pcache;
+   }
+
+   PojoInstance getPojoInstance(Fqn fqn) throws CacheException
+   {
+      return (PojoInstance) get(fqn, PojoInstance.KEY, true);
+   }
+
+   PojoReference getPojoReference(Fqn fqn, String field) throws CacheException
+   {
+      if (field == null)
+         field = PojoReference.KEY;
+
+      return (PojoReference) get(fqn, field, true);
+   }
+
+   PojoReference getPojoReference(Fqn fqn) throws CacheException
+   {
+      return getPojoReference(fqn, null);
+   }
+
+
+   static PojoInstance initializeAopInstance(Fqn sourceFqn)
+   {
+      PojoInstance pojoInstance = new PojoInstance();
+
+      pojoInstance.incrementRefCount(sourceFqn);
+      return pojoInstance;
+   }
+
+   /**
+    * Increment reference count for the pojo. Note that this is not thread safe or atomic.
+    */
+   int incrementRefCount(Fqn originalFqn, Fqn referencingFqn) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(originalFqn);
+      if (pojoInstance == null)
+         throw new PojoCacheException("InternalDelegate.incrementRefCount(): null pojoReference for fqn: " + originalFqn);
+
+      int count = pojoInstance.incrementRefCount(referencingFqn);
+      // need to update it.
+      put(originalFqn, PojoInstance.KEY, pojoInstance);
+      return count;
+   }
+
+   /**
+    * Has a delegate method so we can use the switch.
+    */
+
+   Object get(Fqn fqn, Object key) throws CacheException
+   {
+      return get(fqn, key, false);
+   }
+
+   private Object get(Fqn fqn, Object key, boolean gravitate) throws CacheException
+   {
+      // Only gravitate when we have to and only when the user has enabled it
+      if (gravitate && pcache.getThreadContext().isGravitationEnabled())
+      {
+         cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
+         Object obj = cache.get(fqn, key);
+         cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(false);
+         return obj;
+      }
+
+      return cache.get(fqn, key);
+   }
+
+   private void put(Fqn fqn, Object key, Object value) throws CacheException
+   {
+      cache.put(fqn, key, value);
+   }
+
+   void put(Fqn fqn, Map map) throws CacheException
+   {
+      cache.put(fqn, map);
+   }
+
+
+   /**
+    * decrement reference count for the pojo. Note that this is not thread safe or atomic.
+    */
+   int decrementRefCount(Fqn originalFqn, Fqn referencingFqn) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(originalFqn);
+      if (pojoInstance == null)
+         throw new PojoCacheException("InternalDelegate.decrementRefCount(): null pojoReference.");
+
+      int count = pojoInstance.decrementRefCount(referencingFqn);
+
+      if (count < -1)  // can't dip below -1
+         throw new PojoCacheException("InternalDelegate.decrementRefCount(): null pojoReference.");
+
+      // need to update it.
+      put(originalFqn, PojoInstance.KEY, pojoInstance);
+      return count;
+   }
+
+   static boolean isReferenced(PojoInstance pojoInstance)
+   {
+      // If ref counter is greater than 0, we fqn is being referenced.
+      return (pojoInstance.getRefCount() > 0);
+   }
+
+   int getRefCount(Fqn fqn) throws CacheException
+   {
+      return getPojoInstance(fqn).getRefCount();
+   }
+
+   String XgetRefFqn(Fqn fqn) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(fqn);
+      return getRefFqn(pojoInstance);
+   }
+
+   String getRefFqn(PojoInstance pojoInstance) throws CacheException
+   {
+      if (pojoInstance == null)
+         return null;
+
+      String aliasFqn = pojoInstance.getInternalFqn();
+
+      if (aliasFqn == null || aliasFqn.length() == 0) return null;
+
+      return getRefFqnFromAlias(aliasFqn);
+   }
+
+   void setRefFqn(Fqn fqn, String internalFqn) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(fqn);
+      if (pojoInstance == null)
+         pojoInstance = new PojoInstance();
+
+      pojoInstance.setInternalFqn(internalFqn);
+      put(fqn, PojoInstance.KEY, pojoInstance);
+   }
+
+   void removeRefFqn(Fqn fqn) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(fqn);
+      if (pojoInstance == null)
+         throw new PojoCacheException("InternalDelegate.getInternalFqn(): null pojoReference.");
+
+      pojoInstance.removeInternalFqn();
+      put(fqn, PojoInstance.KEY, pojoInstance);
+   }
+
+   Object getPojo(Fqn fqn, String field) throws CacheException
+   {
+      PojoReference pojoReference = getPojoReference(fqn, field);
+      Fqn realFqn = null;
+      if (pojoReference != null)
+      {
+         // This is outward facing node
+         realFqn = pojoReference.getFqn();
+      }
+      else
+      {
+         // If we are looking for a field then there must be a reference
+         if (field != null)
+            return null;
+
+         // This is the internal node.
+         realFqn = fqn;
+      }
+
+      PojoInstance pojoInstance = getPojoInstance(realFqn);
+      if (pojoInstance == null)
+         return null;
+
+      return pojoInstance.get();
+   }
+
+   void setPojo(Fqn fqn, Object pojo) throws CacheException
+   {
+      PojoInstance pojoInstance = getPojoInstance(fqn);
+      if (pojoInstance == null)
+      {
+         pojoInstance = new PojoInstance();
+         put(fqn, PojoInstance.KEY, pojoInstance);
+      }
+
+      pojoInstance.set(pojo);
+      // No need to do a cache put since pojo is transient anyway.
+   }
+
+   static boolean isMultipleReferenced(PojoInstance pojoInstance)
+   {
+      if (pojoInstance.getRefCount() > (PojoInstance.INITIAL_COUNTER_VALUE + 1)) return true;
+
+      return false;
+   }
+
+   static void setPojo(PojoInstance pojoInstance, Object pojo)
+   {
+      // No need to do a cache put since pojo is transient anyway.
+      pojoInstance.set(pojo);
+   }
+
+   void setPojo(Fqn fqn, Object pojo, PojoInstance pojoInstance) throws CacheException
+   {
+      if (pojoInstance == null)
+      {
+         pojoInstance = new PojoInstance();
+         put(fqn, PojoInstance.KEY, pojoInstance);
+      }
+
+      pojoInstance.set(pojo);
+      // No need to do a cache put since pojo is transient anyway.
+   }
+
+   void putPojoReference(Fqn fqn, PojoReference pojoReference) throws CacheException
+   {
+      putPojoReference(fqn, pojoReference, PojoReference.KEY);
+   }
+
+   void putPojoReference(Fqn fqn, PojoReference pojoReference, String field) throws CacheException
+   {
+      if (field == null)
+         field = PojoReference.KEY;
+
+      put(fqn, field, pojoReference);
+   }
+
+   void putAopClazz(Fqn fqn, Class clazz) throws CacheException
+   {
+      put(fqn, InternalConstant.CLASS_INTERNAL, clazz);
+   }
+
+   /**
+    * We store the class name in string and put it in map instead of directly putting
+    * it into cache for optimization.
+    */
+   static void putAopClazz(Class clazz, Map map)
+   {
+      map.put(InternalConstant.CLASS_INTERNAL, clazz);
+   }
+
+   Class peekAopClazz(Fqn fqn) throws CacheException
+   {
+      return (Class) get(fqn, InternalConstant.CLASS_INTERNAL);
+   }
+
+   void removeInternalAttributes(Fqn fqn) throws CacheException
+   {
+      cache.remove(fqn, PojoInstance.KEY);
+      cache.remove(fqn, InternalConstant.CLASS_INTERNAL);
+   }
+
+   void cleanUp(Fqn fqn, String field) throws CacheException
+   {
+      if (field != null)
+      {
+         cache.remove(fqn, field);
+         return;
+      }
+
+      // We can't do a brute force remove anymore?
+      if (cache.getRoot().getChild(fqn).getChildren().size() == 0)
+      {
+         // remove everything
+         cache.removeNode(fqn);
+//         cache_.getRoot().getChild(fqn).clearData();
+//         removeNodeWithoutInterceptor(fqn);
+      }
+      else
+      {
+         // Assume everything here is all PojoCache data for optimization
+         cache.getRoot().getChild(fqn).clearData();
+         if (log.isTraceEnabled())
+         {
+            log.trace("cleanup(): fqn: " + fqn + " is not empty. That means it has sub-pojos. Will not remove node");
+         }
+      }
+   }
+
+   String createIndirectFqn(String fqn) throws CacheException
+   {
+      String indirectFqn = getIndirectFqn(fqn);
+      Fqn internalFqn = getInternalFqn(fqn);
+      put(internalFqn, indirectFqn, fqn);
+      return indirectFqn;
+   }
+
+   private Fqn getInternalFqn(String fqn)
+   {
+      if (fqn == null || fqn.length() == 0)
+         throw new IllegalStateException("InternalDelegate.getInternalFqn(). fqn is either null or empty!");
+
+      String indirectFqn = getIndirectFqn(fqn);
+      return new Fqn(InternalConstant.JBOSS_INTERNAL_MAP, indirectFqn);
+//      return JBOSS_INTERNAL_MAP;
+   }
+
+   static String getIndirectFqn(String fqn)
+   {
+      // TODO This is not unique. Will need to come up with a better one in the future.
+      return ObjectUtil.getIndirectFqn(fqn);
+   }
+
+   void removeIndirectFqn(String oldFqn) throws CacheException
+   {
+      String indirectFqn = getIndirectFqn(oldFqn);
+      cache.remove(getInternalFqn(oldFqn), indirectFqn);
+   }
+
+   void setIndirectFqn(String oldFqn, String newFqn) throws CacheException
+   {
+      String indirectFqn = getIndirectFqn(oldFqn);
+      Fqn tmpFqn = getInternalFqn(oldFqn);
+      put(tmpFqn, indirectFqn, newFqn);
+   }
+
+   void updateIndirectFqn(Fqn originalFqn, Fqn newFqn) throws CacheException
+   {
+      put(getInternalFqn(originalFqn.toString()), getIndirectFqn(originalFqn.toString()), newFqn.toString());
+   }
+
+   private String getRefFqnFromAlias(String aliasFqn) throws CacheException
+   {
+      return (String) get(getInternalFqn(aliasFqn), aliasFqn, true);
+   }
+
+   Fqn getNextFqnInLine(Fqn currentFqn) throws CacheException
+   {
+      PojoInstance ai = getPojoInstance(currentFqn);
+      return ai.getAndRemoveFirstFqnInList();
+   }
+
+   /**
+    * Test if this internal node.
+    *
+    * @param fqn
+    */
+   public static boolean isInternalNode(Fqn fqn)
+   {
+      // we ignore all the node events corresponding to JBOSS_INTERNAL
+      if (fqn.isChildOrEquals(InternalConstant.JBOSS_INTERNAL)) return true;
+
+      return false;
+   }
+
+   public boolean lockPojo(Fqn id) throws CacheException
+   {
+      final int RETRY = 5;
+
+      if (log.isDebugEnabled())
+         log.debug("lockPojo(): id:" + id);
+
+      boolean isNeeded = true;
+      int retry = 0;
+
+      while (isNeeded)
+      {
+         try
+         {
+            cache.put(id, InternalConstant.POJOCACHE_LOCK, "LOCK");
+            isNeeded = false;
+         }
+         catch (UpgradeException upe)
+         {
+            log.warn("lockPojo(): can't upgrade the lock during lockPojo. Will re-try. id: " + id
+                     + " retry times: " + retry);
+            if (retry++ > RETRY)
+               return false;
+
+            // try to sleep a little as well.
+            try
+            {
+               Thread.sleep(10);
+            }
+            catch (InterruptedException e)
+            {
+            }
+         }
+      }
+
+      return true;
+   }
+}
\ No newline at end of file

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,138 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.impl;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-
-/**
- * Handle the object graph management.
- *
- * @author Ben Wang
- *         Date: Aug 4, 2005
- * @version $Id$
- */
-class ObjectGraphHandler extends AbstractHandler
-{
-   private PojoCacheImpl cache;
-   private InternalHelper internal_;
-   private final static Log log = LogFactory.getLog(ObjectGraphHandler.class);
-
-   public ObjectGraphHandler(PojoCacheImpl cache, InternalHelper internal)
-   {
-      this.cache = cache;
-      internal_ = internal;
-   }
-
-   protected Fqn<?> getFqn(Object obj)
-   {
-      return null;
-   }
-
-   protected boolean handles(Class<?> clazz)
-   {
-      return false;
-   }
-
-   @Override
-   protected Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance) throws CacheException
-   {
-      // Note this is actually the aliasFqn, not the real fqn!
-      Object obj;
-
-      obj = cache.getObject(fqn);
-      if (obj == null)
-         throw new PojoCacheException("ObjectGraphHandler.get(): null object from internal ref node." +
-                                      " Internal ref node: " + fqn);
-
-      return obj; // No need to set the instance under fqn. It is located in refFqn anyway.
-   }
-
-   @Override
-   protected void put(Fqn<?> fqn, Fqn<?> referencingFqn, Object obj) throws CacheException
-   {
-      setupRefCounting(fqn, referencingFqn);
-   }
-
-   boolean isMultipleReferenced(Fqn<?> internalFqn)
-   {
-      // Note this is actually the aliasFqn, not the real fqn!
-      PojoInstance pojoInstance = null;
-      try
-      {
-         pojoInstance = internal_.getPojoInstance(internalFqn);
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("Exception in isMultipleReferenced", e);
-      }
-      // check if this is a refernce
-      return InternalHelper.isMultipleReferenced(pojoInstance);
-
-   }
-
-   @Override
-   protected Object remove(Fqn<?> fqn, Fqn<?> referencingFqn, Object pojo)
-         throws CacheException
-   {
-      if (log.isDebugEnabled())
-      {
-         log.debug("remove(): removing object fqn: " + referencingFqn
-                   + " Will just de-reference it.");
-      }
-      removeFromReference(fqn, referencingFqn);
-
-      return null;
-   }
-
-   /**
-    * Remove the object from the the reference fqn, meaning just decrement the ref counter.
-    */
-   private void removeFromReference(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
-   {
-      synchronized (originalFqn)
-      {  // we lock the internal fqn here so no one else has access.
-         // Decrement ref counting on the internal node
-         if (decrementRefCount(originalFqn, referencingFqn) == PojoInstance.INITIAL_COUNTER_VALUE)
-         {
-            // No one is referring it so it is safe to remove
-            // TODO we should make sure the parent nodes are also removed they are empty as well.
-            cache.detach(originalFqn);
-         }
-      }
-   }
-
-   /**
-    * 1. increment reference counter
-    * 2. put in refFqn so we can get it.
-    *
-    * @param fqn    The original fqn node
-    * @param refFqn The new internal fqn node
-    */
-   private void setupRefCounting(Fqn<?> fqn, Fqn<?> referencingFqn) throws CacheException
-   {
-      synchronized (fqn)
-      {
-         // increment the reference counting
-         incrementRefCount(fqn, referencingFqn);
-      }
-   }
-
-   private int incrementRefCount(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
-   {
-      return internal_.incrementRefCount(originalFqn, referencingFqn);
-   }
-
-   private int decrementRefCount(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
-   {
-      return internal_.decrementRefCount(originalFqn, referencingFqn);
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/ObjectGraphHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,138 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheException;
+
+/**
+ * Handle the object graph management.
+ *
+ * @author Ben Wang
+ *         Date: Aug 4, 2005
+ * @version $Id$
+ */
+class ObjectGraphHandler extends AbstractHandler
+{
+   private PojoCacheImpl cache;
+   private InternalHelper internal_;
+   private final static Log log = LogFactory.getLog(ObjectGraphHandler.class);
+
+   public ObjectGraphHandler(PojoCacheImpl cache, InternalHelper internal)
+   {
+      this.cache = cache;
+      internal_ = internal;
+   }
+
+   protected Fqn<?> getFqn(Object obj)
+   {
+      return null;
+   }
+
+   protected boolean handles(Class<?> clazz)
+   {
+      return false;
+   }
+
+   @Override
+   protected Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance) throws CacheException
+   {
+      // Note this is actually the aliasFqn, not the real fqn!
+      Object obj;
+
+      obj = cache.find(fqn);
+      if (obj == null)
+         throw new PojoCacheException("ObjectGraphHandler.get(): null object from internal ref node." +
+                                      " Internal ref node: " + fqn);
+
+      return obj; // No need to set the instance under fqn. It is located in refFqn anyway.
+   }
+
+   @Override
+   protected void put(Fqn<?> fqn, Fqn<?> referencingFqn, Object obj) throws CacheException
+   {
+      setupRefCounting(fqn, referencingFqn);
+   }
+
+   boolean isMultipleReferenced(Fqn<?> internalFqn)
+   {
+      // Note this is actually the aliasFqn, not the real fqn!
+      PojoInstance pojoInstance = null;
+      try
+      {
+         pojoInstance = internal_.getPojoInstance(internalFqn);
+      }
+      catch (CacheException e)
+      {
+         throw new PojoCacheException("Exception in isMultipleReferenced", e);
+      }
+      // check if this is a refernce
+      return InternalHelper.isMultipleReferenced(pojoInstance);
+
+   }
+
+   @Override
+   protected Object remove(Fqn<?> fqn, Fqn<?> referencingFqn, Object pojo)
+         throws CacheException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("remove(): removing object fqn: " + referencingFqn
+                   + " Will just de-reference it.");
+      }
+      removeFromReference(fqn, referencingFqn);
+
+      return null;
+   }
+
+   /**
+    * Remove the object from the the reference fqn, meaning just decrement the ref counter.
+    */
+   private void removeFromReference(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
+   {
+      synchronized (originalFqn)
+      {  // we lock the internal fqn here so no one else has access.
+         // Decrement ref counting on the internal node
+         if (decrementRefCount(originalFqn, referencingFqn) == PojoInstance.INITIAL_COUNTER_VALUE)
+         {
+            // No one is referring it so it is safe to remove
+            // TODO we should make sure the parent nodes are also removed they are empty as well.
+            cache.detach(originalFqn);
+         }
+      }
+   }
+
+   /**
+    * 1. increment reference counter
+    * 2. put in refFqn so we can get it.
+    *
+    * @param fqn    The original fqn node
+    * @param refFqn The new internal fqn node
+    */
+   private void setupRefCounting(Fqn<?> fqn, Fqn<?> referencingFqn) throws CacheException
+   {
+      synchronized (fqn)
+      {
+         // increment the reference counting
+         incrementRefCount(fqn, referencingFqn);
+      }
+   }
+
+   private int incrementRefCount(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
+   {
+      return internal_.incrementRefCount(originalFqn, referencingFqn);
+   }
+
+   private int decrementRefCount(Fqn<?> originalFqn, Fqn<?> referencingFqn) throws CacheException
+   {
+      return internal_.decrementRefCount(originalFqn, referencingFqn);
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,357 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.impl;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.Advised;
-import org.jboss.aop.Advisor;
-import org.jboss.aop.InstanceAdvisor;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.aop.proxy.ClassProxy;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.Region;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.collection.CollectionInterceptorUtil;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
-import org.jboss.cache.pojo.memory.FieldPersistentReference;
-import org.jboss.cache.pojo.util.AopUtil;
-
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Delegate class for PojoCache, the real implementation code happens here.
- *
- * @author Ben Wang
- */
-public class PojoCacheDelegate
-{
-   private PojoCacheImpl pojoCache;
-   private Cache<Object, Object> cache;
-   private final static Log log = LogFactory.getLog(PojoCacheDelegate.class);
-   private InternalHelper internal_;
-   private AdvisedPojoHandler advisedHandler_;
-   private ObjectGraphHandler graphHandler_;
-   private CollectionClassHandler collectionHandler_;
-   private ArrayHandler arrayHandler;
-   private SerializableObjectHandler serializableHandler_;
-   // Use ThreadLocal to hold a boolean isBulkRemove
-   private ThreadLocal<Boolean> bulkRemove_ = new ThreadLocal<Boolean>();
-   private final String DETACH = "DETACH";
-   private PojoUtil util_ = new PojoUtil();
-
-   public PojoCacheDelegate(PojoCacheImpl cache)
-   {
-      pojoCache = cache;
-      this.cache = pojoCache.getCache();
-      internal_ = new InternalHelper(cache);
-      graphHandler_ = new ObjectGraphHandler(pojoCache, internal_);
-      collectionHandler_ = new CollectionClassHandler(pojoCache, internal_);
-      serializableHandler_ = new SerializableObjectHandler(pojoCache, internal_);
-      advisedHandler_ = new AdvisedPojoHandler(pojoCache, internal_, util_);
-      arrayHandler = new ArrayHandler(pojoCache);
-   }
-
-   public void setBulkRemove(boolean bulk)
-   {
-      bulkRemove_.set(bulk);
-   }
-
-   private boolean getBulkRemove()
-   {
-      return bulkRemove_.get();
-   }
-
-   public Object getObject(Fqn fqn, String field, Object source) throws CacheException
-   {
-      // TODO Must we really to couple with BR? JBCACHE-669
-      Object pojo = internal_.getPojo(fqn, field);
-      if (pojo != null)
-      {
-         // we already have an advised instance
-         if (log.isDebugEnabled())
-         {
-            log.debug("getObject(): id: " + fqn + " retrieved from existing instance directly. ");
-         }
-         return pojo;
-      }
-
-      // OK. So we are here meaning that this is a failover or passivation since the transient
-      // pojo instance is not around. Let's also make sure the right classloader is used
-      // as well.
-      ClassLoader prevCL = Thread.currentThread().getContextClassLoader();
-      try
-      {
-         Region region = cache.getRegion(fqn, false);
-         if (region != null && region.getClassLoader() != null)
-            Thread.currentThread().setContextClassLoader(region.getClassLoader());
-
-         return getObjectInternal(fqn, field, source);
-      }
-      finally
-      {
-         Thread.currentThread().setContextClassLoader(prevCL);
-      }
-   }
-
-   /**
-    * Note that caller of this method will take care of synchronization within the <code>fqn</code> sub-tree.
-    */
-   public Object putObject(Fqn fqn, Object obj, String field, Object source) throws CacheException
-   {
-      // Skip some un-necessary update if obj is the same class as the old one
-      Object oldValue = internal_.getPojo(fqn, field);
-      boolean allowArray = source instanceof ArrayInterceptable;
-      if (oldValue == obj && skipDuplicateAttach(obj, allowArray))
-      {
-         if (log.isDebugEnabled())
-         {
-            log.debug("putObject(): id: " + fqn + " pojo is already in the cache. Return right away.");
-         }
-         return obj;
-      }
-
-      // remove old value before overwriting it. This is necessary to detach any interceptor.
-      // TODO Or can we simply walk thru that somewhere? Well, there is also implication of Collection though
-      pojoCache.detach(fqn, field, source);
-
-      if (obj == null)
-         return oldValue;// we are done
-
-      AbstractHandler handler = getHandler(obj.getClass(), allowArray);
-      Fqn<?> internalFqn = handler.getFqn(obj);
-
-      if (internalFqn != null)
-      {
-         graphHandler_.put(internalFqn, fqn, obj);
-      }
-      else
-      {
-         internalFqn = createInternalFqn(fqn, obj);
-         if (log.isDebugEnabled())
-            log.debug("attach(): id: " + fqn + " will store the pojo in the internal area: " + internalFqn);
-
-         handler.put(internalFqn, fqn, obj);
-
-         // Used by notification sub-system
-         cache.put(internalFqn, InternalConstant.POJOCACHE_STATUS, "ATTACHED");
-      }
-
-      setPojoReference(fqn, obj, field, internalFqn);
-
-      return oldValue;
-   }
-
-   private boolean skipDuplicateAttach(Object obj, boolean allowArray)
-   {
-      return obj == null || getHandler(obj.getClass(), allowArray) != serializableHandler_;
-   }
-
-   private AbstractHandler getHandler(Class<?> clazz, boolean allowArray)
-   {
-      if (advisedHandler_.handles(clazz))
-         return advisedHandler_;
-
-      if (collectionHandler_.handles(clazz))
-         return collectionHandler_;
-
-      if (allowArray && arrayHandler.handles(clazz))
-         return arrayHandler;
-
-      if (serializableHandler_.handles(clazz))
-         return serializableHandler_;
-
-      throw new CacheException("Can not manage object. It must be either instrumented, a collection, an array, or Serializable: "
-            + clazz.getName());
-   }
-
-
-   private Fqn createInternalFqn(Fqn fqn, Object obj) throws CacheException
-   {
-      // Create an internal Fqn name
-      return AopUtil.createInternalFqn(fqn, cache);
-   }
-
-   private Fqn setPojoReference(Fqn fqn, Object obj, String field, Fqn internalFqn) throws CacheException
-   {
-      // Create PojoReference
-      CachedType type = pojoCache.getCachedType(obj.getClass());
-      PojoReference pojoReference = new PojoReference();
-      pojoReference.setPojoClass(type.getType());
-
-      // store PojoReference
-      pojoReference.setFqn(internalFqn);
-      internal_.putPojoReference(fqn, pojoReference, field);
-      if (log.isDebugEnabled())
-      {
-         log.debug("put(): inserting PojoReference with id: " + fqn);
-      }
-      // store obj in the internal fqn
-      return internalFqn;
-   }
-
-   private void createChildNodeFirstWithoutLocking(Fqn internalFqn)
-   {
-      int size = internalFqn.size();
-      Fqn f = internalFqn.getSubFqn(0, size - 1);
-      Fqn child = internalFqn.getSubFqn(size - 1, size);
-
-      Node base = cache.getRoot().getChild(f);
-      if (base == null)
-      {
-         log.debug("The node retrieved is null from fqn: " + f);
-         return;
-      }
-      base.addChild(child);
-   }
-
-   /**
-    * Note that caller of this method will take care of synchronization within the <code>fqn</code> sub-tree.
-    *
-    * @param fqn
-    * @return detached object
-    * @throws CacheException
-    */
-   public Object removeObject(Fqn fqn, String field, Object source) throws CacheException
-   {
-      // the class attribute is implicitly stored as an immutable read-only attribute
-      PojoReference pojoReference = internal_.getPojoReference(fqn, field);
-      if (pojoReference == null)
-      {
-         //  clazz and pojoReference can be not null if this node is the replicated brother node.
-         if (log.isTraceEnabled())
-         {
-            log.trace("removeObject(): clazz is null. id: " + fqn + " No need to remove.");
-         }
-         return null;
-      }
-
-      Fqn<?> internalFqn = pojoReference.getFqn();
-
-      if (log.isDebugEnabled())
-      {
-         log.debug("removeObject(): removing object from id: " + fqn
-                   + " with the corresponding internal id: " + internalFqn);
-      }
-
-      Object result = pojoCache.getObject(internalFqn);
-      if (result == null)
-         return null;
-
-      if (graphHandler_.isMultipleReferenced(internalFqn))
-      {
-         graphHandler_.remove(internalFqn, fqn, result);
-      }
-      else
-      {
-         cache.put(internalFqn, InternalConstant.POJOCACHE_STATUS, "DETACHING");
-         boolean allowArray = source instanceof ArrayInterceptable;
-         result = getHandler(result.getClass(), allowArray).remove(internalFqn, fqn, result);
-      }
-
-      internal_.cleanUp(fqn, field);
-      return result;
-   }
-
-   public Map findObjects(Fqn fqn) throws CacheException
-   {
-
-      // Traverse from fqn to do getObject, if it return a pojo we then stop.
-      Map map = new HashMap();
-      Object pojo = getObject(fqn, null, null);
-      if (pojo != null)
-      {
-         map.put(fqn, pojo);// we are done!
-         return map;
-      }
-
-      findChildObjects(fqn, map);
-      if (log.isDebugEnabled())
-      {
-         log.debug("_findObjects(): id: " + fqn + " size of pojos found: " + map.size());
-      }
-      return map;
-   }
-
-   private Object getObjectInternal(Fqn<?> fqn, String field, Object source) throws CacheException
-   {
-      Fqn<?> internalFqn = fqn;
-      PojoReference pojoReference = internal_.getPojoReference(fqn, field);
-      if (pojoReference != null)
-      {
-         internalFqn = pojoReference.getFqn();
-      }
-      else if (field != null)
-      {
-         return null;
-      }
-
-      if (log.isDebugEnabled())
-         log.debug("getObject(): id: " + fqn + " with a corresponding internal id: " + internalFqn);
-
-      /**
-       * Reconstruct the managed POJO
-       */
-      Object obj;
-
-      PojoInstance pojoInstance = internal_.getPojoInstance(internalFqn);
-
-      if (pojoInstance == null)
-         return null;
-         //throw new PojoCacheException("PojoCacheDelegate.getObjectInternal(): null PojoInstance for fqn: " + internalFqn);
-
-      Class<?> clazz = pojoInstance.getPojoClass();
-      boolean allowArray = source instanceof ArrayInterceptable;
-      obj = getHandler(clazz, allowArray).get(internalFqn, clazz, pojoInstance);
-
-      InternalHelper.setPojo(pojoInstance, obj);
-      return obj;
-   }
-
-   private void findChildObjects(Fqn fqn, Map map) throws CacheException
-   {
-      // We need to traverse then
-      Node root = cache.getRoot();
-      Node current = root.getChild(fqn);
-
-      if (current == null) return;
-
-      Collection<Node> col = current.getChildren();
-      if (col == null) return;
-      for (Node n : col)
-      {
-         Fqn newFqn = n.getFqn();
-         if (InternalHelper.isInternalNode(newFqn)) continue;// skip
-
-         Object pojo = getObject(newFqn, null, null);
-         if (pojo != null)
-         {
-            map.put(newFqn, pojo);
-         }
-         else
-         {
-            findChildObjects(newFqn, map);
-         }
-      }
-   }
-
-   public boolean exists(Fqn<?> id)
-   {
-      return internal_.getPojoReference(id, null) != null || internal_.getPojoInstance(id) != null;
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheDelegate.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,349 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.Advised;
+import org.jboss.aop.Advisor;
+import org.jboss.aop.InstanceAdvisor;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.Region;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.collection.CollectionInterceptorUtil;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.BaseInterceptor;
+import org.jboss.cache.pojo.memory.FieldPersistentReference;
+import org.jboss.cache.pojo.util.AopUtil;
+
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Delegate class for PojoCache, the real implementation code happens here.
+ *
+ * @author Ben Wang
+ */
+public class PojoCacheDelegate
+{
+   private PojoCacheImpl pojoCache;
+   private Cache<Object, Object> cache;
+   private final static Log log = LogFactory.getLog(PojoCacheDelegate.class);
+   private InternalHelper internal_;
+   private AdvisedPojoHandler advisedHandler_;
+   private ObjectGraphHandler graphHandler_;
+   private CollectionClassHandler collectionHandler_;
+   private ArrayHandler arrayHandler;
+   private SerializableObjectHandler serializableHandler_;
+   // Use ThreadLocal to hold a boolean isBulkRemove
+   private PojoUtil util_ = new PojoUtil();
+
+   public PojoCacheDelegate(PojoCacheImpl cache)
+   {
+      pojoCache = cache;
+      this.cache = pojoCache.getCache();
+      internal_ = new InternalHelper(cache);
+      graphHandler_ = new ObjectGraphHandler(pojoCache, internal_);
+      collectionHandler_ = new CollectionClassHandler(pojoCache, internal_);
+      serializableHandler_ = new SerializableObjectHandler(pojoCache, internal_);
+      advisedHandler_ = new AdvisedPojoHandler(pojoCache, internal_, util_);
+      arrayHandler = new ArrayHandler(pojoCache);
+   }
+
+   public Object getObject(Fqn fqn, String field, Object source) throws CacheException
+   {
+      // TODO Must we really to couple with BR? JBCACHE-669
+      Object pojo = internal_.getPojo(fqn, field);
+      if (pojo != null)
+      {
+         // we already have an advised instance
+         if (log.isDebugEnabled())
+         {
+            log.debug("getObject(): id: " + fqn + " retrieved from existing instance directly. ");
+         }
+         return pojo;
+      }
+
+      // OK. So we are here meaning that this is a failover or passivation since the transient
+      // pojo instance is not around. Let's also make sure the right classloader is used
+      // as well.
+      ClassLoader prevCL = Thread.currentThread().getContextClassLoader();
+      try
+      {
+         Region region = cache.getRegion(fqn, false);
+         if (region != null && region.getClassLoader() != null)
+            Thread.currentThread().setContextClassLoader(region.getClassLoader());
+
+         return getObjectInternal(fqn, field, source);
+      }
+      finally
+      {
+         Thread.currentThread().setContextClassLoader(prevCL);
+      }
+   }
+
+   /**
+    * Note that caller of this method will take care of synchronization within the <code>fqn</code> sub-tree.
+    */
+   public Object putObject(Fqn fqn, Object obj, String field, Object source) throws CacheException
+   {
+      internal_.lockPojo(fqn);
+
+      // Skip some un-necessary update if obj is the same class as the old one
+      Object oldValue = internal_.getPojo(fqn, field);
+      boolean allowArray = source instanceof ArrayInterceptable;
+      if (oldValue == obj && skipDuplicateAttach(obj, allowArray))
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("putObject(): id: " + fqn + " pojo is already in the cache. Return right away.");
+         }
+         return obj;
+      }
+
+      // remove old value before overwriting it. This is necessary to detach any interceptor.
+      // TODO Or can we simply walk thru that somewhere? Well, there is also implication of Collection though
+      pojoCache.detach(fqn, field, source);
+
+      if (obj == null)
+         return oldValue;// we are done
+
+      AbstractHandler handler = getHandler(obj.getClass(), allowArray);
+      Fqn<?> internalFqn = handler.getFqn(obj);
+
+      if (internalFqn != null)
+      {
+         graphHandler_.put(internalFqn, fqn, obj);
+      }
+      else
+      {
+         internalFqn = createInternalFqn(fqn, obj);
+         if (log.isDebugEnabled())
+            log.debug("attach(): id: " + fqn + " will store the pojo in the internal area: " + internalFqn);
+
+         handler.put(internalFqn, fqn, obj);
+
+         // Used by notification sub-system
+         cache.put(internalFqn, InternalConstant.POJOCACHE_STATUS, "ATTACHED");
+      }
+
+      setPojoReference(fqn, obj, field, internalFqn);
+
+      return oldValue;
+   }
+
+   private boolean skipDuplicateAttach(Object obj, boolean allowArray)
+   {
+      return obj == null || getHandler(obj.getClass(), allowArray) != serializableHandler_;
+   }
+
+   private AbstractHandler getHandler(Class<?> clazz, boolean allowArray)
+   {
+      if (advisedHandler_.handles(clazz))
+         return advisedHandler_;
+
+      if (collectionHandler_.handles(clazz))
+         return collectionHandler_;
+
+      if (allowArray && arrayHandler.handles(clazz))
+         return arrayHandler;
+
+      if (serializableHandler_.handles(clazz))
+         return serializableHandler_;
+
+      throw new CacheException("Can not manage object. It must be either instrumented, a collection, an array, or Serializable: "
+            + clazz.getName());
+   }
+
+
+   private Fqn createInternalFqn(Fqn fqn, Object obj) throws CacheException
+   {
+      // Create an internal Fqn name
+      return AopUtil.createInternalFqn(fqn, cache);
+   }
+
+   private Fqn setPojoReference(Fqn fqn, Object obj, String field, Fqn internalFqn) throws CacheException
+   {
+      // Create PojoReference
+      CachedType type = pojoCache.getCachedType(obj.getClass());
+      PojoReference pojoReference = new PojoReference();
+      pojoReference.setPojoClass(type.getType());
+
+      // store PojoReference
+      pojoReference.setFqn(internalFqn);
+      internal_.putPojoReference(fqn, pojoReference, field);
+      if (log.isDebugEnabled())
+      {
+         log.debug("put(): inserting PojoReference with id: " + fqn);
+      }
+      // store obj in the internal fqn
+      return internalFqn;
+   }
+
+   private void createChildNodeFirstWithoutLocking(Fqn internalFqn)
+   {
+      int size = internalFqn.size();
+      Fqn f = internalFqn.getSubFqn(0, size - 1);
+      Fqn child = internalFqn.getSubFqn(size - 1, size);
+
+      Node base = cache.getRoot().getChild(f);
+      if (base == null)
+      {
+         log.debug("The node retrieved is null from fqn: " + f);
+         return;
+      }
+      base.addChild(child);
+   }
+
+   /**
+    * Note that caller of this method will take care of synchronization within the <code>fqn</code> sub-tree.
+    *
+    * @param fqn
+    * @return detached object
+    * @throws CacheException
+    */
+   public Object removeObject(Fqn fqn, String field, Object source) throws CacheException
+   {
+      internal_.lockPojo(fqn);
+
+      // the class attribute is implicitly stored as an immutable read-only attribute
+      PojoReference pojoReference = internal_.getPojoReference(fqn, field);
+      if (pojoReference == null)
+      {
+         //  clazz and pojoReference can be not null if this node is the replicated brother node.
+         if (log.isTraceEnabled())
+         {
+            log.trace("removeObject(): clazz is null. id: " + fqn + " No need to remove.");
+         }
+         return null;
+      }
+
+      Fqn<?> internalFqn = pojoReference.getFqn();
+
+      if (log.isDebugEnabled())
+      {
+         log.debug("removeObject(): removing object from id: " + fqn
+                   + " with the corresponding internal id: " + internalFqn);
+      }
+
+      Object result = pojoCache.find(internalFqn);
+      if (result == null)
+         return null;
+
+      if (graphHandler_.isMultipleReferenced(internalFqn))
+      {
+         graphHandler_.remove(internalFqn, fqn, result);
+      }
+      else
+      {
+         cache.put(internalFqn, InternalConstant.POJOCACHE_STATUS, "DETACHING");
+         boolean allowArray = source instanceof ArrayInterceptable;
+         result = getHandler(result.getClass(), allowArray).remove(internalFqn, fqn, result);
+      }
+
+      internal_.cleanUp(fqn, field);
+      return result;
+   }
+
+   public Map findObjects(Fqn fqn) throws CacheException
+   {
+
+      // Traverse from fqn to do getObject, if it return a pojo we then stop.
+      Map map = new HashMap();
+      Object pojo = getObject(fqn, null, null);
+      if (pojo != null)
+      {
+         map.put(fqn, pojo);// we are done!
+         return map;
+      }
+
+      findChildObjects(fqn, map);
+      if (log.isDebugEnabled())
+      {
+         log.debug("_findObjects(): id: " + fqn + " size of pojos found: " + map.size());
+      }
+      return map;
+   }
+
+   private Object getObjectInternal(Fqn<?> fqn, String field, Object source) throws CacheException
+   {
+      Fqn<?> internalFqn = fqn;
+      PojoReference pojoReference = internal_.getPojoReference(fqn, field);
+      if (pojoReference != null)
+      {
+         internalFqn = pojoReference.getFqn();
+      }
+      else if (field != null)
+      {
+         return null;
+      }
+
+      if (log.isDebugEnabled())
+         log.debug("getObject(): id: " + fqn + " with a corresponding internal id: " + internalFqn);
+
+      /**
+       * Reconstruct the managed POJO
+       */
+      Object obj;
+
+      PojoInstance pojoInstance = internal_.getPojoInstance(internalFqn);
+
+      if (pojoInstance == null)
+         return null;
+         //throw new PojoCacheException("PojoCacheDelegate.getObjectInternal(): null PojoInstance for fqn: " + internalFqn);
+
+      Class<?> clazz = pojoInstance.getPojoClass();
+      boolean allowArray = source instanceof ArrayInterceptable;
+      obj = getHandler(clazz, allowArray).get(internalFqn, clazz, pojoInstance);
+
+      InternalHelper.setPojo(pojoInstance, obj);
+      return obj;
+   }
+
+   private void findChildObjects(Fqn fqn, Map map) throws CacheException
+   {
+      // We need to traverse then
+      Node root = cache.getRoot();
+      Node current = root.getChild(fqn);
+
+      if (current == null) return;
+
+      Collection<Node> col = current.getChildren();
+      if (col == null) return;
+      for (Node n : col)
+      {
+         Fqn newFqn = n.getFqn();
+         if (InternalHelper.isInternalNode(newFqn)) continue;// skip
+
+         Object pojo = getObject(newFqn, null, null);
+         if (pojo != null)
+         {
+            map.put(newFqn, pojo);
+         }
+         else
+         {
+            findChildObjects(newFqn, map);
+         }
+      }
+   }
+
+   public boolean exists(Fqn<?> id)
+   {
+      return internal_.getPojoReference(id, null) != null || internal_.getPojoInstance(id) != null;
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,356 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.impl;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.regex.Pattern;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DefaultCacheFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Version;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.factories.XmlConfigurationParser;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.PojoCacheThreadContext;
-import org.jboss.cache.pojo.annotation.Attach;
-import org.jboss.cache.pojo.annotation.Detach;
-import org.jboss.cache.pojo.annotation.Find;
-
-/**
- * Implementation class for PojoCache interface
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoCacheImpl implements PojoCache
-{
-   private CacheSPI<Object, Object> cache = null;
-   protected final Log log_ = LogFactory.getLog(PojoCacheImpl.this.getClass());
-   private PojoCacheDelegate delegate_;
-   // Class -> CachedType
-   // use WeakHashMap to allow class reloading
-   private Map cachedTypes_ = new WeakHashMap();
-   private boolean hasCreate_ = false;
-   private CacheListenerAdaptor listenerAdaptor = new CacheListenerAdaptor(this);
-   private PojoCacheThreadContext threadContext = new PojoCacheThreadContextImpl();
-
-   public PojoCacheImpl(String configStr, boolean toStart)
-   {
-      try
-      {
-         //         cache_ = new PojoTreeCache();
-         //         cache_.setConfiguration(new XmlConfigurationParser().parseFile(configStr));
-
-         XmlConfigurationParser parser = new XmlConfigurationParser();
-         Configuration expected = parser.parseFile(configStr);
-
-         init(expected, toStart);
-      }
-      catch (Exception e)
-      {
-         throw new PojoCacheException("Failed to start " + configStr, e);
-      }
-   }
-
-   public PojoCacheImpl(Configuration config, boolean toStart)
-   {
-      init(config, toStart);
-   }
-
-   private void init(Configuration config, boolean toStart)
-   {
-      try
-      {
-         cache = (CacheSPI<Object, Object>) DefaultCacheFactory.getInstance().createCache(config, toStart);
-      }
-      catch (Exception e)
-      {
-         throw new PojoCacheException("init " + config + " failed", e);
-      }
-
-      delegate_ = new PojoCacheDelegate(this);
-   }
-
-   public CacheSPI<Object, Object> getCacheSPI()
-   {
-      return cache;
-   }
-
-   public Object attach(String id, Object pojo) throws PojoCacheException
-   {
-      return attach(Fqn.fromString(id), pojo);
-   }
-
-   @Attach
-   public Object attach(Fqn<?> id, Object pojo) throws PojoCacheException
-   {
-      try
-      {
-         Object obj = putObject(id, pojo, null, null);
-         return obj;
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("putObject failed " + id, e);
-      }
-   }
-
-   @Attach
-   public Object attach(Fqn<?> id, Object pojo, String field, Object source) throws PojoCacheException
-   {
-      try
-      {
-         Object obj = putObject(id, pojo, field, source);
-         return obj;
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("putObject failed " + id, e);
-      }
-   }
-
-   /**
-    * This public API is called from internal package only.
-    */
-   public Object putObject(Fqn<?> id, Object pojo, String field, Object source) throws CacheException
-   {
-      return delegate_.putObject(id, pojo, field, source);
-   }
-
-   public Object detach(String id) throws PojoCacheException
-   {
-      return detach(Fqn.fromString(id));
-   }
-
-   @Detach
-   public Object detach(Fqn<?> id, String field, Object source) throws PojoCacheException
-   {
-      try
-      {
-         Object pojo = getObject(id, field, source);// TODO need optimization here since it will be redundant here
-         if (pojo == null) return pojo;
-
-         Object obj = removeObject(id, field, source);
-         return obj;
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("detach " + id + " failed", e);
-      }
-   }
-
-   public Object detach(Fqn<?> id) throws PojoCacheException
-   {
-      return detach(id, null, null);
-   }
-
-   public Object removeObject(Fqn<?> id, String field, Object source) throws CacheException
-   {
-      delegate_.setBulkRemove(false);
-      return delegate_.removeObject(id, field, source);
-   }
-
-   public String getPojoID(Object pojo)
-   {
-      throw new PojoCacheException("getPojoID not yet implemented");
-   }
-
-   public boolean exists(Fqn<?> id)
-   {
-      return delegate_.exists(id);
-   }
-
-   public Object find(String id) throws PojoCacheException
-   {
-      return find(Fqn.fromString(id));
-   }
-
-   @Find
-   public Object find(Fqn<?> id) throws PojoCacheException
-   {
-      try
-      {
-         return getObject(id);
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("find " + id + " failed ", e);
-      }
-   }
-
-   public Object getObject(Fqn<?> id) throws CacheException
-   {
-      return getObject(id, null, null);
-   }
-
-   public Object getObject(Fqn<?> id, String field, Object source) throws CacheException
-   {
-      return delegate_.getObject(id, field, source);
-   }
-
-
-   public Map<Fqn<?>, Object> findAll(String id) throws PojoCacheException
-   {
-      return findAll(Fqn.fromString(id));
-   }
-
-   @Find
-   public Map<Fqn<?>, Object> findAll(Fqn<?> id) throws PojoCacheException
-   {
-      // Should produce "/"
-      if (id == null) id = Fqn.ROOT;
-
-      try
-      {
-         return delegate_.findObjects(id);
-      }
-      catch (CacheException e)
-      {
-         throw new PojoCacheException("findAll " + id + " failed", e);
-      }
-   }
-
-   public String getVersion()
-   {
-      return Version.printVersion();
-   }
-
-   public void create() throws PojoCacheException
-   {
-      log_.info("PojoCache version: " + getVersion());
-      try
-      {
-         cache.create();
-      }
-      catch (Exception e)
-      {
-         throw new PojoCacheException("PojoCache create exception", e);
-      }
-
-      hasCreate_ = true;
-   }
-
-   public void start() throws PojoCacheException
-   {
-      if (!hasCreate_)
-      {
-         create();
-      }
-
-      try
-      {
-         log_.info("PojoCache version: " + getVersion());
-         cache.start();
-      }
-      catch (Exception e)
-      {
-         throw new PojoCacheException("Failed starting " + e, e);
-      }
-   }
-
-   public void stop() throws PojoCacheException
-   {
-      cache.stop();
-   }
-
-   public void destroy() throws PojoCacheException
-   {
-      cache.destroy();
-   }
-
-   public Collection<Object> getListeners()
-   {
-      return listenerAdaptor.getListeners();
-   }
-
-   public void addListener(Object listener)
-   {
-      addListener(listener, null);
-   }
-
-   public void addListener(Object listener, Pattern pattern)
-   {
-      // Add and remove listner operations must be serialized to ensure that
-      // the adaptor is always present only once, when at least one listener
-      // is registered.
-      synchronized (listenerAdaptor)
-      {
-         try
-         {
-            boolean wasEmpty = listenerAdaptor.isEmpty();
-            listenerAdaptor.addListener(listener, pattern);
-            if (wasEmpty)
-               cache.addCacheListener(listenerAdaptor);
-         }
-         catch (IllegalArgumentException e)
-         {
-            // simplify stack trace for user
-            e.fillInStackTrace();
-            throw e;
-         }
-      }
-   }
-
-   public void removeListener(Object listener)
-   {
-      synchronized (listenerAdaptor)
-      {
-         listenerAdaptor.removeListener(listener);
-         if (listenerAdaptor.isEmpty())
-            cache.removeCacheListener(listenerAdaptor);
-      }
-   }
-
-   public PojoCacheThreadContext getThreadContext()
-   {
-      return threadContext;
-   }
-
-   public Cache<Object,Object> getCache()
-   {
-      return cache;
-   }
-
-   /**
-    * Obtain a cache aop type for user to traverse the defined "primitive" types in aop.
-    * Note that this is not a synchronized call now for speed optimization.
-    *
-    * @param clazz The original pojo class
-    * @return CachedType
-    */
-   public synchronized CachedType getCachedType(Class clazz)
-   {
-      CachedType type = (CachedType) cachedTypes_.get(clazz);
-      if (type == null)
-      {
-         type = new CachedType(clazz);
-         cachedTypes_.put(clazz, type);
-         return type;
-      }
-      else
-      {
-         return type;
-      }
-   }
-
-   public String toString()
-   {
-      return getClass().getName() +
-              " cache=" + cache +
-              " delegate=" + delegate_ +
-              " types=" + cachedTypes_.size();
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,411 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.impl;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.regex.Pattern;
+
+import javax.transaction.Status;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.CacheSPI;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Version;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.factories.XmlConfigurationParser;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.PojoCacheThreadContext;
+import org.jboss.cache.pojo.interceptors.PojoTxSynchronizationHandler;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Implementation class for PojoCache interface
+ *
+ * @author Ben Wang
+ * @version $Id$
+ */
+public class PojoCacheImpl implements PojoCache
+{
+   private CacheSPI<Object, Object> cache = null;
+   protected final Log log_ = LogFactory.getLog(PojoCacheImpl.this.getClass());
+   private PojoCacheDelegate delegate_;
+   // Class -> CachedType
+   // use WeakHashMap to allow class reloading
+   private Map cachedTypes_ = new WeakHashMap();
+   private boolean hasCreate_ = false;
+   private CacheListenerAdaptor listenerAdaptor = new CacheListenerAdaptor(this);
+   private PojoCacheThreadContext threadContext = new PojoCacheThreadContextImpl();
+
+   public PojoCacheImpl(String configStr, boolean toStart)
+   {
+      try
+      {
+         //         cache_ = new PojoTreeCache();
+         //         cache_.setConfiguration(new XmlConfigurationParser().parseFile(configStr));
+
+         XmlConfigurationParser parser = new XmlConfigurationParser();
+         Configuration expected = parser.parseFile(configStr);
+
+         init(expected, toStart);
+      }
+      catch (Exception e)
+      {
+         throw new PojoCacheException("Failed to start " + configStr, e);
+      }
+   }
+
+   public PojoCacheImpl(Configuration config, boolean toStart)
+   {
+      init(config, toStart);
+   }
+
+   private void init(Configuration config, boolean toStart)
+   {
+      try
+      {
+         cache = (CacheSPI<Object, Object>) DefaultCacheFactory.getInstance().createCache(config, toStart);
+      }
+      catch (Exception e)
+      {
+         throw new PojoCacheException("init " + config + " failed", e);
+      }
+
+      delegate_ = new PojoCacheDelegate(this);
+   }
+
+   public CacheSPI<Object, Object> getCacheSPI()
+   {
+      return cache;
+   }
+
+   public Object attach(String id, Object pojo) throws PojoCacheException
+   {
+      return attach(Fqn.fromString(id), pojo);
+   }
+
+   public Object attach(Fqn<?> id, Object pojo) throws PojoCacheException
+   {
+      return attach(id, pojo, null, null);
+   }
+
+   public Object attach(Fqn<?> id, Object pojo, String field, Object source) throws PojoCacheException
+   {
+      TransactionManager tm = getTransactionManager();
+      boolean createdTransaction = setupTransaction(tm);
+      try
+      {
+         Object obj = delegate_.putObject(id, pojo, field, source);
+         return obj;
+      }
+      catch (Throwable t)
+      {
+         setRollbackOnly(tm);
+         throw new PojoCacheException("attach failed " + id, t);
+      }
+      finally
+      {
+         if (createdTransaction)
+            endTransaction(tm, id);
+      }
+   }
+
+   public Object detach(Fqn<?> id, String field, Object source) throws PojoCacheException
+   {
+      TransactionManager tm = getTransactionManager();
+      boolean createdTransaction = setupTransaction(tm);
+      try
+      {
+         Object obj = delegate_.removeObject(id, field, source);
+         return obj;
+      }
+      catch (Throwable t)
+      {
+         setRollbackOnly(tm);
+         throw new PojoCacheException("detach failed " + id, t);
+      }
+      finally
+      {
+         if (createdTransaction)
+            endTransaction(tm, id);
+      }
+   }
+
+   private void endTransaction(TransactionManager tm, Fqn<?> id)
+   {
+      try
+      {
+         switch (tm.getStatus())
+         {
+            case Status.STATUS_PREPARING:
+            case Status.STATUS_PREPARED:
+            case Status.STATUS_ACTIVE:
+               tm.commit();
+               break;
+            case Status.STATUS_MARKED_ROLLBACK:
+               tm.rollback();
+               break;
+         }
+      }
+      catch (Throwable t)
+      {
+         if (log_.isWarnEnabled())
+            log_.warn("Could not end transaction for operation on: " + id, t);
+      }
+   }
+
+   private void setRollbackOnly(TransactionManager tm)
+   {
+      try
+      {
+         if (tm.getStatus() != Status.STATUS_MARKED_ROLLBACK)
+            tm.setRollbackOnly();
+      }
+      catch (Throwable t)
+      {
+         if (log_.isWarnEnabled())
+            log_.warn("Could not rollback transaction!", t);
+      }
+   }
+
+   private boolean setupTransaction(TransactionManager tm)
+   {
+      boolean created = false;
+      try
+      {
+         Transaction transaction = tm.getTransaction();
+         if (transaction == null)
+         {
+            tm.begin();
+            transaction = tm.getTransaction();
+            created = true;
+         }
+
+         transaction.registerSynchronization(PojoTxSynchronizationHandler.create());
+      }
+      catch (Exception e)
+      {
+         throw new PojoCacheException("Error creating transaction", e);
+      }
+
+      return created;
+   }
+
+   private TransactionManager getTransactionManager()
+   {
+      TransactionManager tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+      if (tm == null)
+         tm = BatchModeTransactionManager.getInstance();
+
+      return tm;
+   }
+
+   public Object detach(String id) throws PojoCacheException
+   {
+      return detach(Fqn.fromString(id));
+   }
+
+
+
+   public Object detach(Fqn<?> id) throws PojoCacheException
+   {
+      return detach(id, null, null);
+   }
+
+   public String getPojoID(Object pojo)
+   {
+      throw new PojoCacheException("getPojoID not yet implemented");
+   }
+
+   public boolean exists(Fqn<?> id)
+   {
+      return delegate_.exists(id);
+   }
+
+   public Object find(String id) throws PojoCacheException
+   {
+      return find(Fqn.fromString(id));
+   }
+
+   public Object find(Fqn<?> id) throws PojoCacheException
+   {
+      try
+      {
+         return find(id, null, null);
+      }
+      catch (CacheException e)
+      {
+         throw new PojoCacheException("find " + id + " failed ", e);
+      }
+   }
+
+   public Object find(Fqn<?> id, String field, Object source) throws CacheException
+   {
+      return delegate_.getObject(id, field, source);
+   }
+
+
+   public Map<Fqn<?>, Object> findAll(String id) throws PojoCacheException
+   {
+      return findAll(Fqn.fromString(id));
+   }
+
+   public Map<Fqn<?>, Object> findAll(Fqn<?> id) throws PojoCacheException
+   {
+      // Should produce "/"
+      if (id == null) id = Fqn.ROOT;
+
+      try
+      {
+         return delegate_.findObjects(id);
+      }
+      catch (CacheException e)
+      {
+         throw new PojoCacheException("findAll " + id + " failed", e);
+      }
+   }
+
+   public String getVersion()
+   {
+      return Version.printVersion();
+   }
+
+   public void create() throws PojoCacheException
+   {
+      log_.info("PojoCache version: " + getVersion());
+      try
+      {
+         cache.create();
+      }
+      catch (Exception e)
+      {
+         throw new PojoCacheException("PojoCache create exception", e);
+      }
+
+      hasCreate_ = true;
+   }
+
+   public void start() throws PojoCacheException
+   {
+      if (!hasCreate_)
+      {
+         create();
+      }
+
+      try
+      {
+         log_.info("PojoCache version: " + getVersion());
+         cache.start();
+      }
+      catch (Exception e)
+      {
+         throw new PojoCacheException("Failed starting " + e, e);
+      }
+   }
+
+   public void stop() throws PojoCacheException
+   {
+      cache.stop();
+   }
+
+   public void destroy() throws PojoCacheException
+   {
+      cache.destroy();
+   }
+
+   public Collection<Object> getListeners()
+   {
+      return listenerAdaptor.getListeners();
+   }
+
+   public void addListener(Object listener)
+   {
+      addListener(listener, null);
+   }
+
+   public void addListener(Object listener, Pattern pattern)
+   {
+      // Add and remove listner operations must be serialized to ensure that
+      // the adaptor is always present only once, when at least one listener
+      // is registered.
+      synchronized (listenerAdaptor)
+      {
+         try
+         {
+            boolean wasEmpty = listenerAdaptor.isEmpty();
+            listenerAdaptor.addListener(listener, pattern);
+            if (wasEmpty)
+               cache.addCacheListener(listenerAdaptor);
+         }
+         catch (IllegalArgumentException e)
+         {
+            // simplify stack trace for user
+            e.fillInStackTrace();
+            throw e;
+         }
+      }
+   }
+
+   public void removeListener(Object listener)
+   {
+      synchronized (listenerAdaptor)
+      {
+         listenerAdaptor.removeListener(listener);
+         if (listenerAdaptor.isEmpty())
+            cache.removeCacheListener(listenerAdaptor);
+      }
+   }
+
+   public PojoCacheThreadContext getThreadContext()
+   {
+      return threadContext;
+   }
+
+   public Cache<Object,Object> getCache()
+   {
+      return cache;
+   }
+
+   /**
+    * Obtain a cache aop type for user to traverse the defined "primitive" types in aop.
+    * Note that this is not a synchronized call now for speed optimization.
+    *
+    * @param clazz The original pojo class
+    * @return CachedType
+    */
+   public synchronized CachedType getCachedType(Class clazz)
+   {
+      CachedType type = (CachedType) cachedTypes_.get(clazz);
+      if (type == null)
+      {
+         type = new CachedType(clazz);
+         cachedTypes_.put(clazz, type);
+         return type;
+      }
+      else
+      {
+         return type;
+      }
+   }
+
+   public String toString()
+   {
+      return getClass().getName() +
+              " cache=" + cache +
+              " delegate=" + delegate_ +
+              " types=" + cachedTypes_.size();
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,173 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.impl;
-
-import java.lang.reflect.Field;
-import java.util.List;
-
-import org.jboss.aop.Advised;
-import org.jboss.aop.Domain;
-import org.jboss.aop.InstanceAdvisor;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.annotation.TxUndo;
-import org.jboss.cache.pojo.collection.CachedArray;
-import org.jboss.cache.pojo.collection.CachedArrayRegistry;
-import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
-
-/**
- * Utility class for method wrappers that we are interested to rollback (i.e., rollback).
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoUtil
-{
-   private static final String BindingName = "ReentrancyStopperInterceptor.";
-
-   @TxUndo
-   public void attachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      _attachInterceptor(pojo, advisor, interceptor);
-   }
-
-   @TxUndo
-   public void detachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      _detachInterceptor(advisor, interceptor);
-   }
-
-   @TxUndo
-   public void detachCollectionInterceptor(AbstractCollectionInterceptor interceptor) {
-      interceptor.detach(true);
-   }
-
-   @TxUndo
-   public void attachArray(Object array, CachedArray cached) {
-      CachedArrayRegistry.register(array, cached);
-   }
-
-   @TxUndo
-   public void detachArray(Object array, CachedArray cached) {
-      CachedArrayRegistry.unregister(array);
-   }
-
-   public void undoAttachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      _detachInterceptor(advisor, interceptor);
-   }
-
-   public void undoDetachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      Object pojo = ((CacheFieldInterceptor) interceptor).getAopInstance().get();
-      if (pojo == null)
-      {
-         throw new PojoCacheException("PojoUtil.detachInterceptor(): null pojo");
-      }
-
-      _attachInterceptor(pojo, advisor, interceptor);
-   }
-
-   public void undoDetachCollectionInterceptor(AbstractCollectionInterceptor interceptor) {
-      interceptor.attach(null, false);
-   }
-
-   public void undoAttachArray(Object array, CachedArray cached) {
-      CachedArrayRegistry.unregister(array);
-   }
-
-   public void undoDetachArray(Object array, CachedArray cached) {
-      CachedArrayRegistry.register(array, cached);
-   }
-
-
-   @TxUndo
-   public void inMemorySubstitution(Object obj, Field field, Object newValue)
-   {
-      _inMemorySubstitution(obj, field, newValue);
-   }
-
-   public void undoInMemorySubstitution(Object obj, Field field, Object oldValue)
-   {
-      _inMemorySubstitution(obj, field, oldValue);
-   }
-
-   private void _attachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      advisor.appendInterceptor(interceptor);
-   }
-
-   private Domain getInstanceDomain(Object obj)
-   {
-      Advised advised = ((Advised) obj);
-      InstanceAdvisor advisor = advised._getInstanceAdvisor();
-      return advisor.getDomain();
-   }
-
-   private void _inMemorySubstitution(Object obj, Field field, Object newValue)
-   {
-      try
-      {
-         field.set(obj, newValue);
-      }
-      catch (IllegalAccessException e)
-      {
-         throw new PojoCacheException(
-               "PojoUtil.inMemorySubstitution(): Can't swap out the class of field \" " +
-               "+field.getLastElementAsString()," + e);
-      }
-   }
-
-   private void _detachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
-   {
-      advisor.removeInterceptor(interceptor.getName());
-      // retrieve pojo
-      Object pojo = ((CacheFieldInterceptor) interceptor).getAopInstance().get();
-
-      if (pojo == null)
-      {
-         throw new PojoCacheException("PojoUtil.detachInterceptor(): null pojo");
-      }
-   }
-
-   @TxUndo
-   public int incrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      return _incrementReferenceCount(sourceFqn, count, refList);
-   }
-
-   public int undoIncrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      return _decrementReferenceCount(sourceFqn, count, refList);
-   }
-
-   private int _incrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      refList.add(sourceFqn);
-      return count + 1;
-   }
-
-   @TxUndo
-   public int decrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      return _decrementReferenceCount(sourceFqn, count, refList);
-   }
-
-   public int undoDecrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      return _incrementReferenceCount(sourceFqn, count, refList);
-   }
-
-   private int _decrementReferenceCount(Fqn sourceFqn, int count, List refList)
-   {
-      refList.remove(sourceFqn);
-      return count - 1;
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/impl/PojoUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,201 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.impl;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.jboss.aop.InstanceAdvisor;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.collection.CachedArray;
+import org.jboss.cache.pojo.collection.CachedArrayRegistry;
+import org.jboss.cache.pojo.interceptors.PojoTxSynchronizationHandler;
+import org.jboss.cache.pojo.interceptors.dynamic.AbstractCollectionInterceptor;
+import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
+import org.jboss.cache.pojo.util.MethodCall;
+
+/**
+ * Utility class for method wrappers that we are interested to rollback (i.e., rollback).
+ *
+ * @author Ben Wang
+ * @version $Id$
+ */
+public class PojoUtil
+{
+   public void attachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      _attachInterceptor(pojo, advisor, interceptor);
+      Method method = MethodDeclarations.undoAttachInterceptor;
+      MethodCall mc = new MethodCall(method, new Object[] {pojo, advisor, interceptor}, this);
+      addUndo(mc);
+   }
+
+   public void detachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      _detachInterceptor(advisor, interceptor);
+      Method method = MethodDeclarations.undoDetachInterceptor;
+      MethodCall mc = new MethodCall(method, new Object[] {advisor, interceptor}, this);
+      addUndo(mc);
+   }
+
+   private void addUndo(MethodCall mc)
+   {
+      PojoTxSynchronizationHandler handler = PojoTxSynchronizationHandler.current();
+      if (handler != null)
+         handler.addToList(mc);
+   }
+
+   public void detachCollectionInterceptor(AbstractCollectionInterceptor interceptor) {
+      interceptor.detach(true);
+      Method method = MethodDeclarations.undoDetachCollectionInterceptor;
+      MethodCall mc = new MethodCall(method, new Object[] {interceptor}, this);
+      addUndo(mc);
+   }
+
+   public void attachArray(Object array, CachedArray cached) {
+      CachedArrayRegistry.register(array, cached);
+      Method method = MethodDeclarations.undoAttachArray;
+      MethodCall mc = new MethodCall(method, new Object[] {array, cached}, this);
+      addUndo(mc);
+   }
+
+   public void detachArray(Object array, CachedArray cached) {
+      CachedArrayRegistry.unregister(array);
+      Method method = MethodDeclarations.undoDetachArray;
+      MethodCall mc = new MethodCall(method, new Object[] {array, cached}, this);
+      addUndo(mc);
+   }
+
+   public void undoAttachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      _detachInterceptor(advisor, interceptor);
+   }
+
+   public void undoDetachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      Object pojo = ((CacheFieldInterceptor) interceptor).getAopInstance().get();
+      if (pojo == null)
+      {
+         throw new PojoCacheException("PojoUtil.detachInterceptor(): null pojo");
+      }
+
+      _attachInterceptor(pojo, advisor, interceptor);
+   }
+
+   public void undoDetachCollectionInterceptor(AbstractCollectionInterceptor interceptor) {
+      interceptor.attach(null, false);
+   }
+
+   public void undoAttachArray(Object array, CachedArray cached) {
+      CachedArrayRegistry.unregister(array);
+   }
+
+   public void undoDetachArray(Object array, CachedArray cached) {
+      CachedArrayRegistry.register(array, cached);
+   }
+
+   public void inMemorySubstitution(Object obj, Field field, Object newValue)
+   {
+      Method method = MethodDeclarations.undoInMemorySubstitution;
+      Object[] args;
+      try
+      {
+         args = new Object[]{obj, field, field.get(obj)};
+      }
+      catch (Throwable t)
+      {
+         throw new PojoCacheException("Severe error building undo list", t);
+      }
+
+      _inMemorySubstitution(obj, field, newValue);
+
+      MethodCall mc = new MethodCall(method, args, this);
+      addUndo(mc);
+   }
+
+   public void undoInMemorySubstitution(Object obj, Field field, Object oldValue)
+   {
+      _inMemorySubstitution(obj, field, oldValue);
+   }
+
+   private void _attachInterceptor(Object pojo, InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      advisor.appendInterceptor(interceptor);
+   }
+
+   private void _inMemorySubstitution(Object obj, Field field, Object newValue)
+   {
+      try
+      {
+         field.set(obj, newValue);
+      }
+      catch (IllegalAccessException e)
+      {
+         throw new PojoCacheException(
+               "PojoUtil.inMemorySubstitution(): Can't swap out the class of field \" " +
+               "+field.getLastElementAsString()," + e);
+      }
+   }
+
+   private void _detachInterceptor(InstanceAdvisor advisor, Interceptor interceptor)
+   {
+      advisor.removeInterceptor(interceptor.getName());
+      // retrieve pojo
+      Object pojo = ((CacheFieldInterceptor) interceptor).getAopInstance().get();
+
+      if (pojo == null)
+      {
+         throw new PojoCacheException("PojoUtil.detachInterceptor(): null pojo");
+      }
+   }
+
+   public int incrementReferenceCount(Fqn<?> sourceFqn, int count, List<?> refList)
+   {
+      int ret = _incrementReferenceCount(sourceFqn, count, refList);
+      Method method = MethodDeclarations.undoIncrementReferenceCount;
+      Object[] args = new Object[]{sourceFqn, count, refList};
+      MethodCall mc = new MethodCall(method, args, this);
+      addUndo(mc);
+      return ret;
+   }
+
+   public int undoIncrementReferenceCount(Fqn sourceFqn, int count, List refList)
+   {
+      return _decrementReferenceCount(sourceFqn, count, refList);
+   }
+
+   private int _incrementReferenceCount(Fqn sourceFqn, int count, List refList)
+   {
+      refList.add(sourceFqn);
+      return count + 1;
+   }
+
+   public int decrementReferenceCount(Fqn<?> sourceFqn, int count, List<?> refList)
+   {
+      int ret = _decrementReferenceCount(sourceFqn, count, refList);
+      Method method = MethodDeclarations.undoDecrementReferenceCount;
+      Object[] args = new Object[]{sourceFqn, count, refList};
+      MethodCall mc = new MethodCall(method, args, this);
+      addUndo(mc);
+      return ret;
+   }
+
+   public int undoDecrementReferenceCount(Fqn sourceFqn, int count, List refList)
+   {
+      return _incrementReferenceCount(sourceFqn, count, refList);
+   }
+
+   private int _decrementReferenceCount(Fqn sourceFqn, int count, List refList)
+   {
+      refList.remove(sourceFqn);
+      return count - 1;
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckIdInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/CheckIdInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckIdInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,50 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Fqn;
-
-/**
- * Interceptor (done via aop advice) to check the validity of the id specified by the user.
- *
- * @version $Id$
- */
-public class CheckIdInterceptor extends AbstractInterceptor
-{
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("CheckIdInterceptor.invoke(): invocation not MethodInvocation");
-      }
-
-      MethodInvocation invocation = (MethodInvocation) in;
-      invocation.getAdvisor();
-      try
-      {
-         checkFqnValidity((Fqn) invocation.getArguments()[0]);
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-      }
-   }
-
-
-   private static void checkFqnValidity(Fqn id)
-   {
-      // throws exception is fqn is JBossInternal
-//      if (id.hasElement(InternalConstant.JBOSS_INTERNAL_STRING))
-//      {
-//         throw new IllegalArgumentException("CheckIdIntercepto.checkFqnValidity(): fqn is not valid: " + id);
-//      }
-   }
-}
-

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckNonSerializableInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/CheckNonSerializableInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/CheckNonSerializableInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,57 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.util.AopUtil;
-
-/**
- * Interceptor (done via aop advice) to check the validity of the id specified by the user.
- *
- * @version $Id$
- */
-public class CheckNonSerializableInterceptor extends AbstractInterceptor
-{
-   private boolean marshallNonSerializable_ = false;
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("CheckIdInterceptor.invoke(): invocation not MethodInvocation");
-      }
-
-      MethodInvocation invocation = (MethodInvocation) in;
-      Fqn id = (Fqn) invocation.getArguments()[0];
-      Object obj = invocation.getArguments()[1];
-      if (!marshallNonSerializable_)
-      {
-         AopUtil.checkObjectType(obj);
-      }
-      else
-      {
-         log.debug("invoke(): marshallNonSerializable is set to true. We will skip object type checking for id:"
-                   + id.toString());
-      }
-
-      try
-      {
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-      }
-   }
-
-   public void setMarshallNonSerializable(boolean isTrue)
-   {
-      marshallNonSerializable_ = isTrue;
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/MethodReentrancyStopperInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/MethodReentrancyStopperInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/MethodReentrancyStopperInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,88 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.pojo.PojoCacheException;
-
-import java.lang.reflect.Method;
-
-/**
- * @author Ben Wang
- */
-
-public class MethodReentrancyStopperInterceptor implements Interceptor
-{
-   private final Log log_ = LogFactory.getLog(MethodReentrancyStopperInterceptor.class);
-   private ThreadLocal<Boolean> done;
-   private String methodName;
-
-   public MethodReentrancyStopperInterceptor()
-   {
-      done = new ThreadLocal<Boolean>();
-      done.set(false);
-   }
-
-   public void setMethodName(String mname)
-   {
-      methodName = mname;
-   }
-
-   public String getName()
-   {
-      return MethodReentrancyStopperInterceptor.class.getName() + "-" + methodName;
-   }
-
-   public Object invoke(Invocation invocation) throws Throwable
-   {
-      boolean wasDone = done.get();
-
-      try
-      {
-         if (!wasDone)
-         {
-            done.set(true);
-            return invocation.invokeNext();
-         }
-         else
-         {
-            //Needs adding, and will invoke target joinpoint skipping the rest of the chain
-            if (log_.isDebugEnabled())
-            {
-               Method method = ((MethodInvocation) invocation).getMethod();
-               log_.debug("Detect recursive interception. Will call the target directly: " + method.getName());
-            }
-
-            if (methodName.equals("toString"))
-            {
-               return invocation.getTargetObject().getClass().getName();
-            }
-            else if (methodName.equals("hashCode"))
-            {
-               return 0;
-            }
-            else
-            {
-               throw new PojoCacheException("MethodReentrancyStopperInterceptor.invoke(): unknown method name"
-                                            + methodName);
-            }
-         }
-      }
-      finally
-      {
-         if (!wasDone)
-         {
-            done.set(false);
-         }
-      }
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoBeginInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoBeginInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoBeginInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,44 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.aop.metadata.SimpleMetaData;
-
-/**
- * The first interceptor that deals initialization.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoBeginInterceptor extends AbstractInterceptor
-{
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("BeginInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-      // Let's initialize the metadata
-      SimpleMetaData simple = new SimpleMetaData();
-      invocation.setMetaData(simple);
-
-      try
-      {
-         log.debug("**** Entering method: **** " + invocation.getMethod());
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-//         reset(); // reset
-         log.debug("Leaving method: " + invocation.getMethod());
-      }
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoEventInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoEventInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoEventInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-
-/**
- * Handles the POJO event notification.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoEventInterceptor extends AbstractInterceptor
-{
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("PojoEventInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-      try
-      {
-         System.out.println("**** Entering method: **** " + invocation.getMethod());
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-         System.out.println("Leaving method: " + invocation.getMethod());
-      }
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoFailedTxMockupInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoFailedTxMockupInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoFailedTxMockupInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,65 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.impl.InternalConstant;
-
-import javax.transaction.Transaction;
-
-/**
- * Interceptor to mockup tx failure that resulting in rollback. User can simulate a rollback
- * by setting the static method <code>setRollback</code>. Note that you will need to use
- * setRollback for every method call, that is, it will reset itself after a rollback
- * has been performed.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoFailedTxMockupInterceptor extends AbstractInterceptor
-{
-   public static boolean TX_ROLLBACK = false;
-
-   public static void setTxRollback(boolean isTrue)
-   {
-      TX_ROLLBACK = isTrue;
-   }
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException(
-                 "PojoFailedTxMockupInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-      try
-      {
-         Object obj = null;
-         obj = invocation.invokeNext(); // proceed to next advice or actual call
-         if(TX_ROLLBACK)
-         {
-            Transaction tx = (Transaction)
-                    invocation.getMetaData().getMetaData(PojoTxInterceptor.TAG, PojoTxInterceptor.TX);
-
-            Fqn id = (Fqn) invocation.getArguments()[0];
-
-            if(!id.isChildOrEquals(InternalConstant.JBOSS_INTERNAL))
-            {
-               tx.setRollbackOnly();
-               TX_ROLLBACK = false;
-            }
-         }
-         return obj;
-      } finally
-      {
-      }
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,145 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.transaction.BatchModeTransactionManager;
-
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-/**
- * Interceptor (done via aop advice) for transaction
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoTxInterceptor extends AbstractInterceptor
-{
-   private TransactionManager localTm_ = null;
-   private TransactionManager txManager_;
-   public static final String TAG = "PC";
-   public static final String TX = "TX";
-
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("TxInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-
-      if (txManager_ == null)
-      {
-         txManager_ = getCache(invocation).getTransactionManager();
-      }
-
-      Transaction tx = null;
-      if (txManager_ != null)
-      {
-         // Use the configured one if so setup.
-         localTm_ = txManager_;
-      }
-      else
-      {
-         localTm_ = BatchModeTransactionManager.getInstance();
-      }
-
-      tx = localTm_.getTransaction();
-
-      boolean needTx = false;
-      if (tx == null) needTx = true;
-      Fqn id = null;
-      try
-      {
-         if (needTx)
-         {
-            id = (Fqn) invocation.getArguments()[0];
-            log.debug("Initiating a local transaction for batch processing with id: " + id.toString());
-            // Start one of our own as batch processing.
-            try
-            {
-               localTm_.begin();
-               tx = localTm_.getTransaction();
-               // Stuff tx context into the metadata
-               invocation.getMetaData().addMetaData(TAG, TX, tx);
-               return invocation.invokeNext(); // proceed to next advice or actual call
-            }
-            catch (Exception e)
-            {
-               log.warn(invocation.getMethod().getName() + ": exception occurred: " + e);
-               try
-               {
-                  localTm_.setRollbackOnly();
-               }
-               catch (Exception e2)
-               {
-                  log.error("setRollbackOnly", e2);
-               }
-
-               throw new PojoCacheException("PojoCache operation will be rollback. id: " + id
-                                            + ". Operation: " + invocation.getMethod().getName(), e);
-            }
-         }
-         else
-         {
-            invocation.getMetaData().addMetaData(TAG, TX, tx);
-            return invocation.invokeNext(); // proceed to next advice or actual call
-         }
-      }
-      finally
-      {
-         if (needTx)
-         {
-            endTransaction(id);
-         }
-      }
-   }
-
-   private void endTransaction(Fqn id)
-   {
-      if (localTm_ == null)
-      {
-         log.warn("endTransaction(): tm is null for id: " + id);
-         return;
-      }
-
-
-      try
-      {
-         if (localTm_.getTransaction().getStatus() != Status.STATUS_MARKED_ROLLBACK)
-         {
-            localTm_.commit();
-         }
-         else if (localTm_.getTransaction().getStatus() == Status.STATUS_ROLLEDBACK)
-         {
-            log.info("endTransaction(): has been rolled back for id: " + id);
-         }
-         else
-         {
-            log.info("endTransaction(): rolling back tx for id: " + id);
-            localTm_.rollback();
-         }
-      }
-      catch (RollbackException re)
-      {
-         // Do nothing here since cache may rollback automatically.
-         log.warn("endTransaction(): rolling back transaction with exception: " + re);
-      }
-      catch (Exception e)
-      {
-         log.warn("endTransaction(): Failed with exception: " + e);
-      }
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxLockInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxLockInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxLockInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,96 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.lock.UpgradeException;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.impl.InternalConstant;
-
-/**
- * Interceptor that handles the parent node lock associated with transaction.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoTxLockInterceptor extends AbstractInterceptor
-{
-   public static final String LOCK_KEY = InternalConstant.POJOCACHE_KEY_PREFIX + "LOCK";
-   // retry times for lockPojo just in case there is upgrade exception during concurrent access.
-   private final int RETRY = 5;
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      MethodInvocation invocation = (MethodInvocation) in;
-      try
-      {
-         handleLock(invocation);
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-//         handleUnLock(invocation);
-      }
-   }
-
-   private void handleLock(MethodInvocation invocation) throws Throwable
-   {
-      Fqn id = (Fqn) invocation.getArguments()[0];
-      Cache<Object, Object> cache = getCache(invocation);
-//      Object owner = cache.getLockOwner();
-      Object owner = null;
-      if (!lockPojo(owner, id, cache))
-      {
-         throw new PojoCacheException("PojoCache.removeObject(): Can't obtain the pojo lock under id: " + id);
-      }
-   }
-
-   private boolean lockPojo(Object owner, Fqn id, Cache<Object, Object> cache) throws CacheException
-   {
-      if (log.isDebugEnabled())
-      {
-         log.debug("lockPojo(): id:" + id + " Owner: " + owner);
-      }
-
-      boolean isNeeded = true;
-      int retry = 0;
-   
-      while (isNeeded)
-      {
-         try
-         {
-            cache.put(id, LOCK_KEY, "LOCK");
-            isNeeded = false;
-         }
-         catch (UpgradeException upe)
-         {
-            log.warn("lockPojo(): can't upgrade the lock during lockPojo. Will re-try. id: " + id
-                     + " retry times: " + retry);
-            if (retry++ > RETRY)
-            {
-               return false;
-            }
-            // try to sleep a little as well.
-            try
-            {
-               Thread.sleep(10);
-            }
-            catch (InterruptedException e)
-            {
-            }
-         }
-      }
-
-      return true;
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,95 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.util.MethodCall;
-
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Handling the rollback operation for PojoCache level, specifically interceptor add/remove, etc.
- *
- * @author Ben Wang
- * @version $Id$
- */
-
-class PojoTxSynchronizationHandler implements Synchronization
-{
-   private static Log log = LogFactory.getLog(PojoTxSynchronizationHandler.class.getName());
-   private List undoList_ = new ArrayList();
-
-   PojoTxSynchronizationHandler()
-   {
-   }
-
-   public void beforeCompletion()
-   {
-      // Not interested
-   }
-
-   public void afterCompletion(int status)
-   {
-      try
-      {
-         switch (status)
-         {
-            case Status.STATUS_COMMITTED:
-               break;
-            case Status.STATUS_MARKED_ROLLBACK:
-            case Status.STATUS_ROLLEDBACK:
-               log.debug("Running Pojo rollback phase");
-               runRollbackPhase();
-               log.debug("Finished rollback phase");
-               break;
-
-            default:
-               throw new IllegalStateException("illegal status: " + status);
-         }
-      }
-      finally
-      {
-         resetUndoOp();
-      }
-   }
-
-   private void runRollbackPhase()
-   {
-      // Rollback the pojo interceptor add/remove
-      for (int i = (undoList_.size() - 1); i >= 0; i--)
-      {
-         MethodCall mc = (MethodCall) undoList_.get(i);
-         try
-         {
-            mc.invoke();
-         }
-         catch (Throwable t)
-         {
-            throw new PojoCacheException(
-                  "PojoTxSynchronizationHandler.runRollbackPhase(): error: " + t, t);
-         }
-      }
-   }
-
-   public void addToList(MethodCall mc)
-   {
-      undoList_.add(mc);
-   }
-
-   public void resetUndoOp()
-   {
-      undoList_.clear();
-      PojoTxUndoSynchronizationInterceptor.reset();
-   }
-}
-

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxSynchronizationHandler.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.interceptors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.util.MethodCall;
+
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handling the rollback operation for PojoCache level, specifically interceptor add/remove, etc.
+ *
+ * @author Ben Wang
+ * @version $Id$
+ */
+
+public class PojoTxSynchronizationHandler implements Synchronization
+{
+   private static Log log = LogFactory.getLog(PojoTxSynchronizationHandler.class.getName());
+   private List undoList_ = new ArrayList();
+
+   private static ThreadLocal<PojoTxSynchronizationHandler> handler = new ThreadLocal<PojoTxSynchronizationHandler>();
+
+   PojoTxSynchronizationHandler()
+   {
+   }
+
+   public static PojoTxSynchronizationHandler current()
+   {
+      return handler.get();
+   }
+
+   public static PojoTxSynchronizationHandler create()
+   {
+      PojoTxSynchronizationHandler current = handler.get();
+      if (current == null)
+      {
+         current = new PojoTxSynchronizationHandler();
+         handler.set(current);
+      }
+
+      return current;
+   }
+
+   public void beforeCompletion()
+   {
+      // Not interested
+   }
+
+   public void afterCompletion(int status)
+   {
+      try
+      {
+         switch (status)
+         {
+            case Status.STATUS_COMMITTED:
+               break;
+            case Status.STATUS_MARKED_ROLLBACK:
+            case Status.STATUS_ROLLEDBACK:
+               log.debug("Running Pojo rollback phase");
+               runRollbackPhase();
+               log.debug("Finished rollback phase");
+               break;
+
+            default:
+               throw new IllegalStateException("illegal status: " + status);
+         }
+      }
+      finally
+      {
+         resetUndoOp();
+      }
+   }
+
+   private void runRollbackPhase()
+   {
+      // Rollback the pojo interceptor add/remove
+      for (int i = (undoList_.size() - 1); i >= 0; i--)
+      {
+         MethodCall mc = (MethodCall) undoList_.get(i);
+         try
+         {
+            mc.invoke();
+         }
+         catch (Throwable t)
+         {
+            throw new PojoCacheException(
+                  "PojoTxSynchronizationHandler.runRollbackPhase(): error: " + t, t);
+         }
+      }
+   }
+
+   public void addToList(MethodCall mc)
+   {
+      undoList_.add(mc);
+   }
+
+   public void resetUndoOp()
+   {
+      undoList_.clear();
+      handler.set(null);
+      //PojoTxUndoSynchronizationInterceptor.reset();
+   }
+}
+

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,123 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.impl.MethodDeclarations;
-import org.jboss.cache.pojo.util.MethodCall;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * Interceptor (done via aop advice) for transaction rollback. This is is attached to the
- * operation that needs a corresponding rollback, e.g., attachInterceptor.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoTxUndoInterceptor extends AbstractInterceptor
-{
-   /// Just that AOP requires an extra key.
-   public static final String TAG = "PojoCache";
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("TxUndoInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-
-      PojoTxSynchronizationHandler handler =
-            PojoTxUndoSynchronizationInterceptor.getSynchronizationHandler();
-
-      if (handler == null)
-      {
-         return invocation.invokeNext();
-// TODO handler is null can mean we are not calling the right interceptor stack. Need to revisit.
-// E.g., a fresh getObject or find will trigger this.
-//         throw new IllegalStateException("PojoTxUndoInterceptor.invoke(): PojoTxSynchronizationHandler is null");
-      }
-
-      // Add to the rollback list
-      String methodName = invocation.getMethod().getName();
-      // TODO Needs to handle Collection interceptor as well.
-      if (methodName.equals(MethodDeclarations.attachInterceptor.getName()))
-      {
-         Method method = MethodDeclarations.undoAttachInterceptor;
-         MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.detachInterceptor.getName()))
-      {
-         Method method = MethodDeclarations.undoDetachInterceptor;
-         MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.detachCollectionInterceptor.getName()))
-      {
-         Method method = MethodDeclarations.undoDetachCollectionInterceptor;
-         MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.attachArray.getName()))
-      {
-         Method method = MethodDeclarations.undoAttachArray;
-         MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.detachArray.getName()))
-      {
-         Method method = MethodDeclarations.undoDetachArray;
-         MethodCall mc = new MethodCall(method, invocation.getArguments(), invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.inMemorySubstitution.getName()))
-      {
-         Method method = MethodDeclarations.undoInMemorySubstitution;
-         Object obj = invocation.getArguments()[0];
-         Field field = (Field) invocation.getArguments()[1];
-         Object oldValue = field.get(obj);
-         Object[] args = new Object[]{obj, field, oldValue};
-         MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.incrementReferenceCount.getName()))
-      {
-         Method method = MethodDeclarations.undoIncrementReferenceCount;
-         Fqn fqn = (Fqn) invocation.getArguments()[0];
-         int count = (Integer) invocation.getArguments()[1];
-         List referenceList = (List) invocation.getArguments()[2];
-         Object[] args = new Object[]{fqn, count, referenceList};
-         MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else if (methodName.equals(MethodDeclarations.decrementReferenceCount.getName()))
-      {
-         Method method = MethodDeclarations.undoDecrementReferenceCount;
-         Fqn fqn = (Fqn) invocation.getArguments()[0];
-         int count = (Integer) invocation.getArguments()[1];
-         List referenceList = (List) invocation.getArguments()[2];
-         Object[] args = new Object[]{fqn, count, referenceList};
-         MethodCall mc = new MethodCall(method, args, invocation.getTargetObject());
-         handler.addToList(mc);
-      }
-      else
-      {
-         throw new PojoCacheException("PojoTxUndoInterceptor: invalid invocation name: " + methodName);
-      }
-
-      return invocation.invokeNext();
-   }
-
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoSynchronizationInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoSynchronizationInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/PojoTxUndoSynchronizationInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,92 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.pojo.PojoCacheException;
-
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-
-/**
- * Interceptor that handles registration of tx synchronization for rollback
- * operations.
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class PojoTxUndoSynchronizationInterceptor extends AbstractInterceptor
-{
-   // We stores the handler in thread local since the afterCompletion won't be
-   // called untill tx.commit(). Note that this is static since it can be
-   // recursive call to attach/detach.
-   private static ThreadLocal synchronizationHandler_ = new ThreadLocal();
-
-   public Object invoke(Invocation in) throws Throwable
-   {
-      if (!(in instanceof MethodInvocation))
-      {
-         throw new IllegalArgumentException("TxSyncrhonizationInterceptor.invoke(): invocation not MethodInvocation");
-      }
-      MethodInvocation invocation = (MethodInvocation) in;
-      try
-      {
-         registerTxHandler(invocation);
-         return invocation.invokeNext(); // proceed to next advice or actual call
-      }
-      finally
-      {
-      }
-   }
-
-   private void registerTxHandler(MethodInvocation invocation) throws PojoCacheException
-   {
-      try
-      {
-         // Need to have this in case of rollback
-         PojoTxSynchronizationHandler handler = (PojoTxSynchronizationHandler) synchronizationHandler_.get();
-         if (handler == null)
-         {
-            // First entry point for this transaction scope.
-            Transaction tx = (Transaction) invocation.getMetaData(PojoTxInterceptor.TAG, PojoTxInterceptor.TX);
-            if (tx == null)
-            {
-               throw new IllegalStateException("PojoCache.registerTxHanlder(). Can't have null tx handle.");
-            }
-
-            handler = new PojoTxSynchronizationHandler();
-
-            log.debug("Registering PojoTxSynchronizationHandler for rollback if ncessary " + handler);
-            // Register so we can rollback if necessary
-            tx.registerSynchronization(handler);
-
-            synchronizationHandler_.set(handler);
-         }
-      }
-      catch (RollbackException e)
-      {
-         throw new PojoCacheException("PojoTxUndoSynchronizationInterceptor.registerTxHandler(): Exception: " + e);
-      }
-      catch (SystemException e)
-      {
-         throw new PojoCacheException("PojoTxUndoSynchronizationInterceptor.registerTxHandler(): Exception: " + e);
-      }
-   }
-
-   public static PojoTxSynchronizationHandler getSynchronizationHandler()
-   {
-      return (PojoTxSynchronizationHandler) synchronizationHandler_.get();
-   }
-
-   public static void reset()
-   {
-      synchronizationHandler_.set(null);
-   }
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/StaticFieldInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/StaticFieldInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/StaticFieldInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,110 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.interceptors;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.impl.InternalConstant;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-
-import java.lang.reflect.Field;
-
-/**
- * interceptor to intercept for static field replication.
- *
- * @author Ben Wang
- */
-
-public class StaticFieldInterceptor implements Interceptor
-{
-   private final Log log_ = LogFactory.getLog(StaticFieldInterceptor.class);
-   private PojoCacheImpl pCache_;
-   private Fqn fqn_;
-   private String name_;
-   private String key_;
-
-   public StaticFieldInterceptor()
-   {
-   }
-
-   public String getName()
-   {
-      if (name_ == null)
-      {
-         this.name_ = "StaticFieldInterceptor on [" + fqn_ + "]";
-      }
-      return name_;
-   }
-
-   public Object invoke(Invocation invocation) throws Throwable
-   {
-      /*
-      // Kind of ad hoc now. MethodInvocation should not invoke this.
-      if(invocation instanceof MethodInvocation)
-         return invocation.invokeNext();
-
-      needInit(((FieldInvocation)invocation).getField());
-      if (invocation instanceof FieldWriteInvocation)
-      {
-         FieldInvocation fieldInvocation =
-                 (FieldInvocation) invocation;
-
-         Advisor advisor = fieldInvocation.getAdvisor();
-         Field field = fieldInvocation.getField();
-         if(log_.isTraceEnabled())
-         {
-            log_.trace("invoke(): field write interception for fqn: " +fqn_ + " and field: " +field);
-         }
-
-         // Only if this field is replicatable. static, transient and final are not.
-         Object value = ((FieldWriteInvocation) fieldInvocation).getValue();
-
-         cache_.put(fqn_, key_, value);
-         Object obj = fieldInvocation.getTargetObject();
-      } else if (invocation instanceof FieldReadInvocation)
-      {
-         FieldInvocation fieldInvocation =
-                 (FieldInvocation) invocation;
-         Field field = fieldInvocation.getField();
-         Advisor advisor = fieldInvocation.getAdvisor();
-         return cache_.get(fqn_, key_);
-      }
-      */
-      return invocation.invokeNext();
-
-   }
-
-   private void needInit(Field field)
-   {
-      if (pCache_ == null)
-      {
-         String cn = field.getDeclaringClass().getName();
-         fqn_ = Fqn.fromString(InternalConstant.JBOSS_INTERNAL_STATIC + "/" + cn);
-         key_ = field.getName();
-      }
-   }
-
-   boolean isChildOf(Fqn parentFqn)
-   {
-      return fqn_.isChildOf(parentFqn);
-   }
-
-   public Fqn getFqn()
-   {
-      return fqn_;
-   }
-
-   public void setFqn(Fqn fqn)
-   {
-      this.fqn_ = fqn;
-   }
-
-}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,130 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.interceptors.dynamic;
-
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.impl.PojoInstance;
-import org.jboss.cache.pojo.util.ObjectUtil;
-
-/**
- * Abstract base class for collection interceptor.
- *
- * @author Ben Wang
- * @version $Id$
- */
- at SuppressWarnings({"CanBeFinal"})
-public abstract class AbstractCollectionInterceptor implements BaseInterceptor
-{
-   Fqn fqn;
-   PojoCacheImpl cache;
-
-   private boolean attached_ = true;
-   private PojoInstance pojoInstance_;
-
-   AbstractCollectionInterceptor(PojoCacheImpl cache, Fqn fqn)
-   {
-      this.fqn = fqn;
-      this.cache = cache;
-   }
-
-   @SuppressWarnings({"CanBeFinal"})
-   public Fqn getFqn()
-   {
-      return fqn;
-   }
-
-   @SuppressWarnings({"CanBeFinal"})
-   public void setFqn(Fqn fqn)
-   {
-      this.fqn = fqn;
-   }
-
-   @SuppressWarnings({"CanBeFinal"})
-   public PojoInstance getAopInstance()
-   {
-      return pojoInstance_;
-   }
-
-   public void setAopInstance(PojoInstance pojoInstance)
-   {
-      this.pojoInstance_ = pojoInstance;
-   }
-
-   /**
-    * Attaching the Collection to PojoCache.
-    */
-   public void attach(Fqn fqn, boolean copyToCache)
-   {
-      // This is a hook to allow re-attching the Collection without specifying the fqn.
-      if (fqn != null)
-      {
-         setFqn(fqn);
-      }
-      attached_ = true;
-      // Reattach anything in-memory to cache
-   }
-
-   public void detach(boolean removeFromCache)
-   {
-      attached_ = false;
-      // Detach by tranferring the cache content to in-memory copy
-   }
-
-   public boolean isAttached()
-   {
-      return attached_;
-   }
-
-   // Verify an attached collection is truly attached
-   public void verifyAttached(Object target)
-   {
-      // If locally detached, we use the local in-memory copy
-      if (! isAttached())
-         return;
-
-      if (cache.getCache().get(fqn, PojoInstance.KEY) != null)
-         return;
-
-      String identity = ObjectUtil.identityString(target);
-      throw new PojoCacheAlreadyDetachedException(identity + " has possibly been detached remotely. Internal id: " + fqn);
-   }
-
-   Object copyOrConstruct(Object mem)
-   {
-      if (mem instanceof Cloneable) {
-         try
-         {
-            return mem.getClass().getMethod("clone").invoke(mem);
-         }
-         catch (Exception e)
-         {
-         }
-      }
-
-      try
-      {
-         return mem.getClass().newInstance();
-      }
-      catch (Exception e)
-      {
-      }
-
-      return null;
-   }
-
-   abstract void setInMemoryCopy(Object obj);
-   abstract Object getInMemoryCopy();
-   public abstract Object getSerializationCopy();
-   abstract void setCacheCopy(Object obj);
-   abstract Object getCacheCopy();
-   abstract void setCurrentCopy(Object obj);
-   public abstract Object getCurrentCopy();
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/AbstractCollectionInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.interceptors.dynamic;
+
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.impl.PojoInstance;
+import org.jboss.cache.pojo.util.ObjectUtil;
+
+/**
+ * Abstract base class for collection interceptor.
+ *
+ * @author Ben Wang
+ * @version $Id$
+ */
+ at SuppressWarnings({"CanBeFinal"})
+public abstract class AbstractCollectionInterceptor implements BaseInterceptor
+{
+   Fqn fqn;
+   PojoCacheImpl cache;
+   ClassProxy boundProxy;
+
+   private boolean attached_ = true;
+   private PojoInstance pojoInstance_;
+
+   AbstractCollectionInterceptor(PojoCacheImpl cache, Fqn fqn)
+   {
+      this.fqn = fqn;
+      this.cache = cache;
+   }
+
+   @SuppressWarnings({"CanBeFinal"})
+   public Fqn getFqn()
+   {
+      return fqn;
+   }
+
+   @SuppressWarnings({"CanBeFinal"})
+   public void setFqn(Fqn fqn)
+   {
+      this.fqn = fqn;
+   }
+
+   @SuppressWarnings({"CanBeFinal"})
+   public PojoInstance getAopInstance()
+   {
+      return pojoInstance_;
+   }
+
+   public void setAopInstance(PojoInstance pojoInstance)
+   {
+      this.pojoInstance_ = pojoInstance;
+   }
+
+   /**
+    * Attaching the Collection to PojoCache.
+    */
+   public void attach(Fqn fqn, boolean copyToCache)
+   {
+      // This is a hook to allow re-attching the Collection without specifying the fqn.
+      if (fqn != null)
+      {
+         setFqn(fqn);
+      }
+      attached_ = true;
+      // Reattach anything in-memory to cache
+   }
+
+   public void detach(boolean removeFromCache)
+   {
+      attached_ = false;
+      // Detach by tranferring the cache content to in-memory copy
+   }
+
+   public boolean isAttached()
+   {
+      return attached_;
+   }
+
+   // Verify an attached collection is truly attached
+   public void verifyAttached(Object target)
+   {
+      // If locally detached, we use the local in-memory copy
+      if (! isAttached())
+         return;
+
+      if (cache.getCache().get(fqn, PojoInstance.KEY) != null)
+         return;
+
+      String identity = ObjectUtil.identityString(target);
+      throw new PojoCacheAlreadyDetachedException(identity + " has possibly been detached remotely. Internal id: " + fqn);
+   }
+
+   Object copyOrConstruct(Object mem)
+   {
+      if (mem instanceof Cloneable) {
+         try
+         {
+            return mem.getClass().getMethod("clone").invoke(mem);
+         }
+         catch (Exception e)
+         {
+         }
+      }
+
+      try
+      {
+         return mem.getClass().newInstance();
+      }
+      catch (Exception e)
+      {
+      }
+
+      return null;
+   }
+
+   abstract void setInMemoryCopy(Object obj);
+   abstract Object getInMemoryCopy();
+   public abstract Object getSerializationCopy();
+   abstract void setCacheCopy(Object obj);
+   abstract Object getCacheCopy();
+   abstract void setCurrentCopy(Object obj);
+   public abstract Object getCurrentCopy();
+
+   public ClassProxy getBoundProxy()
+   {
+      return boundProxy;
+   }
+
+   public void setBoundProxy(ClassProxy boundProxy)
+   {
+      this.boundProxy = boundProxy;
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,204 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.interceptors.dynamic;
-
-import java.lang.reflect.Field;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.Advisor;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.aop.array.ArrayRegistry;
-import org.jboss.aop.joinpoint.FieldInvocation;
-import org.jboss.aop.joinpoint.FieldReadInvocation;
-import org.jboss.aop.joinpoint.FieldWriteInvocation;
-import org.jboss.aop.joinpoint.Invocation;
-import org.jboss.aop.joinpoint.MethodInvocation;
-import org.jboss.cache.Cache;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
-import org.jboss.cache.pojo.collection.CachedArray;
-import org.jboss.cache.pojo.collection.CachedArrayRegistry;
-import org.jboss.cache.pojo.impl.CachedType;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-import org.jboss.cache.pojo.impl.PojoInstance;
-import org.jboss.cache.pojo.impl.PojoUtil;
-import org.jboss.cache.pojo.util.ObjectUtil;
-
-/**
- * Main dynamic interceptor to intercept for field replication.
- *
- * @author Ben Wang
- */
-
-public class CacheFieldInterceptor implements BaseInterceptor
-{
-   private final Log log_ = LogFactory.getLog(CacheFieldInterceptor.class);
-   Cache<Object, Object> cache_;
-   private PojoCacheImpl pCache_;
-   Fqn fqn_;
-   private String name_;
-   private PojoInstance pojoInstance_;
-   private PojoUtil util_;
-
-   public CacheFieldInterceptor(PojoCacheImpl pCache, Fqn fqn, CachedType type)
-   {
-      this.pCache_ = pCache;
-      this.cache_ = pCache_.getCache();
-      this.fqn_ = fqn;
-      util_ = new PojoUtil();
-   }
-
-   private CacheFieldInterceptor()
-   {
-   }
-
-   public PojoInstance getAopInstance()
-   {
-      return pojoInstance_;
-   }
-
-   public Object clone()
-   {
-      BaseInterceptor interceptor = new CacheFieldInterceptor();
-      interceptor.setFqn(getFqn());
-      interceptor.setAopInstance(getAopInstance());
-      return interceptor;
-   }
-
-   public void setInterceptor(Interceptor intcptr)
-   {
-      BaseInterceptor interceptor = (BaseInterceptor) intcptr;
-      setFqn(interceptor.getFqn());
-      setAopInstance(interceptor.getAopInstance());
-   }
-
-   public void setAopInstance(PojoInstance pojoInstance)
-   {
-      this.pojoInstance_ = pojoInstance;
-   }
-
-   public String getName()
-   {
-      if (name_ == null)
-      {
-         this.name_ = "CacheFieldInterceptor on [" + fqn_ + "]";
-      }
-      return name_;
-   }
-
-   public Object invoke(Invocation invocation) throws Throwable
-   {
-      // Kind of ad hoc now. MethodInvocation should not invoke this.
-      if (invocation instanceof MethodInvocation)
-         return invocation.invokeNext();
-
-      if (invocation instanceof FieldWriteInvocation)
-      {
-         Object target = invocation.getTargetObject();
-         FieldInvocation fieldInvocation =
-               (FieldInvocation) invocation;
-
-         Advisor advisor = fieldInvocation.getAdvisor();
-         Field field = fieldInvocation.getField();
-         if (log_.isTraceEnabled())
-         {
-            log_.trace("invoke(): field write interception for fqn: " + fqn_ + " and field: " + field);
-         }
-
-         verifyAttached(target);
-
-         // Only if this field is replicatable. static, transient and final are not.
-         CachedType fieldType = pCache_.getCachedType(field.getType());
-         Object value = ((FieldWriteInvocation) fieldInvocation).getValue();
-         if (!CachedType.isNonReplicable(field))
-         {
-            if (CachedType.isSimpleAttribute(field))
-            {
-               cache_.put(fqn_, field.getName(), value);
-            }
-            else
-            {
-               pCache_.attach(fqn_, value, field.getName(), target);
-            }
-         }
-
-         util_.inMemorySubstitution(target, field, value);
-      }
-      else if (invocation instanceof FieldReadInvocation)
-      {
-         Object target = invocation.getTargetObject();
-         FieldInvocation fieldInvocation =
-               (FieldInvocation) invocation;
-         Field field = fieldInvocation.getField();
-         Advisor advisor = fieldInvocation.getAdvisor();
-
-         // Only if this field is replicatable
-         CachedType fieldType = pCache_.getCachedType(field.getType());
-         if (!CachedType.isNonReplicable(field))
-         {
-            Object result;
-            if (CachedType.isSimpleAttribute(field))
-            {
-               result = cache_.get(fqn_, field.getName());
-            }
-            else
-            {
-               result = pCache_.getObject(fqn_, field.getName(), target);
-
-               // Work around AOP issue with field reads
-               if (result != null && result.getClass().isArray())
-                  registerArrayWithAOP(target, field.getName(), result);
-            }
-
-            // If the result is null, the object might have been detached
-            if (result == null)
-               verifyAttached(target);
-
-            // Update last known state associated with this pojo.
-            util_.inMemorySubstitution(target, field, result);
-
-            // Allow interceptor chain to process, but ignore the result
-            invocation.invokeNext();
-
-            return result;
-         }
-      }
-
-      return invocation.invokeNext();
-   }
-
-   private void registerArrayWithAOP(Object owner, String fieldName, Object array)
-   {
-      CachedArray cached = CachedArrayRegistry.lookup(array);
-      if (cached != null)
-         ArrayRegistry.getInstance().addFieldReference(owner, fieldName, array);
-   }
-
-   /**
-    * Check if the pojo is detached already.
-    */
-   private void verifyAttached(Object target)
-   {
-      if (cache_.get(fqn_, PojoInstance.KEY) != null)
-         return;
-
-      String identity = ObjectUtil.identityString(target);
-      throw new PojoCacheAlreadyDetachedException(identity + " has possibly been detached remotely. Internal id: " + fqn_);
-   }
-
-   public Fqn getFqn()
-   {
-      return fqn_;
-   }
-
-   public void setFqn(Fqn fqn)
-   {
-      this.fqn_ = fqn;
-   }
-
-}
\ No newline at end of file

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,204 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.interceptors.dynamic;
+
+import java.lang.reflect.Field;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.Advisor;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.array.ArrayRegistry;
+import org.jboss.aop.joinpoint.FieldInvocation;
+import org.jboss.aop.joinpoint.FieldReadInvocation;
+import org.jboss.aop.joinpoint.FieldWriteInvocation;
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheAlreadyDetachedException;
+import org.jboss.cache.pojo.collection.CachedArray;
+import org.jboss.cache.pojo.collection.CachedArrayRegistry;
+import org.jboss.cache.pojo.impl.CachedType;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+import org.jboss.cache.pojo.impl.PojoInstance;
+import org.jboss.cache.pojo.impl.PojoUtil;
+import org.jboss.cache.pojo.util.ObjectUtil;
+
+/**
+ * Main dynamic interceptor to intercept for field replication.
+ *
+ * @author Ben Wang
+ */
+
+public class CacheFieldInterceptor implements BaseInterceptor
+{
+   private final Log log_ = LogFactory.getLog(CacheFieldInterceptor.class);
+   Cache<Object, Object> cache_;
+   private PojoCacheImpl pCache_;
+   Fqn fqn_;
+   private String name_;
+   private PojoInstance pojoInstance_;
+   private PojoUtil util_;
+
+   public CacheFieldInterceptor(PojoCacheImpl pCache, Fqn fqn, CachedType type)
+   {
+      this.pCache_ = pCache;
+      this.cache_ = pCache_.getCache();
+      this.fqn_ = fqn;
+      util_ = new PojoUtil();
+   }
+
+   private CacheFieldInterceptor()
+   {
+   }
+
+   public PojoInstance getAopInstance()
+   {
+      return pojoInstance_;
+   }
+
+   public Object clone()
+   {
+      BaseInterceptor interceptor = new CacheFieldInterceptor();
+      interceptor.setFqn(getFqn());
+      interceptor.setAopInstance(getAopInstance());
+      return interceptor;
+   }
+
+   public void setInterceptor(Interceptor intcptr)
+   {
+      BaseInterceptor interceptor = (BaseInterceptor) intcptr;
+      setFqn(interceptor.getFqn());
+      setAopInstance(interceptor.getAopInstance());
+   }
+
+   public void setAopInstance(PojoInstance pojoInstance)
+   {
+      this.pojoInstance_ = pojoInstance;
+   }
+
+   public String getName()
+   {
+      if (name_ == null)
+      {
+         this.name_ = "CacheFieldInterceptor on [" + fqn_ + "]";
+      }
+      return name_;
+   }
+
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      // Kind of ad hoc now. MethodInvocation should not invoke this.
+      if (invocation instanceof MethodInvocation)
+         return invocation.invokeNext();
+
+      if (invocation instanceof FieldWriteInvocation)
+      {
+         Object target = invocation.getTargetObject();
+         FieldInvocation fieldInvocation =
+               (FieldInvocation) invocation;
+
+         Advisor advisor = fieldInvocation.getAdvisor();
+         Field field = fieldInvocation.getField();
+         if (log_.isTraceEnabled())
+         {
+            log_.trace("invoke(): field write interception for fqn: " + fqn_ + " and field: " + field);
+         }
+
+         verifyAttached(target);
+
+         // Only if this field is replicatable. static, transient and final are not.
+         CachedType fieldType = pCache_.getCachedType(field.getType());
+         Object value = ((FieldWriteInvocation) fieldInvocation).getValue();
+         if (!CachedType.isNonReplicable(field))
+         {
+            if (CachedType.isSimpleAttribute(field))
+            {
+               cache_.put(fqn_, field.getName(), value);
+            }
+            else
+            {
+               pCache_.attach(fqn_, value, field.getName(), target);
+            }
+         }
+
+         util_.inMemorySubstitution(target, field, value);
+      }
+      else if (invocation instanceof FieldReadInvocation)
+      {
+         Object target = invocation.getTargetObject();
+         FieldInvocation fieldInvocation =
+               (FieldInvocation) invocation;
+         Field field = fieldInvocation.getField();
+         Advisor advisor = fieldInvocation.getAdvisor();
+
+         // Only if this field is replicatable
+         CachedType fieldType = pCache_.getCachedType(field.getType());
+         if (!CachedType.isNonReplicable(field))
+         {
+            Object result;
+            if (CachedType.isSimpleAttribute(field))
+            {
+               result = cache_.get(fqn_, field.getName());
+            }
+            else
+            {
+               result = pCache_.find(fqn_, field.getName(), target);
+
+               // Work around AOP issue with field reads
+               if (result != null && result.getClass().isArray())
+                  registerArrayWithAOP(target, field.getName(), result);
+            }
+
+            // If the result is null, the object might have been detached
+            if (result == null)
+               verifyAttached(target);
+
+            // Update last known state associated with this pojo.
+            util_.inMemorySubstitution(target, field, result);
+
+            // Allow interceptor chain to process, but ignore the result
+            invocation.invokeNext();
+
+            return result;
+         }
+      }
+
+      return invocation.invokeNext();
+   }
+
+   private void registerArrayWithAOP(Object owner, String fieldName, Object array)
+   {
+      CachedArray cached = CachedArrayRegistry.lookup(array);
+      if (cached != null)
+         ArrayRegistry.getInstance().addFieldReference(owner, fieldName, array);
+   }
+
+   /**
+    * Check if the pojo is detached already.
+    */
+   private void verifyAttached(Object target)
+   {
+      if (cache_.get(fqn_, PojoInstance.KEY) != null)
+         return;
+
+      String identity = ObjectUtil.identityString(target);
+      throw new PojoCacheAlreadyDetachedException(identity + " has possibly been detached remotely. Internal id: " + fqn_);
+   }
+
+   public Fqn getFqn()
+   {
+      return fqn_;
+   }
+
+   public void setFqn(Fqn fqn)
+   {
+      this.fqn_ = fqn;
+   }
+
+}
\ No newline at end of file

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,216 +0,0 @@
-/*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.cache.pojo.interceptors.dynamic;
-
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.pojo.PojoCacheException;
-import org.jboss.cache.pojo.collection.CachedMapImpl;
-import org.jboss.cache.pojo.collection.CollectionInterceptorUtil;
-import org.jboss.cache.pojo.impl.PojoCacheImpl;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Map interceptor that delegates to the underlying impl.
- *
- * @author Ben Wang
- */
- at SuppressWarnings({"CanBeFinal"})
-public class CachedMapInterceptor extends AbstractCollectionInterceptor
-{
-
-   //   protected static final Log log_ = LogFactory.getLog(CachedMapInterceptor.class);
-   private static final Map managedMethods_ =
-         CollectionInterceptorUtil.getManagedMethods(Map.class);
-   private Map methodMap_;
-   private Map cacheImpl_;
-   private Map inMemImpl_;
-   private Map current_;
-
-   public CachedMapInterceptor(PojoCacheImpl cache, Fqn fqn, Class clazz, Map obj)
-   {
-      super(cache, fqn);
-      methodMap_ = CollectionInterceptorUtil.getMethodMap(clazz);
-      cacheImpl_ = new CachedMapImpl(cache, this);
-      inMemImpl_ = obj;
-      current_ = cacheImpl_;
-   }
-
-   private CachedMapInterceptor(PojoCacheImpl cache, Fqn fqn)
-   {
-      super(cache, fqn);
-   }
-
-   public Object clone()
-   {
-      CachedMapInterceptor interceptor = new CachedMapInterceptor(cache, fqn);
-      interceptor.setFqn(getFqn());
-      interceptor.setAopInstance(getAopInstance());
-      interceptor.setCurrentCopy(getCurrentCopy());
-      interceptor.setInMemoryCopy(getInMemoryCopy());
-      interceptor.setCacheCopy(getCacheCopy());
-      return interceptor;
-   }
-
-   public void setInterceptor(Interceptor intcptr)
-   {
-      CachedMapInterceptor interceptor = (CachedMapInterceptor) intcptr;
-      setFqn(interceptor.getFqn());
-      setAopInstance(interceptor.getAopInstance());
-      setCurrentCopy(interceptor.getCurrentCopy());
-      setInMemoryCopy(interceptor.getInMemoryCopy());
-      setCacheCopy(interceptor.getCacheCopy());
-   }
-
-   public Object getCurrentCopy()
-   {
-      return current_;
-   }
-
-   void setInMemoryCopy(Object obj)
-   {
-      inMemImpl_ = (Map) obj;
-   }
-
-   Object getInMemoryCopy()
-   {
-      return inMemImpl_;
-   }
-
-   void setCacheCopy(Object obj)
-   {
-      cacheImpl_ = (Map) obj;
-   }
-
-   Object getCacheCopy()
-   {
-      return cacheImpl_;
-   }
-
-   void setCurrentCopy(Object obj)
-   {
-      current_ = (Map) obj;
-   }
-
-   /**
-    * When we want to associate this proxy with the cache again. We will need to translate the in-memory
-    * content to the cache store first.
-    */
-   public void attach(Fqn fqn, boolean copyToCache)
-   {
-      super.attach(fqn, copyToCache);
-
-      if (copyToCache)
-         toCache();
-
-      current_ = cacheImpl_;
-   }
-
-   private void toCache()
-   {
-      if (inMemImpl_ == null)
-         throw new IllegalStateException("CachedMapInterceptor.toCache(). inMemImpl is null.");
-
-      for (Object key : inMemImpl_.keySet())
-      {
-         Object val = inMemImpl_.get(key);
-         cacheImpl_.put(key, val);
-      }
-
-      inMemImpl_.clear();
-      inMemImpl_ = null;   // we are done with this.
-   }
-
-   /**
-    * When we want to separate this proxy from the cache. We will destroy the cache content and copy them to
-    * the in-memory copy.
-    */
-   public void detach(boolean removeFromCache)
-   {
-      super.detach(removeFromCache);
-
-      toMemory(removeFromCache);
-
-      current_ = inMemImpl_;
-   }
-
-   private void toMemory(boolean removeFromCache)
-   {
-      if (inMemImpl_ == null)
-      {
-         inMemImpl_ = new HashMap();
-      }
-
-      Iterator it = cacheImpl_.keySet().iterator();
-      inMemImpl_.clear();
-      while (it.hasNext())
-      {
-         Object key = it.next();
-         Object val = null;
-         if (removeFromCache)
-         {
-            val = cacheImpl_.remove(key);
-         }
-         else
-         {
-            val = cacheImpl_.get(key);
-         }
-         inMemImpl_.put(key, val);
-      }
-   }
-
-   public Object getSerializationCopy()
-   {
-      if (current_ == inMemImpl_)
-         return inMemImpl_;
-
-      Map map;
-      Object mem = inMemImpl_;
-      if (mem == null)
-      {
-         map = new HashMap();
-      }
-      else
-      {
-         map = (Map) copyOrConstruct(mem);
-         if (map == null)
-            throw new PojoCacheException("Could not serialize class, since it can not be copied: " + mem.getClass().getName());
-      }
-
-      map.clear();
-      Iterator it = cacheImpl_.keySet().iterator();
-      while (it.hasNext())
-      {
-         Object key = it.next();
-         Object val = cacheImpl_.get(key);
-         map.put(key, val);
-      }
-      return map;
-   }
-
-   public String getName()
-   {
-      return "CachedMapInterceptor";
-   }
-
-   public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable
-   {
-      if (current_ == null)
-         throw new IllegalStateException("CachedMapInterceptor.invoke(). current_ is null.");
-
-      return CollectionInterceptorUtil.invoke(invocation,
-                                              this,
-                                              current_,
-                                              methodMap_, managedMethods_);
-   }
-
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CachedMapInterceptor.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, the OpenSource J2EE webOS
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.pojo.interceptors.dynamic;
+
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.pojo.PojoCacheException;
+import org.jboss.cache.pojo.collection.CachedMapImpl;
+import org.jboss.cache.pojo.collection.CollectionInterceptorUtil;
+import org.jboss.cache.pojo.impl.PojoCacheImpl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Map interceptor that delegates to the underlying impl.
+ *
+ * @author Ben Wang
+ */
+ at SuppressWarnings({"CanBeFinal"})
+public class CachedMapInterceptor extends AbstractCollectionInterceptor
+{
+
+   //   protected static final Log log_ = LogFactory.getLog(CachedMapInterceptor.class);
+   private static final Map managedMethods_ =
+         CollectionInterceptorUtil.getManagedMethods(Map.class);
+   private Map methodMap_;
+   private Map cacheImpl_;
+   private Map inMemImpl_;
+   private Map current_;
+
+   public CachedMapInterceptor(PojoCacheImpl cache, Fqn fqn, Class clazz, Map obj)
+   {
+      super(cache, fqn);
+      methodMap_ = CollectionInterceptorUtil.getMethodMap(clazz);
+      cacheImpl_ = new CachedMapImpl(cache, this);
+      inMemImpl_ = obj;
+      current_ = cacheImpl_;
+   }
+
+   private CachedMapInterceptor(PojoCacheImpl cache, Fqn fqn)
+   {
+      super(cache, fqn);
+   }
+
+   public Object clone()
+   {
+      CachedMapInterceptor interceptor = new CachedMapInterceptor(cache, fqn);
+      interceptor.setFqn(getFqn());
+      interceptor.setAopInstance(getAopInstance());
+      interceptor.setCurrentCopy(getCurrentCopy());
+      interceptor.setInMemoryCopy(getInMemoryCopy());
+      interceptor.setCacheCopy(getCacheCopy());
+      return interceptor;
+   }
+
+   public void setInterceptor(Interceptor intcptr)
+   {
+      CachedMapInterceptor interceptor = (CachedMapInterceptor) intcptr;
+      setFqn(interceptor.getFqn());
+      setAopInstance(interceptor.getAopInstance());
+      setCurrentCopy(interceptor.getCurrentCopy());
+      setInMemoryCopy(interceptor.getInMemoryCopy());
+      setCacheCopy(interceptor.getCacheCopy());
+   }
+
+   public Object getCurrentCopy()
+   {
+      return current_;
+   }
+
+   void setInMemoryCopy(Object obj)
+   {
+      inMemImpl_ = (Map) obj;
+   }
+
+   Object getInMemoryCopy()
+   {
+      return inMemImpl_;
+   }
+
+   void setCacheCopy(Object obj)
+   {
+      cacheImpl_ = (Map) obj;
+   }
+
+   Object getCacheCopy()
+   {
+      return cacheImpl_;
+   }
+
+   void setCurrentCopy(Object obj)
+   {
+      current_ = (Map) obj;
+   }
+
+   /**
+    * When we want to associate this proxy with the cache again. We will need to translate the in-memory
+    * content to the cache store first.
+    */
+   public void attach(Fqn fqn, boolean copyToCache)
+   {
+      super.attach(fqn, copyToCache);
+
+      if (copyToCache)
+         toCache();
+
+      current_ = cacheImpl_;
+   }
+
+   private void toCache()
+   {
+      if (inMemImpl_ == null)
+         throw new IllegalStateException("CachedMapInterceptor.toCache(). inMemImpl is null.");
+
+      for (Object key : inMemImpl_.keySet())
+      {
+         Object val = inMemImpl_.get(key);
+         cacheImpl_.put(key, val);
+      }
+
+      inMemImpl_.clear();
+      inMemImpl_ = null;   // we are done with this.
+   }
+
+   /**
+    * When we want to separate this proxy from the cache. We will destroy the cache content and copy them to
+    * the in-memory copy.
+    */
+   public void detach(boolean removeFromCache)
+   {
+      super.detach(removeFromCache);
+
+      toMemory(removeFromCache);
+
+      current_ = inMemImpl_;
+   }
+
+   private void toMemory(boolean removeFromCache)
+   {
+      if (inMemImpl_ == null)
+      {
+         inMemImpl_ = new HashMap();
+      }
+
+      Iterator it = cacheImpl_.keySet().iterator();
+      inMemImpl_.clear();
+      while (it.hasNext())
+      {
+         Object key = it.next();
+         Object val = null;
+         if (removeFromCache)
+         {
+            val = cacheImpl_.remove(key);
+         }
+         else
+         {
+            val = cacheImpl_.get(key);
+         }
+         inMemImpl_.put(key, val);
+      }
+   }
+
+   public Object getSerializationCopy()
+   {
+      if (current_ == inMemImpl_)
+         return inMemImpl_;
+
+      Map map;
+      Object mem = inMemImpl_;
+      if (mem == null)
+      {
+         map = new HashMap();
+      }
+      else
+      {
+         map = (Map) copyOrConstruct(mem);
+         if (map == null)
+            throw new PojoCacheException("Could not serialize class, since it can not be copied: " + mem.getClass().getName());
+      }
+
+      map.clear();
+      Iterator it = cacheImpl_.keySet().iterator();
+      while (it.hasNext())
+      {
+         Object key = it.next();
+         Object val = cacheImpl_.get(key);
+         map.put(key, val);
+      }
+      return map;
+   }
+
+   public String getName()
+   {
+      return "CachedMapInterceptor";
+   }
+
+   public Object invoke(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable
+   {
+      if (current_ == null)
+         throw new IllegalStateException("CachedMapInterceptor.invoke(). current_ is null.");
+
+      return CollectionInterceptorUtil.invoke(invocation,
+                                              this,
+                                              current_,
+                                              methodMap_, managedMethods_);
+   }
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,29 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.util;
-
-import java.util.Set;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-
-/**
- * Utility for the 2.0 Cache API
- *
- * @author Ben Wang
- * @version $Id$
- */
-public class CacheApiUtil
-{
-   public static Set<Node> getNodeChildren(Cache<Object, Object> cache, Fqn fqn)
-   {
-      Node n = cache.getRoot().getChild(fqn);
-      return n != null ? n.getChildren() : null;
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java (from rev 6048, pojo/trunk/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/java/org/jboss/cache/pojo/util/CacheApiUtil.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.util;
+
+import java.util.Set;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+
+/**
+ * Utility for the 2.0 Cache API
+ *
+ * @author Ben Wang
+ * @version $Id$
+ */
+public class CacheApiUtil
+{
+   public static Set<Node> getNodeChildren(Cache<Object, Object> cache, Fqn fqn)
+   {
+      Node n = cache.getRoot().getChild(fqn);
+      return n != null ? n.getChildren() : null;
+   }
+   
+   
+}

Deleted: pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml
===================================================================
--- pojo/trunk/src/main/resources/META-INF/pojocache-aop.xml	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,160 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    This is the PojoCache configuration file that specifies:
-      1. Interceptor stack for API
-      2. Annotation binding for POJO (via "prepare" element)
-
-    Basically, this is a variant of jboss-aop.xml. Note that
-    except for the customization of interceptor stack, you should
-    not need to modify this file.
-
-    To run PojoCache, you will need to define a system property:
-    jboss.aop.path that contains the path to this file such that JBoss Aop
-    can locate it.
--->
-<aop>
-
-   <!--
-   This defines the PojoCache 2.0 interceptor stack. Unless necessary, don't modify the stack here!
-   -->
-
-   <!-- Check id range validity -->
-   <interceptor name="CheckId" class="org.jboss.cache.pojo.interceptors.CheckIdInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!-- Track Tx undo operation -->
-   <interceptor name="Undo" class="org.jboss.cache.pojo.interceptors.PojoTxUndoInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!-- Begining of interceptor chain -->
-   <interceptor name="Start" class="org.jboss.cache.pojo.interceptors.PojoBeginInterceptor"
-                scope="PER_INSTANCE">
-   </interceptor>
-
-   <!-- Check if we need a local tx for batch processing -->
-   <interceptor name="Tx" class="org.jboss.cache.pojo.interceptors.PojoTxInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!--
-      Mockup failed tx for testing. You will need to set PojoFailedTxMockupInterceptor.setRollback(true)
-      to activate it.
-    -->
-   <interceptor name="MockupTx" class="org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!-- Perform parent level node locking -->
-   <interceptor name="TxLock" class="org.jboss.cache.pojo.interceptors.PojoTxLockInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!-- Interceptor to perform Pojo level rollback -->
-   <interceptor name="TxUndo" class="org.jboss.cache.pojo.interceptors.PojoTxUndoSynchronizationInterceptor"
-                scope="PER_INSTANCE"/>
-
-   <!-- Interceptor to used to check recursive field interception. -->
-   <interceptor name="ReentrantToString" class="org.jboss.cache.pojo.interceptors.MethodReentrancyStopperInterceptor"
-                scope="PER_INSTANCE">
-               <attribute name="MethodName">toString</attribute>
-   </interceptor>
-
-   <interceptor name="ReentrantHashCode" class="org.jboss.cache.pojo.interceptors.MethodReentrancyStopperInterceptor"
-                scope="PER_INSTANCE">
-               <attribute name="MethodName">hashCode</attribute>
-   </interceptor>
-
-   <!-- Whether to allow non-serializable pojo. Default is false. -->
-   <interceptor name="MarshallNonSerializable"
-                class="org.jboss.cache.pojo.interceptors.CheckNonSerializableInterceptor"
-                scope="PER_INSTANCE">
-         <attribute name="marshallNonSerializable">false</attribute>
-                </interceptor>
-
-   <!-- This defines the stack macro -->
-   <stack name="Attach">
-      <interceptor-ref name="Start"/>
-      <interceptor-ref name="CheckId"/>
-      <interceptor-ref name="MarshallNonSerializable"/>
-      <interceptor-ref name="Tx"/>
-      <!-- NOTE: You can comment this out during production although leaving it here is OK. -->
-      <interceptor-ref name="MockupTx"/>
-      <interceptor-ref name="TxLock"/>
-      <interceptor-ref name="TxUndo"/>
-   </stack>
-
-   <stack name="Detach">
-      <interceptor-ref name="Start"/>
-      <interceptor-ref name="CheckId"/>
-      <interceptor-ref name="Tx"/>
-      <!-- NOTE: You can comment this out during production although leaving it here is OK. -->
-      <interceptor-ref name="MockupTx"/>
-      <interceptor-ref name="TxLock"/>
-      <interceptor-ref name="TxUndo"/>
-   </stack>
-
-   <stack name="Find">
-      <interceptor-ref name="Start"/>
-      <interceptor-ref name="CheckId"/>
-   </stack>
-
-   <!--
-      The following section should be READ-ONLY!! It defines the annotation binding to the stack.
-   -->
-
-   <!-- This binds the jointpoint to specific in-memory operations. Currently in PojoUtil. -->
-   <bind pointcut="execution(*
-      @org.jboss.cache.pojo.annotation.Reentrant->toString())">
-      <interceptor-ref name="ReentrantToString"/>
-   </bind>
-
-   <bind pointcut="execution(*
-      @org.jboss.cache.pojo.annotation.Reentrant->hashCode())">
-      <interceptor-ref name="ReentrantHashCode"/>
-   </bind>
-
-   <bind pointcut="execution(*
-      org.jboss.cache.pojo.impl.PojoUtil->@org.jboss.cache.pojo.annotation.TxUndo(..))">
-      <interceptor-ref name="Undo"/>
-   </bind>
-
-   <bind pointcut="execution(* org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Attach(..))">
-      <stack-ref name="Attach"/>
-   </bind>
-
-   <bind pointcut="execution(* org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Detach(..))">
-      <stack-ref name="Detach"/>
-   </bind>
-
-   <bind pointcut="execution(* org.jboss.cache.pojo.impl.PojoCacheImpl->@org.jboss.cache.pojo.annotation.Find(..))">
-      <stack-ref name="Find"/>
-   </bind>
-
-
-   <!--
-      Following is declaration for JDK50 annotation. You use the specific annotation on your
-      POJO such that it can be instrumented. Idea is user will then need only to annotate like:
-        @org.jboss.cache.pojo.annotation.Replicable
-      in his POJO. There will be no need of jboss-aop.xml from user's side.
-      Note that this annotation is inheritant, meaning the subclass will be
-      instrumented as well.
-   -->
-
-   <!-- If a POJO has Replicable annotation, it will be asepectized. -->
-   <!--
-   Supports inheritance and polymorphism. It can either be a concrete class
-   or an interface. All sub-classes or interface implementors will be instrumeneted.
-   -->
-   <prepare expr="field(* $instanceof{@org.jboss.cache.pojo.annotation.Replicable}->*)" />
-   
-   <!--  Work around that ensures annotated classes which do not access fields are instrumented -->
-
-
-   <!-- Array support -->
-   <!-- Comment entire section to disable -->
-   <arrayreplacement expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})"/>
-   <interceptor name="pojocache-array" class="org.jboss.cache.pojo.interceptors.dynamic.ArrayInterceptor"/>
-   <introduction expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})">
-       <interfaces>org.jboss.cache.pojo.impl.ArrayInterceptable</interfaces>
-   </introduction>
-   <arraybind name="pojocache-array" type="READ_WRITE">
-      <interceptor-ref name="pojocache-array"/>
-   </arraybind>
-</aop>

Copied: pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml (from rev 6048, pojo/trunk/src/main/resources/META-INF/pojocache-aop.xml)
===================================================================
--- pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/main/resources/META-INF/pojocache-aop.xml	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    This is a variant of jboss-aop.xml. 
+-->
+<aop>
+   <!-- If a POJO has a Replicable annotation, it will be asepectized. -->
+   
+   <!-- 
+   Supports inheritance and polymorphism. It can either be a concrete class
+   or an interface. All sub-classes or interface implementors will be instrumeneted.
+   -->
+   <prepare expr="field(* $instanceof{@org.jboss.cache.pojo.annotation.Replicable}->*)" />
+   
+   <!--  Work around that ensures annotated classes which do not access fields are instrumented -->
+   <introduction expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})"/>
+
+   <!-- Array support -->
+   <!-- Comment entire section to disable -->
+   <arrayreplacement expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})"/>
+   <interceptor name="pojocache-array" class="org.jboss.cache.pojo.interceptors.dynamic.ArrayInterceptor"/>
+   <introduction expr="class($instanceof{@org.jboss.cache.pojo.annotation.Replicable})">
+       <interfaces>org.jboss.cache.pojo.impl.ArrayInterceptable</interfaces>
+   </introduction>
+   <arraybind name="pojocache-array" type="READ_WRITE">
+      <interceptor-ref name="pojocache-array"/>
+   </arraybind>
+</aop>

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,82 +0,0 @@
-package org.jboss.cache.pojo.collection;
-
-import static org.testng.AssertJUnit.fail;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.config.Configuration.CacheMode;
-import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * List implementation testing.
- *
- * @author Ben Wang
- */
-
- at Test(groups = {"functional"})
-public class CachedListImplTest 
-{
-   Log log = LogFactory.getLog(CachedListImplTest.class);
-   PojoCache cache_, cache1_;
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log.info("setUp() ....");
-      boolean toStart = false;
-      cache_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
-      cache_.getCache().getConfiguration().setFetchInMemoryState(false);
-      cache1_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
-      cache1_.getCache().getConfiguration().setFetchInMemoryState(false);
-      cache_.start();
-      cache1_.start();
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache_.stop();
-      cache1_.stop();
-   }
-
-   @SuppressWarnings("unchecked")
-   public void testSimpleRepl()
-   {
-      List<String> list = new ArrayList<String>();
-      list.add("1");
-      list.add("2");
-
-      cache_.attach("list", list);
-
-      // proxy now
-      list = (List<String>) cache_.find("list");
-
-      // test repl
-      try {
-         cache_.getCache().put(Fqn.fromString("test"), "1", list);
-         fail("Should have a non-serializable exception on list: " +list);
-      } catch (Exception ex)
-      {
-         // OK. It works
-      }
-
-      // JBCACHE-975
-      list = (List<String>) cache_.detach("list");
-
-      // test repl
-      cache_.getCache().put(Fqn.fromString("test"), "1", list);
-
-      ArrayList<String> l1 = (ArrayList<String>) cache1_.getCache().get(Fqn.fromString("test"), "1");
-      System.out.println(" list : " + l1);
-   }
-}
-

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/collection/CachedListImplTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,73 @@
+package org.jboss.cache.pojo.collection;
+
+import static org.testng.AssertJUnit.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * List implementation testing.
+ *
+ * @author Ben Wang
+ */
+
+ at Test(groups = {"functional"})
+public class CachedListImplTest
+{
+   Log log = LogFactory.getLog(CachedListImplTest.class);
+   PojoCache cache_, cache1_;
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log.info("setUp() ....");
+      boolean toStart = false;
+      cache_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache_.getCache().getConfiguration().setFetchInMemoryState(false);
+      cache1_ = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache1_.getCache().getConfiguration().setFetchInMemoryState(false);
+      cache_.start();
+      cache1_.start();
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache_.stop();
+      cache1_.stop();
+   }
+
+   @SuppressWarnings("unchecked")
+   public void testSimpleRepl()
+   {
+      List<String> list = new ArrayList<String>();
+      list.add("1");
+      list.add("2");
+
+      cache_.attach("list", list);
+
+      // proxy now
+      list = (List<String>) cache_.find("list");
+
+      // JBCACHE-975
+      list = (List<String>) cache_.detach("list");
+
+      // test repl
+      cache_.getCache().put(Fqn.fromString("test"), "1", list);
+
+      ArrayList<String> l1 = (ArrayList<String>) cache1_.getCache().get(Fqn.fromString("test"), "1");
+      System.out.println(" list : " + l1);
+   }
+}
+

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,139 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.rollback;
-
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertTrue;
-
-import java.util.ArrayList;
-
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.proxy.ClassProxy;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor;
-import org.jboss.cache.pojo.test.Person;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Additional basic tests
- *
- * @author Ben Wang
- */
-
- at Test(groups = {"functional"})
-public class ListUndoTest
-{
-   Log log_ = LogFactory.getLog(ListUndoTest.class);
-   PojoCache cache_;
-   TransactionManager tx_mgr;
-
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log_.info("setUp() ....");
-      String configFile = "META-INF/local-service.xml";
-      boolean toStart = false;
-      cache_ = PojoCacheFactory.createCache(configFile, toStart);
-      cache_.start();
-      tx_mgr = DummyTransactionManager.getInstance();
-
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache_.stop();
-   }
-
-//   public void testDummy() {}
-
-   private void setTxRollback(boolean isTrue)
-   {
-      PojoFailedTxMockupInterceptor.TX_ROLLBACK = isTrue;
-   }
-
-   public void testSimple() throws Exception
-   {
-      ArrayList<String> list = new ArrayList<String>();
-      list.add("test1");
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", list);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(list));
-
-      cache_.attach("/a", list);
-   }
-
-   public void testSimpleTxWithRollback1() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      ArrayList<String> list = new ArrayList<String>();
-      list.add("English");
-      test.setLanguages(list);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", test);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(test.getLanguages()));
-
-      cache_.attach("/a", test);
-   }
-
-   private boolean isProxy(Object pojo)
-   {
-      if (pojo instanceof ClassProxy) return true;
-      return false;
-   }
-
-   public void testSimpleTxWithRollback2() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      ArrayList<String> list = new ArrayList<String>();
-      list.add("English");
-      test.setLanguages(list);
-
-      cache_.attach("/a", test);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.detach("/a");
-      }
-      catch (Exception e)
-      {
-      }
-
-      assertTrue("Should still have cache interceptor ", isProxy(test.getLanguages()));
-      cache_.detach("/a");
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ListUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.rollback;
+
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.ArrayList;
+
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.test.Person;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Additional basic tests
+ *
+ * @author Ben Wang
+ */
+
+ at Test(groups = {"functional"})
+public class ListUndoTest
+{
+   Log log_ = LogFactory.getLog(ListUndoTest.class);
+   PojoCache cache_;
+   TransactionManager tx_mgr;
+
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log_.info("setUp() ....");
+      String configFile = "META-INF/local-service.xml";
+      boolean toStart = false;
+      cache_ = PojoCacheFactory.createCache(configFile, toStart);
+      cache_.start();
+      tx_mgr = DummyTransactionManager.getInstance();
+
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache_.stop();
+   }
+
+//   public void testDummy() {}
+
+   public void testSimple() throws Exception
+   {
+      ArrayList<String> list = new ArrayList<String>();
+      list.add("test1");
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", list);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(list));
+
+      cache_.attach("/a", list);
+   }
+
+   public void testSimpleTxWithRollback1() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      ArrayList<String> list = new ArrayList<String>();
+      list.add("English");
+      test.setLanguages(list);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", test);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(test.getLanguages()));
+
+      cache_.attach("/a", test);
+   }
+
+   private boolean isProxy(Object pojo)
+   {
+      if (pojo instanceof ClassProxy) return true;
+      return false;
+   }
+
+   public void testSimpleTxWithRollback2() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      ArrayList<String> list = new ArrayList<String>();
+      list.add("English");
+      test.setLanguages(list);
+
+      cache_.attach("/a", test);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.detach("/a");
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+
+      assertTrue("Should still have cache interceptor ", isProxy(test.getLanguages()));
+      cache_.detach("/a");
+   }
+}

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,120 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.rollback;
-
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertTrue;
-
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.Advised;
-import org.jboss.aop.advice.Interceptor;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor;
-import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
-import org.jboss.cache.pojo.test.Person;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Additional basic tests
- *
- * @author Ben Wang
- */
-
- at Test(groups = {"functional"})
-public class LocalUndoTest
-{
-   Log log_ = LogFactory.getLog(LocalUndoTest.class);
-   PojoCache cache_;
-   TransactionManager tx_mgr;
-
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log_.info("setUp() ....");
-      String configFile = "META-INF/local-service.xml";
-      boolean toStart = false;
-      cache_ = PojoCacheFactory.createCache(configFile, toStart);
-      cache_.start();
-      tx_mgr = DummyTransactionManager.getInstance();
-
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache_.stop();
-   }
-
-//   public void testDummy() {}
-
-   private void setTxRollback(boolean isTrue)
-   {
-      PojoFailedTxMockupInterceptor.TX_ROLLBACK = isTrue;
-   }
-
-   public void testSimpleTxWithRollback1() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-
-      setTxRollback(true);
-      try
-      {
-    	  cache_.attach("/a", test);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", hasCacheInterceptor(test));
-   }
-
-   private boolean hasCacheInterceptor(Object pojo)
-   {
-      Interceptor[] interceptors = ((Advised) pojo)._getInstanceAdvisor().getInterceptors();
-      for (int i = 0; i < interceptors.length; i++)
-      {
-         if (interceptors[i] instanceof CacheFieldInterceptor)
-            return true;
-      }
-      return false;
-   }
-
-   public void testSimpleTxWithRollback2() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      cache_.attach("/a", test);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.detach("/a");
-      }
-      catch (Exception e)
-      {
-      }
-
-      assertTrue("Should still have cache interceptor ", hasCacheInterceptor(test));
-   }
-
-
-
-
-}

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/LocalUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.rollback;
+
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.Advised;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.interceptors.dynamic.CacheFieldInterceptor;
+import org.jboss.cache.pojo.test.Person;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Additional basic tests
+ *
+ * @author Ben Wang
+ */
+
+ at Test(groups = {"functional"})
+public class LocalUndoTest
+{
+   Log log_ = LogFactory.getLog(LocalUndoTest.class);
+   PojoCache cache_;
+   TransactionManager tx_mgr;
+
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log_.info("setUp() ....");
+      String configFile = "META-INF/local-service.xml";
+      boolean toStart = false;
+      cache_ = PojoCacheFactory.createCache(configFile, toStart);
+      cache_.start();
+      tx_mgr = DummyTransactionManager.getInstance();
+
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache_.stop();
+   }
+
+//   public void testDummy() {}
+
+   public void testSimpleTxWithRollback1() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", test);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", hasCacheInterceptor(test));
+   }
+
+   private boolean hasCacheInterceptor(Object pojo)
+   {
+      Interceptor[] interceptors = ((Advised) pojo)._getInstanceAdvisor().getInterceptors();
+      for (int i = 0; i < interceptors.length; i++)
+      {
+         if (interceptors[i] instanceof CacheFieldInterceptor)
+            return true;
+      }
+      return false;
+   }
+
+   public void testSimpleTxWithRollback2() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      cache_.attach("/a", test);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.detach("/a");
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+
+      assertTrue("Should still have cache interceptor ", hasCacheInterceptor(test));
+   }
+
+
+
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,143 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.rollback;
-
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertTrue;
-
-import java.util.HashMap;
-
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.proxy.ClassProxy;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor;
-import org.jboss.cache.pojo.test.Person;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Additional basic tests
- *
- * @author Ben Wang
- */
-
- at Test(groups = {"functional"})
-public class MapUndoTest
-{
-   Log log_ = LogFactory.getLog(MapUndoTest.class);
-   PojoCache cache_;
-   TransactionManager tx_mgr;
-
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log_.info("setUp() ....");
-      String configFile = "META-INF/local-service.xml";
-      boolean toStart = false;
-      cache_ = PojoCacheFactory.createCache(configFile, toStart);
-      cache_.start();
-      tx_mgr = DummyTransactionManager.getInstance();
-
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache_.stop();
-   }
-
-//   public void testDummy() {}
-
-   private void setTxRollback(boolean isTrue)
-   {
-      PojoFailedTxMockupInterceptor.TX_ROLLBACK = isTrue;
-   }
-
-   public void testSimple() throws Exception
-   {
-      HashMap<String, String> map = new HashMap<String, String>();
-      map.put("1", "test1");
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", map);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(map));
-
-      cache_.attach("/a", map);
-   }
-
-   public void testSimpleTxWithRollback1() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      HashMap<String, String> map = new HashMap<String, String>();
-      map.put("1", "English");
-      test.setHobbies(map);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", test);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(test.getHobbies()));
-
-      cache_.attach("/a", test);
-   }
-
-   private boolean isProxy(Object pojo)
-   {
-      if (pojo instanceof ClassProxy) return true;
-      return false;
-   }
-
-   public void testSimpleTxWithRollback2() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      HashMap<String, String> map = new HashMap<String, String>();
-      map.put("1", "English");
-      test.setHobbies(map);
-
-      cache_.attach("/a", test);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.detach("/a");
-      }
-      catch (Exception e)
-      {
-      }
-
-      assertTrue("Should still have cache interceptor ", isProxy(test.getHobbies()));
-      cache_.detach("/a");
-   }
-
-
-
-
-}

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/MapUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,140 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.rollback;
+
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.HashMap;
+
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.test.Person;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Additional basic tests
+ *
+ * @author Ben Wang
+ */
+
+ at Test(groups = {"functional"})
+public class MapUndoTest
+{
+   Log log_ = LogFactory.getLog(MapUndoTest.class);
+   PojoCache cache_;
+   TransactionManager tx_mgr;
+
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log_.info("setUp() ....");
+      String configFile = "META-INF/local-service.xml";
+      boolean toStart = false;
+      cache_ = PojoCacheFactory.createCache(configFile, toStart);
+      cache_.start();
+      tx_mgr = DummyTransactionManager.getInstance();
+
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache_.stop();
+   }
+
+//   public void testDummy() {}
+
+   public void testSimple() throws Exception
+   {
+      HashMap<String, String> map = new HashMap<String, String>();
+      map.put("1", "test1");
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", map);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(map));
+
+      cache_.attach("/a", map);
+   }
+
+   public void testSimpleTxWithRollback1() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      HashMap<String, String> map = new HashMap<String, String>();
+      map.put("1", "English");
+      test.setHobbies(map);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", test);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(test.getHobbies()));
+
+      cache_.attach("/a", test);
+   }
+
+   private boolean isProxy(Object pojo)
+   {
+      if (pojo instanceof ClassProxy) return true;
+      return false;
+   }
+
+   public void testSimpleTxWithRollback2() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      HashMap<String, String> map = new HashMap<String, String>();
+      map.put("1", "English");
+      test.setHobbies(map);
+
+      cache_.attach("/a", test);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.detach("/a");
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+
+      assertTrue("Should still have cache interceptor ", isProxy(test.getHobbies()));
+      cache_.detach("/a");
+   }
+
+
+
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,393 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.rollback;
-
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.fail;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.UserTransaction;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.config.Configuration.CacheMode;
-import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
-import org.jboss.cache.util.TestingUtil;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.jboss.cache.pojo.test.Person;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- */
-
- at Test(groups = {"functional"})
-public class ReplicatedTxTest
-{
-   Log log = LogFactory.getLog(org.jboss.cache.pojo.rollback.ReplicatedTxTest.class);
-   PojoCache cache, cache1;
-   final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
-   DummyTransactionManager tx_mgr;
-   Throwable t1_ex, t2_ex;
-   long start = 0;
-
-
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log.info("setUp() ....");
-      boolean toStart = false;
-      cache = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
-      cache.start();
-      cache1 = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
-      cache1.start();
-
-      System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
-
-      tx_mgr = DummyTransactionManager.getInstance();
-      t1_ex = t2_ex = null;
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache.stop();
-      cache1.stop();
-
-      DummyTransactionManager.destroy();
-   }
-
-//   public void testDummy() {}
-
-   UserTransaction getTransaction() throws SystemException, NotSupportedException, NamingException
-   {
-      Properties prop = new Properties();
-      prop.put(Context.INITIAL_CONTEXT_FACTORY,
-               "org.jboss.cache.transaction.DummyContextFactory");
-      return (UserTransaction) new InitialContext(prop).lookup("UserTransaction");
-   }
-
-   private Person createPerson(String id, String name, int age)
-   {
-      Person p = new Person();
-      p.setName(name);
-      p.setAge(age);
-      return p;
-   }
-
-   public void testSimple() throws Exception
-   {
-      log.info("testSimple() ....");
-      UserTransaction tx = getTransaction();
-      tx.begin();
-      Person p = createPerson("/person/test1", "Harald Gliebe", 32);
-      cache.attach("/person/test1", p);
-
-      tx.commit();
-      tx.begin();
-      p.setName("Benoit");
-      tx.commit();
-      Person p1 = (Person) cache1.find("/person/test1");
-      assertEquals("Benoit", p.getName());
-      assertEquals("Benoit", p1.getName());
-      tx.begin();
-      p1.setAge(61);
-      tx.commit();
-      assertEquals(61, p.getAge());
-      assertEquals(61, p1.getAge());
-   }
-
-   /**
-    * Concurrent puts (whole POJO) from the same cache instance (different threads) with rollback.
-    */
-   public void testConcurrentPuts() throws Exception
-   {
-      Thread t1 = new Thread()
-      {
-         public void run()
-         {
-            try
-            {
-               Person p = createPerson("/person/test6", "p6", 50);
-               List<String> lang = new ArrayList<String>();
-               lang.add("German");
-               p.setLanguages(lang);
-               UserTransaction tx = getTransaction();
-               tx.begin();
-               cache.attach("/person/test6", p);
-               TestingUtil.sleepThread(17000);
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               t1_ex = ex;
-            }
-         }
-      };
-
-      Thread t2 = new Thread()
-      {
-         public void run()
-         {
-            UserTransaction tx = null;
-            Person p = createPerson("/person/test6", "p6", 50);
-            try
-            {
-               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
-               List<String> lang = new ArrayList<String>();
-               lang.add("German");
-               p.setLanguages(lang);
-               tx = getTransaction();
-               tx.begin();
-               cache.attach("/person/test6", p);
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               try
-               {
-                  tx.rollback();
-               }
-               catch (SystemException e)
-               {
-                  e.printStackTrace();
-                  t2_ex = e;
-               }
-            }
-
-            cache.attach("/person/test6", p);
-
-         }
-      };
-
-      t1.start();
-      t2.start();
-
-      t1.join();
-      t2.join();
-
-      // t2 should rollback due to timeout while t2 should succeed
-      if (t2_ex != null)
-         fail("Thread1 failed: " + t2_ex);
-      if (t1_ex != null)
-         fail("Thread2 failed: " + t1_ex);
-
-      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 1, size);
-      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 1, size);
-   }
-
-   /**
-    * Concurrent puts from the same cache instance (different threads) with rollback.
-    */
-   public void testConcurrentPuts1() throws Exception
-   {
-      Thread t1 = new Thread()
-      {
-         public void run()
-         {
-            try
-            {
-               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
-               UserTransaction tx = getTransaction();
-               tx.begin();
-               lang.add("German");
-               TestingUtil.sleepThread(17000);
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               t1_ex = ex;
-            }
-         }
-      };
-
-      Thread t2 = new Thread()
-      {
-         public void run()
-         {
-            UserTransaction tx = null;
-            try
-            {
-               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
-               List<String> lang = ((Person) cache1.find("/person/test6")).getLanguages();
-               tx = getTransaction();
-               tx.begin();
-               lang.add("English");
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               try
-               {
-                  tx.rollback();
-               }
-               catch (SystemException e)
-               {
-                  e.printStackTrace();
-                  t2_ex = e;
-               }
-            }
-         }
-      };
-
-      Person p = createPerson("/person/test6", "p6", 50);
-      cache.attach("/person/test6", p);
-      List<String> lang = new ArrayList<String>();
-      lang.add("German");
-      p.setLanguages(lang);
-
-      t1.start();
-      t2.start();
-
-      t1.join();
-      t2.join();
-
-      // t2 should rollback due to timeout while t2 should succeed
-      if (t2_ex != null)
-         fail("Thread1 failed: " + t2_ex);
-      if (t1_ex != null)
-         fail("Thread2 failed: " + t1_ex);
-
-      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 2, size);
-      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 2, size);
-   }
-
-   /**
-    * Concurrent puts from the different cache instances (different threads) with rollback.
-    */
-   public void testConcurrentPuts2() throws Exception
-   {
-      Thread t1 = new Thread()
-      {
-         public void run()
-         {
-            try
-            {
-               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
-               UserTransaction tx = getTransaction();
-               tx.begin();
-               lang.add("German");
-               TestingUtil.sleepThread(17000);
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               t1_ex = ex;
-            }
-         }
-      };
-
-      Thread t2 = new Thread()
-      {
-         public void run()
-         {
-            UserTransaction tx = null;
-            try
-            {
-               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
-               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
-               tx = getTransaction();
-               tx.begin();
-               lang.add("English");
-               tx.commit();
-            }
-            catch (RollbackException rollback)
-            {
-               ;
-            }
-            catch (Exception ex)
-            {
-               try
-               {
-                  tx.rollback();
-               }
-               catch (SystemException e)
-               {
-                  e.printStackTrace();
-                  t2_ex = e;
-               }
-            }
-         }
-      };
-
-      Person p = createPerson("/person/test6", "p6", 50);
-      cache.attach("/person/test6", p);
-      List<String> lang = new ArrayList<String>();
-      lang.add("German");
-      p.setLanguages(lang);
-
-      t1.start();
-      t2.start();
-
-      t1.join();
-      t2.join();
-
-      // t2 should rollback due to timeout while t2 should succeed
-      if (t2_ex != null)
-         fail("Thread1 failed: " + t2_ex);
-      if (t1_ex != null)
-         fail("Thread2 failed: " + t1_ex);
-
-      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 2, size);
-      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
-      assertEquals("number of languages", 2, size);
-   }
-
-   void log(String s)
-   {
-      long now;
-      if (start == 0)
-         start = System.currentTimeMillis();
-      now = System.currentTimeMillis();
-
-      System.out.println("[" + Thread.currentThread().getName() + "] [" + (now - start) + "] " + s);
-   }
-
-
-
-
-
-}

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/ReplicatedTxTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,395 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.rollback;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
+import org.jboss.cache.util.TestingUtil;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.test.Person;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ */
+
+ at Test(groups = {"functional"})
+public class ReplicatedTxTest
+{
+   Log log = LogFactory.getLog(org.jboss.cache.pojo.rollback.ReplicatedTxTest.class);
+   PojoCache cache, cache1;
+   final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
+   DummyTransactionManager tx_mgr;
+   Throwable t1_ex, t2_ex;
+   long start = 0;
+
+
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log.info("setUp() ....");
+      boolean toStart = false;
+      cache = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache.start();
+      cache1 = PojoCacheFactory.createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC), toStart);
+      cache1.start();
+
+      System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
+
+      tx_mgr = DummyTransactionManager.getInstance();
+      t1_ex = t2_ex = null;
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache.stop();
+      cache1.stop();
+
+      DummyTransactionManager.destroy();
+   }
+
+//   public void testDummy() {}
+
+   UserTransaction getTransaction() throws SystemException, NotSupportedException, NamingException
+   {
+      Properties prop = new Properties();
+      prop.put(Context.INITIAL_CONTEXT_FACTORY,
+               "org.jboss.cache.transaction.DummyContextFactory");
+      return (UserTransaction) new InitialContext(prop).lookup("UserTransaction");
+   }
+
+   private Person createPerson(String id, String name, int age)
+   {
+      Person p = new Person();
+      p.setName(name);
+      p.setAge(age);
+      return p;
+   }
+
+   public void testSimple() throws Exception
+   {
+      log.info("testSimple() ....");
+      UserTransaction tx = getTransaction();
+      tx.begin();
+      Person p = createPerson("/person/test1", "Harald Gliebe", 32);
+      cache.attach("/person/test1", p);
+
+      tx.commit();
+      tx.begin();
+      p.setName("Benoit");
+      tx.commit();
+      Person p1 = (Person) cache1.find("/person/test1");
+      assertEquals("Benoit", p.getName());
+      assertEquals("Benoit", p1.getName());
+      tx.begin();
+      p1.setAge(61);
+      tx.commit();
+      assertEquals(61, p.getAge());
+      assertEquals(61, p1.getAge());
+   }
+
+   /**
+    * Concurrent puts (whole POJO) from the same cache instance (different threads) with rollback.
+    */
+   public void testConcurrentPuts() throws Exception
+   {
+      Thread t1 = new Thread()
+      {
+         public void run()
+         {
+            try
+            {
+               Person p = createPerson("/person/test6", "p6", 50);
+               List<String> lang = new ArrayList<String>();
+               lang.add("German");
+               p.setLanguages(lang);
+               UserTransaction tx = getTransaction();
+               tx.begin();
+               cache.attach("/person/test6", p);
+               TestingUtil.sleepThread(17000);
+               tx.commit();
+            }
+            catch (RollbackException rollback)
+            {
+               ;
+            }
+            catch (Exception ex)
+            {
+               t1_ex = ex;
+            }
+         }
+      };
+
+      Thread t2 = new Thread()
+      {
+         public void run()
+         {
+            UserTransaction tx = null;
+            Person p = createPerson("/person/test6", "p6", 50);
+            try
+            {
+               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
+               List<String> lang = new ArrayList<String>();
+               lang.add("German");
+               p.setLanguages(lang);
+               tx = getTransaction();
+               tx.begin();
+               cache.attach("/person/test6", p);
+               tx.commit();
+            }
+            catch (RollbackException rollback)
+            {
+               ;
+            }
+            catch (Exception ex)
+            {
+               try
+               {
+                  tx.rollback();
+               }
+               catch (SystemException e)
+               {
+                  e.printStackTrace();
+                  t2_ex = e;
+               }
+            }
+
+            cache.attach("/person/test6", p);
+
+         }
+      };
+
+      t1.start();
+      t2.start();
+
+      t1.join();
+      t2.join();
+
+      // t2 should rollback due to timeout while t2 should succeed
+      if (t2_ex != null)
+         fail("Thread1 failed: " + t2_ex);
+      if (t1_ex != null)
+         fail("Thread2 failed: " + t1_ex);
+
+      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 1, size);
+      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 1, size);
+   }
+
+   /**
+    * Concurrent puts from the same cache instance (different threads) with rollback.
+    */
+   public void testConcurrentPuts1() throws Exception
+   {
+      Thread t1 = new Thread()
+      {
+         public void run()
+         {
+            try
+            {
+               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
+               UserTransaction tx = getTransaction();
+               tx.begin();
+               lang.add("German");
+               TestingUtil.sleepThread(17000);
+               tx.commit();
+            }
+            catch (RollbackException rollback)
+            {
+               ;
+            }
+            catch (Exception ex)
+            {
+               t1_ex = ex;
+            }
+         }
+      };
+
+      Thread t2 = new Thread()
+      {
+         public void run()
+         {
+            UserTransaction tx = null;
+            try
+            {
+               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
+               List<String> lang = ((Person) cache1.find("/person/test6")).getLanguages();
+               System.out.println(lang == null);
+               tx = getTransaction();
+               tx.begin();
+               lang.add("English");
+               tx.commit();
+               System.out.println("Successful!");
+            }
+            catch (RollbackException rollback)
+            {
+            }
+            catch (Exception ex)
+            {
+               ex.printStackTrace();
+               try
+               {
+                  tx.rollback();
+               }
+               catch (SystemException e)
+               {
+                  e.printStackTrace();
+                  t2_ex = e;
+               }
+            }
+         }
+      };
+
+      Person p = createPerson("/person/test6", "p6", 50);
+      cache.attach("/person/test6", p);
+      List<String> lang = new ArrayList<String>();
+      lang.add("German");
+      p.setLanguages(lang);
+
+      t1.start();
+      t2.start();
+
+      t1.join();
+      t2.join();
+
+      // t2 should rollback due to timeout while t2 should succeed
+      if (t2_ex != null)
+         fail("Thread1 failed: " + t2_ex);
+      if (t1_ex != null)
+         fail("Thread2 failed: " + t1_ex);
+
+      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 2, size);
+      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 2, size);
+   }
+
+   /**
+    * Concurrent puts from the different cache instances (different threads) with rollback.
+    */
+   public void testConcurrentPuts2() throws Exception
+   {
+      Thread t1 = new Thread()
+      {
+         public void run()
+         {
+            try
+            {
+               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
+               UserTransaction tx = getTransaction();
+               tx.begin();
+               lang.add("German");
+               TestingUtil.sleepThread(17000);
+               tx.commit();
+            }
+            catch (RollbackException rollback)
+            {
+               ;
+            }
+            catch (Exception ex)
+            {
+               t1_ex = ex;
+            }
+         }
+      };
+
+      Thread t2 = new Thread()
+      {
+         public void run()
+         {
+            UserTransaction tx = null;
+            try
+            {
+               TestingUtil.sleepThread(1000); // give Thread1 time to createPerson
+               List<String> lang = ((Person) cache.find("/person/test6")).getLanguages();
+               tx = getTransaction();
+               tx.begin();
+               lang.add("English");
+               tx.commit();
+            }
+            catch (RollbackException rollback)
+            {
+               ;
+            }
+            catch (Exception ex)
+            {
+               try
+               {
+                  tx.rollback();
+               }
+               catch (SystemException e)
+               {
+                  e.printStackTrace();
+                  t2_ex = e;
+               }
+            }
+         }
+      };
+
+      Person p = createPerson("/person/test6", "p6", 50);
+      cache.attach("/person/test6", p);
+      List<String> lang = new ArrayList<String>();
+      lang.add("German");
+      p.setLanguages(lang);
+
+      t1.start();
+      t2.start();
+
+      t1.join();
+      t2.join();
+
+      // t2 should rollback due to timeout while t2 should succeed
+      if (t2_ex != null)
+         fail("Thread1 failed: " + t2_ex);
+      if (t1_ex != null)
+         fail("Thread2 failed: " + t1_ex);
+
+      int size = ((Person) cache.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 2, size);
+      size = ((Person) cache1.find("/person/test6")).getLanguages().size();
+      assertEquals("number of languages", 2, size);
+   }
+
+   void log(String s)
+   {
+      long now;
+      if (start == 0)
+         start = System.currentTimeMillis();
+      now = System.currentTimeMillis();
+
+      System.out.println("[" + Thread.currentThread().getName() + "] [" + (now - start) + "] " + s);
+   }
+
+
+
+
+
+}

Deleted: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java	2008-06-25 18:35:22 UTC (rev 6047)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -1,137 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
-package org.jboss.cache.pojo.rollback;
-
-import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertTrue;
-
-import java.util.HashSet;
-
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.aop.proxy.ClassProxy;
-import org.jboss.cache.pojo.PojoCache;
-import org.jboss.cache.pojo.PojoCacheFactory;
-import org.jboss.cache.pojo.interceptors.PojoFailedTxMockupInterceptor;
-import org.jboss.cache.pojo.test.Person;
-import org.jboss.cache.transaction.DummyTransactionManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Additional basic tests
- *
- * @author Ben Wang
- */
-
- at Test(groups = {"functional"})
-public class SetUndoTest
-{
-   Log log_ = LogFactory.getLog(SetUndoTest.class);
-   PojoCache cache_;
-   TransactionManager tx_mgr;
-
-
-   @BeforeMethod(alwaysRun = true)
-   protected void setUp() throws Exception
-   {
-      log_.info("setUp() ....");
-      String configFile = "META-INF/local-service.xml";
-      boolean toStart = false;
-      cache_ = PojoCacheFactory.createCache(configFile, toStart);
-      cache_.start();
-      tx_mgr = DummyTransactionManager.getInstance();
-
-   }
-
-   @AfterMethod(alwaysRun = true)
-   protected void tearDown() throws Exception
-   {
-      cache_.stop();
-   }
-
-//   public void testDummy() {}
-
-   private void setTxRollback(boolean isTrue)
-   {
-      PojoFailedTxMockupInterceptor.TX_ROLLBACK = isTrue;
-   }
-
-   public void testSimple() throws Exception
-   {
-      HashSet<String> set = new HashSet<String>();
-      set.add("test1");
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", set);
-      }
-      catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(set));
-
-      cache_.attach("/a", set);
-   }
-
-   public void testSimpleTxWithRollback1() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      HashSet<String> set = new HashSet<String>();
-      set.add("English");
-      test.setSkills(set);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.attach("/a", test);
-      } catch (Exception e)
-      {
-      }
-      assertFalse("Should not have cache interceptor ", isProxy(test.getSkills()));
-
-      cache_.attach("/a", test);
-   }
-
-   private boolean isProxy(Object pojo)
-   {
-      if (pojo instanceof ClassProxy) return true;
-      return false;
-   }
-
-   public void testSimpleTxWithRollback2() throws Exception
-   {
-      log_.info("testSimpleTxWithRollback1() ....");
-      Person test = new Person();
-      test.setName("Ben");
-      test.setAge(10);
-      HashSet<String> set = new HashSet<String>();
-      set.add("English");
-      test.setSkills(set);
-
-      cache_.attach("/a", test);
-
-      setTxRollback(true);
-      try
-      {
-         cache_.detach("/a");
-      } catch (Exception e)
-      {
-      }
-
-      assertTrue("Should still have cache interceptor ", isProxy(test.getSkills()));
-      cache_.detach("/a");
-   }
-}

Copied: pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java (from rev 6048, pojo/trunk/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java)
===================================================================
--- pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java	                        (rev 0)
+++ pojo/tags/2.2.0.CR1/src/test/java/org/jboss/cache/pojo/rollback/SetUndoTest.java	2008-06-27 22:03:17 UTC (rev 6109)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package org.jboss.cache.pojo.rollback;
+
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.HashSet;
+
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.aop.proxy.ClassProxy;
+import org.jboss.cache.pojo.PojoCache;
+import org.jboss.cache.pojo.PojoCacheFactory;
+import org.jboss.cache.pojo.test.Person;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Additional basic tests
+ *
+ * @author Ben Wang
+ */
+
+ at Test(groups = {"functional"})
+public class SetUndoTest
+{
+   Log log_ = LogFactory.getLog(SetUndoTest.class);
+   PojoCache cache_;
+   TransactionManager tx_mgr;
+
+
+   @BeforeMethod(alwaysRun = true)
+   protected void setUp() throws Exception
+   {
+      log_.info("setUp() ....");
+      String configFile = "META-INF/local-service.xml";
+      boolean toStart = false;
+      cache_ = PojoCacheFactory.createCache(configFile, toStart);
+      cache_.start();
+      tx_mgr = DummyTransactionManager.getInstance();
+
+   }
+
+   @AfterMethod(alwaysRun = true)
+   protected void tearDown() throws Exception
+   {
+      cache_.stop();
+   }
+
+   public void testSimple() throws Exception
+   {
+      HashSet<String> set = new HashSet<String>();
+      set.add("test1");
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", set);
+         tx_mgr.rollback();
+      }
+      catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(set));
+
+      cache_.attach("/a", set);
+   }
+
+   public void testSimpleTxWithRollback1() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      HashSet<String> set = new HashSet<String>();
+      set.add("English");
+      test.setSkills(set);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.attach("/a", test);
+         tx_mgr.rollback();
+      } catch (Exception e)
+      {
+      }
+      assertFalse("Should not have cache interceptor ", isProxy(test.getSkills()));
+
+      cache_.attach("/a", test);
+   }
+
+   private boolean isProxy(Object pojo)
+   {
+      if (pojo instanceof ClassProxy) return true;
+      return false;
+   }
+
+   public void testSimpleTxWithRollback2() throws Exception
+   {
+      log_.info("testSimpleTxWithRollback1() ....");
+      Person test = new Person();
+      test.setName("Ben");
+      test.setAge(10);
+      HashSet<String> set = new HashSet<String>();
+      set.add("English");
+      test.setSkills(set);
+
+      cache_.attach("/a", test);
+
+      try
+      {
+         tx_mgr.begin();
+         cache_.detach("/a");
+         tx_mgr.rollback();
+      } catch (Exception e)
+      {
+      }
+
+      assertTrue("Should still have cache interceptor ", isProxy(test.getSkills()));
+      cache_.detach("/a");
+   }
+}




More information about the jbosscache-commits mailing list