[exo-jcr-commits] exo-jcr SVN: r4402 - in jcr/trunk: applications/product-patches/as/ear/META-INF and 23 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Mon May 23 03:39:33 EDT 2011


Author: tolusha
Date: 2011-05-23 03:39:32 -0400 (Mon, 23 May 2011)
New Revision: 4402

Added:
   jcr/trunk/applications/product-patches/as/jboss/bin/
   jcr/trunk/applications/product-patches/as/jboss/exo-readme.txt
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManagerListener.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/ActionNonTxAware.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/infinispan/
   jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jta.xml
   jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/data-source-provider.xml
Removed:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionException.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java
Modified:
   jcr/trunk/applications/exo.jcr.applications.jboss/pom.xml
   jcr/trunk/applications/product-patches/as/ear/META-INF/weblogic-application.xml
   jcr/trunk/applications/product-patches/as/jboss/exo-configuration.xml
   jcr/trunk/applications/product-patches/as/jetty/exo-configuration.xml
   jcr/trunk/applications/product-patches/as/jonas/apps/autoload/exoplatform.ear/META-INF/application.xml
   jcr/trunk/applications/product-patches/as/jonas/exo-configuration.xml
   jcr/trunk/applications/product-patches/as/tomcat/exo-configuration.xml
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/XASession.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/CompositeChangesLog.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/TransactionChangesLog.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionRegistry.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/TrackedXASession.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/GenericTransactionService.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/JBossTransactionsService.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestUserTransaction.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestXATransaction.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/storage/JDBCWDCTest.java
   jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml
   jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel.xml
   jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml
Log:
EXOJCR-480: Managed transactions support

Modified: jcr/trunk/applications/exo.jcr.applications.jboss/pom.xml
===================================================================
--- jcr/trunk/applications/exo.jcr.applications.jboss/pom.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/exo.jcr.applications.jboss/pom.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -115,11 +115,14 @@
                   </copy>
                   <!--copying exo-configuration.xml-->
                   <copy todir="${exo.projects.directory.working}/exo-jboss/" verbose="true" overwrite="true">
-                     <fileset dir="${basedir}/../product-patches/as/jboss/" includes="*.xml" />
+                     <fileset dir="${basedir}/../product-patches/as/jboss/" includes="exo-*.*" />
                   </copy>
                   <copy todir="${exo.projects.directory.working}/exo-jboss/server/default/conf/" verbose="true" overwrite="true">
                      <fileset dir="${basedir}/../product-patches/as/jboss/exoplatform.sar/META-INF/" includes="login*.xml" />
                   </copy>
+                  <copy todir="${exo.projects.directory.working}/exo-jboss/bin/" verbose="true" overwrite="true">
+                     <fileset dir="${basedir}/../product-patches/as/jboss/bin/" includes="*.*" />
+                  </copy>
                </tasks>
             </configuration>
          </plugin>

Modified: jcr/trunk/applications/product-patches/as/ear/META-INF/weblogic-application.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/ear/META-INF/weblogic-application.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/ear/META-INF/weblogic-application.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -24,7 +24,7 @@
   <classloader-structure> 
   <classloader-structure> 
   	<module-ref> 
-  		<module-uri>localadapter.rar</module-uri> 
+  		<module-uri>exo-jcr.rar</module-uri> 
   	</module-ref> 
   	<module-ref> 
   		<module-uri>browser.war</module-uri> 

Modified: jcr/trunk/applications/product-patches/as/jboss/exo-configuration.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/jboss/exo-configuration.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/jboss/exo-configuration.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -178,12 +178,12 @@
          </object-param>
       </init-params>
    </component>
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
      <key>org.jboss.cache.transaction.TransactionManagerLookup</key>
      <type>org.jboss.cache.transaction.JBossStandaloneJTAManagerLookup</type>
   </component>
    
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
     <key>org.exoplatform.services.transaction.TransactionService</key>
     <type>org.exoplatform.services.transaction.jbosscache.JBossTransactionsService</type>
     <init-params>
@@ -193,6 +193,21 @@
       </value-param>
     </init-params>   
   </component>
+  <component profiles="ispn">
+     <key>org.infinispan.transaction.lookup.TransactionManagerLookup</key>
+     <type>org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup</type>
+  </component>
+   
+  <component profiles="ispn">
+    <key>org.exoplatform.services.transaction.TransactionService</key>
+    <type>org.exoplatform.services.transaction.infinispan.JBossTransactionsService</type>
+    <init-params>
+      <value-param>
+        <name>timeout</name>
+        <value>3000</value>
+      </value-param>
+    </init-params>   
+  </component>
 
   <component profiles="ispn,jbc">
     <key>org.exoplatform.services.rpc.RPCService</key>
@@ -299,7 +314,7 @@
          </value-param>
          <value-param>
             <name>cache-folder-name</name>
-            <value>../temp/ftp_cache</value>
+            <value>${exo.jcr.parent.dir:..}/temp/ftp_cache</value>
          </value-param>
 
          <!-- bytes per second -->
@@ -358,7 +373,7 @@
                <name>ref-addresses</name>
                <description>ref-addresses</description>
                <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
-               <property name="url" value="jdbc:hsqldb:file:../temp/data/exodb" />
+               <property name="url" value="jdbc:hsqldb:file:${exo.jcr.parent.dir:..}/temp/data/exodb" />
                <property name="username" value="sa" />
                <property name="password" value="" />
             </properties-param>

Added: jcr/trunk/applications/product-patches/as/jboss/exo-readme.txt
===================================================================
--- jcr/trunk/applications/product-patches/as/jboss/exo-readme.txt	                        (rev 0)
+++ jcr/trunk/applications/product-patches/as/jboss/exo-readme.txt	2011-05-23 07:39:32 UTC (rev 4402)
@@ -0,0 +1,15 @@
+Thank you for your interest in eXo JCR
+
+To launch it, go to the bin directory and execute the following command:
+
+In Unix environment
+
+* "./run.sh" to launch eXo JCR with the default configuration
+* "./run.sh ispn" to launch eXo JCR with the configuration for Infinispan
+* "./run.sh jbc" to launch eXo JCR with the configuration for JBoss Cache
+
+In Windows environment
+
+* "run.bat" to launch eXo JCR with the default configuration
+* "run.bat ispn" to launch eXo JCR with the configuration for Infinispan
+* "run.bat jbc" to launch eXo JCR with the configuration for JBoss Cache

Modified: jcr/trunk/applications/product-patches/as/jetty/exo-configuration.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/jetty/exo-configuration.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/jetty/exo-configuration.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -178,12 +178,12 @@
          </object-param>
       </init-params>
    </component>
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
      <key>org.jboss.cache.transaction.TransactionManagerLookup</key>
      <type>org.jboss.cache.transaction.JBossStandaloneJTAManagerLookup</type>
   </component>
    
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
     <key>org.exoplatform.services.transaction.TransactionService</key>
     <type>org.exoplatform.services.transaction.jbosscache.JBossTransactionsService</type>
     <init-params>
@@ -193,6 +193,21 @@
       </value-param>
     </init-params>   
   </component>
+  <component profiles="ispn">
+     <key>org.infinispan.transaction.lookup.TransactionManagerLookup</key>
+     <type>org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup</type>
+  </component>
+   
+  <component profiles="ispn">
+    <key>org.exoplatform.services.transaction.TransactionService</key>
+    <type>org.exoplatform.services.transaction.infinispan.JBossTransactionsService</type>
+    <init-params>
+      <value-param>
+        <name>timeout</name>
+        <value>3000</value>
+      </value-param>
+    </init-params>   
+  </component>
   
   <component profiles="ispn,jbc">
     <key>org.exoplatform.services.rpc.RPCService</key>

Modified: jcr/trunk/applications/product-patches/as/jonas/apps/autoload/exoplatform.ear/META-INF/application.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/jonas/apps/autoload/exoplatform.ear/META-INF/application.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/jonas/apps/autoload/exoplatform.ear/META-INF/application.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -41,6 +41,6 @@
     </web>
   </module>
   <module>
-    <connector>localadapter.rar</connector>
+    <connector>exo-jcr.rar</connector>
   </module>
 </application>

Modified: jcr/trunk/applications/product-patches/as/jonas/exo-configuration.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/jonas/exo-configuration.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/jonas/exo-configuration.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -178,12 +178,12 @@
          </object-param>
       </init-params>
    </component>
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
      <key>org.jboss.cache.transaction.TransactionManagerLookup</key>
      <type>org.jboss.cache.transaction.JBossStandaloneJTAManagerLookup</type>
   </component>
    
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
     <key>org.exoplatform.services.transaction.TransactionService</key>
     <type>org.exoplatform.services.transaction.jbosscache.JBossTransactionsService</type>
     <init-params>
@@ -193,6 +193,21 @@
       </value-param>
     </init-params>   
   </component>
+  <component profiles="ispn">
+     <key>org.infinispan.transaction.lookup.TransactionManagerLookup</key>
+     <type>org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup</type>
+  </component>
+   
+  <component profiles="ispn">
+    <key>org.exoplatform.services.transaction.TransactionService</key>
+    <type>org.exoplatform.services.transaction.infinispan.JBossTransactionsService</type>
+    <init-params>
+      <value-param>
+        <name>timeout</name>
+        <value>3000</value>
+      </value-param>
+    </init-params>   
+  </component>
   
   <component profiles="ispn,jbc">
     <key>org.exoplatform.services.rpc.RPCService</key>

Modified: jcr/trunk/applications/product-patches/as/tomcat/exo-configuration.xml
===================================================================
--- jcr/trunk/applications/product-patches/as/tomcat/exo-configuration.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/applications/product-patches/as/tomcat/exo-configuration.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -178,12 +178,12 @@
          </object-param>
       </init-params>
    </component>
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
      <key>org.jboss.cache.transaction.TransactionManagerLookup</key>
      <type>org.jboss.cache.transaction.JBossStandaloneJTAManagerLookup</type>
   </component>
    
-  <component profiles="ispn,jbc">
+  <component profiles="jbc">
     <key>org.exoplatform.services.transaction.TransactionService</key>
     <type>org.exoplatform.services.transaction.jbosscache.JBossTransactionsService</type>
     <init-params>
@@ -193,6 +193,21 @@
       </value-param>
     </init-params>   
   </component>
+  <component profiles="ispn">
+     <key>org.infinispan.transaction.lookup.TransactionManagerLookup</key>
+     <type>org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup</type>
+  </component>
+   
+  <component profiles="ispn">
+    <key>org.exoplatform.services.transaction.TransactionService</key>
+    <type>org.exoplatform.services.transaction.infinispan.JBossTransactionsService</type>
+    <init-params>
+      <value-param>
+        <name>timeout</name>
+        <value>3000</value>
+      </value-param>
+    </init-params>   
+  </component>
   
   <component profiles="ispn,jbc">
     <key>org.exoplatform.services.rpc.RPCService</key>

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/ExtendedSession.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -33,6 +33,7 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.nodetype.ConstraintViolationException;
+import javax.transaction.xa.XAResource;
 
 /**
  * Created by The eXo Platform SAS.
@@ -147,4 +148,31 @@
     */
    void registerLifecycleListener(SessionLifecycleListener listener);
 
+   /**
+    * Gives the local timeout of the session
+    * 
+    * @return the timeout the local timeout expressed in milliseconds
+    */
+   long getTimeout();
+
+   /**
+    * Sets the local timeout of the session
+    * 
+    * @param timeout the new local timeout any value lower or equals to 0 will disable the timeout,
+    * the expected value is expressed in milliseconds 
+    */
+   void setTimeout(long timeout);
+   
+   /**
+    * Indicates whether the session has expired or not. A session expired when it has not
+    * been modified since an amount of time bigger than the timeout
+    * @return <code>true</code> if it has expired, <code>false</code> otherwise.
+    */
+   boolean hasExpired();
+   
+   /**
+    * Gives the XA representation of the session
+    * @return the {@link XAResource} corresponding to the session
+    */
+   XAResource getXAResource();
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/XASession.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/XASession.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/XASession.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * 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.exoplatform.services.jcr.core;
-
-import org.exoplatform.services.transaction.TransactionException;
-
-import javax.jcr.Session;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-
-/**
- * Created by The eXo Platform SAS.<br/> XASession
- * 
- * @author <a href="mailto:gennady.azarenkov at exoplatform.com">Gennady Azarenkov</a>
- * @version $Id: XASession.java 11907 2008-03-13 15:36:21Z ksm $
- */
-
-public interface XASession extends Session
-{
-
-   /**
-    * @return XAResource
-    */
-   XAResource getXAResource();
-
-   /**
-    * Enlists XAResource in TM.
-    * 
-    * @throws XAException
-    */
-   void enlistResource() throws XAException;
-
-   /**
-    * Delists XAResource in TM.
-    * 
-    * @throws XAException
-    */
-   void delistResource() throws XAException;
-   
-   /**
-    * Returns TransactionException of a last commit XA intransaction context. Can be null. For information purpose.
-    *
-    * @return TransactionException commit exception
-    */
-   TransactionException getCommitException();
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/CompositeChangesLog.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/CompositeChangesLog.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/CompositeChangesLog.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -43,6 +43,13 @@
    void addLog(PlainChangesLog log);
 
    /**
+    * Removes a given PlainChangesLog
+    * 
+    * @param log
+    */
+   void removeLog(PlainChangesLog log);
+
+   /**
     * @return systemId
     */
    String getSystemId();

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/TransactionChangesLog.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/TransactionChangesLog.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/TransactionChangesLog.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -66,6 +66,14 @@
       changesLogs.add(log);
    }
 
+   /**
+    * {@inheritDoc}
+    */
+   public void removeLog(PlainChangesLog log)
+   {
+      changesLogs.remove(log);
+   }
+
    /*
     * (non-Javadoc)
     * 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -59,6 +59,7 @@
 import org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager;
 import org.exoplatform.services.jcr.impl.dataflow.persistent.LinkedWorkspaceStorageCacheImpl;
 import org.exoplatform.services.jcr.impl.dataflow.persistent.LocalWorkspaceDataManagerStub;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
 import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
 import org.exoplatform.services.jcr.impl.storage.value.StandaloneStoragePluginProvider;
 import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
@@ -459,6 +460,7 @@
             public Void run()
             {
                workspaceContainer.registerComponentImplementation(initilizerType);
+               workspaceContainer.registerComponentImplementation(TransactionableResourceManager.class);
                workspaceContainer.registerComponentImplementation(SessionFactory.class);
                return null;
             }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -24,12 +24,10 @@
 import org.exoplatform.services.jcr.access.DynamicIdentity;
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
 import org.exoplatform.services.jcr.core.security.JCRRuntimePermissions;
-import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.security.ConversationState;
 import org.exoplatform.services.security.IdentityConstants;
-import org.exoplatform.services.transaction.TransactionService;
 
 import javax.jcr.LoginException;
 import javax.jcr.RepositoryException;
@@ -48,25 +46,18 @@
 
    private final ExoContainer container;
 
-   private final TransactionService tService;
-
    private final String workspaceName;
 
-   private final TransactionableResourceManager txResourceManager;
-
    /**
     * JCR Session factory.
     * 
-    * @param tService TransactionService
     * @param config WorkspaceEntry
     * @param containerContext ExoContainerContext
     */
-   public SessionFactory(TransactionService tService, WorkspaceEntry config, ExoContainerContext containerContext)
+   public SessionFactory(WorkspaceEntry config, ExoContainerContext containerContext)
    {
       this.container = containerContext.getContainer();
       this.workspaceName = config.getName();
-      this.tService = tService;
-      this.txResourceManager = new TransactionableResourceManager();
 
       boolean tracking =
          "true".equalsIgnoreCase(PrivilegedSystemHelper.getProperty("exo.jcr.session.tracking.active", "false"));
@@ -105,21 +96,10 @@
    }
 
    /**
-    * JCR Session factory.
-    * 
-    * @param config WorkspaceEntry
-    * @param containerContext ExoContainerContext
-    */
-   public SessionFactory(WorkspaceEntry config, ExoContainerContext containerContext)
-   {
-      this((TransactionService)null, config, containerContext);
-   }
-
-   /**
     * Creates Session object by given Credentials
     * 
     * @param credentials
-    * @return XASessionImpl if TransactionService present or SessionImpl otherwise
+    * @return the SessionImpl corresponding to the given {@link ConversationState}
     * @throws RepositoryException
     */
    SessionImpl createSession(ConversationState user) throws RepositoryException, LoginException
@@ -142,26 +122,13 @@
             security.checkPermission(JCRRuntimePermissions.CREATE_DYNAMIC_SESSION_PERMISSION);
          }
       }
-      if (tService == null)
-      {
-         if (SessionReference.isStarted())
-         {
-            return new TrackedSession(workspaceName, user, container);
-         }
-         else
-         {
-            return new SessionImpl(workspaceName, user, container);
-         }
-      }
-
       if (SessionReference.isStarted())
       {
-         return new TrackedXASession(workspaceName, user, container, tService, txResourceManager);
+         return new TrackedSession(workspaceName, user, container);
       }
       else
       {
-         return new XASessionImpl(workspaceName, user, container, tService, txResourceManager);
+         return new SessionImpl(workspaceName, user, container);
       }
    }
-
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -28,6 +28,7 @@
 import org.exoplatform.services.jcr.core.NamespaceAccessor;
 import org.exoplatform.services.jcr.core.SessionLifecycleListener;
 import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
 import org.exoplatform.services.jcr.datamodel.ItemData;
 import org.exoplatform.services.jcr.datamodel.ItemType;
 import org.exoplatform.services.jcr.datamodel.NodeData;
@@ -41,6 +42,7 @@
 import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
 import org.exoplatform.services.jcr.impl.dataflow.ItemDataMoveVisitor;
 import org.exoplatform.services.jcr.impl.dataflow.persistent.LocalWorkspaceDataManagerStub;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
 import org.exoplatform.services.jcr.impl.ext.action.SessionActionCatalog;
 import org.exoplatform.services.jcr.impl.ext.action.SessionActionInterceptor;
 import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
@@ -92,6 +94,7 @@
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.observation.ObservationManager;
 import javax.jcr.version.VersionException;
+import javax.transaction.xa.XAResource;
 import javax.xml.stream.XMLStreamException;
 
 /**
@@ -150,6 +153,8 @@
 
    private boolean live;
    
+   private boolean expired;
+   
    private Exception closedByCallStack;
 
    private final List<SessionLifecycleListener> lifecycleListeners;
@@ -170,6 +175,16 @@
 
    protected final NodeTypeDataManager nodeTypeManager;
 
+   /**
+    * Transaction resources manager.
+    */
+   private final TransactionableResourceManager txResourceManager;
+   
+   /**
+    * The local timeout of the session, by default it will use the global timeout defined at repository configuration level
+    */
+   private long timeout;
+
    public SessionImpl(String workspaceName, ConversationState userState, ExoContainer container)
       throws RepositoryException
    {
@@ -178,6 +193,7 @@
       this.live = true;
       this.id = IdGenerator.generate();
       this.userState = userState;
+      this.txResourceManager = (TransactionableResourceManager)container.getComponentInstanceOfType(TransactionableResourceManager.class);
 
       this.repository = (RepositoryImpl)container.getComponentInstanceOfType(RepositoryImpl.class);
       this.systemLocationFactory = (LocationFactory)container.getComponentInstanceOfType(LocationFactory.class);
@@ -947,6 +963,16 @@
    }
 
    /**
+    * Makes the current session expired. This will automatically logout the session and set the expired
+    * flag to true.
+    */
+   public void expire()
+   {
+      this.expired = true;
+      logout();
+   }
+   
+   /**
     * {@inheritDoc}
     */
    public void move(String srcAbsPath, String destAbsPath) throws ItemExistsException, PathNotFoundException,
@@ -1097,4 +1123,51 @@
          repository.getName(), workspaceName, live);
    }
 
+   /**
+    * Checks if a global Tx has been started if so the session and its change will be dynamically enrolled
+    * @param statesLog the changes to enlist in case a Global Tx has been started 
+    * @return <code>true</code> if a global Tx has been started and the session could
+    * be enrolled successfully, <code>false</code> otherwise
+    */
+   public boolean canEnrollChangeToGlobalTx(PlainChangesLog statesLog)
+   {
+      return txResourceManager.canEnrollChangeToGlobalTx(this, statesLog);
+   }
+
+   /**
+    * Gives the local timeout of the session
+    * 
+    * @return the timeout the local timeout expressed in milliseconds
+    */
+   public long getTimeout()
+   {
+      return timeout;
+   }
+
+   /**
+    * Sets the local timeout of the session
+    * 
+    * @param timeout the new local timeout any value lower or equals to 0 will disable the timeout,
+    * the expected value is expressed in milliseconds 
+    */
+   public void setTimeout(long timeout)
+   {
+      this.timeout = (timeout <= 0 ? 0 : timeout);
+   }
+   
+   /**
+    * {@inheritDoc}
+    */
+   public XAResource getXAResource()
+   {
+      return txResourceManager;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean hasExpired()
+   {
+      return expired;
+   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionRegistry.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionRegistry.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionRegistry.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -226,11 +226,21 @@
       {
          for (SessionImpl session : sessionsMap.values())
          {
-            if (session.getLastAccessTime() + sessionTimeOut < System.currentTimeMillis())
+            if (session.getLastAccessTime() + getTimeout(session) < System.currentTimeMillis())
             {
-               session.logout();
+               session.expire();
             }
          }
       }
+      
+      /**
+       * Checks if the session has a local timeout if so it will use it otherwise it will use the
+       * global timeout
+       */
+      private long getTimeout(SessionImpl session)
+      {
+         long localSessionTimeout = session.getTimeout();
+         return localSessionTimeout == 0 ? sessionTimeOut : localSessionTimeout;
+      }
    }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/TrackedXASession.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/TrackedXASession.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/TrackedXASession.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * 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.exoplatform.services.jcr.impl.core;
-
-import org.exoplatform.container.ExoContainer;
-import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
-import org.exoplatform.services.security.ConversationState;
-import org.exoplatform.services.transaction.TransactionService;
-
-import javax.jcr.RepositoryException;
-
-/**
- * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
- * @version $Revision$
- */
-public class TrackedXASession extends XASessionImpl
-{
-
-   private final SessionReference ref = new SessionReference(this);
-
-   public TrackedXASession(String workspaceName, ConversationState userState, ExoContainer container,
-      TransactionService tService, TransactionableResourceManager txResourceManager) throws RepositoryException
-   {
-      super(workspaceName, userState, container, tService, txResourceManager);
-   }
-
-   @Override
-   public void logout()
-   {
-      ref.closed = true;
-      super.logout();
-   }
-}
\ No newline at end of file

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionException.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionException.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionException.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2010 eXo Platform SAS.
- *
- * 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.exoplatform.services.jcr.impl.core;
-
-import javax.transaction.xa.XAException;
-
-/**
- * Provides XAException functionality with constructor for errorcode and message.
- * 
- * @author <a href="mailto:peter.nedonosko at exoplatform.com">Peter Nedonosko</a>
- * @version $Id$
- *  */
-public class XASessionException extends XAException
-{
-
-   /**
-    * serialVersionUID.
-    */
-   private static final long serialVersionUID = -1853702973389878895L;
-
-   public XASessionException()
-   {
-      super();
-   }
-
-   public XASessionException(int errcode)
-   {
-      super(errcode);
-   }
-
-   public XASessionException(String s)
-   {
-      super(s);
-   }
-   
-   public XASessionException(String s, int errorCode)
-   {
-      super(s);
-      this.errorCode = errorCode;
-   }
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionImpl.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/XASessionImpl.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,425 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * 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.exoplatform.services.jcr.impl.core;
-
-import org.exoplatform.container.ExoContainer;
-import org.exoplatform.services.jcr.core.XASession;
-import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-import org.exoplatform.services.security.ConversationState;
-import org.exoplatform.services.transaction.ExoResource;
-import org.exoplatform.services.transaction.TransactionException;
-import org.exoplatform.services.transaction.TransactionService;
-
-import javax.jcr.RepositoryException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-/**
- * Created by The eXo Platform SAS.
- * 
- * @author <a href="mailto:gennady.azarenkov at exoplatform.com">Gennady Azarenkov</a>
- * @version $Id: XASessionImpl.java 34801 2009-07-31 15:44:50Z dkatayev $
- */
-public class XASessionImpl extends SessionImpl implements XASession, XAResource, ExoResource
-{
-
-   /**
-    * Session logger.
-    */
-   private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.XASessionImpl");
-
-   /**
-    * Transaction service.
-    */
-   private final TransactionService tService;
-
-   /**
-    * Transaction resources manager.
-    */
-   private final TransactionableResourceManager txResourceManager;
-
-   /**
-    * Start flags.
-    */
-   private int startFlags = TMNOFLAGS;
-
-   /**
-    * Transaction timeout.
-    */
-   private int txTimeout;
-
-   /**
-    * An arbitrary payload required by the ExoResource implementation.
-    */
-   private Object payload;
-
-   /**
-    * TransactionException of a last commit in context of a transaction. 
-    * Can be set on commit and will be restet on enlist/delist resource or rollback. 
-    */
-   private TransactionException commitException = null;
-
-   /**
-    * XASessionImpl constructor.
-    * 
-    * @param workspaceName
-    *          workspace name
-    * @param userState
-    *          user ConversationState
-    * @param container
-    *          ExoContainer
-    * @param tService
-    *          Transaction service
-    * @param txResourceManager
-    *          Transaction resources manager.
-    * @throws RepositoryException
-    *           Repository error
-    */
-   XASessionImpl(String workspaceName, ConversationState userState, ExoContainer container,
-      TransactionService tService, TransactionableResourceManager txResourceManager) throws RepositoryException
-   {
-      super(workspaceName, userState, container);
-      this.txTimeout = tService.getDefaultTimeout();
-      this.tService = tService;
-      this.txResourceManager = txResourceManager;
-
-      // enlist on login instead of this.txResourceManager.add(this);
-      try
-      {
-         this.enlistResource();
-      }
-      catch (XAException e)
-      {
-         throw new RepositoryException(e);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public XAResource getXAResource()
-   {
-      return this;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void delistResource() throws XAException
-   {
-      // TODO if session is dead? can we delist it?
-      try
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Delist session: " + getSessionInfo() + ", " + this);
-         }
-
-         commitException = null;
-         txResourceManager.remove(this);
-         tService.delistResource(this);
-      }
-      catch (RollbackException e)
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Delist error, session: " + getSessionInfo() + ", " + this, e);
-         }
-
-         throw new XASessionException("Cannot delist resource XASession " + getSessionInfo() + ". " + e);
-      }
-      catch (SystemException e)
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Delist error, session: " + getSessionInfo() + ", " + this, e);
-         }
-
-         throw new XASessionException("Cannot delist resource XASession " + getSessionInfo() + ". " + e);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void enlistResource() throws XAException
-   {
-      // TODO if session is dead? can we enlist it?
-      try
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Enlist session: " + getSessionInfo() + ", " + this);
-         }
-
-         commitException = null;
-         txResourceManager.add(this);
-         tService.enlistResource(this);
-      }
-      catch (RollbackException e)
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Enlist error, session: " + getSessionInfo() + ", " + this, e);
-         }
-
-         throw new XASessionException("Cannot enlist resource XASession " + getSessionInfo() + ". " + e);
-      }
-      catch (SystemException e)
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Enlist error, session: " + getSessionInfo() + ", " + this, e);
-         }
-
-         throw new XASessionException("Cannot enlist resource XASession " + getSessionInfo() + ". " + e);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void commit(Xid xid, boolean onePhase) throws XAException
-   {
-      try
-      {
-         txResourceManager.commit(this, onePhase);
-      }
-      catch (TransactionException e)
-      {
-         commitException = e;
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Commit Error. Xid:" + xid + ", session: " + getSessionInfo() + ", " + this, e);
-         }
-
-         throw new XASessionException(e.toString(), e.getErrorCode());
-      }
-
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("Commit. Xid:" + xid + ", session: " + getSessionInfo() + ", " + this);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void start(Xid xid, int flags) throws XAException
-   {
-      txResourceManager.start(this);
-      startFlags = flags;
-
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("Start. Xid:" + xid + ", " + flags + ", session: " + getSessionInfo() + ", " + this);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void end(Xid xid, int flags) throws XAException
-   {
-      startFlags = flags;
-
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("End. Xid:" + xid + ", " + flags + ", session: " + getSessionInfo() + ", " + this);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void forget(Xid xid) throws XAException
-   {
-      // TODO forget = rollback?
-      //txResourceManager.rollback(this);
-
-      //if (LOG.isDebugEnabled())
-      //{
-      //   LOG.debug("Forget. Xid:" + xid + ", session: " + getSessionInfo() + ", " + this);
-      //}
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public int getTransactionTimeout() throws XAException
-   {
-      return txTimeout;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean isSameRM(XAResource resource) throws XAException
-   {
-      if (resource instanceof XASessionImpl)
-      {
-         XASessionImpl session = (XASessionImpl)resource;
-         boolean isSame =
-            getUserID().equals(session.getUserID())
-               && getWorkspace().getName().equals(session.getWorkspace().getName())
-               && ((RepositoryImpl)getRepository()).getName().equals(
-                  ((RepositoryImpl)session.getRepository()).getName());
-
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("isSameRM: " + getSessionInfo() + " -- " + session.getSessionInfo() + " : " + isSame + ", "
-               + this + " -- " + session + ", Flags:" + startFlags);
-         }
-
-         return isSame;
-      }
-      return false;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public int prepare(Xid xid) throws XAException
-   {
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("Prepare. Xid:" + xid + ", session: " + getSessionInfo() + ", " + this);
-      }
-
-      return XA_OK;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public Xid[] recover(int xid) throws XAException
-   {
-      return null;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void rollback(Xid xid) throws XAException
-   {
-      txResourceManager.rollback(this);
-      commitException = null;
-
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("Rollback. Xid:" + xid + ", session: " + getSessionInfo() + ", " + this);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean setTransactionTimeout(int seconds) throws XAException
-   {
-      try
-      {
-         tService.setTransactionTimeout(seconds);
-      }
-      catch (SystemException e)
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("Cannot set transaction timeout " + seconds + "sec via XASession " + getSessionInfo() + ". ", e);
-         }
-
-         throw new XASessionException("Cannot set transaction timeout " + seconds + "sec via XASession "
-            + getSessionInfo() + ". " + e);
-      }
-      this.txTimeout = seconds;
-      return true;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   @Override
-   public void logout()
-   {
-      if (LOG.isDebugEnabled())
-      {
-         LOG.debug("Logout. Session: " + getSessionInfo() + ", " + this);
-      }
-
-      try
-      {
-         // Rolling back this session only
-         getTransientNodesManager().getTransactManager().rollback();
-
-         super.logout();
-      }
-      finally
-      {
-         // Delist and remove session from this user sessions list in TransactionableDataManager
-         // txResourceManager.remove(this) will be called in delistResource()
-         try
-         {
-            delistResource();
-            startFlags = TMNOFLAGS;
-         }
-         catch (XAException e)
-         {
-            LOG.error("Logout error " + e, e);
-         }
-      }
-   }
-
-   /**
-    * Get XASession info string.
-    * 
-    * @return info string
-    */
-   private String getSessionInfo()
-   {
-      return getUserID() + "@" + workspaceName;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public Object getPayload()
-   {
-      return payload;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void setPayload(Object payload)
-   {
-      this.payload = payload;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public TransactionException getCommitException()
-   {
-      return commitException;
-   }
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -53,9 +53,7 @@
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.security.IdentityConstants;
-import org.jboss.cache.Cache;
-import org.jboss.cache.Node;
-import org.jboss.cache.loader.CacheLoader;
+import org.exoplatform.services.transaction.ActionNonTxAware;
 import org.picocontainer.Startable;
 
 import java.io.BufferedOutputStream;
@@ -76,7 +74,6 @@
 
 import javax.jcr.RepositoryException;
 import javax.jcr.lock.LockException;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 
 /**
@@ -198,7 +195,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(getNumLocks, null);
+         return getNumLocks.run();
       }
       catch (LockException e)
       {
@@ -214,7 +211,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(hasLocks, null);
+         return hasLocks.run();
       }
       catch (LockException e)
       {
@@ -230,7 +227,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(isLockLive, nodeId);
+         return isLockLive.run(nodeId);
       }
       catch (LockException e)
       {
@@ -244,7 +241,7 @@
     */
    public void refreshLockData(LockData newLockData) throws LockException
    {
-      executeLockActionNonTxAware(refresh, newLockData);
+      refresh.run(newLockData);
    }
 
    /**
@@ -254,7 +251,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(lockExist, nodeId);
+         return lockExist.run(nodeId);
       }
       catch (LockException e)
       {
@@ -270,7 +267,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(getLockDataById, nodeId);
+         return getLockDataById.run(nodeId);
       }
       catch (LockException e)
       {
@@ -286,7 +283,7 @@
    {
       try
       {
-         return executeLockActionNonTxAware(getLockList, null);
+         return getLockList.run();
       }
       catch (LockException e)
       {
@@ -757,47 +754,6 @@
    }
 
    /**
-    * Execute the given action outside a transaction. This is needed since the {@link Cache} used by implementation 
-    * of {@link CacheableLockManager}
-    * to manage the persistence of its locks thanks to a {@link CacheLoader} and a {@link CacheLoader} lock the cache {@link Node}
-    * even for read operations which cause deadlock issue when a XA {@link Transaction} is already opened
-    * @throws LockException when a exception occurs
-    */
-   private <R, A> R executeLockActionNonTxAware(LockActionNonTxAware<R, A> action, A arg) throws LockException
-   {
-      Transaction tx = null;
-      try
-      {
-         if (tm != null)
-         {
-            try
-            {
-               tx = tm.suspend();
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot suspend the current transaction", e);
-            }
-         }
-         return action.execute(arg);
-      }
-      finally
-      {
-         if (tx != null)
-         {
-            try
-            {
-               tm.resume(tx);
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot resume the current transaction", e);
-            }
-         }
-      }
-   }
-
-   /**
     * Actions that are not supposed to be called within a transaction
     * 
     * Created by The eXo Platform SAS
@@ -805,9 +761,15 @@
     *          nicolas.filotto at exoplatform.com
     * 21 janv. 2010
     */
-   protected static interface LockActionNonTxAware<R, A>
+   protected abstract class LockActionNonTxAware<R, A> extends ActionNonTxAware<R, A, LockException>
    {
-      R execute(A arg) throws LockException;
+      /**
+       * @see org.exoplatform.services.transaction.ActionNonTxAware#getTransactionManager()
+       */
+      protected TransactionManager getTransactionManager()
+      {
+         return tm;
+      }
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -18,6 +18,7 @@
  */
 package org.exoplatform.services.jcr.impl.dataflow.persistent;
 
+import org.exoplatform.commons.utils.SecurityHelper;
 import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
 import org.exoplatform.services.jcr.dataflow.persistent.MandatoryItemsPersistenceListener;
 import org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache;
@@ -34,7 +35,8 @@
 import org.exoplatform.services.jcr.impl.backup.ResumeException;
 import org.exoplatform.services.jcr.impl.backup.SuspendException;
 import org.exoplatform.services.jcr.impl.backup.Suspendable;
-import org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.JBossCacheWorkspaceStorageCache;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManagerListener;
 import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
 import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection;
 import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
@@ -46,6 +48,8 @@
 import org.exoplatform.services.transaction.TransactionService;
 
 import java.io.Serializable;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
@@ -54,6 +58,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.jcr.RepositoryException;
+import javax.transaction.Status;
 import javax.transaction.TransactionManager;
 
 /**
@@ -79,6 +84,11 @@
     */
    protected final ConcurrentMap<Integer, DataRequest> requestCache;
 
+   /**
+    * The resource manager
+    */
+   private final TransactionableResourceManager txResourceManager;
+   
    private TransactionManager transactionManager;
 
    /**
@@ -300,40 +310,6 @@
       }
    }
 
-   protected class SaveInTransaction extends TxIsolatedOperation
-   {
-      final ItemStateChangesLog changes;
-
-      SaveInTransaction(ItemStateChangesLog changes)
-      {
-         super(transactionManager);
-         this.changes = changes;
-      }
-
-      @Override
-      protected void action() throws RepositoryException
-      {
-         CacheableWorkspaceDataManager.super.save(changes);
-      }
-
-      @Override
-      protected void txAction() throws RepositoryException
-      {
-         super.txAction();
-
-         // notify listeners after transaction commit but before the current resume!
-         try
-         {
-            notifySaveItems(changes, false);
-         }
-         catch (Throwable th)
-         {
-            // TODO XA layer can throws runtime exceptions
-            throw new RepositoryException(th);
-         }
-      }
-   }
-
    /**
    * This class is a decorator on the top of the {@link WorkspaceStorageCache} to manage the case
    * where the cache is disabled at the beginning then potentially enabled later
@@ -369,15 +345,18 @@
     *          Items cache
     * @param systemDataContainerHolder
     *          System Workspace data container (persistent level)
+    * @param txResourceManager
+    *          the resource manager used to manage the whole tx
     * @param transactionService 
     *          TransactionService  
     * @param rpcService
     *          the service for executing commands on all nodes of cluster
     */
    public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer, WorkspaceStorageCache cache,
-      SystemDataContainerHolder systemDataContainerHolder, TransactionService transactionService, RPCService rpcService)
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager, 
+      TransactionService transactionService, RPCService rpcService)
    {
-      super(dataContainer, systemDataContainerHolder);
+      super(dataContainer, systemDataContainerHolder, txResourceManager);
       this.cache = cache;
 
       this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
@@ -386,6 +365,7 @@
       transactionManager = transactionService.getTransactionManager();
 
       this.rpcService = rpcService;
+      this.txResourceManager = txResourceManager;
       doInitRemoteCommands();
    }
 
@@ -398,12 +378,15 @@
     *          Items cache
     * @param systemDataContainerHolder
     *          System Workspace data container (persistent level)
+    * @param txResourceManager
+    *          the resource manager used to manage the whole tx
     * @param transactionService TransactionService         
     */
    public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer, WorkspaceStorageCache cache,
-      SystemDataContainerHolder systemDataContainerHolder, TransactionService transactionService)
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager,
+      TransactionService transactionService)
    {
-      this(dataContainer, cache, systemDataContainerHolder, transactionService, null);
+      this(dataContainer, cache, systemDataContainerHolder, txResourceManager, transactionService, null);
    }
 
    /**
@@ -415,26 +398,31 @@
     *          Items cache
     * @param systemDataContainerHolder
     *          System Workspace data container (persistent level)
+    * @param txResourceManager
+    *          the resource manager used to manage the whole tx
     */
    public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer, WorkspaceStorageCache cache,
-      SystemDataContainerHolder systemDataContainerHolder, RPCService rpcService)
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager,
+      RPCService rpcService)
    {
-      super(dataContainer, systemDataContainerHolder);
+      super(dataContainer, systemDataContainerHolder, txResourceManager);
       this.cache = cache;
 
       this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
       addItemPersistenceListener(new CacheItemsPersistenceListener());
 
-      if (cache instanceof JBossCacheWorkspaceStorageCache)
+      try
       {
-         transactionManager = ((JBossCacheWorkspaceStorageCache)cache).getTransactionManager();
+         transactionManager = (TransactionManager)cache.getClass().getMethod("getTransactionManager", null).invoke(null, null);
       }
-      else
+      catch (Exception e)
       {
+         LOG.debug("Could not get the transaction manager from the cache", e);
          transactionManager = null;
       }
 
       this.rpcService = rpcService;
+      this.txResourceManager = txResourceManager;      
       doInitRemoteCommands();
    }
 
@@ -447,26 +435,29 @@
     *          Items cache
     * @param systemDataContainerHolder
     *          System Workspace data container (persistent level)
+    * @param txResourceManager
+    *          the resource manager used to manage the whole tx
     */
    public CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer, WorkspaceStorageCache cache,
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager)
+   {
+      this(dataContainer, cache, systemDataContainerHolder, txResourceManager, (RPCService)null);
+   }
+
+   /**
+    * CacheableWorkspaceDataManager constructor.
+    * 
+    * @param dataContainer
+    *          Workspace data container (persistent level)
+    * @param cache
+    *          Items cache
+    * @param systemDataContainerHolder
+    *          System Workspace data container (persistent level)
+    */
+   protected CacheableWorkspaceDataManager(WorkspaceDataContainer dataContainer, WorkspaceStorageCache cache,
       SystemDataContainerHolder systemDataContainerHolder)
    {
-      super(dataContainer, systemDataContainerHolder);
-      this.cache = cache;
-
-      this.requestCache = new ConcurrentHashMap<Integer, DataRequest>();
-      addItemPersistenceListener(new CacheItemsPersistenceListener());
-
-      if (cache instanceof JBossCacheWorkspaceStorageCache)
-      {
-         transactionManager = ((JBossCacheWorkspaceStorageCache)cache).getTransactionManager();
-      }
-      else
-      {
-         transactionManager = null;
-      }
-
-      this.rpcService = null;
+      this(dataContainer, cache, systemDataContainerHolder, null, (RPCService)null);
    }
 
    /**
@@ -687,31 +678,187 @@
       }
 
       workingThreads.incrementAndGet();
-
       try
       {
-         if (isTxAware())
+         SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Void>()
          {
-            // save in dedicated XA transaction
-            new SaveInTransaction(changesLog).perform();
+            public Void run() throws Exception
+            {
+               doSave(changesLog);
+               return null;
+            }
+         });      
+      }
+      catch (PrivilegedActionException e)
+      {
+         Throwable cause = e.getCause();
+         if (cause instanceof RepositoryException)
+         {
+            throw (RepositoryException)cause;
          }
+         else if (cause instanceof RuntimeException)
+         {
+            throw (RuntimeException)cause;
+         }
          else
          {
+            throw new RuntimeException(cause);
+         }
+      }
+      finally
+      {
+         workingThreads.decrementAndGet();
+      }
+   }
 
-            // save normaly 
+   private void doSave(final ItemStateChangesLog changesLog) throws RepositoryException
+   {
+      if (isTxAware())
+      {
+         if (txResourceManager != null && txResourceManager.isGlobalTxActive())
+         {
             super.save(changesLog);
-
+            registerListener(changesLog);
+         }
+         else
+         {
+            doBegin();
+            try
+            {
+               super.save(changesLog);
+            }
+            catch (Exception e)
+            {
+               doRollback();
+               if (e instanceof RepositoryException)
+               {
+                  throw (RepositoryException)e;
+               }
+               else
+               {
+                  throw new RepositoryException("Could not save the changes", e);
+               }
+            }
+            doCommit();
             // notify listeners after storage commit
             notifySaveItems(changesLog, false);
          }
       }
-      finally
+      else
       {
-         workingThreads.decrementAndGet();
+         // save normally 
+         super.save(changesLog);
+
+         // notify listeners after storage commit
+         notifySaveItems(changesLog, false);
+      }      
+   }
+   
+   /**
+    * Commits the tx
+    * @throws RepositoryException if the tx could not be committed.
+    */
+   private void doCommit() throws RepositoryException
+   {
+      try
+      {
+         transactionManager.commit();
       }
+      catch (Exception e)
+      {
+         throw new RepositoryException("Could not commit the changes", e);
+      }
    }
 
    /**
+    * Starts a new Tx
+    * @throws RepositoryException if the tx could not be created
+    */
+   private void doBegin() throws RepositoryException
+   {
+      try
+      {
+         transactionManager.begin();
+      }
+      catch (Exception e)
+      {
+         throw new RepositoryException("Could not create a new Tx", e);
+      }
+   }
+   
+   /**
+    * Performs rollback of the action.
+    */
+   private void doRollback()
+   {
+      try
+      {
+         transactionManager.rollback();
+      }
+      catch (Exception e)
+      {
+         LOG.error("Rollback error ", e);
+      }
+   }
+   
+   /**
+    * This will allow to notify listeners that are not TxAware once the Tx is committed
+    * @param changesLog
+    * @throws RepositoryException if any error occurs
+    */
+   private void registerListener(final ItemStateChangesLog changesLog) throws RepositoryException
+   {
+      try
+      {
+         // Why calling the listeners non tx aware has been done like this:
+         // 1. If we call them in the commit phase and we use Arjuna with ISPN, we get:
+         //       ActionStatus.COMMITTING > is not in a valid state to be invoking cache operations on.
+         //       at org.infinispan.interceptors.TxInterceptor.enlist(TxInterceptor.java:195)
+         //       at org.infinispan.interceptors.TxInterceptor.enlistReadAndInvokeNext(TxInterceptor.java:167)
+         //       at org.infinispan.interceptors.TxInterceptor.visitGetKeyValueCommand(TxInterceptor.java:162)
+         //       at org.infinispan.commands.read.GetKeyValueCommand.acceptVisitor(GetKeyValueCommand.java:64)
+         //    This is due to the fact that ISPN enlist the cache even for a read access and enlistments are not 
+         //    allowed in the commit phase
+         // 2. If we call them in the commit phase, we use Arjuna with ISPN and we suspend the current tx, we get deadlocks because we 
+         //    try to acquire locks on cache entries that have been locked by the main tx.
+         // 3. If we call them in the afterComplete, we use JOTM with ISPN and we suspend and resume the current tx, we get:
+         //       jotm: resume: Invalid Transaction Status:STATUS_COMMITTED (Current.java, line 743) 
+         //       javax.transaction.InvalidTransactionException: Invalid resume org.objectweb.jotm.TransactionImpl
+         //       at org.objectweb.jotm.Current.resume(Current.java:744)
+         //    This is due to the fact that it is not allowed to resume a tx when its status is STATUS_COMMITED
+
+         txResourceManager.addListener(new TransactionableResourceManagerListener()
+         {
+            public void onCommit(boolean onePhase) throws Exception
+            {
+            }
+
+            public void onAfterCompletion(int status) throws Exception
+            {
+               if (status == Status.STATUS_COMMITTED)
+               {
+                  // Since the tx is successfully committed we can call components non tx aware
+                  
+                  // The listeners will need to be executed outside the current tx so we suspend
+                  // the current tx we can face enlistment issues on product like ISPN
+                  transactionManager.suspend();
+                  notifySaveItems(changesLog, false);
+                  // Since the resume method could cause issue with some TM at this stage, we don't resume the tx
+               }
+            }
+
+            public void onAbort() throws Exception
+            {
+            }
+         });
+      }
+      catch (Exception e)
+      {
+         throw new RepositoryException("The listener for the components not tx aware could not be added", e);
+      }
+   }
+
+   /**
     * Get cached ItemData.
     * 
     * @param parentData

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,376 +0,0 @@
-package org.exoplatform.services.jcr.impl.dataflow.persistent;
-
-import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.ItemExistsException;
-import javax.jcr.RepositoryException;
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-/**
- * Handles XA transactionaly isolated operation. I.e. Action of this operation will be executed in dedicated global transaction.
- * If another current transaction exists, the one will be suspended and resumed after the execution.
- * At other hand if nested isolated operations perform they will use same (current, active) transaction. 
- */
-public abstract class TxIsolatedOperation
-{
-   protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.TxIsolatedOperation");
-
-   protected final TransactionManager txManager;
-
-   protected final static ThreadLocal<Transaction> currentIsolated = new ThreadLocal<Transaction>();
-
-   public TxIsolatedOperation(TransactionManager txManager)
-   {
-      this.txManager = txManager;
-   }
-
-   /**
-    * Action body for a final implementation. 
-    * 
-    * @throws RepositoryException
-    */
-   protected abstract void action() throws RepositoryException;
-
-   protected void beginTx() throws NotSupportedException, SystemException
-   {
-      txManager.begin(); // start new global tx
-   }
-
-   protected void commitTx() throws SecurityException, IllegalStateException, RollbackException,
-      HeuristicMixedException, HeuristicRollbackException, SystemException
-   {
-      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-      {
-         public Object run() throws Exception
-         {
-            txManager.commit(); // commit global tx
-            return null;
-         }
-      };
-      try
-      {
-         AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof RollbackException)
-         {
-            throw (RollbackException)cause;
-         }
-         else if (cause instanceof HeuristicMixedException)
-         {
-            throw (HeuristicMixedException)cause;
-         }
-         else if (cause instanceof HeuristicRollbackException)
-         {
-            throw (HeuristicRollbackException)cause;
-         }
-         else if (cause instanceof SecurityException)
-         {
-            throw (SecurityException)cause;
-         }
-         else if (cause instanceof IllegalStateException)
-         {
-            throw (IllegalStateException)cause;
-         }
-         else if (cause instanceof SystemException)
-         {
-            throw (SystemException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   protected void rollbackTx() throws NotSupportedException, SystemException
-   {
-      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-      {
-         public Object run() throws Exception
-         {
-            txManager.rollback(); // rollback global tx
-            return null;
-         }
-      };
-      try
-      {
-         AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof SecurityException)
-         {
-            throw (SecurityException)cause;
-         }
-         else if (cause instanceof IllegalStateException)
-         {
-            throw (IllegalStateException)cause;
-         }
-         else if (cause instanceof SystemException)
-         {
-            throw (SystemException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   /**
-    * Apply action in new XA transaction (begin then commit or rollback). 
-    * Action will runs in dedicated XA transaction, i.e. only JCR storage stuff will be involved to.
-    * But if it's a nested isolated operation it will run the action assuming the same (current, active) transaction.
-    * 
-    * @throws RepositoryException if error occurs 
-    */
-   //   * @throws SystemException if XA unexpected error
-   //   * @throws NotSupportedException if unsupported XA operation
-   //   * @throws HeuristicRollbackException if all relevant updates have been rolled back on commit
-   //   * @throws HeuristicMixedException if some relevant updates have been committed and others have been rolled back on commit
-   //   * @throws RollbackException rollback performed
-   //   * @throws IllegalStateException if thread is not associated with a transaction
-   //   * @throws SecurityException if thread is not allowed to commit the transaction   
-   protected void txAction() throws RepositoryException
-   {
-      final boolean actInTx = currentIsolated.get() == null;
-      if (actInTx)
-      {
-         // it's rooted isolated operation
-         boolean rollback = true;
-         try
-         {
-            beginTx();
-
-            // remember current isolated transaction for this thread
-            Transaction current = txManager.getTransaction();
-            if (current != null)
-            {
-               currentIsolated.set(current);
-            }
-
-            action();
-
-            try
-            {
-               commitTx();
-            }
-            catch (RollbackException e)
-            {
-               // Indicate that the transaction has been rolled back rather than committed.
-               // TODO throw new RepositoryException(e);
-               LOG.error("Transaction has been rolled back", e);
-            }
-            catch (HeuristicRollbackException e)
-            {
-               // if all relevant updates have been rolled back on commit
-               // TODO throw new RepositoryException(e);
-               LOG.error("Relevant updates have been rolled back", e);
-            }
-            catch (HeuristicMixedException e)
-            {
-               // if some relevant updates have been committed and others have been rolled back on commit
-               // TODO partial commit - got inconsistency. rollback not possible?
-               // doRollback();
-               // TODO throw new RepositoryException(e);
-               LOG.error("Some relevant updates have been committed and others have been rolled back", e);
-            }
-            catch (IllegalStateException e)
-            {
-               // if thread is not associated with a transaction
-               // TODO can we do rollback if not in the tx thread?
-               // doRollback();
-               // TODO throw new RepositoryException(e);
-               LOG.error("Commit impossible, thread is not associated with the transaction", e);
-            }
-            catch (SecurityException e)
-            {
-               // if thread is not allowed to commit the transaction
-               // TODO can we do the rollback, will it have a rights?
-               // doRollback();               
-               // TODO throw new RepositoryException(e);
-               LOG.error("Commit impossible, thread is not allowed to commit the transaction", e);
-            }
-            catch (SystemException e)
-            {
-               // if XA unexpected error
-               // TODO rollback not possible?
-               // doRollback();
-               // TODO throw new RepositoryException(e);
-               LOG.error("Commit impossible dur to unexpected XA error", e);
-            }
-            finally
-            {
-               rollback = false;
-            }
-         }
-         catch (NotSupportedException e)
-         {
-            // if unsupported XA operation: nested transaction
-            rollback = false;
-            doRollback();
-            throw new RepositoryException(e);
-         }
-         catch (SystemException e)
-         {
-            // if XA unexpected error on begin or get transaction
-            rollback = false;
-            doRollback();
-            throw new RepositoryException("Unexpected error on begin or get of a transaction", e);
-         }
-         finally
-         {
-            if (rollback)
-            {
-               doRollback();
-            }
-
-            // remove current isolated transaction from this thread
-            currentIsolated.remove();
-         }
-      }
-      else
-      {
-         // it's nested isolated operation
-         action();
-      }
-   }
-
-   /**
-    * Performs rollback of the action.
-    */
-   private void doRollback()
-   {
-      try
-      {
-         rollbackTx();
-      }
-      catch (Exception e1)
-      {
-         LOG.error("Rollback error ", e1);
-      }
-   }
-
-   /**
-    * Apply the action in new XA transaction. Action should run in dedicated XA transaction,
-    * i.e. only JCR storage stuff should be involved to.
-    */
-   public void perform() throws RepositoryException
-   {
-      try
-      {
-         // Care about dedicated XA transaction for storage save:
-         // suspend current ransaction and create one new for the JCR storage (cache etc.)
-         // after the new transaction done we'll resume the current.
-
-         Transaction current = txManager.suspend();
-         Throwable actionError = null; // used for resume errors handling
-         try
-         {
-            txAction();
-         }
-         //         catch (RollbackException e)
-         //         {
-         //            // Indicate that the transaction has been rolled back rather than committed.
-         //            throw new RepositoryException(actionError = e);
-         //         }
-         catch (JCRInvalidItemStateException e)
-         {
-            throw new JCRInvalidItemStateException(e.getMessage(), e.getIdentifier(), e.getState(), actionError = e);
-         }
-         catch (InvalidItemStateException e)
-         {
-            throw new InvalidItemStateException(actionError = e);
-         }
-         catch (ItemExistsException e)
-         {
-            throw new ItemExistsException(actionError = e);
-         }
-         catch (ReadOnlyWorkspaceException e)
-         {
-            throw new ReadOnlyWorkspaceException(actionError = e);
-         }
-         catch (RepositoryException e)
-         {
-            throw new RepositoryException(actionError = e);
-         }
-         catch (Throwable e)
-         {
-            throw new RepositoryException(actionError = e);
-         }
-         finally
-         {
-            if (current != null)
-            {
-               try
-               {
-                  txManager.resume(current);
-               }
-               catch (InvalidTransactionException e)
-               {
-                  if (actionError == null)
-                  {
-                     throw new RepositoryException("Error of Transaction resume", e);
-                  }
-                  else
-                  {
-                     LOG.error("Error of Transaction resume", e);
-                  }
-               }
-               catch (IllegalStateException e)
-               {
-                  if (actionError == null)
-                  {
-                     throw new RepositoryException("Error of Transaction resume", e);
-                  }
-                  else
-                  {
-                     LOG.error("Error of Transaction resume", e);
-                  }
-               }
-               catch (SystemException e)
-               {
-                  if (actionError == null)
-                  {
-                     throw new RepositoryException("Error of Transaction resume", e);
-                  }
-                  else
-                  {
-                     LOG.error("Error of Transaction resume", e);
-                  }
-               }
-            }
-         }
-      }
-      catch (SystemException e)
-      {
-         throw new RepositoryException("Error of Transaction suspend", e);
-      }
-   }
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -41,6 +41,8 @@
 import org.exoplatform.services.jcr.datamodel.ValueData;
 import org.exoplatform.services.jcr.impl.Constants;
 import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
+import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManagerListener;
 import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
 import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
 import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
@@ -105,8 +107,13 @@
     * Read-only status.
     */
    protected boolean readOnly = false;
-
+   
    /**
+    * The resource manager
+    */
+   private final TransactionableResourceManager txResourceManager;
+   
+   /**
     * WorkspacePersistentDataManager constructor.
     * 
     * @param dataContainer
@@ -114,15 +121,32 @@
     * @param systemDataContainerHolder
     *          holder of system workspace data container
     */
-   public WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
+   protected WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
       SystemDataContainerHolder systemDataContainerHolder)
    {
+      this(dataContainer, systemDataContainerHolder, null);
+   }
+   
+   /**
+    * WorkspacePersistentDataManager constructor.
+    * 
+    * @param dataContainer
+    *          workspace data container
+    * @param systemDataContainerHolder
+    *          holder of system workspace data container
+    * @param txResourceManager
+    *          the resource manager used to manage the whole tx
+    */
+   public WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
+      SystemDataContainerHolder systemDataContainerHolder, TransactionableResourceManager txResourceManager)
+   {
       this.dataContainer = dataContainer;
       this.systemDataContainer = systemDataContainerHolder.getContainer();
 
       this.listeners = new ArrayList<ItemsPersistenceListener>();
       this.mandatoryListeners = new ArrayList<MandatoryItemsPersistenceListener>();
       this.liestenerFilters = new ArrayList<ItemsPersistenceListenerFilter>();
+      this.txResourceManager = txResourceManager;
    }
 
    /**
@@ -140,7 +164,8 @@
 
       // whole log will be reconstructed with persisted data 
       ItemStateChangesLog persistedLog;
-
+      boolean failed = true;
+      ConnectionMode mode = getMode();
       try
       {
          if (changesLog instanceof PlainChangesLogImpl)
@@ -166,7 +191,9 @@
             // we don't support other types now... i.e. add else-if for that type here
             throw new RepositoryException("Unsupported changes log class " + changesLog.getClass());
          }
-         persister.commit();
+         notifySaveItems(persistedLog, true);
+         onCommit(persister, mode);
+         failed = false;
       }
       catch (IOException e)
       {
@@ -174,12 +201,79 @@
       }
       finally
       {
+         persister.clear();
+         if (failed)
+         {
+            onRollback(persister, mode);
+         }
+      }
+   }
+
+   /**
+    * @return the current tx mode
+    */
+   private ConnectionMode getMode()
+   {
+      if (txResourceManager != null && txResourceManager.isGlobalTxActive())
+      {
+         return ConnectionMode.PARTIALLY_MANAGED;
+      }
+      return ConnectionMode.NORMAL;
+   }
+
+   /**
+    * @param persister
+    * @throws RepositoryException
+    */
+   private void onRollback(final ChangesLogPersister persister, ConnectionMode mode) throws RepositoryException
+   {
+      if (mode == ConnectionMode.NORMAL || mode == ConnectionMode.PARTIALLY_MANAGED)
+      {
+         // The rollback is done normally
          persister.rollback();
+      }      
+   }
+
+   /**
+    * @param persister
+    * @throws RepositoryException
+    */
+   private void onCommit(final ChangesLogPersister persister, ConnectionMode mode) throws RepositoryException
+   {
+      if (mode == ConnectionMode.NORMAL)
+      {
+         // The commit is done normally
+         persister.commit();
       }
+      else if (mode == ConnectionMode.PARTIALLY_MANAGED)
+      {
+         // The commit or rollback will be done by callback once the tx will be completed since it could
+         // fail later in the tx
+         txResourceManager.addListener(new TransactionableResourceManagerListener()
+         {
+            
+            public void onCommit(boolean onePhase) throws Exception
+            {
+               persister.commit();
+            }
+            
+            public void onAfterCompletion(int status) throws Exception
+            {
+            }
+            
+            public void onAbort() throws Exception
+            {
+               persister.rollback();
+            }
+         });
+      }      
+   }
 
-      notifySaveItems(persistedLog, true);
+   private enum ConnectionMode
+   {
+      NORMAL, PARTIALLY_MANAGED
    }
-
+   
    class ChangesLogPersister
    {
 
@@ -201,6 +295,12 @@
          }
       }
 
+      protected void clear()
+      {
+         // help to GC
+         addedNodes.clear();
+      }
+
       protected void rollback() throws IllegalStateException, RepositoryException
       {
          if (thisConnection != null && thisConnection.isOpened())
@@ -211,9 +311,6 @@
          {
             systemConnection.rollback();
          }
-
-         // help to GC
-         addedNodes.clear();
       }
 
       protected WorkspaceStorageConnection getSystemConnection() throws RepositoryException
@@ -471,7 +568,6 @@
    /**
     * {@inheritDoc}
     */
-   @Override
    public int getLastOrderNumber(final NodeData nodeData) throws RepositoryException
    {
       final WorkspaceStorageConnection con = dataContainer.openConnection();

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -910,69 +910,86 @@
    public void commitTransaction()
    {
       CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
-      TransactionManager tm = getTransactionManager();
+      final TransactionManager tm = getTransactionManager();
       try
       {
-         List<ChangesContainer> containers = changesContainer.getSortedList();
-         for (ChangesContainer cacheChange : containers)
+         final List<ChangesContainer> containers = changesContainer.getSortedList();
+         PrivilegedAction<Void> action = new PrivilegedAction<Void>()
          {
-            boolean isTxCreated = false;
-            try
+            public Void run()
             {
-               if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
-               {
-                  // No tx exists so we create a new tx
-                  if (LOG.isTraceEnabled())
-                     LOG.trace("No Tx is active we then create a new tx");
-                  tm.begin();
-                  isTxCreated = true;
-               }
+               commitChanges(tm, containers);
+               return null;
             }
-            catch (Exception e)
+         };
+         AccessController.doPrivileged(action);         
+      }
+      finally
+      {
+         changesList.set(null);
+         changesContainer = null;
+      }
+   }
+
+   /**
+    * @param tm
+    * @param containers
+    */
+   private void commitChanges(TransactionManager tm, List<ChangesContainer> containers)
+   {
+      for (ChangesContainer cacheChange : containers)
+      {
+         boolean isTxCreated = false;
+         try
+         {
+            if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
             {
-               LOG.warn("Could not create a new tx", e);
+               // No tx exists so we create a new tx
+               if (LOG.isTraceEnabled())
+                  LOG.trace("No Tx is active we then create a new tx");
+               tm.begin();
+               isTxCreated = true;
             }
-            try
-            {
-               cacheChange.apply();
-            }
-            catch (RuntimeException e)
-            {
-               if (isTxCreated)
-               {
-                  try
-                  {
-                     if (LOG.isTraceEnabled())
-                        LOG.trace("An error occurs the tx will be rollbacked");
-                     tm.rollback();
-                  }
-                  catch (Exception e1)
-                  {
-                     LOG.warn("Could not rollback the tx", e1);
-                  }
-               }
-               throw e;
-            }
+         }
+         catch (Exception e)
+         {
+            LOG.warn("Could not create a new tx", e);
+         }
+         try
+         {
+            cacheChange.apply();
+         }
+         catch (RuntimeException e)
+         {
             if (isTxCreated)
             {
                try
                {
                   if (LOG.isTraceEnabled())
-                     LOG.trace("The tx will be committed");
-                  tm.commit();
+                     LOG.trace("An error occurs the tx will be rollbacked");
+                  tm.rollback();
                }
-               catch (Exception e)
+               catch (Exception e1)
                {
-                  LOG.warn("Could not commit the tx", e);
+                  LOG.warn("Could not rollback the tx", e1);
                }
             }
+            throw e;
          }
+         if (isTxCreated)
+         {
+            try
+            {
+               if (LOG.isTraceEnabled())
+                  LOG.trace("The tx will be committed");
+               tm.commit();
+            }
+            catch (Exception e)
+            {
+               LOG.warn("Could not commit the tx", e);
+            }
+         }
       }
-      finally
-      {
-         changesList.set(null);
-         changesContainer = null;
-      }
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -18,7 +18,6 @@
  */
 package org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan;
 
-import org.exoplatform.commons.utils.SecurityHelper;
 import org.exoplatform.container.configuration.ConfigurationManager;
 import org.exoplatform.management.annotations.Managed;
 import org.exoplatform.management.annotations.ManagedDescription;
@@ -50,12 +49,12 @@
 import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
+import org.exoplatform.services.transaction.ActionNonTxAware;
 import org.infinispan.Cache;
 import org.infinispan.lifecycle.ComponentStatus;
 
 import java.io.File;
 import java.io.IOException;
-import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -67,7 +66,6 @@
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 
 /**
@@ -100,6 +98,228 @@
    
    protected final BufferedISPNCache cache;
 
+   private final CacheActionNonTxAware<Void, Void> commitTransaction = new CacheActionNonTxAware<Void, Void>()
+   {
+      @Override
+      protected Void execute(Void arg) throws RuntimeException
+      {
+         cache.commitTransaction();
+         return null;
+      }
+   };
+
+   private final CacheActionNonTxAware<ItemData, String> getFromCacheById =
+      new CacheActionNonTxAware<ItemData, String>()
+      {
+         @Override
+         protected ItemData execute(String id) throws RuntimeException
+         {
+            return id == null ? null : (ItemData)cache.get(new CacheId(id));
+         }
+      };
+
+   private final CacheActionNonTxAware<List<NodeData>, NodeData> getChildNodes =
+      new CacheActionNonTxAware<List<NodeData>, NodeData>()
+      {
+         @Override
+         protected List<NodeData> execute(NodeData parent) throws RuntimeException
+         {
+            // get list of children uuids
+            final Set<String> set = (Set<String>)cache.get(new CacheNodesId(parent.getIdentifier()));
+
+            if (set != null)
+            {
+               final List<NodeData> childs = new ArrayList<NodeData>();
+
+               for (String childId : set)
+               {
+                  NodeData child = (NodeData)cache.get(new CacheId(childId));
+                  if (child == null)
+                  {
+                     return null;
+                  }
+
+                  childs.add(child);
+               }
+
+               // order children by orderNumber, as HashSet returns children in other order
+               Collections.sort(childs, new NodesOrderComparator<NodeData>());
+               return childs;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+
+   private final CacheActionNonTxAware<ItemData, Object> getFromCacheByPath =
+      new CacheActionNonTxAware<ItemData, Object>()
+      {
+         @Override
+         protected ItemData execute(Object... args) throws RuntimeException
+         {
+            String parentIdentifier = (String)args[0];
+            QPathEntry name = (QPathEntry)args[1];
+            ItemType itemType = (ItemType)args[2];
+            String itemId = null;
+
+            if (itemType == ItemType.UNKNOWN)
+            {
+               // Try as node first.
+               itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.NODE));
+
+               if (itemId == null || itemId.equals(NullItemData.NULL_ID))
+               {
+                  // node with such a name is not found or marked as not-exist, so check the properties
+                  String propId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.PROPERTY));
+                  if (propId != null)
+                  {
+                     itemId = propId;
+                  }
+               }
+            }
+            else if (itemType == ItemType.NODE)
+            {
+               itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.NODE));;
+            }
+            else
+            {
+               itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.PROPERTY));;
+            }
+
+            if (itemId != null)
+            {
+               if (itemId.equals(NullItemData.NULL_ID))
+               {
+                  if (itemType == ItemType.UNKNOWN || itemType == ItemType.NODE)
+                  {
+                     return new NullNodeData();
+                  }
+                  else
+                  {
+                     return new NullPropertyData();
+                  }
+               }
+               else
+               {
+                  return get(itemId);
+               }
+            }
+            return null;
+         }
+      };
+
+   private final CacheActionNonTxAware<Integer, NodeData> getChildNodesCount =
+      new CacheActionNonTxAware<Integer, NodeData>()
+      {
+         @Override
+         protected Integer execute(NodeData parent) throws RuntimeException
+         {
+            Set<String> list = (Set<String>)cache.get(new CacheNodesId(parent.getIdentifier()));
+            return list != null ? list.size() : -1;
+         }
+      };
+
+   private final CacheActionNonTxAware<List<PropertyData>, Object> getChildProps =
+      new CacheActionNonTxAware<List<PropertyData>, Object>()
+      {
+         @Override
+         protected List<PropertyData> execute(Object... args) throws RuntimeException
+         {
+            String parentId = (String)args[0];
+            boolean withValue = (Boolean)args[1];
+            // get list of children uuids
+            final Set<String> set = (Set<String>)cache.get(new CachePropsId(parentId));
+            if (set != null)
+            {
+               final List<PropertyData> childs = new ArrayList<PropertyData>();
+
+               for (String childId : set)
+               {
+                  PropertyData child = (PropertyData)cache.get(new CacheId(childId));
+
+                  if (child == null)
+                  {
+                     return null;
+                  }
+                  if (withValue && child.getValues().size() <= 0)
+                  {
+                     return null;
+                  }
+                  childs.add(child);
+               }
+               return childs;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+
+   private final CacheActionNonTxAware<List<PropertyData>, String> getReferencedProperties =
+      new CacheActionNonTxAware<List<PropertyData>, String>()
+      {
+         @Override
+         protected List<PropertyData> execute(String identifier) throws RuntimeException
+         {
+            // get list of children uuids
+            final Set<String> set = (Set<String>)cache.get(new CacheRefsId(identifier));
+            if (set != null)
+            {
+               final List<PropertyData> props = new ArrayList<PropertyData>();
+
+               for (String childId : set)
+               {
+                  PropertyData prop = (PropertyData)cache.get(new CacheId(childId));
+
+                  if (prop == null || prop instanceof NullItemData)
+                  {
+                     return null;
+                  }
+                  // add property as many times as has referenced values 
+                  List<ValueData> lData = prop.getValues();
+                  for (int i = 0, length = lData.size(); i < length; i++)
+                  {
+                     ValueData vdata = lData.get(i);
+                     try
+                     {
+                        if (new String(vdata.getAsByteArray(), Constants.DEFAULT_ENCODING).equals(identifier))
+                        {
+                           props.add(prop);
+                        }
+                     }
+                     catch (IllegalStateException e)
+                     {
+                        // property was not added, force read from lower layer
+                        return null;
+                     }
+                     catch (IOException e)
+                     {
+                        // property was not added, force read from lower layer
+                        return null;
+                     }
+                  }
+               }
+               return props;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+
+   private final CacheActionNonTxAware<Long, Void> getSize = new CacheActionNonTxAware<Long, Void>()
+   {
+      @Override
+      protected Long execute(Void arg) throws RuntimeException
+      {
+         return (long)cache.size();
+      }
+   };
+
    /**
     * Node order comparator for getChildNodes().
     */
@@ -243,6 +463,16 @@
    }
 
    /**
+    * Return TransactionManager used by ISPN backing the JCR cache.
+    * 
+    * @return TransactionManager
+    */
+   public TransactionManager getTransactionManager()
+   {
+      return cache.getTransactionManager();
+   }
+
+   /**
     * {@inheritDoc}
     */
    public void put(ItemData item)
@@ -457,51 +687,7 @@
     */
    public ItemData get(String parentIdentifier, QPathEntry name, ItemType itemType)
    {
-      String itemId = null;
-
-      if (itemType == ItemType.UNKNOWN)
-      {
-         // Try as node first.
-         itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.NODE));
-
-         if (itemId == null || itemId.equals(NullItemData.NULL_ID))
-         {
-            // node with such a name is not found or marked as not-exist, so check the properties
-            String propId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.PROPERTY));
-            if (propId != null)
-            {
-               itemId = propId;
-            }
-         }
-      }
-      else if (itemType == ItemType.NODE)
-      {
-         itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.NODE));;
-      }
-      else
-      {
-         itemId = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.PROPERTY));;
-      }
-
-      if (itemId != null)
-      {
-         if (itemId.equals(NullItemData.NULL_ID))
-         {
-            if (itemType == ItemType.UNKNOWN || itemType == ItemType.NODE)
-            {
-               return new NullNodeData();
-            }
-            else
-            {
-               return new NullPropertyData();
-            }
-         }
-         else
-         {
-            return get(itemId);
-         }
-      }
-      return null;
+      return getFromCacheByPath.run(parentIdentifier, name, itemType);
    }
 
    /**
@@ -509,7 +695,7 @@
     */
    public ItemData get(String id)
    {
-      return id == null ? null : (ItemData)cache.get(new CacheId(id));
+      return getFromCacheById.run(id);
    }
 
    /**
@@ -517,32 +703,7 @@
     */
    public List<NodeData> getChildNodes(final NodeData parent)
    {
-      // get list of children uuids
-      final Set<String> set = (Set<String>)cache.get(new CacheNodesId(parent.getIdentifier()));
-
-      if (set != null)
-      {
-         final List<NodeData> childs = new ArrayList<NodeData>();
-
-         for (String childId : set)
-         {
-            NodeData child = (NodeData)cache.get(new CacheId(childId));
-            if (child == null)
-            {
-               return null;
-            }
-
-            childs.add(child);
-         }
-
-         // order children by orderNumber, as HashSet returns children in other order
-         Collections.sort(childs, new NodesOrderComparator<NodeData>());
-         return childs;
-      }
-      else
-      {
-         return null;
-      }
+      return getChildNodes.run(parent);
    }
 
    /**
@@ -550,8 +711,7 @@
     */
    public int getChildNodesCount(NodeData parent)
    {
-      Set<String> list = (Set<String>)cache.get(new CacheNodesId(parent.getIdentifier()));
-      return list != null ? list.size() : -1;
+      return getChildNodesCount.run(parent);
    }
 
    /**
@@ -579,32 +739,7 @@
     */
    protected List<PropertyData> getChildProps(String parentId, boolean withValue)
    {
-      // get list of children uuids
-      final Set<String> set = (Set<String>)cache.get(new CachePropsId(parentId));
-      if (set != null)
-      {
-         final List<PropertyData> childs = new ArrayList<PropertyData>();
-
-         for (String childId : set)
-         {
-            PropertyData child = (PropertyData)cache.get(new CacheId(childId));
-
-            if (child == null)
-            {
-               return null;
-            }
-            if (withValue && child.getValues().size() <= 0)
-            {
-               return null;
-            }
-            childs.add(child);
-         }
-         return childs;
-      }
-      else
-      {
-         return null;
-      }
+      return getChildProps.run(parentId, withValue);
    }
 
    /**
@@ -612,7 +747,7 @@
     */
    public long getSize()
    {
-      return cache.size();
+      return getSize.run();
    }
 
    /**
@@ -1039,53 +1174,7 @@
     */
    private void dedicatedTxCommit()
    {
-      // Ensure that the commit is done in a dedicated tx to avoid deadlock due
-      // to global XA Tx
-      final TransactionManager tm = cache.getTransactionManager();
-      Transaction tx = null;
-      try
-      {
-         if (tm != null)
-         {
-            try
-            {
-               tx = SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Transaction>()
-               {
-                  public Transaction run() throws Exception
-                  {
-                     return tm.suspend();
-                  }
-               });
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot suspend the current transaction", e);
-            }
-         }
-         cache.commitTransaction();
-      }
-      finally
-      {
-         if (tx != null)
-         {
-            try
-            {
-               final Transaction privilegedTx = tx;
-               SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Object>()
-               {
-                  public Object run() throws Exception
-                  {
-                     tm.resume(privilegedTx);
-                     return null;
-                  }
-               });
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot resume the current transaction", e);
-            }
-         }
-      }
+      commitTransaction.run();
    }
 
    /**
@@ -1121,54 +1210,11 @@
    }
 
    /**
-    * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#getReferencedProperties(java.lang.String)
+    * {@inheritDoc}
     */
    public List<PropertyData> getReferencedProperties(String identifier)
    {
-      // get list of children uuids
-      final Set<String> set = (Set<String>)cache.get(new CacheRefsId(identifier));
-      if (set != null)
-      {
-         final List<PropertyData> props = new ArrayList<PropertyData>();
-
-         for (String childId : set)
-         {
-            PropertyData prop = (PropertyData)cache.get(new CacheId(childId));
-
-            if (prop == null || prop instanceof NullItemData)
-            {
-               return null;
-            }
-            // add property as many times as has referenced values 
-            List<ValueData> lData = prop.getValues();
-            for (int i = 0, length = lData.size(); i < length; i++)
-            {
-               ValueData vdata = lData.get(i);
-               try
-               {
-                  if (new String(vdata.getAsByteArray(), Constants.DEFAULT_ENCODING).equals(identifier))
-                  {
-                     props.add(prop);
-                  }
-               }
-               catch (IllegalStateException e)
-               {
-                  // property was not added, force read from lower layer
-                  return null;
-               }
-               catch (IOException e)
-               {
-                  // property was not added, force read from lower layer
-                  return null;
-               }
-            }
-         }
-         return props;
-      }
-      else
-      {
-         return null;
-      }
+      return getReferencedProperties.run(identifier);
    }
    
    /**
@@ -1236,4 +1282,23 @@
          }
       };
    }
+
+   /**
+    * Actions that are not supposed to be called within a transaction
+    * 
+    * Created by The eXo Platform SAS
+    * Author : Nicolas Filotto 
+    *          nicolas.filotto at exoplatform.com
+    * 21 janv. 2010
+    */
+   protected abstract class CacheActionNonTxAware<R, A> extends ActionNonTxAware<R, A, RuntimeException>
+   {
+      /**
+       * {@inheritDoc}
+       */
+      protected TransactionManager getTransactionManager()
+      {
+         return ISPNCacheWorkspaceStorageCache.this.getTransactionManager();
+      }
+   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -110,68 +110,84 @@
       CompressedChangesBuffer changesContainer = getChangesBufferSafe();
       try
       {
-         //log.info("Before=" + changesContainer.toString());
-         //Collections.sort(changesContainer);
-         List<ChangesContainer> containers = changesContainer.getSortedList();
-         //log.info("After=" + changesContainer.toString());
-         for (ChangesContainer cacheChange : containers)
+         final List<ChangesContainer> containers = changesContainer.getSortedList();
+         PrivilegedAction<Void> action = new PrivilegedAction<Void>()
          {
-            boolean isTxCreated = false;
-            try
+            public Void run()
             {
-               if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
-               {
-                  // No tx exists so we create a new tx
-                  if (LOG.isTraceEnabled()) LOG.trace("No Tx is active we then create a new tx");
-                  tm.begin();
-                  isTxCreated = true;
-               }
+               commitChanges(containers);
+               return null;
             }
-            catch (Exception e)
+         };
+         AccessController.doPrivileged(action);         
+      }
+      finally
+      {
+         changesList.set(null);
+         changesContainer = null;
+      }
+   }   
+
+   /**
+    * @param containers
+    */
+   private void commitChanges(List<ChangesContainer> containers)
+   {
+      for (ChangesContainer cacheChange : containers)
+      {
+         boolean isTxCreated = false;
+         try
+         {
+            if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
             {
-               LOG.warn("Could not create a new tx", e);
+               // No tx exists so we create a new tx
+               if (LOG.isTraceEnabled())
+                  LOG.trace("No Tx is active we then create a new tx");
+               tm.begin();
+               isTxCreated = true;
             }
-            try
-            {
-               cacheChange.apply();
-            }
-            catch (RuntimeException e)
-            {
-               if (isTxCreated)
-               {
-                  try
-                  {
-                     if (LOG.isTraceEnabled()) LOG.trace("An error occurs the tx will be rollbacked");
-                     tm.rollback();
-                  }
-                  catch (Exception e1)
-                  {
-                     LOG.warn("Could not rollback the tx", e1);
-                  }
-               }
-               throw e;
-            }
+         }
+         catch (Exception e)
+         {
+            LOG.warn("Could not create a new tx", e);
+         }
+         try
+         {
+            cacheChange.apply();
+         }
+         catch (RuntimeException e)
+         {
             if (isTxCreated)
             {
                try
                {
-                  if (LOG.isTraceEnabled()) LOG.trace("The tx will be committed");
-                  tm.commit();
+                  if (LOG.isTraceEnabled())
+                     LOG.trace("An error occurs the tx will be rollbacked");
+                  tm.rollback();
                }
-               catch (Exception e)
+               catch (Exception e1)
                {
-                  LOG.warn("Could not commit the tx", e);
+                  LOG.warn("Could not rollback the tx", e1);
                }
             }
+            throw e;
          }
+         if (isTxCreated)
+         {
+            try
+            {
+               if (LOG.isTraceEnabled())
+                  LOG.trace("The tx will be committed");
+               tm.commit();
+            }
+            catch (Exception e)
+            {
+               LOG.warn("Could not commit the tx", e);
+            }
+         }
       }
-      finally
-      {
-         changesList.set(null);
-         changesContainer = null;
-      }
    }
-
+   
    /**
     * Tries to get buffer and if it is null throws an exception otherwise returns buffer. 
     * 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -49,6 +49,7 @@
 import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory.CacheType;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
+import org.exoplatform.services.transaction.ActionNonTxAware;
 import org.exoplatform.services.transaction.TransactionService;
 import org.jboss.cache.Cache;
 import org.jboss.cache.CacheStatus;
@@ -73,7 +74,6 @@
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 
 /**
@@ -165,7 +165,234 @@
    protected final Fqn<String> childPropsList;
 
    protected final Fqn<String> rootFqn;
+   
+   private final CacheActionNonTxAware<Void, Void> commitTransaction = new CacheActionNonTxAware<Void, Void>()
+   {
+      @Override
+      protected Void execute(Void arg) throws RuntimeException
+      {
+         cache.commitTransaction();
+         return null;
+      }
+   };
 
+   private final CacheActionNonTxAware<ItemData, String> getFromCacheById =
+      new CacheActionNonTxAware<ItemData, String>()
+      {
+         @Override
+         protected ItemData execute(String id) throws RuntimeException
+         {
+            return getFromCacheById(id);
+         }
+      };
+
+   private final CacheActionNonTxAware<List<NodeData>, NodeData> getChildNodes =
+      new CacheActionNonTxAware<List<NodeData>, NodeData>()
+      {
+         @Override
+         protected List<NodeData> execute(NodeData parent) throws RuntimeException
+         {
+            // empty Set<Object> marks that there is no child nodes
+            // get list of children uuids
+            final Set<Object> set =
+               (Set<Object>)cache.get(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST);
+            if (set != null)
+            {
+               final List<NodeData> childs = new ArrayList<NodeData>();
+
+               for (Object child : set)
+               {
+                  NodeData node = (NodeData)cache.get(makeItemFqn((String)child), ITEM_DATA);
+
+                  if (node == null || node instanceof NullItemData)
+                  {
+                     return null;
+                  }
+
+                  childs.add(node);
+               }
+
+               // order children by orderNumber, as HashSet returns children in other order
+               Collections.sort(childs, new NodesOrderComparator<NodeData>());
+
+               return childs;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+
+   private final CacheActionNonTxAware<ItemData, Object> getFromCacheByPath =
+      new CacheActionNonTxAware<ItemData, Object>()
+      {
+         @Override
+         protected ItemData execute(Object... args) throws RuntimeException
+         {
+            String parentId = (String)args[0];
+            QPathEntry name = (QPathEntry)args[1];
+            ItemType itemType = (ItemType)args[2];
+            String itemId = null;
+
+            if (itemType == ItemType.UNKNOWN)
+            {
+               // Try as node first.
+               itemId = (String)cache.get(makeChildFqn(childNodes, parentId, name), ITEM_ID);
+
+               if (itemId == null || itemId.equals(NullItemData.NULL_ID))
+               {
+                  // node with such a name is not found or marked as not-exist, so check the properties
+                  String propId = (String)cache.get(makeChildFqn(childProps, parentId, name), ITEM_ID);
+                  if (propId != null)
+                  {
+                     itemId = propId;
+                  }
+               }
+            }
+            else if (itemType == ItemType.NODE)
+            {
+               itemId = (String)cache.get(makeChildFqn(childNodes, parentId, name), ITEM_ID);
+            }
+            else
+            {
+               itemId = (String)cache.get(makeChildFqn(childProps, parentId, name), ITEM_ID);
+            }
+
+            if (itemId != null)
+            {
+               if (itemId.equals(NullItemData.NULL_ID))
+               {
+                  if (itemType == ItemType.UNKNOWN || itemType == ItemType.NODE)
+                  {
+                     return new NullNodeData();
+                  }
+                  else
+                  {
+                     return new NullPropertyData();
+                  }
+               }
+               else
+               {
+                  return get(itemId);
+               }
+            }
+            return null;
+         }
+      };
+
+   private final CacheActionNonTxAware<Integer, NodeData> getChildNodesCount =
+      new CacheActionNonTxAware<Integer, NodeData>()
+      {
+         @Override
+         protected Integer execute(NodeData parent) throws RuntimeException
+         {
+            // get list of children uuids
+            final Set<Object> set =
+               (Set<Object>)cache.get(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST);
+
+            return set != null ? set.size() : -1;
+         }
+      };
+      
+   private final CacheActionNonTxAware<List<PropertyData>, Object> getChildProps =
+      new CacheActionNonTxAware<List<PropertyData>, Object>()
+      {
+         @Override
+         protected List<PropertyData> execute(Object... args) throws RuntimeException
+         {
+            String parentId = (String)args[0];
+            boolean withValue = (Boolean)args[1];
+            // get set of property uuids
+            final Set<Object> set = (Set<Object>)cache.get(makeChildListFqn(childPropsList, parentId), ITEM_LIST);
+            if (set != null)
+            {
+               final List<PropertyData> childs = new ArrayList<PropertyData>();
+
+               for (Object child : set)
+               {
+                  PropertyData prop = (PropertyData)cache.get(makeItemFqn((String)child), ITEM_DATA);
+                  if (prop == null || prop instanceof NullItemData)
+                  {
+                     return null;
+                  }
+                  if (withValue && prop.getValues().size() <= 0)
+                  {
+                     // don't return list of empty-valued props (but listChildProperties() can)
+                     return null;
+                  }
+                  childs.add(prop);
+               }
+               return childs;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+     
+   private final CacheActionNonTxAware<List<PropertyData>, String> getReferencedProperties =
+      new CacheActionNonTxAware<List<PropertyData>, String>()
+      {
+         @Override
+         protected List<PropertyData> execute(String identifier) throws RuntimeException
+         {
+            // get set of property uuids
+            final Set<String> set = (Set<String>)cache.get(makeRefFqn(identifier), ITEM_LIST);
+            if (set != null)
+            {
+               final List<PropertyData> props = new ArrayList<PropertyData>();
+
+               for (String propId : set)
+               {
+                  PropertyData prop = (PropertyData)cache.get(makeItemFqn(propId), ITEM_DATA);
+                  if (prop == null || prop instanceof NullItemData)
+                  {
+                     return null;
+                  }
+
+                  // add property as many times as has referenced values
+                  List<ValueData> lData = prop.getValues();
+                  for (int i = 0, length = lData.size(); i < length; i++)
+                  {
+                     ValueData vdata = lData.get(i);
+                     try
+                     {
+                        if (new String(vdata.getAsByteArray(), Constants.DEFAULT_ENCODING).equals(identifier))
+                        {
+                           props.add(prop);
+                        }
+                     }
+                     catch (IllegalStateException e)
+                     {
+                        // Do not nothing.
+                     }
+                     catch (IOException e)
+                     {
+                        // Do not nothing.
+                     }
+                  }
+               }
+               return props;
+            }
+            else
+            {
+               return null;
+            }
+         }
+      };
+
+   private final CacheActionNonTxAware<Long, Void> getSize = new CacheActionNonTxAware<Long, Void>()
+   {
+      @Override
+      protected Long execute(Void arg) throws RuntimeException
+      {
+         // Total number of JBC nodes in the cache - the total amount of resident nodes
+         return numNodes(cache.getNode(rootFqn)) - 7;
+      }
+   };
+      
    /**
     * Indicates whether the cache has already been initialized or not
     */
@@ -683,60 +910,15 @@
     */
    public ItemData get(String parentId, QPathEntry name, ItemType itemType)
    {
-      String itemId = null;
-
-      if (itemType == ItemType.UNKNOWN)
-      {
-         // Try as node first.
-         itemId = (String)cache.get(makeChildFqn(childNodes, parentId, name), ITEM_ID);
-
-         if (itemId == null || itemId.equals(NullItemData.NULL_ID))
-         {
-            // node with such a name is not found or marked as not-exist, so check the properties
-            String propId = (String)cache.get(makeChildFqn(childProps, parentId, name), ITEM_ID);
-            if (propId != null)
-            {
-               itemId = propId;
-            }
-         }
-      }
-      else if (itemType == ItemType.NODE)
-      {
-         itemId = (String)cache.get(makeChildFqn(childNodes, parentId, name), ITEM_ID);
-      }
-      else
-      {
-         itemId = (String)cache.get(makeChildFqn(childProps, parentId, name), ITEM_ID);
-      }
-
-      if (itemId != null)
-      {
-         if (itemId.equals(NullItemData.NULL_ID))
-         {
-            if (itemType == ItemType.UNKNOWN || itemType == ItemType.NODE)
-            {
-               return new NullNodeData();
-            }
-            else
-            {
-               return new NullPropertyData();
-            }
-         }
-         else
-         {
-            return get(itemId);
-         }
-      }
-
-      return null;
+      return getFromCacheByPath.run(parentId, name, itemType);
    }
-
+   
    /**
     * {@inheritDoc}
     */
    public ItemData get(String id)
    {
-      return getFromCacheById(id);
+      return getFromCacheById.run(id);
    }
 
    /**
@@ -744,47 +926,15 @@
     */
    public List<NodeData> getChildNodes(final NodeData parent)
    {
-      // empty Set<Object> marks that there is no child nodes
-      // get list of children uuids
-      final Set<Object> set =
-         (Set<Object>)cache.get(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST);
-      if (set != null)
-      {
-         final List<NodeData> childs = new ArrayList<NodeData>();
-
-         for (Object child : set)
-         {
-            NodeData node = (NodeData)cache.get(makeItemFqn((String)child), ITEM_DATA);
-
-            if (node == null || node instanceof NullItemData)
-            {
-               return null;
-            }
-
-            childs.add(node);
-         }
-
-         // order children by orderNumber, as HashSet returns children in other order
-         Collections.sort(childs, new NodesOrderComparator<NodeData>());
-
-         return childs;
-      }
-      else
-      {
-         return null;
-      }
+      return getChildNodes.run(parent);
    }
-
+   
    /**
     * {@inheritDoc}
     */
    public int getChildNodesCount(NodeData parent)
    {
-      // get list of children uuids
-      final Set<Object> set =
-         (Set<Object>)cache.get(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST);
-
-      return set != null ? set.size() : -1;
+      return getChildNodesCount.run(parent);
    }
 
    /**
@@ -802,54 +952,13 @@
    {
       return getChildProps(parent.getIdentifier(), false);
    }
-
+   
    /**
     * {@inheritDoc}
     */
    public List<PropertyData> getReferencedProperties(String identifier)
    {
-      // get set of property uuids
-      final Set<String> set = (Set<String>)cache.get(makeRefFqn(identifier), ITEM_LIST);
-      if (set != null)
-      {
-         final List<PropertyData> props = new ArrayList<PropertyData>();
-
-         for (String propId : set)
-         {
-            PropertyData prop = (PropertyData)cache.get(makeItemFqn(propId), ITEM_DATA);
-            if (prop == null || prop instanceof NullItemData)
-            {
-               return null;
-            }
-
-            // add property as many times as has referenced values
-            List<ValueData> lData = prop.getValues();
-            for (int i = 0, length = lData.size(); i < length; i++)
-            {
-               ValueData vdata = lData.get(i);
-               try
-               {
-                  if (new String(vdata.getAsByteArray(), Constants.DEFAULT_ENCODING).equals(identifier))
-                  {
-                     props.add(prop);
-                  }
-               }
-               catch (IllegalStateException e)
-               {
-                  // Do not nothing.
-               }
-               catch (IOException e)
-               {
-                  // Do not nothing.
-               }
-            }
-         }
-         return props;
-      }
-      else
-      {
-         return null;
-      }
+      return getReferencedProperties.run(identifier);
    }
 
    /**
@@ -894,41 +1003,15 @@
     */
    protected List<PropertyData> getChildProps(String parentId, boolean withValue)
    {
-      // get set of property uuids
-      final Set<Object> set = (Set<Object>)cache.get(makeChildListFqn(childPropsList, parentId), ITEM_LIST);
-      if (set != null)
-      {
-         final List<PropertyData> childs = new ArrayList<PropertyData>();
-
-         for (Object child : set)
-         {
-            PropertyData prop = (PropertyData)cache.get(makeItemFqn((String)child), ITEM_DATA);
-            if (prop == null || prop instanceof NullItemData)
-            {
-               return null;
-            }
-            if (withValue && prop.getValues().size() <= 0)
-            {
-               // don't return list of empty-valued props (but listChildProperties() can)
-               return null;
-            }
-            childs.add(prop);
-         }
-         return childs;
-      }
-      else
-      {
-         return null;
-      }
+      return getChildProps.run(parentId, withValue);
    }
-
+   
    /**
     * {@inheritDoc}
     */
    public long getSize()
    {
-      // Total number of JBC nodes in the cache - the total amount of resident nodes
-      return numNodes(cache.getNode(rootFqn)) - 7;
+      return getSize.run();
    }
 
    /**
@@ -1531,7 +1614,7 @@
    private enum ModifyChildOption {
       NOT_MODIFY, MODIFY, FORCE_MODIFY
    }
-
+   
    /**
     * Allows to commit the cache changes in a dedicated XA Tx in order to avoid potential
     * deadlocks
@@ -1540,37 +1623,7 @@
    {
       // Ensure that the commit is done in a dedicated tx to avoid deadlock due
       // to global XA Tx
-      TransactionManager tm = getTransactionManager();
-      Transaction tx = null;
-      try
-      {
-         if (tm != null)
-         {
-            try
-            {
-               tx = tm.suspend();
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot suspend the current transaction", e);
-            }
-         }
-         cache.commitTransaction();
-      }
-      finally
-      {
-         if (tx != null)
-         {
-            try
-            {
-               tm.resume(tx);
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot resume the current transaction", e);
-            }
-         }
-      }
+      commitTransaction.run();
    }
 
    /**
@@ -1662,4 +1715,23 @@
          createResidentNode(itemsRoot);
       }
    }
+   
+   /**
+    * Actions that are not supposed to be called within a transaction
+    * 
+    * Created by The eXo Platform SAS
+    * Author : Nicolas Filotto 
+    *          nicolas.filotto at exoplatform.com
+    * 21 janv. 2010
+    */
+   protected abstract class CacheActionNonTxAware<R, A> extends ActionNonTxAware<R, A, RuntimeException>
+   {
+      /**
+       * @see org.exoplatform.services.transaction.ActionNonTxAware#getTransactionManager()
+       */
+      protected TransactionManager getTransactionManager()
+      {
+         return JBossCacheWorkspaceStorageCache.this.getTransactionManager();
+      }
+   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -33,8 +33,6 @@
 import org.exoplatform.services.jcr.impl.dataflow.persistent.LocalWorkspaceDataManagerStub;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
-import org.exoplatform.services.transaction.TransactionException;
-import org.exoplatform.services.transaction.TransactionResource;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -49,7 +47,7 @@
  * @author Gennady Azarenkov
  * @version $Id: TransactionableDataManager.java 11907 2008-03-13 15:36:21Z ksm $
  */
-public class TransactionableDataManager implements TransactionResource, DataManager
+public class TransactionableDataManager implements DataManager
 {
 
    // use LocalWorkspaceDataManagerStub, otherwise JVM will use save(ItemStateChangesLog changes) instead of
@@ -60,22 +58,14 @@
 
    private TransactionChangesLog transactionLog;
 
+   private SessionImpl session;
+   
    public TransactionableDataManager(LocalWorkspaceDataManagerStub dataManager, SessionImpl session)
       throws RepositoryException
    {
       super();
+      this.session = session;
       this.storageDataManager = dataManager;
-
-      // TODO EXOJCR-272
-      //      try
-      //      {
-      //         this.storageDataManager = new LocalWorkspaceStorageDataManagerProxy(dataManager, session.getValueFactory());
-      //      }
-      //      catch (Exception e1)
-      //      {
-      //         String infoString = "[Error of read value factory: " + e1.getMessage() + "]";
-      //         throw new RepositoryException(infoString);
-      //      }
    }
 
    // --------------- ItemDataConsumer --------
@@ -309,9 +299,9 @@
    // --------------- --------
 
    /**
-    * {@inheritDoc}
+    * Initializes the tx changes log
     */
-   public void start()
+   void start()
    {
       if (LOG.isDebugEnabled())
       {
@@ -325,47 +315,23 @@
    }
 
    /**
-    * {@inheritDoc}
+    * Re move a given changes log
     */
-   public void commit() throws TransactionException
+   void removeLog(PlainChangesLog log)
    {
-      if (txStarted())
-      {
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("tx commit() " + this + "\n" + transactionLog.dump());
-         }
-
-         try
-         {
-            TransactionChangesLog tl = transactionLog;
-            transactionLog = null;
-            storageDataManager.save(tl);
-         }
-         catch (InvalidItemStateException e)
-         {
-            throw new TransactionException(e.getMessage(), e);
-         }
-         catch (RepositoryException e)
-         {
-            throw new TransactionException(e.getMessage(), e);
-         }
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void rollback()
-   {
       if (LOG.isDebugEnabled())
       {
-         LOG.debug("tx rollback() " + this + (transactionLog != null ? "\n" + transactionLog.dump() : "[NULL]"));
+         LOG.debug("tx removeLog() " + this + (transactionLog != null ? "\n" + transactionLog.dump() : "[NULL]"));
       }
 
       if (txStarted())
       {
-         transactionLog = null;
+         transactionLog.removeLog(log);
+         if (transactionLog.getSize() == 0)
+         {
+            // Clear tx changes log if there is no log left
+            transactionLog = null;
+         }
       }
    }
 
@@ -388,12 +354,14 @@
             + (statesLog != null ? "\n" + statesLog.dump() : "[NULL]") + "=====================");
       }
 
-      if (txStarted())
+      if (session.canEnrollChangeToGlobalTx(statesLog))
       {
+         // Save within a global tx
          transactionLog.addLog(statesLog);
       }
       else
       {
+         // Regular save
          storageDataManager.save(new TransactionChangesLog(statesLog));
       }
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManager.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManager.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -18,237 +18,882 @@
  */
 package org.exoplatform.services.jcr.impl.dataflow.session;
 
-import org.exoplatform.services.jcr.impl.core.XASessionImpl;
-import org.exoplatform.services.transaction.TransactionException;
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.LocalWorkspaceDataManagerStub;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.transaction.TransactionService;
 
 import java.lang.ref.SoftReference;
-import java.util.Iterator;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentLinkedQueue;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import javax.jcr.RepositoryException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
 import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
 
 /**
  * Created by The eXo Platform SAS.
  * <p/>
- * Manager provides consistency of transaction operations performed by same user but in different
- * Repository Sessions.
+ * Used to perform an atomic prepare/commit/rollback between all the JCR sessions tied
+ * to the current transaction
  * <p/>
- * Manager stores list of XASessions involved in transaction by a user and then can be used to
- * broadcast transaction start/commit/rollback to all live Sessions of the user.
- * <p/>
- * Broadcast of operations it's an atomic operation regarding to the Sessions list. Until operation
- * broadcast request is active other requests or list modifications will wait for.
- * <p/>
  * 
  * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
  * @version $Id: TransactionableResourceManager.java 34801 2009-07-31 15:44:50Z dkatayev $
  */
-public class TransactionableResourceManager
+public class TransactionableResourceManager implements XAResource
 {
 
    /**
-    * XASessions involved in transaction. Sessions stored by userId.
+    * Logger.
     */
-   private ConcurrentHashMap<String, ConcurrentLinkedQueue<SoftReference<XASessionImpl>>> txResources =
-      new ConcurrentHashMap<String, ConcurrentLinkedQueue<SoftReference<XASessionImpl>>>();
+   private static Log log = ExoLogger.getLogger("exo.jcr.component.core.TransactionableResourceManager");
 
    /**
+    * Sessions involved in transaction. 
+    */
+   private final ThreadLocal<TransactionContext> contexts = new ThreadLocal<TransactionContext>();
+
+   /**
+    * Transaction manager.
+    */
+   private final TransactionManager tm;
+
+   /**
+    * The eXo container in which the TransactionableResourceManager has been registered
+    */
+   private final ExoContainer container;
+
+   /**
+    * The data manager
+    */
+   private volatile LocalWorkspaceDataManagerStub workspaceDataManager;
+
+   /**
+    * The current tx timeout in seconds
+    */
+   private int txTimeout;
+
+   /**
     * TransactionableResourceManager constructor.
     */
-   public TransactionableResourceManager()
+   public TransactionableResourceManager(ExoContainerContext ctx)
    {
+      this(ctx, null);
    }
 
    /**
-    * Add session to the transaction group.
-    * 
-    * @param userSession
-    *          XASessionImpl, user XASession
+    * TransactionableResourceManager constructor.
     */
-   public void add(XASessionImpl userSession)
+   public TransactionableResourceManager(ExoContainerContext ctx, TransactionService tService)
    {
-      final ConcurrentLinkedQueue<SoftReference<XASessionImpl>> joinedList = txResources.get(userSession.getUserID());
-      if (joinedList != null)
+      this.tm = tService == null ? null : tService.getTransactionManager();
+      this.container = ctx.getContainer();
+   }
+
+   /**
+    * Lazily gets the LocalWorkspaceDataManagerStub from the eXo container. This is required to
+    * prevent cyclic dependency
+    */
+   private LocalWorkspaceDataManagerStub getWorkspaceDataManager()
+   {
+      if (workspaceDataManager == null)
       {
-         // remove unused session from user list and put this list at the end
-         // threads of same user
-         for (Iterator<SoftReference<XASessionImpl>> siter = joinedList.iterator(); siter.hasNext();)
+         synchronized (this)
          {
-            XASessionImpl xaSession = siter.next().get();
-            if (xaSession == null || !xaSession.isLive())
+            if (workspaceDataManager == null)
             {
-               siter.remove();
+               LocalWorkspaceDataManagerStub workspaceDataManager =
+                  (LocalWorkspaceDataManagerStub)container
+                     .getComponentInstanceOfType(LocalWorkspaceDataManagerStub.class);
+               if (workspaceDataManager == null)
+               {
+                  throw new IllegalStateException("The workspace data manager cannot be found");
+               }
+               this.workspaceDataManager = workspaceDataManager;
             }
          }
+      }
+      return workspaceDataManager;
+   }
 
-         joinedList.add(new SoftReference<XASessionImpl>(userSession));
+   /**
+    * Indicates whether a global tx is active or not
+    * @return <code>true</code> if a global tx is active, <code>false</code> otherwise.
+    */
+   public boolean isGlobalTxActive()
+   {
+      TransactionContext ctx;
+      return (ctx = contexts.get()) != null && ctx.getXidContext() != null;
+   }
 
-         // make sure the list is not removed by another Session of same user, see
-         // remove()
-         txResources.putIfAbsent(userSession.getUserID(), joinedList);
-      }
-      else
+   /**
+    * Checks if a global Tx has been started if so the session and its change will be dynamically enrolled
+    * @param session the session to enlist in case a Global Tx has been started
+    * @param changes the changes to enlist in case a Global Tx has been started 
+    * @return <code>true</code> if a global Tx has been started and the session and its change could
+    * be enrolled successfully, <code>false</code> otherwise
+    */
+   public boolean canEnrollChangeToGlobalTx(final SessionImpl session, final PlainChangesLog changes)
+   {
+      try
       {
-         // sync for same userId operations
-         final ConcurrentLinkedQueue<SoftReference<XASessionImpl>> newJoinedList =
-            new ConcurrentLinkedQueue<SoftReference<XASessionImpl>>();
-         final ConcurrentLinkedQueue<SoftReference<XASessionImpl>> previous =
-            txResources.putIfAbsent(userSession.getUserID(), newJoinedList);
-         if (previous != null)
+         if (tm != null && session.isLive() && tm.getStatus() == Status.STATUS_ACTIVE)
          {
-            previous.add(new SoftReference<XASessionImpl>(userSession));
+            SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Void>()
+            {
+               public Void run() throws Exception
+               {
+                  add(session, changes);
+                  return null;
+               }
+            });
+            return true;
          }
-         else
-         {
-            newJoinedList.add(new SoftReference<XASessionImpl>(userSession));
-         }
       }
+      catch (Exception e)
+      {
+         log.warn("Could not check if a global Tx has been started or register the session into the resource manager",
+            e);
+      }
+      return false;
    }
 
    /**
-    * Remove session from user Sessions list.
-    * 
-    * @param userSession
-    *          XASessionImpl, user XASession
+    * Add a new listener to register to the current tx
+    * @param listener the listener to add
     */
-   public void remove(XASessionImpl userSession)
+   public void addListener(TransactionableResourceManagerListener listener)
    {
-      final ConcurrentLinkedQueue<SoftReference<XASessionImpl>> joinedList = txResources.get(userSession.getUserID());
-      if (joinedList != null)
+      TransactionContext ctx = contexts.get();
+      if (ctx == null)
       {
-         // traverse and remove unused sessions and given one
-         // threads of same user
-         for (Iterator<SoftReference<XASessionImpl>> siter = joinedList.iterator(); siter.hasNext();)
-         {
-            XASessionImpl xaSession = siter.next().get();
-            if (xaSession == null || !xaSession.isLive() || xaSession == userSession)
-            {
-               siter.remove();
-            }
-         }
-
-         // if list is empty - remove mapping to the list
-         if (joinedList.size() <= 0)
-         {
-            txResources.remove(userSession.getUserID());
-         }
+         throw new IllegalStateException("There is no active transaction context");
       }
+      XidContext xidCtx = ctx.getXidContext();
+      if (xidCtx == null)
+      {
+         throw new IllegalStateException("There is no active xid context");
+      }
+      xidCtx.addListener(listener);
    }
 
    /**
-    * Commit all sessions.
+    * Add session to the transaction group.
     * 
     * @param userSession
-    *          XASessionImpl, commit initializing session
-    * @throws TransactionException
-    *           Transaction error
+    *          SessionImpl, user Session
+    * @throws SystemException 
+    * @throws RollbackException 
+    * @throws IllegalStateException 
     */
-   public void commit(XASessionImpl userSession, boolean onePhase) throws TransactionException
+   private void add(SessionImpl session, PlainChangesLog changes) throws SystemException, IllegalStateException,
+      RollbackException
    {
-      ConcurrentLinkedQueue<SoftReference<XASessionImpl>> joinedList;
-      if (onePhase)
+      Transaction tx = tm.getTransaction();
+      if (tx == null)
       {
-         joinedList = txResources.remove(userSession.getUserID());
+         // No active tx so there is no need to register the session
+         return;
       }
-      else
+      // Get the current TransactionContext
+      TransactionContext ctx = getOrCreateTransactionContext();
+      // Register the tx if it has not been done already
+      ctx.registerTransaction(tx);
+      // Register the given changes
+      ctx.add(session, changes);
+   }
+
+   /**
+    * Gives the current {@link TransactionContext} from the ThreadLocal and create it doesn't exist
+    */
+   private TransactionContext getOrCreateTransactionContext()
+   {
+      TransactionContext ctx = contexts.get();
+      if (ctx == null)
       {
-         // TODO keep session on commit to be able to rollback all via XASessions(XAResource) and TM lifecycle
-         joinedList = txResources.get(userSession.getUserID());
+         // No transaction context exists so we create a new one
+         ctx = new TransactionContext();
+         contexts.set(ctx);
       }
+      return ctx;
+   }
 
-      if (joinedList != null)
+   /**
+    * This synchronization is used to apply all changes before commit phase and it is also used to execute actions once the tx is completed
+    * which is necessary in case we use non tx aware resources like the lucene indexes and the observation
+    * @author <a href="mailto:nfilotto at exoplatform.com">Nicolas Filotto</a>
+    * @version $Id$
+    *
+    */
+   private class TransactionableResourceManagerSynchronization implements Synchronization
+   {
+      private final Xid xid;
+
+      /**
+       * Indicates whether or not there is another after completion method to call
+       */
+      private final AtomicBoolean isLastAfterCompletion = new AtomicBoolean(true);
+
+      public TransactionableResourceManagerSynchronization(Xid xid)
       {
-         Iterator<SoftReference<XASessionImpl>> it = joinedList.iterator();
-         boolean hasCommitedXASession = false;
+         this.xid = xid;
+      }
+
+      /**
+       * @see javax.transaction.Synchronization#beforeCompletion()
+       */
+      public void beforeCompletion()
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("BeforeCompletion Xid:" + xid + ": " + this);
+         }
+         TransactionContext ctx = contexts.get();
+         if (ctx == null)
+         {
+            if (log.isDebugEnabled())
+            {
+               log.debug("Could not find the context");
+            }
+            return;
+         }
+         else
+         {
+            // define the current branch id
+            ctx.setXid(xid);
+         }
+         Map<PlainChangesLog, SessionImpl> changes = ctx.getChanges(xid);
+         if (changes == null || changes.isEmpty())
+         {
+            if (log.isDebugEnabled())
+            {
+               log.debug("There is no change to apply");
+            }
+            return;
+         }
          try
          {
-            while (it.hasNext())
+            TransactionChangesLog allChanges = new TransactionChangesLog();
+            for (Map.Entry<PlainChangesLog, SessionImpl> entry : changes.entrySet())
             {
-               SoftReference<XASessionImpl> sr = it.next();
-               XASessionImpl xaSession = sr.get();
-               if (xaSession != null && xaSession.isLive())
+               SessionImpl session = entry.getValue();
+               // first check if the tx was not too long
+               if (session.hasExpired())
                {
-                  xaSession.getTransientNodesManager().getTransactManager().commit();
+                  // at least one session has expired so we abort the tx
+                  throw new RepositoryException("The tx was too long, at least one session has expired.");
                }
-               hasCommitedXASession = true;
+               // Add the change following the chronology order
+               allChanges.addLog(entry.getKey());
             }
+            getWorkspaceDataManager().save(allChanges);
          }
-         catch (TransactionException e)
+         catch (RepositoryException e)
          {
-            if (onePhase)
+            log.error("Could not apply changes", e);
+            setRollbackOnly();
+            return;
+         }
+         // Since between 2 TM implementations the afterCompletion can be called in the same 
+         // order as the synchronization order or in the reverse order, so we add a second synchronization
+         // such that the afterCompletion method will be called in the second call
+         try
+         {
+            tm.getTransaction().registerSynchronization(new Synchronization()
             {
-               // rollback now
-               while (it.hasNext())
+
+               public void beforeCompletion()
                {
-                  SoftReference<XASessionImpl> sr = it.next();
-                  XASessionImpl xaSession = sr.get();
-                  if (xaSession != null && xaSession.isLive())
-                  {
-                     xaSession.getTransientNodesManager().getTransactManager().rollback();
-                  }
                }
 
-               if (hasCommitedXASession)
+               public void afterCompletion(int status)
                {
-                  // somethings were commited already
-                  throw new TransactionException(XAException.XA_HEURMIX, e);
+                  TransactionableResourceManagerSynchronization.this.afterCompletion(status);
                }
-               else
+            });
+            // Indicates that there is at least one after completion method to come
+            isLastAfterCompletion.set(false);
+         }
+         catch (Exception e)
+         {
+            log.error("Could not register the second synchronization", e);
+         }
+      }
+
+      /**
+       * @see javax.transaction.Synchronization#afterCompletion(int)
+       */
+      public void afterCompletion(int status)
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("AfterCompletion Xid:" + xid + ", " + status + ", " + isLastAfterCompletion.get() + ": " + this);
+         }
+         if (!isLastAfterCompletion.get())
+         {
+            isLastAfterCompletion.set(true);
+            return;
+         }
+         TransactionContext ctx = contexts.get();
+         if (ctx == null)
+         {
+            if (log.isDebugEnabled())
+            {
+               log.debug("Could not find the context");
+            }
+            return;
+         }
+         XidContext xidCtx = ctx.getXidContext(xid);
+         if (xidCtx == null)
+         {
+            if (log.isDebugEnabled())
+            {
+               log.debug("Could not find the xid context");
+            }
+            return;
+         }
+         try
+         {
+            List<TransactionableResourceManagerListener> listeners = xidCtx.getListeners();
+            for (int i = 0, length = listeners.size(); i < length; i++)
+            {
+               TransactionableResourceManagerListener listener = listeners.get(i);
+               try
                {
-                  // all things were rolled back
-                  throw new TransactionException(XAException.XA_HEURRB, e);
+                  listener.onAfterCompletion(status);
                }
+               catch (Exception e)
+               {
+                  log.error("Could not execute the method onAfterCompletion for the status " + status, e);
+               }
             }
 
-            throw new TransactionException(XAException.XA_RBOTHER, e);
+            Map<PlainChangesLog, SessionImpl> changes = xidCtx.getMapChanges();
+            if (changes != null && !changes.isEmpty())
+            {
+               for (Map.Entry<PlainChangesLog, SessionImpl> entry : changes.entrySet())
+               {
+                  SessionImpl session = entry.getValue();
+                  TransactionableDataManager txManager = session.getTransientNodesManager().getTransactManager();
+                  // Remove the change from the tx change log. Please not that a simple reset cannot
+                  // be done since the session could be enrolled in several tx, so each change need to
+                  // be scoped to a given xid
+                  txManager.removeLog(entry.getKey());
+               }
+            }
          }
+         finally
+         {
+            ctx.remove(xid);
+         }
       }
    }
 
    /**
-    * Start transaction on all sessions.
-    * 
-    * @param userSession
-    *          XASessionImpl, start initializing session
+    * @see javax.transaction.xa.XAResource#commit(javax.transaction.xa.Xid, boolean)
     */
-   public void start(XASessionImpl userSession)
+   public void commit(Xid xid, boolean onePhase) throws XAException
    {
-      ConcurrentLinkedQueue<SoftReference<XASessionImpl>> joinedList = txResources.get(userSession.getUserID());
-      if (joinedList != null)
+      if (log.isDebugEnabled())
       {
-         for (SoftReference<XASessionImpl> sr : joinedList)
+         log.debug("Commit. Xid:" + xid + ", onePhase: " + onePhase + ": " + this);
+      }
+      TransactionContext ctx = contexts.get();
+      if (ctx == null)
+      {
+         if (log.isDebugEnabled())
          {
-            XASessionImpl xaSession = sr.get();
-            if (xaSession != null && xaSession.isLive())
+            log.debug("Could not find the context");
+         }
+         return;
+      }
+      XidContext xidCtx = ctx.getXidContext(xid);
+      if (xidCtx != null)
+      {
+         boolean failed = false;
+         List<TransactionableResourceManagerListener> listeners = xidCtx.getListeners();
+         for (int i = 0, length = listeners.size(); i < length; i++)
+         {
+            TransactionableResourceManagerListener listener = listeners.get(i);
+            try
             {
-               TransactionableDataManager txManager = xaSession.getTransientNodesManager().getTransactManager();
-               txManager.start();
+               listener.onCommit(onePhase);
             }
+            catch (Exception e)
+            {
+               log.error("Could not execute the method onCommit(" + onePhase + ")", e);
+               failed = true;
+               break;
+            }
          }
+         if (failed)
+         {
+            if (onePhase)
+            {
+               // In case of one phase commit, we are supposed to roll back the branch
+               abort(listeners);
+               throw new XAException(XAException.XA_RBROLLBACK);
+            }
+            throw new XAException(XAException.XAER_RMERR);
+         }
       }
    }
 
    /**
-    * Rollback transaction on all sessions.
+    * @see javax.transaction.xa.XAResource#end(javax.transaction.xa.Xid, int)
+    */
+   public void end(Xid xid, int flags) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("End. Xid:" + xid + ", " + flags + ": " + this);
+      }
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#forget(javax.transaction.xa.Xid)
+    */
+   public void forget(Xid xid) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("Forget. Xid:" + xid + ": " + this);
+      }
+      abort(xid);
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#getTransactionTimeout()
+    */
+   public int getTransactionTimeout() throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("GetTransactionTimeout. : " + this);
+      }
+      return txTimeout;
+   }
+
+   /**
+    * @return the transaction timeout in milliseconds
+    */
+   private long getTransactionTimeoutMillis()
+   {
+      return txTimeout * 1000L;
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#isSameRM(javax.transaction.xa.XAResource)
+    */
+   public boolean isSameRM(XAResource xares) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("IsSameRM. XAResource:" + xares + ": " + this);
+      }
+
+      // We have one XAResource per workspace
+      return xares == this;
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#prepare(javax.transaction.xa.Xid)
+    */
+   public int prepare(Xid xid) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("Prepare. Xid:" + xid + ": " + this);
+      }
+
+      return XA_OK;
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#recover(int)
+    */
+   public Xid[] recover(int flag) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("Recover. flag:" + flag + ": " + this);
+      }
+      return new Xid[0];
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#rollback(javax.transaction.xa.Xid)
+    */
+   public void rollback(Xid xid) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("Rollback. Xid:" + xid + ": " + this);
+      }
+      abort(xid);
+   }
+
+   /**
+    * @param xid
+    */
+   private void abort(Xid xid) throws XAException
+   {
+      TransactionContext ctx = contexts.get();
+      if (ctx == null)
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("Could not find the context");
+         }
+         return;
+      }
+      XidContext xidCtx = ctx.getXidContext(xid);
+      if (xidCtx != null)
+      {
+         List<TransactionableResourceManagerListener> listeners = xidCtx.getListeners();
+         abort(listeners);
+      }
+   }
+
+   /**
+    * Call the method onAbort on all the given listeners
     * 
-    * @param userSession
-    *          XASessionImpl, rollback initializing session
+    * @param listeners all the listeners on which we need to call the onAbort method
+    * @throws XAException if an error occurs while calling one of the onAbort methods
     */
-   public void rollback(XASessionImpl userSession)
+   private void abort(List<TransactionableResourceManagerListener> listeners) throws XAException
    {
-      ConcurrentLinkedQueue<SoftReference<XASessionImpl>> joinedList = txResources.remove(userSession.getUserID());
-      if (joinedList != null)
+      boolean exception = false;
+      for (int i = 0, length = listeners.size(); i < length; i++)
       {
-         for (SoftReference<XASessionImpl> sr : joinedList)
+         TransactionableResourceManagerListener listener = listeners.get(i);
+         try
          {
-            XASessionImpl xaSession = sr.get();
-            if (xaSession != null && xaSession.isLive())
+            listener.onAbort();
+         }
+         catch (Exception e)
+         {
+            log.error("Could not execute the method onAbort", e);
+            exception = true;
+         }
+      }
+      if (exception)
+      {
+         throw new XAException(XAException.XAER_RMERR);
+      }
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#setTransactionTimeout(int)
+    */
+   public boolean setTransactionTimeout(int txTimeout) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("SetTransactionTimeout. " + txTimeout + ": " + this);
+      }
+      this.txTimeout = txTimeout;
+      // Set the new timeout on the current sessions
+      TransactionContext ctx = contexts.get();
+      if (ctx == null)
+      {
+         if (log.isDebugEnabled())
+         {
+            log.debug("Could not find the context");
+         }
+         return true;
+      }
+      Set<SessionImpl> sessions = ctx.getSessions();
+      if (sessions != null)
+      {
+         for (SessionImpl session : sessions)
+         {
+            session.setTimeout(getTransactionTimeoutMillis());
+         }
+      }
+      return true;
+   }
+
+   /**
+    * @see javax.transaction.xa.XAResource#start(javax.transaction.xa.Xid, int)
+    */
+   public void start(Xid xid, int flags) throws XAException
+   {
+      if (log.isDebugEnabled())
+      {
+         log.debug("Start. Xid:" + xid + ", " + flags + ": " + this);
+      }
+      // Get the current TransactionContext
+      TransactionContext ctx = getOrCreateTransactionContext();
+      // define the current branch id
+      ctx.setXid(xid);
+   }
+
+   /**
+    * Change the status of the tx to 'rollback-only'
+    */
+   private void setRollbackOnly()
+   {
+      try
+      {
+         tm.getTransaction().setRollbackOnly();
+      }
+      catch (Exception e)
+      {
+         log.warn("Could not set the status of the tx to 'rollback-only'", e);
+      }
+   }
+
+   private class TransactionContext
+   {
+      /**
+       * The soft reference of the current tx
+       */
+      private SoftReference<Transaction> srTx;
+
+      /**
+       * The soft reference of the current branch id
+       */
+      private SoftReference<Xid> srXid;
+
+      /**
+       * The the current contexts stored by Xid
+       */
+      private Map<Xid, XidContext> xidContexts;
+
+      /**
+       * This method registers the current tx if it is a new one, and if so
+       * enlist the resource.
+       * @param tx the current tx
+       * @throws SystemException
+       * @throws IllegalStateException
+       * @throws RollbackException
+       */
+      public void registerTransaction(Transaction tx) throws SystemException, IllegalStateException, RollbackException
+      {
+         if (!tx.equals(getTransaction()))
+         {
+            // The current tx has changed
+            // We store the new current tx
+            setTransaction(tx);
+            // We enlist the resource to get the new branch id
+            tx.enlistResource(TransactionableResourceManager.this);
+         }
+      }
+
+      public XidContext getXidContext()
+      {
+         // Get the current Xid from context
+         Xid xid = getXid();
+         if (xid == null || xidContexts == null)
+         {
+            return null;
+         }
+         return xidContexts.get(xid);
+      }
+
+      public XidContext getXidContext(Xid xid)
+      {
+         if (xid == null || xidContexts == null)
+         {
+            return null;
+         }
+         return xidContexts.get(xid);
+      }
+
+      public Map<PlainChangesLog, SessionImpl> getChanges(Xid xid)
+      {
+         XidContext ctx = getXidContext(xid);
+         if (ctx == null)
+         {
+            return null;
+         }
+         return ctx.getMapChanges();
+      }
+
+      private void setTransaction(Transaction tx)
+      {
+         srTx = new SoftReference<Transaction>(tx);
+      }
+
+      public Transaction getTransaction()
+      {
+         return srTx == null ? null : srTx.get();
+      }
+
+      public void setXid(Xid xid)
+      {
+         srXid = new SoftReference<Xid>(xid);
+      }
+
+      private Xid getXid()
+      {
+         return srXid == null ? null : srXid.get();
+      }
+
+      public Set<SessionImpl> getSessions()
+      {
+         // Get the current Xid from context
+         Xid xid = getXid();
+         if (xid == null)
+         {
+            return null;
+         }
+         return getSessions(xid);
+      }
+
+      private Set<SessionImpl> getSessions(Xid xid)
+      {
+         Map<PlainChangesLog, SessionImpl> changes = getChanges(xid);
+         return changes == null ? null : new HashSet<SessionImpl>(changes.values());
+      }
+
+      /**
+       * Add the given session and changes to the transaction context.
+       * @param session the session to add to the transaction context
+       * @param changes the session to add to the transaction context
+       * @throws IllegalStateException
+       * @throws RollbackException
+       * @throws SystemException
+       */
+      public void add(SessionImpl session, PlainChangesLog changes) throws IllegalStateException, RollbackException,
+         SystemException
+      {
+         if (xidContexts == null)
+         {
+            // No xid context has been defined, so we create a new one
+            this.xidContexts = new WeakHashMap<Xid, XidContext>();
+         }
+         // Get the current Xid from context
+         Xid xid = getXid();
+         if (xid == null)
+         {
+            throw new IllegalStateException("Threre is no active branch");
+         }
+         // Retrieve the corresponding sub-context
+         XidContext ctx = xidContexts.get(xid);
+         if (ctx == null)
+         {
+            // No sub-context for this xid, we then create a new context
+            ctx = new XidContext();
+            xidContexts.put(xid, ctx);
+            boolean registered = false;
+            try
             {
-               TransactionableDataManager txManager = xaSession.getTransientNodesManager().getTransactManager();
-               txManager.rollback();
+               // since it is a new branch we can register the corresponding synchronization
+               getTransaction().registerSynchronization(new TransactionableResourceManagerSynchronization(xid));
+               registered = true;
             }
+            finally
+            {
+               if (!registered)
+               {
+                  // if an error occurs automatically unregister the branch
+                  remove(xid);
+               }
+            }
          }
+         if (txTimeout > 0)
+         {
+            // Set the timeout
+            session.setTimeout(getTransactionTimeoutMillis());
+         }
+         if (changes != null)
+         {
+            // Add the changes and the session to the context
+            ctx.put(changes, session);
+            // Start the transaction mode
+            session.getTransientNodesManager().getTransactManager().start();
+         }
       }
+
+      public void remove(Xid xid)
+      {
+         if (xidContexts != null)
+         {
+            xidContexts.remove(xid);
+            if (xidContexts.isEmpty())
+            {
+               // There is not xid context anymore
+               // Remove the context from the TL
+               contexts.set(null);
+            }
+         }
+      }
    }
+
+   /**
+    * This class encapsulate all the information related to a given Xid
+    * @author <a href="mailto:nfilotto at exoplatform.com">Nicolas Filotto</a>
+    * @version $Id$
+    *
+    */
+   private static class XidContext
+   {
+      /**
+       * The list of all the existing listeners
+       */
+      private final List<TransactionableResourceManagerListener> listeners =
+         new ArrayList<TransactionableResourceManagerListener>();
+
+      /**
+       * The map of all changes
+       */
+      private final Map<PlainChangesLog, SessionImpl> mapChanges = new LinkedHashMap<PlainChangesLog, SessionImpl>();
+
+      /**
+       * @return the listeners
+       */
+      public List<TransactionableResourceManagerListener> getListeners()
+      {
+         return listeners;
+      }
+
+      /**
+       * @param listener the listener to add to the list of listeners
+       */
+      public void addListener(TransactionableResourceManagerListener listener)
+      {
+         listeners.add(listener);
+      }
+
+      /**
+       * @return the mapChanges
+       */
+      public Map<PlainChangesLog, SessionImpl> getMapChanges()
+      {
+         return mapChanges;
+      }
+
+      /**
+       * Register changes for a given session
+       * @param changes the changes to add
+       * @param session the session related to the changes
+       */
+      public void put(PlainChangesLog changes, SessionImpl session)
+      {
+         mapChanges.put(changes, session);
+      }
+   }
 }

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManagerListener.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManagerListener.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableResourceManagerListener.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * 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.exoplatform.services.jcr.impl.dataflow.session;
+
+
+/**
+ * Allows to be execute actions when an event occurs at {@link TransactionableResourceManager}
+ * level
+ * 
+ * @author <a href="mailto:nfilotto at exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ *
+ */
+public interface TransactionableResourceManagerListener
+{
+   /**
+    * This method is called within the commit method of the TransactionableResourceManager
+    * @param onePhase indicates whether it is one phase commit or not
+    * @throws Exception if an error occurs
+    */
+   void onCommit(boolean onePhase) throws Exception;
+   
+   /**
+    * This method is called within the abort method of the TransactionableResourceManager
+    * @throws Exception if an error occurs
+    */
+   void onAbort() throws Exception;
+   
+   /**
+    * This method is called within the afterCompletion method of the TransactionableResourceManager
+    * @param status the status of the tx
+    * @throws Exception if an error occurs
+    */
+   void onAfterCompletion(int status) throws Exception;
+}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -62,6 +62,7 @@
 import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
 import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
 import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+import org.exoplatform.services.jdbc.DataSourceProvider;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.naming.InitialContextInitializer;
@@ -84,7 +85,6 @@
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
-import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.sql.DataSource;
 
@@ -153,7 +153,11 @@
    protected final String dbUserName;
 
    protected final String dbPassword;
+   
+   protected final DataSourceProvider dsProvider;
 
+   protected final boolean isManaged;
+
    protected final ValueStoragePluginProvider valueStorageProvider;
 
    protected String storageVersion;
@@ -238,7 +242,9 @@
     * @param wsConfig
     *          Workspace configuration
     * @param valueStrorageProvider
-    *          External Value Stprages provider
+    *          External Value Storages provider
+    * @param dsProvider
+    *          The data source provider
     * @throws RepositoryConfigurationException
     *           if Repository configuration is wrong
     * @throws NamingException
@@ -246,7 +252,7 @@
     */
    public JDBCWorkspaceDataContainer(WorkspaceEntry wsConfig, RepositoryEntry repConfig,
       InitialContextInitializer contextInit, ValueStoragePluginProvider valueStorageProvider,
-      FileCleanerHolder fileCleanerHolder) throws RepositoryConfigurationException, NamingException,
+      FileCleanerHolder fileCleanerHolder, DataSourceProvider dsProvider) throws RepositoryConfigurationException, NamingException,
       RepositoryException, IOException
    {
 
@@ -260,7 +266,8 @@
       this.uniqueName = wsConfig.getUniqueName();
       this.multiDb = Boolean.parseBoolean(wsConfig.getContainer().getParameterValue(MULTIDB));
       this.valueStorageProvider = valueStorageProvider;
-
+      this.dsProvider = dsProvider;
+      
       // ------------- Database config ------------------
       String pDbDialect = null;
       try
@@ -304,6 +311,8 @@
          this.dbUserName = pDbUserName;
          this.dbPassword = pDbPassword;
          this.dbSourceName = null;
+         // A managed data source is only possible when the source name is not null
+         this.isManaged = false;
          LOG.info("Connect to JCR database as user '" + this.dbUserName + "'");
 
          if (pDbDialect == DBConstants.DB_DIALECT_GENERIC || DBConstants.DB_DIALECT_AUTO.equalsIgnoreCase(pDbDialect))
@@ -360,49 +369,48 @@
             // remove in rel.2.0
          }
          this.dbSourceName = sn;
+         if (dsProvider == null)
+         {
+            throw new IllegalArgumentException("Since a data source has been defined, the DataSourceProvider cannot be null, add it in your configuration.");
+         }
+         // the data source cannot be managed if there is no transaction manager
+         this.isManaged = dsProvider.isManaged(dbSourceName);
 
          if (pDbDialect == DBConstants.DB_DIALECT_GENERIC)
          {
             // try to detect via JDBC metadata
-            final DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
+            final DataSource ds = getDataSource();
+            Connection jdbcConn = null;
+            try
             {
-               Connection jdbcConn = null;
-               try
+               jdbcConn = SecurityHelper.doPrivilegedSQLExceptionAction(new PrivilegedExceptionAction<Connection>()
                {
-                  jdbcConn = SecurityHelper.doPrivilegedSQLExceptionAction(new PrivilegedExceptionAction<Connection>()
+                  public Connection run() throws Exception
                   {
-                     public Connection run() throws Exception
-                     {
-                        return ds.getConnection();
-                     }
-                  });
+                     return ds.getConnection();
+                  }
+               });
 
-                  this.dbDialect = DialectDetecter.detect(jdbcConn.getMetaData());
-               }
-               catch (SQLException e)
+               this.dbDialect = DialectDetecter.detect(jdbcConn.getMetaData());
+            }
+            catch (SQLException e)
+            {
+               throw new RepositoryException(e);
+            }
+            finally
+            {
+               if (jdbcConn != null)
                {
-                  throw new RepositoryException(e);
-               }
-               finally
-               {
-                  if (jdbcConn != null)
+                  try
                   {
-                     try
-                     {
-                        jdbcConn.close();
-                     }
-                     catch (SQLException e)
-                     {
-                        throw new RepositoryException(e);
-                     }
+                     jdbcConn.close();
                   }
+                  catch (SQLException e)
+                  {
+                     throw new RepositoryException(e);
+                  }
                }
             }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
          }
          else
          {
@@ -475,7 +483,7 @@
    }
 
    /**
-    * Prepare sefault connection factory.
+    * Prepare default connection factory.
     * 
     * @return GenericConnectionFactory
     * @throws NamingException
@@ -488,14 +496,8 @@
       // by default
       if (dbSourceName != null)
       {
-         DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-         if (ds != null)
-         {
-            return new GenericConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-               swapDirectory, swapCleaner);
-         }
-
-         throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+         return new GenericConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+            swapDirectory, swapCleaner);
       }
 
       return new GenericConnectionFactory(dbDriver, dbUrl, dbUserName, dbPassword, containerName, multiDb,
@@ -677,17 +679,9 @@
          // [PN] 28.06.07
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new MySQLConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new MySQLConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -704,17 +698,9 @@
          // [PN] 13.07.08
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new MySQLConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new MySQLConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -768,17 +754,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new HSQLDBConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new HSQLDBConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -905,7 +883,7 @@
    {
       String str =
          "JDBC based JCR Workspace Data container \n" + "container name: " + containerName + " \n"
-            + "data source JNDI name: " + dbSourceName + "\n" + "is multi database: " + multiDb + "\n"
+            + (isManaged ? "managed " : "") + "data source JNDI name: " + dbSourceName + "\n" + "is multi database: " + multiDb + "\n"
             + "storage version: " + storageVersion + "\n" + "value storage provider: " + valueStorageProvider + "\n"
             + "max buffer size (bytes): " + maxBufferSize + "\n" + "swap directory path: "
             + PrivilegedFileHelper.getAbsolutePath(swapDirectory);
@@ -1423,4 +1401,20 @@
    {
       return connFactory.isReindexingSupport();
    }
+   
+   /**
+    * Get the data source from the InitialContext and wraps it into a {@link ManagedDataSource}
+    * in case it has been configured as managed
+    */
+   protected DataSource getDataSource() throws RepositoryException
+   {
+      try
+      {
+         return dsProvider.getDataSource(dbSourceName);
+      }
+      catch (NamingException e)
+      {
+         throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.", e);
+      }
+   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -39,15 +39,14 @@
 import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
 import org.exoplatform.services.jcr.impl.util.jdbc.DBInitializerException;
 import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+import org.exoplatform.services.jdbc.DataSourceProvider;
 import org.exoplatform.services.naming.InitialContextInitializer;
 import org.picocontainer.Startable;
 
 import java.io.IOException;
 
 import javax.jcr.RepositoryException;
-import javax.naming.InitialContext;
 import javax.naming.NamingException;
-import javax.sql.DataSource;
 
 /**
  * Created by The eXo Platform SAS.
@@ -64,7 +63,9 @@
     * @param wsConfig
     *          Workspace configuration
     * @param valueStrorageProvider
-    *          External Value Stprages provider
+    *          External Value Storages provider
+    * @param dsProvider
+    *          The data source provider
     * @throws RepositoryConfigurationException
     *           if Repository configuration is wrong
     * @throws NamingException
@@ -72,12 +73,11 @@
     */
    public CQJDBCWorkspaceDataContainer(WorkspaceEntry wsConfig, RepositoryEntry repConfig,
       InitialContextInitializer contextInit, ValueStoragePluginProvider valueStorageProvider,
-      FileCleanerHolder fileCleanerHolder) throws RepositoryConfigurationException, NamingException,
+      FileCleanerHolder fileCleanerHolder, DataSourceProvider dsProvider) throws RepositoryConfigurationException, NamingException,
       RepositoryException, IOException
    {
-      super(wsConfig, repConfig, contextInit, valueStorageProvider, fileCleanerHolder);
+      super(wsConfig, repConfig, contextInit, valueStorageProvider, fileCleanerHolder, dsProvider);
    }
-
    /**
     * Init storage database.
     * 
@@ -100,13 +100,9 @@
          // sample of connection factory customization
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-               this.connFactory =
-                  new DefaultOracleConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner, useQueryHints);
-            else
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+            this.connFactory =
+               new DefaultOracleConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner, useQueryHints);
          }
          else
             this.connFactory =
@@ -123,13 +119,9 @@
 
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-               this.connFactory =
-                  new DefaultOracleConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner, useQueryHints);
-            else
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+            this.connFactory =
+               new DefaultOracleConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner, useQueryHints);
          }
          else
             this.connFactory =
@@ -150,13 +142,9 @@
          // [PN] 28.06.07
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-               this.connFactory =
-                  new MySQLConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            else
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+            this.connFactory =
+               new MySQLConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
             this.connFactory =
@@ -171,13 +159,9 @@
          // [PN] 13.07.08
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-               this.connFactory =
-                  new MySQLConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            else
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+            this.connFactory =
+               new MySQLConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
             this.connFactory =
@@ -191,17 +175,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new MSSQLConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new MSSQLConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -223,17 +199,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new DB2ConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new DB2ConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -249,17 +217,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new DB2ConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new DB2ConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -275,17 +235,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-            {
-               this.connFactory =
-                  new SybaseConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            }
-            else
-            {
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
-            }
+            this.connFactory =
+               new SybaseConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
          {
@@ -309,13 +261,9 @@
       {
          if (dbSourceName != null)
          {
-            DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-            if (ds != null)
-               this.connFactory =
-                  new HSQLDBConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-                     swapDirectory, swapCleaner);
-            else
-               throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+            this.connFactory =
+               new HSQLDBConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+                  swapDirectory, swapCleaner);
          }
          else
             this.connFactory =
@@ -358,12 +306,8 @@
       // by default
       if (dbSourceName != null)
       {
-         DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
-         if (ds != null)
-            return new GenericCQConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
-               swapDirectory, swapCleaner);
-
-         throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+         return new GenericCQConnectionFactory(getDataSource(), containerName, multiDb, valueStorageProvider, maxBufferSize,
+            swapDirectory, swapCleaner);
       }
 
       return new GenericCQConnectionFactory(dbDriver, dbUrl, dbUserName, dbPassword, containerName, multiDb,

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/ActionNonTxAware.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/ActionNonTxAware.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/ActionNonTxAware.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * 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.exoplatform.services.transaction;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.security.PrivilegedExceptionAction;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * This class describes all the actions that are not supposed to be called
+ * within a transaction
+ * 
+ * @author <a href="mailto:nfilotto at exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ *
+ */
+public abstract class ActionNonTxAware<R, A, E extends Exception>
+{
+   /**
+    * The logger
+    */
+   protected Log LOG = ExoLogger.getLogger("exo.jcr.component.core.ActionNonTxAware");
+   
+   /**
+    * Executes the action outside the context of the current tx
+    * @param arg the argument to use to execute the action
+    * @return the result of the action
+    * @throws E if an error occurs while executing the action
+    */
+   public R run(A... arg) throws E
+   {
+      final TransactionManager tm = getTransactionManager();
+      Transaction tx = null;
+      try
+      {
+         if (tm != null)
+         {
+            try
+            {
+               tx = SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Transaction>()
+               {
+                  public Transaction run() throws Exception
+                  {
+                     return tm.suspend();
+                  }
+               });
+            }
+            catch (Exception e)
+            {
+               LOG.warn("Cannot suspend the current transaction", e);
+            }
+         }
+         return execute(arg);
+      }
+      finally
+      {
+         if (tx != null)
+         {
+            try
+            {
+               final Transaction privilegedTx = tx;
+               SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Object>()
+               {
+                  public Object run() throws Exception
+                  {
+                     tm.resume(privilegedTx);
+                     return null;
+                  }
+               });
+            }
+            catch (Exception e)
+            {
+               LOG.warn("Cannot resume the current transaction", e);
+            }
+         }
+      }      
+   }
+   
+   /**
+    * Executes the action outside the context of the current tx. This
+    * method is equivalent to {@link ActionNonTxAware#run(Object)} but
+    * with <tt>null</tt> as parameter.
+    * @return the result of the action
+    * @throws E if an error occurs while executing the action
+    */
+   public R run() throws E
+   {
+      return run((A[])null);     
+   }   
+   
+   /**
+    * Executes the action
+    * @param arg the argument to use to execute the action
+    * @return the result of the action
+    * @throws E if an error occurs while executing the action
+    */
+   protected R execute(A... arg) throws E
+   {
+      if (arg == null || arg.length == 0)
+      {
+         return execute((A)null);
+      }
+      return execute(arg[0]);
+   }
+   
+   /**
+    * Executes the action
+    * @param arg the argument to use to execute the action
+    * @return the result of the action
+    * @throws E if an error occurs while executing the action
+    */
+   protected R execute(A arg) throws E
+   {
+      return null;
+   }
+   
+   /**
+    * Gives the Transaction Manager that will be used while executing the action
+    * @return the {@link TransactionManager} to use
+    */
+   protected abstract TransactionManager getTransactionManager();
+}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/GenericTransactionService.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/GenericTransactionService.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/GenericTransactionService.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -18,67 +18,25 @@
  */
 package org.exoplatform.services.transaction.jbosscache;
 
-import org.exoplatform.commons.utils.SecurityHelper;
 import org.exoplatform.container.xml.InitParams;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-import org.exoplatform.services.transaction.ExoResource;
-import org.exoplatform.services.transaction.TransactionService;
+import org.exoplatform.services.transaction.impl.AbstractTransactionService;
 import org.jboss.cache.transaction.TransactionManagerLookup;
 
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
-import javax.transaction.UserTransaction;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
 
 /**
  * @author <a href="mailto:dmitry.kataev at exoplatform.com">Dmytro Katayev</a>
  * @version $Id: GenericTransactionService.java -1   $
  */
-public class GenericTransactionService implements TransactionService
+public class GenericTransactionService extends AbstractTransactionService
 {
-   /**
-    * The logger 
-    */
-   private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.GenericTransactionService");
 
    /**
-    * The default value of a transaction timeout in seconds
-    */
-   private static final int DEFAULT_TIME_OUT = 60;
-
-   /**
     * TransactionManagerLookup.
     */
    protected final TransactionManagerLookup tmLookup;
 
    /**
-    * The default timeout
-    */
-   protected final int defaultTimeout;
-
-   /**
-    * Indicates if the timeout has to be enforced
-    */
-   protected final boolean forceTimeout;
-
-   /**
-    * The current Transaction Manager
-    */
-   private volatile TransactionManager tm;
-
-   /**
     * JBossTransactionManagerLookup  constructor.
     *
     * @param tmLookup TransactionManagerLookup
@@ -90,539 +48,15 @@
 
    public GenericTransactionService(TransactionManagerLookup tmLookup, InitParams params)
    {
+      super(params);
       this.tmLookup = tmLookup;
-      if (params != null && params.getValueParam("timeout") != null)
-      {
-         this.defaultTimeout = Integer.parseInt(params.getValueParam("timeout").getValue());
-         this.forceTimeout = true;
-      }
-      else
-      {
-         this.defaultTimeout = DEFAULT_TIME_OUT;
-         this.forceTimeout = false;
-      }
    }
 
    /**
     * {@inheritDoc}
     */
-   public Xid createXid()
+   public TransactionManager findTransactionManager() throws Exception
    {
-      throw new UnsupportedOperationException("Method createXid() not supported");
+      return tmLookup.getTransactionManager();
    }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void delistResource(final ExoResource exores) throws RollbackException, SystemException
-   {
-      TransactionManager tm = getTransactionManager();
-      final Transaction tx = tm.getTransaction();
-      if (tx != null)
-      {
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tx.delistResource(exores.getXAResource(), XAResource.TMNOFLAGS);
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-
-            if (cause instanceof RollbackException)
-            {
-               throw (RollbackException)cause;
-            }
-            else if (cause instanceof IllegalStateException)
-            {
-               throw (IllegalStateException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-      else
-      {
-         delistResourceOnTxMissing(tm, exores);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void enlistResource(final ExoResource exores) throws RollbackException, SystemException
-   {
-      TransactionManager tm = getTransactionManager();
-      final Transaction tx = tm.getTransaction();
-      if (tx != null)
-      {
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tx.enlistResource(exores.getXAResource());
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-
-            if (cause instanceof RollbackException)
-            {
-               throw (RollbackException)cause;
-            }
-            else if (cause instanceof IllegalStateException)
-            {
-               throw (IllegalStateException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-      else
-      {
-         enlistResourceOnTxMissing(tm, exores);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public int getDefaultTimeout()
-   {
-      return defaultTimeout;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public TransactionManager getTransactionManager()
-   {
-      if (tm == null)
-      {
-         synchronized (this)
-         {
-            if (tm == null)
-            {
-               TransactionManager tm;
-               try
-               {
-                  tm = SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<TransactionManager>()
-                  {
-                     public TransactionManager run() throws Exception
-                     {
-                        return tmLookup.getTransactionManager();
-                     }
-                  });
-               }
-               catch (Exception e)
-               {
-                  throw new RuntimeException("Transaction manager not found", e);
-               }
-               if (forceTimeout)
-               {
-                  // Only set the timeout when a timeout has been given into the
-                  // configuration otherwise we assume that the value will be
-                  // set at the AS level
-                  tm = new TransactionManagerTxTimeoutAware(tm, defaultTimeout);
-               }
-               this.tm = tm;
-            }
-         }
-      }
-      return tm;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public UserTransaction getUserTransaction()
-   {
-      throw new UnsupportedOperationException("Method UserTransaction() not supported");
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void setTransactionTimeout(int seconds) throws SystemException
-   {
-      TransactionManager tm = getTransactionManager();
-      tm.setTransactionTimeout(seconds);
-   }
-
-   /**
-    * Allows to execute an action when we try to enlist a resource when there is no active 
-    * transaction
-    */
-   protected void enlistResourceOnTxMissing(TransactionManager tm, ExoResource exores) throws RollbackException,
-      SystemException
-   {
-   }
-
-   /**
-    * Allows to execute an action when we try to delist a resource when there is no active 
-    * transaction
-    */
-   protected void delistResourceOnTxMissing(TransactionManager tm, ExoResource exores) throws RollbackException,
-      SystemException
-   {
-   }
-
-   /**
-    * This class is used to enforce the {@link Transaction} timeout when a new transaction 
-    * is created through the nested {@link TransactionManager}
-    * 
-    * Created by The eXo Platform SAS
-    * Author : Nicolas Filotto 
-    *          nicolas.filotto at exoplatform.com
-    * 1 f�vr. 2010
-    */
-   private static class TransactionManagerTxTimeoutAware implements TransactionManager
-   {
-      /**
-       * The nested {@link TransactionManager}
-       */
-      private final TransactionManager tm;
-
-      /**
-       * The default timeout of the {@link Transaction}
-       */
-      private final int defaultTimeout;
-
-      /**
-       * This is used to know if a timeout has already been set for the next transaction
-       */
-      private final ThreadLocal<Boolean> timeoutHasBeenSet = new ThreadLocal<Boolean>();
-
-      public TransactionManagerTxTimeoutAware(TransactionManager tm, int defaultTimeout)
-      {
-         this.tm = tm;
-         this.defaultTimeout = defaultTimeout;
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void begin() throws NotSupportedException, SystemException
-      {
-         if (timeoutHasBeenSet.get() != null)
-         {
-            // clean the ThreadLocal
-            timeoutHasBeenSet.set(null);
-         }
-         else
-         {
-            try
-            {
-               // Set the default transaction timeout
-               tm.setTransactionTimeout(defaultTimeout);
-            }
-            catch (Exception e)
-            {
-               LOG.warn("Cannot set the transaction timeout", e);
-            }
-         }
-
-         // Start the transaction
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tm.begin();
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof NotSupportedException)
-            {
-               throw (NotSupportedException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
-         SecurityException, IllegalStateException, SystemException
-      {
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tm.commit();
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof RollbackException)
-            {
-               throw (RollbackException)cause;
-            }
-            else if (cause instanceof HeuristicMixedException)
-            {
-               throw (HeuristicMixedException)cause;
-            }
-            else if (cause instanceof HeuristicRollbackException)
-            {
-               throw (HeuristicRollbackException)cause;
-            }
-            else if (cause instanceof SecurityException)
-            {
-               throw (SecurityException)cause;
-            }
-            else if (cause instanceof IllegalStateException)
-            {
-               throw (IllegalStateException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public int getStatus() throws SystemException
-      {
-         return tm.getStatus();
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public Transaction getTransaction() throws SystemException
-      {
-         try
-         {
-            return SecurityHelper.doPrivilegedExceptionAction(new PrivilegedExceptionAction<Transaction>()
-            {
-               public Transaction run() throws Exception
-               {
-                  return tm.getTransaction();
-               }
-            });
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void resume(final Transaction tx) throws InvalidTransactionException, IllegalStateException,
-         SystemException
-      {
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tm.resume(tx);
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof InvalidTransactionException)
-            {
-               throw (InvalidTransactionException)cause;
-            }
-            else if (cause instanceof IllegalStateException)
-            {
-               throw (IllegalStateException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void rollback() throws IllegalStateException, SecurityException, SystemException
-      {
-         PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
-         {
-            public Object run() throws Exception
-            {
-               tm.rollback();
-               return null;
-            }
-         };
-         try
-         {
-            AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof IllegalStateException)
-            {
-               throw (IllegalStateException)cause;
-            }
-            else if (cause instanceof SecurityException)
-            {
-               throw (SecurityException)cause;
-            }
-            else if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void setRollbackOnly() throws IllegalStateException, SystemException
-      {
-         tm.setRollbackOnly();
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public void setTransactionTimeout(int timeout) throws SystemException
-      {
-         tm.setTransactionTimeout(timeout);
-         timeoutHasBeenSet.set(true);
-      }
-
-      /**
-       * {@inheritDoc}
-       */
-      public Transaction suspend() throws SystemException
-      {
-         PrivilegedExceptionAction<Transaction> action = new PrivilegedExceptionAction<Transaction>()
-         {
-            public Transaction run() throws Exception
-            {
-               return tm.suspend();
-            }
-         };
-         try
-         {
-            return AccessController.doPrivileged(action);
-         }
-         catch (PrivilegedActionException pae)
-         {
-            Throwable cause = pae.getCause();
-            if (cause instanceof SystemException)
-            {
-               throw (SystemException)cause;
-            }
-            else if (cause instanceof RuntimeException)
-            {
-               throw (RuntimeException)cause;
-            }
-            else
-            {
-               throw new RuntimeException(cause);
-            }
-         }
-      }
-   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/JBossTransactionsService.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/JBossTransactionsService.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/transaction/jbosscache/JBossTransactionsService.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -18,16 +18,10 @@
  */
 package org.exoplatform.services.transaction.jbosscache;
 
-import com.arjuna.ats.jta.xa.XidImple;
-
 import org.exoplatform.container.xml.InitParams;
 import org.jboss.cache.transaction.TransactionManagerLookup;
 
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
 import javax.transaction.UserTransaction;
-import javax.transaction.xa.Xid;
 
 /**
  * Add the specific part for Arjuna
@@ -53,24 +47,8 @@
     * {@inheritDoc} 
     */
    @Override
-   public Xid createXid()
+   protected UserTransaction findUserTransaction() throws Exception
    {
-      return new XidImple();
+      return com.arjuna.ats.jta.UserTransaction.userTransaction();
    }
-
-   /**
-    * {@inheritDoc} 
-    */
-   @Override
-   public UserTransaction getUserTransaction()
-   {
-      PrivilegedAction<UserTransaction> action = new PrivilegedAction<UserTransaction>()
-      {
-         public UserTransaction run()
-         {
-            return com.arjuna.ats.jta.UserTransaction.userTransaction();
-         }
-      };
-      return AccessController.doPrivileged(action);
-   }
 }

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestUserTransaction.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestUserTransaction.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestUserTransaction.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -19,7 +19,6 @@
 package org.exoplatform.services.jcr.api.xa;
 
 import org.exoplatform.services.jcr.JcrAPIBaseTest;
-import org.exoplatform.services.jcr.core.XASession;
 import org.exoplatform.services.jcr.impl.core.SessionImpl;
 import org.exoplatform.services.transaction.TransactionService;
 
@@ -199,9 +198,6 @@
 
       ut.begin();
 
-      // In a case of reusing Have to enlist the resource once again!
-      ((XASession)s1).enlistResource();
-
       tx2.addNode("txcommit21");
       s1.save();
       ut.commit();
@@ -251,7 +247,6 @@
       catch (Exception e)
       {
          // ok
-         assertNotNull(((XASession) s1).getCommitException());
       }
 
       s1.logout();

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestXATransaction.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestXATransaction.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestXATransaction.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -19,20 +19,28 @@
 package org.exoplatform.services.jcr.api.xa;
 
 import org.exoplatform.services.jcr.JcrAPIBaseTest;
-import org.exoplatform.services.jcr.core.XASession;
 import org.exoplatform.services.transaction.TransactionService;
 
 import javax.jcr.LoginException;
 import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 import javax.jcr.lock.Lock;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
 import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
 
 /**
  * Created by The eXo Platform SAS. <br>
@@ -57,12 +65,11 @@
    public void testSimpleGlobalTransaction() throws Exception
    {
       assertNotNull(ts);
-      Xid id = ts.createXid();
-      XAResource xares = ((XASession)session).getXAResource();
-      xares.start(id, XAResource.TMNOFLAGS);
+      TransactionManager tm = ts.getTransactionManager();
+      tm.begin();
       session.getRootNode().addNode("txg1");
       session.save();
-      xares.commit(id, true);
+      tm.commit();
       Session s1 =
          repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName());
       assertNotNull(s1.getItem("/txg1"));
@@ -75,13 +82,12 @@
       Session s1 =
          repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName());
 
-      Xid id1 = ts.createXid();
-      XAResource xares = ((XASession)session).getXAResource();
-      xares.start(id1, XAResource.TMNOFLAGS);
+      TransactionManager tm = ts.getTransactionManager();
+      tm.begin();
 
       session.getRootNode().addNode("txg2");
       session.save();
-      // xares.commit(id, true);
+
       try
       {
          s1.getItem("/txg2");
@@ -90,10 +96,9 @@
       catch (PathNotFoundException e)
       {
       }
-      xares.end(id1, XAResource.TMSUSPEND);
+      Transaction tx = tm.suspend();
 
-      Xid id2 = ts.createXid();
-      xares.start(id2, XAResource.TMNOFLAGS);
+      tm.begin();
       session.getRootNode().addNode("txg3");
       session.save();
 
@@ -107,21 +112,119 @@
       }
 
       // End work
-      xares.end(id2, XAResource.TMSUCCESS);
+      tm.commit();
+      try
+      {
+         s1.getItem("/txg2");
+         fail("PathNotFoundException");
+      }
+      catch (PathNotFoundException e)
+      {
+      }
+      assertNotNull(s1.getItem("/txg3"));
 
       // Resume work with former transaction
-      xares.start(id1, XAResource.TMRESUME);
+      tm.resume(tx);
 
       // Commit work recorded when associated with xid2
-      xares.commit(id1, true);
-      // xares.commit(id2, true);
+      tm.commit();
+
       assertNotNull(s1.getItem("/txg2"));
       assertNotNull(s1.getItem("/txg3"));
+      
+      QueryManager manager = s1.getWorkspace().getQueryManager();
+      Query query = manager.createQuery("select * from nt:base where jcr:path = '/txg2'", Query.SQL);
+      QueryResult queryResult = query.execute();
+      assertNotNull(queryResult);
+      NodeIterator iter = queryResult.getNodes();
+      assertEquals(1, iter.getSize());
+      
+      query = manager.createQuery("select * from nt:base where jcr:path = '/txg3'", Query.SQL);
+      queryResult = query.execute();
+      assertNotNull(queryResult);
+      iter = queryResult.getNodes();
+      assertEquals(1, iter.getSize());      
+   }
 
+   public void test2GlobalTransactions2() throws Exception
+   {
+      assertNotNull(ts);
+      Session s1 =
+         repository.login(new SimpleCredentials("admin", "admin".toCharArray()), session.getWorkspace().getName());
+
+      TransactionManager tm = ts.getTransactionManager();
+      tm.begin();
+
+      session.getRootNode().addNode("txg2");
+      session.save();
+
+      try
+      {
+         s1.getItem("/txg2");
+         fail("PathNotFoundException");
+      }
+      catch (PathNotFoundException e)
+      {
+      }
+      Transaction tx = tm.suspend();
+
+      tm.begin();
+      session.getRootNode().addNode("txg3");
+      session.save();
+
+      try
+      {
+         s1.getItem("/txg3");
+         fail("PathNotFoundException");
+      }
+      catch (PathNotFoundException e)
+      {
+      }
+
+      // End work
+      tm.commit();
+      try
+      {
+         s1.getItem("/txg2");
+         fail("PathNotFoundException");
+      }
+      catch (PathNotFoundException e)
+      {
+      }
+      assertNotNull(s1.getItem("/txg3"));
+
+      // Resume work with former transaction
+      tm.resume(tx);
+
+      // Roll back work recorded when associated with xid2
+      tm.rollback();
+      
+      try
+      {
+         s1.getItem("/txg2");
+         fail("PathNotFoundException");
+      }
+      catch (PathNotFoundException e)
+      {
+      }
+      assertNotNull(s1.getItem("/txg3"));
+      
+      QueryManager manager = s1.getWorkspace().getQueryManager();
+      Query query = manager.createQuery("select * from nt:base where jcr:path = '/txg2'", Query.SQL);
+      QueryResult queryResult = query.execute();
+      assertNotNull(queryResult);
+      NodeIterator iter = queryResult.getNodes();
+      assertEquals(0, iter.getSize());
+      
+      query = manager.createQuery("select * from nt:base where jcr:path = '/txg3'", Query.SQL);
+      queryResult = query.execute();
+      assertNotNull(queryResult);
+      iter = queryResult.getNodes();
+      assertEquals(1, iter.getSize());
    }
-
+   
    public void testLockInTransactions() throws LoginException, NoSuchWorkspaceException, RepositoryException,
-      XAException
+      XAException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException
    {
       assertNotNull(ts);
       Session s1 =
@@ -133,9 +236,8 @@
       n1.addMixin("mix:lockable");
       session.getRootNode().save();
 
-      Xid id1 = ts.createXid();
-      XAResource xares = ((XASession)session).getXAResource();
-      xares.start(id1, XAResource.TMNOFLAGS);
+      TransactionManager tm = ts.getTransactionManager();
+      tm.begin();
 
       // lock node
       Lock lock = n1.lock(false, true);
@@ -145,11 +247,8 @@
 
       assertFalse(s2.getRootNode().getNode("testLock").isLocked());
 
-      // End work
-      xares.end(id1, XAResource.TMSUCCESS);
-
       // Commit work recorded when associated with xid2
-      xares.commit(id1, true);
+      tm.commit();
       assertTrue(s2.getRootNode().getNode("testLock").isLocked());
 
       n1.unlock();

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/storage/JDBCWDCTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/storage/JDBCWDCTest.java	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/storage/JDBCWDCTest.java	2011-05-23 07:39:32 UTC (rev 4402)
@@ -108,7 +108,7 @@
 
       container =
          new JDBCWorkspaceDataContainer(config, repositoryEntry, null, new StandaloneStoragePluginProvider(config,
-            holder), holder);
+            holder), holder, null);
 
       Properties logProps = new Properties();
       logProps.put("org.apache.commons.logging.simplelog.defaultlog", "debug");

Added: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jta.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jta.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/jta.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This document was created with Syntext Serna Free. -->
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.JTA">
+  <?dbhtml filename="ch-jta.html"?>
+
+  <title>JTA</title>
+
+  <para>eXo JCR supports the Java Transaction API out of the box. If a
+  <emphasis>TransactionService</emphasis> has been defined (refer to the
+  chapter about the TransactionService for more details) at session save, it
+  checks if a global transaction is active and if so, it automatically
+  enrolles the JCR session in the global transaction. If you intend to use a
+  managed data source, you will have to configure the service
+  <emphasis>DataSourceProvider</emphasis> (for more details please refer to
+  the corresponding chapter).</para>
+</chapter>

Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -129,6 +129,9 @@
   <xi:include href="jcr/statistics.xml"
               xmlns:xi="http://www.w3.org/2001/XInclude" />
               
+  <xi:include href="jcr/jta.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude" />
+
   <xi:include href="jcr/other/acl.xml"
               xmlns:xi="http://www.w3.org/2001/XInclude" />                            
               

Added: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/data-source-provider.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/data-source-provider.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/data-source-provider.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="Kernel.DataSourceProvider">
+  <?dbhtml filename="ch-data-source-provider.html"?>
+
+  <title>The data source provider</title>
+
+  <section>
+    <title>Description</title>
+
+    <para>The <emphasis>DataSourceProvider</emphasis> is a service used to
+    give access to a data source in an uniform manner in order to be able to
+    support data sources that are managed by the application server.</para>
+
+    <para><table>
+        <title>List methods</title>
+
+        <tgroup cols="2">
+          <tbody>
+            <row>
+              <entry>getDataSource(String dataSourceName)</entry>
+
+              <entry>Tries to get the data source from a JNDI lookup. If it
+              can be found and the data source is defined as managed, the
+              service will wrap the original <emphasis>DataSource</emphasis>
+              instance in a new <emphasis>DataSource</emphasis> instance that
+              is aware of its <emphasis>managed</emphasis> state otherwise it
+              will return the original <emphasis>DataSource</emphasis>
+              instance.</entry>
+            </row>
+
+            <row>
+              <entry>isManaged(String dataSourceName)</entry>
+
+              <entry>Indicates whether or not the given data source is
+              managed.</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table></para>
+  </section>
+
+  <section>
+    <title>Configuration</title>
+
+    <para>The configuration of the <emphasis>DataSourceProvider</emphasis>
+    should be defined only if you use managed data sources since by default
+    all the data sources are considered as not managed. See below the default
+    configuration</para>
+
+    <programlisting>&lt;configuration&gt;
+....  
+   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.jdbc.DataSourceProvider&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.jdbc.impl.DataSourceProviderImpl&lt;/type&gt;
+      &lt;init-params&gt;
+         &lt;!--  Indicates that the data source needs to check if a tx is active
+              to decide if the provided connection needs to be managed or not.
+              If it is set to false, the data source will provide only
+              managed connections if the data source itself is managed.  --&gt;
+         &lt;!--value-param&gt;
+            &lt;name&gt;check-tx-active&lt;/name&gt;
+            &lt;value&gt;true&lt;/value&gt;
+         &lt;/value-param--&gt;
+         &lt;!-- Indicates that all the data sources are managed 
+              If set to true the parameter never-managed and 
+              managed-data-sources will be ignored --&gt;
+         &lt;!--value-param&gt;
+            &lt;name&gt;always-managed&lt;/name&gt;
+            &lt;value&gt;true&lt;/value&gt;
+         &lt;/value-param--&gt;
+         &lt;!-- Indicates the list of all the data sources that are 
+              managed, each value tag can contain a list of
+              data source names separated by a comma, in the
+              example below we will register ds-foo1, ds-foo2 
+              and ds-foo3 as managed data source. If always-managed
+              and/or never-managed is set true this parameter is ignored --&gt;
+         &lt;!--values-param&gt;
+            &lt;name&gt;managed-data-sources&lt;/name&gt;
+            &lt;value&gt;ds-foo1, ds-foo2&lt;/value&gt;
+            &lt;value&gt;ds-foo3&lt;/value&gt;
+         &lt;/values-param--&gt;
+      &lt;/init-params&gt;
+   &lt;/component&gt;  
+...
+&lt;/configuration&gt;</programlisting>
+
+    <table>
+      <title>Fields description</title>
+
+      <tgroup cols="2">
+        <tbody>
+          <row>
+            <entry><emphasis>check-tx-active</emphasis></entry>
+
+            <entry>This parameter indicates that the data source needs to
+            check if a transaction is active to decide if the provided
+            connection needs to be managed or not. If it is set to
+            <emphasis>false</emphasis>, the data source will provide only
+            managed connections if the data source itself is managed. By
+            default, this parameter is set to <emphasis>true</emphasis>. If
+            this parameter is set to <emphasis>true</emphasis>, it will need
+            the <emphasis>TransactionService</emphasis> to work propertly, so
+            please ensure that the <emphasis>TransactionService</emphasis> is
+            defined in your configuration.</entry>
+          </row>
+
+          <row>
+            <entry><emphasis>always-managed</emphasis></entry>
+
+            <entry>This parameter indicates that all the data sources are
+            managed. If set to <emphasis>true</emphasis> the parameter
+            <emphasis>never-managed</emphasis> and
+            <emphasis>managed-data-sources</emphasis> will be ignored, so it
+            will consider all the data sources as managed. By default, this
+            parameter is set to <emphasis>false</emphasis>.</entry>
+          </row>
+
+          <row>
+            <entry><emphasis>managed-data-sources</emphasis></entry>
+
+            <entry>This parameter indicates the list of all the data sources
+            that are managed, each value tag can contain a list of data source
+            names separated by a comma. If <emphasis>always-managed</emphasis>
+            and/or <emphasis>never-managed</emphasis> is set
+            <emphasis>true</emphasis> this parameter is ignored.</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+  </section>
+</chapter>

Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel/transaction-service.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -1,65 +1,229 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<chapter id="Kernel.TransactionService">
-  <?dbhtml filename="ch-tranasction-service.html"?>
-
-  <title>TransactionService</title>
-
-  <section>
-    <title>Base information</title>
-
-    <para>TransactionServices provides acces to XA TransactionManager and
-    UserTransaction (See JTA specification for details).</para>
-
-    <table>
-      <title>List methods</title>
-
-      <tgroup cols="2">
-        <tbody>
-          <row>
-            <entry>getTransactionManager()</entry>
-
-            <entry>Get used TransactionManager</entry>
-          </row>
-
-          <row>
-            <entry>getUserTransaction()</entry>
-
-            <entry>Get UserTransaction on TransactionManager</entry>
-          </row>
-
-          <row>
-            <entry>getDefaultTimeout()</entry>
-
-            <entry>Return default TimeOut</entry>
-          </row>
-
-          <row>
-            <entry>setTransactionTimeout(int seconds)</entry>
-
-            <entry>Set TimeOut in second</entry>
-          </row>
-
-          <row>
-            <entry>enlistResource(ExoResource xares)</entry>
-
-            <entry>Enlist XA resource in TransactionManager</entry>
-          </row>
-
-          <row>
-            <entry>delistResource(ExoResource xares)</entry>
-
-            <entry>Delist XA resource from TransactionManager</entry>
-          </row>
-
-          <row>
-            <entry>createXid()</entry>
-
-            <entry>Creates unique XA transaction identifier.</entry>
-          </row>
-        </tbody>
-      </tgroup>
-    </table>
-  </section>
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="Kernel.TransactionService">
+  <?dbhtml filename="ch-tranasction-service.html"?>
+
+  <title>TransactionService</title>
+
+  <section>
+    <title>Base information</title>
+
+    <para>TransactionServices provides access to the TransactionManager and
+    the UserTransaction (See JTA specification for details).</para>
+
+    <table>
+      <title>List methods</title>
+
+      <tgroup cols="2">
+        <tbody>
+          <row>
+            <entry>getTransactionManager()</entry>
+
+            <entry>Get used TransactionManager</entry>
+          </row>
+
+          <row>
+            <entry>getUserTransaction()</entry>
+
+            <entry>Get UserTransaction on TransactionManager</entry>
+          </row>
+
+          <row>
+            <entry>getDefaultTimeout()</entry>
+
+            <entry>Return default TimeOut</entry>
+          </row>
+
+          <row>
+            <entry>setTransactionTimeout(int seconds)</entry>
+
+            <entry>Set TimeOut in second</entry>
+          </row>
+
+          <row>
+            <entry>enlistResource(XAResource xares)</entry>
+
+            <entry>Enlist XA resource in TransactionManager</entry>
+          </row>
+
+          <row>
+            <entry>delistResource(XAResource xares)</entry>
+
+            <entry>Delist XA resource from TransactionManager</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+  </section>
+
+  <section>
+    <title>Existing TransactionService implementations</title>
+
+    <para>eXo JCR proposes out of the box several implementations, they all
+    implement the abstract class
+    <emphasis>org.exoplatform.services.transaction.impl.AbstractTransactionService</emphasis>.
+    This main class implement the biggest part of all the methods proposed by
+    the <emphasis>TransactionService</emphasis>. For each sub-class of
+    <emphasis>AbstractTransactionService</emphasis>, you can set the
+    transaction timeout by configuration using the value parameter
+    <emphasis>timeout</emphasis> that is expressed in seconds. </para>
+
+    <section>
+      <title>JOTM in standalone mode</title>
+
+      <para>To use JOTM as TransactionManager in standalone mode simply add
+      the following component configuration:</para>
+
+      <programlisting>   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.impl.jotm.TransactionServiceJotmImpl&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Generic TransactionService based on the TransactionManagerLookup
+      of JBoss Cache</title>
+
+      <para>If you intend to use JBoss Cache, you can use a generic
+      TransactionService based on its TransactionManagerLookup which is able
+      to automatically find the TransactionManager of several Application
+      Servers thanks to a set of JNDI lookups. This generic TransactionService
+      covers mainly the TransactionManager lookups, the UserTransaction is
+      actually simply the TransactionManager instance that has been wrapped.
+      See below an example of configuration:</para>
+
+      <programlisting>   &lt;!-- Configuration of the TransactionManagerLookup --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.jboss.cache.transaction.TransactionManagerLookup&lt;/key&gt;
+      &lt;type&gt;org.jboss.cache.transaction.GenericTransactionManagerLookup&lt;/type&gt;
+   &lt;/component&gt;
+   &lt;!-- Configuration of the TransactionService --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.jbosscache.GenericTransactionService&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Specific GenericTransactionService for JBoss Cache and
+      Arjuna</title>
+
+      <para>If you intend to use JBoss Cache with Arjuna, you can use a more
+      specific GenericTransactionService, it is mostly interesting in case you
+      want to use the real UserTransaction. See below an example of
+      configuration:</para>
+
+      <programlisting>   &lt;!-- Configuration of the TransactionManagerLookup --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.jboss.cache.transaction.TransactionManagerLookup&lt;/key&gt;
+      &lt;type&gt;org.jboss.cache.transaction.JBossStandaloneJTAManagerLookup&lt;/type&gt;
+   &lt;/component&gt;
+   &lt;!-- Configuration of the TransactionService --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.jbosscache.JBossTransactionsService&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Generic TransactionService based on the TransactionManagerLookup
+      of Infinispan</title>
+
+      <para>If you intend to use Infinispan, you can use a generic
+      TransactionService based on its TransactionManagerLookup which is able
+      to automatically find the TransactionManager of several Application
+      Servers thanks to a set of JNDI lookups. This generic TransactionService
+      covers mainly the TransactionManager lookups, the UserTransaction is
+      actually simply the TransactionManager instance that has been wrapped.
+      See below an example of configuration:</para>
+
+      <programlisting>   &lt;!-- Configuration of the TransactionManagerLookup --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.infinispan.transaction.lookup.TransactionManagerLookup&lt;/key&gt;
+      &lt;type&gt;org.infinispan.transaction.lookup.GenericTransactionManagerLookup&lt;/type&gt;
+   &lt;/component&gt;
+   &lt;!-- Configuration of the TransactionService --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.infinispan.GenericTransactionService&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>Specific GenericTransactionService for Infinispan and
+      Arjuna</title>
+
+      <para>If you intend to use Infinispan with Arjuna, you can use a more
+      specific GenericTransactionService, it is mostly interesting in case you
+      want to use the real UserTransaction. See below an example of
+      configuration:</para>
+
+      <programlisting>   &lt;!-- Configuration of the TransactionManagerLookup --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.infinispan.transaction.lookup.TransactionManagerLookup&lt;/key&gt;
+      &lt;type&gt;org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup&lt;/type&gt;
+   &lt;/component&gt;
+   &lt;!-- Configuration of the TransactionService --&gt;
+   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.infinispan.JBossTransactionsService&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+
+    <section>
+      <title>A very specific TransactionService for JBoss AS</title>
+
+      <para>If you intend to use JBoss AS with JBoss Cache and Infinispan, you
+      can use a very specific TransactionService for JBoss AS. See below an
+      example of configuration:</para>
+
+      <programlisting>   &lt;component&gt;
+      &lt;key&gt;org.exoplatform.services.transaction.TransactionService&lt;/key&gt;
+      &lt;type&gt;org.exoplatform.services.transaction.impl.jboss.JBossTransactionService&lt;/type&gt;
+      &lt;!-- Uncomment the lines below if you want to set default transaction timeout that is expressed in seconds --&gt;
+      &lt;!--init-params&gt;
+         &lt;value-param&gt;
+            &lt;name&gt;timeout&lt;/name&gt;
+            &lt;value&gt;60&lt;/value&gt;
+         &lt;/value-param&gt;
+      &lt;/init-params--&gt;
+   &lt;/component&gt;</programlisting>
+    </section>
+  </section>
+</chapter>

Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel.xml	2011-05-23 06:57:15 UTC (rev 4401)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/kernel.xml	2011-05-23 07:39:32 UTC (rev 4402)
@@ -44,6 +44,9 @@
 
   <xi:include href="kernel/transaction-service.xml"
               xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+  <xi:include href="kernel/data-source-provider.xml"
+              xmlns:xi="http://www.w3.org/2001/XInclude" />
 
   <xi:include href="kernel/jndi-naming.xml"
               xmlns:xi="http://www.w3.org/2001/XInclude" />



More information about the exo-jcr-commits mailing list