[exo-jcr-commits] exo-jcr SVN: r3571 - in jcr/trunk/exo.jcr.component.core: src/main/java/org/exoplatform/services/jcr and 19 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Nov 26 08:07:28 EST 2010


Author: nzamosenchuk
Date: 2010-11-26 08:07:26 -0500 (Fri, 26 Nov 2010)
New Revision: 3571

Added:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/
   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/CacheLockImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableLockManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableSessionLockManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/LockData.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/
   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/CacheId.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheKey.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheNodesId.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePropsId.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheQPath.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheRefsId.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CompressedISPNChangesBuffer.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/infinispan/
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheFactory.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheHelper.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/JBossCacheHelper.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/lab/infinispan/
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/lab/infinispan/TestISPNCache.java
   jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-config.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml
   jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config-ispn.xml
Removed:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheLockImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableSessionLockManager.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/PrivilegedCacheHelper.java
Modified:
   jcr/trunk/exo.jcr.component.core/pom.xml
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/CacheableJDBCLockManagerImpl.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/LockJDBCConnection.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexChangesFilter.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/ExoJBossCacheFactory.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/config/TestTemplateConfigurationHelper.java
   jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
Log:
EXOJCR-1054 : Porting ISPN codebase into main trunk.

Modified: jcr/trunk/exo.jcr.component.core/pom.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/pom.xml	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/pom.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -164,7 +164,7 @@
         <artifactId>commons-beanutils</artifactId>
       </dependency>
       <dependency>
-        <groupId>jgroups</groupId>
+        <groupId>org.jgroups</groupId>
         <artifactId>jgroups</artifactId>
       </dependency>
       <dependency>
@@ -207,6 +207,14 @@
          <artifactId>jbosscache-core</artifactId>
       </dependency>
       <dependency>
+        <groupId>org.infinispan</groupId>
+        <artifactId>infinispan-core</artifactId>
+      </dependency>
+      <dependency>
+        <groupId>org.infinispan</groupId>
+        <artifactId>infinispan-cachestore-jdbc</artifactId>
+      </dependency>
+      <dependency>
          <groupId>org.apache.jackrabbit</groupId>
          <artifactId>jackrabbit-jcr-tests</artifactId>
          <classifier>sources</classifier>

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,285 +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.config;
-
-import org.exoplatform.commons.utils.PrivilegedFileHelper;
-import org.exoplatform.container.configuration.ConfigurationManager;
-
-import java.io.ByteArrayInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Pattern;
-
-/**
- * Builds configuration from template using map of template-variables <--> value.
- * Class provides extra functionality for filtering parameters by pattern, excluding 
- * unnecessary parameters. 
- * 
- * @author <a href="mailto:nikolazius at gmail.com">Nikolay Zamosenchuk</a>
- * @version $Id: TemplateConfigurationHelper.java 34360 2009-07-22 23:58:59Z nzamosenchuk $
- *
- */
-public class TemplateConfigurationHelper
-{
-   // list with include-patterns
-   private List<Pattern> includes = new ArrayList<Pattern>();
-
-   // list with exclude-patterns
-   private List<Pattern> excludes = new ArrayList<Pattern>();
-
-   private ConfigurationManager cfm;
-
-   /**
-    * Creates instance of template configuration helper with given lists of filtering 
-    * patterns. Parameter will be included only if it matches any include-pattern and
-    * doesn't match any exclude-pattern. I.e. You can include "extended-*" and exclude
-    * "extended-type". Please refer to Java regexp documentation. Filtering for this
-    * example, should be defined as following:
-    * include: "^extended-.*"
-    * exclude: "^extended-type"
-    * 
-    * @param includes Array with string representation of include reg-exp patterns
-    * @param excludes Array with string representation of exclude reg-exp patterns
-    * @param ConfigurationManager instance for looking up resources
-    */
-   public TemplateConfigurationHelper(String[] includes, String[] excludes, ConfigurationManager cfm)
-   {
-      super();
-      this.cfm = cfm;
-      // compile include patterns
-      for (String regex : includes)
-      {
-         this.includes.add(Pattern.compile(regex));
-      }
-      // compile exclude patterns
-      for (String regex : excludes)
-      {
-         this.excludes.add(Pattern.compile(regex));
-      }
-   }
-
-   /**
-    * Creates instance of TemplateConfigurationHelper pre-configured for JBossCache parameters,<br>
-    * including: "jbosscache-*" and "jgroups-configuration", and excluding "jbosscache-configuration"
-    * 
-    * @param ConfigurationManager instance for looking up resources
-    * @return
-    */
-   public static TemplateConfigurationHelper createJBossCacheHelper(ConfigurationManager cfm)
-   {
-      return new TemplateConfigurationHelper(new String[]{"^jbosscache-.*", "^jgroups-configuration"},
-         new String[]{"^jbosscache-configuration"}, cfm);
-   }
-
-   /**
-    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
-    * (like : "${parameter.name}") with values provided in the map. 
-    * 
-    * @param inputStream
-    * @param parameters
-    * @return
-    * @throws IOException
-    */
-   public InputStream fillTemplate(InputStream inputStream, Map<String, String> parameters) throws IOException
-   {
-      if (inputStream == null || parameters == null || parameters.size() == 0)
-      {
-         return inputStream;
-      }
-      // parameters filtering
-      Map<String, String> preparedParams = prepareParameters(parameters);
-      // read stream
-      String configuration = readStream(inputStream);
-      for (Entry<String, String> entry : preparedParams.entrySet())
-      {
-         configuration = configuration.replace(entry.getKey(), entry.getValue());
-      }
-      // create new stream
-      InputStream configurationStream = new ByteArrayInputStream(configuration.getBytes());
-      return configurationStream;
-   }
-
-   /**
-    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
-    * (like : "${parameter.name}") with values provided in the map. 
-    * 
-    * @param filename
-    * @param parameters
-    * @return
-    * @throws IOException
-    */
-   public InputStream fillTemplate(String filename, Map<String, String> parameters) throws IOException
-   {
-      InputStream inputStream = null;
-      // try to get using configuration manager
-      try
-      {
-         inputStream = cfm.getInputStream(filename);
-      }
-      catch (Exception e)
-      {
-         // will try to use another resolve mechanism 
-      }
-
-      // try to get resource by class loader
-      if (inputStream == null)
-      {
-         ClassLoader cl = Thread.currentThread().getContextClassLoader();
-         inputStream = cl == null ? null : cl.getResourceAsStream(filename);
-      }
-
-      // check system class loader
-      if (inputStream == null)
-      {
-         inputStream = getClass().getClassLoader().getResourceAsStream(filename);
-      }
-
-      // try to get as file stream
-      if (inputStream == null)
-      {
-         try
-         {
-            inputStream = PrivilegedFileHelper.fileInputStream(filename);
-         }
-         catch (IOException e)
-         {
-            // Still can't resolve
-         }
-      }
-      // inputStream still remains null, so file was not opened
-      if (inputStream == null)
-      {
-         throw new IOException("Can't find or open file:" + filename);
-      }
-      return fillTemplate(inputStream, parameters);
-   }
-
-   /**
-    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
-    * (like : "${parameter.name}") with values provided in the map. 
-    * 
-    * @param inputStream
-    * @param parameters
-    * @return
-    * @throws IOException
-    */
-   public InputStream fillTemplate(InputStream inputStream, List<SimpleParameterEntry> parameters) throws IOException
-   {
-      Map<String, String> map = new HashMap<String, String>();
-      for (SimpleParameterEntry parameterEntry : parameters)
-      {
-         map.put(parameterEntry.getName(), parameterEntry.getValue());
-      }
-      return fillTemplate(inputStream, map);
-   }
-
-   /**
-    * Reads configuration file from file-system and replaces all the occurrences of template-variables 
-    * (like : "${parameter.name}") with values provided in the map. 
-    * 
-    * @param filename
-    * @param parameters
-    * @return
-    * @throws IOException
-    */
-   public InputStream fillTemplate(String filename, List<SimpleParameterEntry> parameters) throws IOException
-   {
-      Map<String, String> map = new HashMap<String, String>();
-      for (SimpleParameterEntry parameterEntry : parameters)
-      {
-         map.put(parameterEntry.getName(), parameterEntry.getValue());
-      }
-      return fillTemplate(filename, map);
-   }
-
-   /**
-    * Checks if String mathes to any pattern from the list
-    * 
-    * @param patterns
-    * @param parameter
-    * @return
-    */
-   private boolean matches(List<Pattern> patterns, String parameter)
-   {
-      for (Pattern pattern : patterns)
-      {
-         if (pattern.matcher(parameter).matches())
-         {
-            // string matched
-            return true;
-         }
-      }
-      return false;
-   }
-
-   /**
-    * Filters the map of parameters, leaving only those than matches filtering regular expressions.
-    * Also adds "${}" to the parameter key: <br>
-    * I.e. such map provided on input:
-    * 
-    * "jbosscache-cache.loader":"org.exoplatform"
-    * "jbosscache-configuration":"/conf/test.xml"
-    * "max-volatile-size":"100Kb"
-    * 
-    * the output will be like:
-    * 
-    * "${jbosscache-cache.loader}":"org.exoplatform"
-    * 
-    * Other will be ignored (depending on includes/excludes lists provided in constructor).
-    * 
-    * @param parameters
-    * @return
-    */
-   protected Map<String, String> prepareParameters(Map<String, String> parameters)
-   {
-      Map<String, String> map = new HashMap<String, String>();
-      for (Entry<String, String> entry : parameters.entrySet())
-      {
-         if (matches(includes, entry.getKey()) && !matches(excludes, entry.getKey()))
-         {
-            map.put("${" + entry.getKey() + "}", entry.getValue());
-         }
-      }
-      return map;
-   }
-
-   /**
-    * Reads bytes from input stream and builds a string from them
-    * 
-    * @param inputStream
-    * @return
-    * @throws IOException
-    */
-   protected String readStream(InputStream inputStream) throws IOException
-   {
-      StringBuffer out = new StringBuffer();
-      byte[] b = new byte[4096];
-      for (int n; (n = inputStream.read(b)) != -1;)
-      {
-         out.append(new String(b, 0, n));
-      }
-      return out.toString();
-   }
-}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,271 @@
+/*
+ * 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.config;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.commons.utils.PrivilegedFileHelper;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+/**
+ * Builds configuration from template using map of template-variables <--> value.
+ * Class provides extra functionality for filtering parameters by pattern, excluding 
+ * unnecessary parameters. 
+ * 
+ * @author <a href="mailto:nikolazius at gmail.com">Nikolay Zamosenchuk</a>
+ * @version $Id: TemplateConfigurationHelper.java 34360 2009-07-22 23:58:59Z nzamosenchuk $
+ *
+ */
+public class TemplateConfigurationHelper
+{
+   // list with include-patterns
+   private List<Pattern> includes = new ArrayList<Pattern>();
+
+   // list with exclude-patterns
+   private List<Pattern> excludes = new ArrayList<Pattern>();
+
+   private ConfigurationManager cfm;
+
+   /**
+    * Creates instance of template configuration helper with given lists of filtering 
+    * patterns. Parameter will be included only if it matches any include-pattern and
+    * doesn't match any exclude-pattern. I.e. You can include "extended-*" and exclude
+    * "extended-type". Please refer to Java regexp documentation. Filtering for this
+    * example, should be defined as following:
+    * include: "^extended-.*"
+    * exclude: "^extended-type"
+    * 
+    * @param includes Array with string representation of include reg-exp patterns
+    * @param excludes Array with string representation of exclude reg-exp patterns
+    * @param ConfigurationManager instance for looking up resources
+    */
+   public TemplateConfigurationHelper(String[] includes, String[] excludes, ConfigurationManager cfm)
+   {
+      super();
+      this.cfm = cfm;
+      // compile include patterns
+      for (String regex : includes)
+      {
+         this.includes.add(Pattern.compile(regex));
+      }
+      // compile exclude patterns
+      for (String regex : excludes)
+      {
+         this.excludes.add(Pattern.compile(regex));
+      }
+   }
+
+   /**
+    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
+    * (like : "${parameter.name}") with values provided in the map. 
+    * 
+    * @param inputStream
+    * @param parameters
+    * @return
+    * @throws IOException
+    */
+   public InputStream fillTemplate(InputStream inputStream, Map<String, String> parameters) throws IOException
+   {
+      if (inputStream == null || parameters == null || parameters.size() == 0)
+      {
+         return inputStream;
+      }
+      // parameters filtering
+      Map<String, String> preparedParams = prepareParameters(parameters);
+      // read stream
+      String configuration = readStream(inputStream);
+      for (Entry<String, String> entry : preparedParams.entrySet())
+      {
+         configuration = configuration.replace(entry.getKey(), entry.getValue());
+      }
+      // create new stream
+      InputStream configurationStream = new ByteArrayInputStream(configuration.getBytes());
+      return configurationStream;
+   }
+
+   /**
+    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
+    * (like : "${parameter.name}") with values provided in the map. 
+    * 
+    * @param filename
+    * @param parameters
+    * @return
+    * @throws IOException
+    */
+   public InputStream fillTemplate(String filename, Map<String, String> parameters) throws IOException
+   {
+      InputStream inputStream = null;
+      // try to get using configuration manager
+      try
+      {
+         inputStream = cfm.getInputStream(filename);
+      }
+      catch (Exception e)
+      {
+         // will try to use another resolve mechanism 
+      }
+
+      // try to get resource by class loader
+      if (inputStream == null)
+      {
+         ClassLoader cl = Thread.currentThread().getContextClassLoader();
+         inputStream = cl == null ? null : cl.getResourceAsStream(filename);
+      }
+
+      // check system class loader
+      if (inputStream == null)
+      {
+         inputStream = getClass().getClassLoader().getResourceAsStream(filename);
+      }
+
+      // try to get as file stream
+      if (inputStream == null)
+      {
+         try
+         {
+            inputStream = PrivilegedFileHelper.fileInputStream(filename);
+         }
+         catch (IOException e)
+         {
+            // Still can't resolve
+         }
+      }
+      // inputStream still remains null, so file was not opened
+      if (inputStream == null)
+      {
+         throw new IOException("Can't find or open file:" + filename);
+      }
+      return fillTemplate(inputStream, parameters);
+   }
+
+   /**
+    * Reads configuration file from a stream and replaces all the occurrences of template-variables 
+    * (like : "${parameter.name}") with values provided in the map. 
+    * 
+    * @param inputStream
+    * @param parameters
+    * @return
+    * @throws IOException
+    */
+   public InputStream fillTemplate(InputStream inputStream, List<SimpleParameterEntry> parameters) throws IOException
+   {
+      Map<String, String> map = new HashMap<String, String>();
+      for (SimpleParameterEntry parameterEntry : parameters)
+      {
+         map.put(parameterEntry.getName(), parameterEntry.getValue());
+      }
+      return fillTemplate(inputStream, map);
+   }
+
+   /**
+    * Reads configuration file from file-system and replaces all the occurrences of template-variables 
+    * (like : "${parameter.name}") with values provided in the map. 
+    * 
+    * @param filename
+    * @param parameters
+    * @return
+    * @throws IOException
+    */
+   public InputStream fillTemplate(String filename, List<SimpleParameterEntry> parameters) throws IOException
+   {
+      Map<String, String> map = new HashMap<String, String>();
+      for (SimpleParameterEntry parameterEntry : parameters)
+      {
+         map.put(parameterEntry.getName(), parameterEntry.getValue());
+      }
+      return fillTemplate(filename, map);
+   }
+
+   /**
+    * Checks if String mathes to any pattern from the list
+    * 
+    * @param patterns
+    * @param parameter
+    * @return
+    */
+   private boolean matches(List<Pattern> patterns, String parameter)
+   {
+      for (Pattern pattern : patterns)
+      {
+         if (pattern.matcher(parameter).matches())
+         {
+            // string matched
+            return true;
+         }
+      }
+      return false;
+   }
+
+   /**
+    * Filters the map of parameters, leaving only those than matches filtering regular expressions.
+    * Also adds "${}" to the parameter key: <br>
+    * I.e. such map provided on input:
+    * 
+    * "jbosscache-cache.loader":"org.exoplatform"
+    * "jbosscache-configuration":"/conf/test.xml"
+    * "max-volatile-size":"100Kb"
+    * 
+    * the output will be like:
+    * 
+    * "${jbosscache-cache.loader}":"org.exoplatform"
+    * 
+    * Other will be ignored (depending on includes/excludes lists provided in constructor).
+    * 
+    * @param parameters
+    * @return
+    */
+   protected Map<String, String> prepareParameters(Map<String, String> parameters)
+   {
+      Map<String, String> map = new HashMap<String, String>();
+      for (Entry<String, String> entry : parameters.entrySet())
+      {
+         if (matches(includes, entry.getKey()) && !matches(excludes, entry.getKey()))
+         {
+            map.put("${" + entry.getKey() + "}", entry.getValue());
+         }
+      }
+      return map;
+   }
+
+   /**
+    * Reads bytes from input stream and builds a string from them
+    * 
+    * @param inputStream
+    * @return
+    * @throws IOException
+    */
+   protected String readStream(InputStream inputStream) throws IOException
+   {
+      StringBuffer out = new StringBuffer();
+      byte[] b = new byte[4096];
+      for (int n; (n = inputStream.read(b)) != -1;)
+      {
+         out.append(new String(b, 0, n));
+      }
+      return out.toString();
+   }
+}


Property changes on: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/config/TemplateConfigurationHelper.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: 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	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/AbstractCacheableLockManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.lock.cacheable;
+
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
+import org.exoplatform.services.jcr.dataflow.CompositeChangesLog;
+import org.exoplatform.services.jcr.dataflow.DataManager;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
+import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
+import org.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.ItemType;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.lock.LockRemover;
+import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
+import org.exoplatform.services.jcr.impl.core.lock.SessionLockManager;
+import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
+import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
+import org.exoplatform.services.jcr.observation.ExtendedEvent;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.security.IdentityConstants;
+import org.picocontainer.Startable;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 
+ *
+ * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
+ * @version $Id: AbstractCacheableLockManagerImpl.java 2806 2010-07-21 08:00:15Z tolusha $
+ */
+public abstract class AbstractCacheableLockManager implements CacheableLockManager, ItemsPersistenceListener, Startable
+{
+   /**
+    *  The name to property time out.  
+    */
+   public static final String TIME_OUT = "time-out";
+
+   /**
+    * Default lock time out. 30min
+    */
+   public static final long DEFAULT_LOCK_TIMEOUT = 1000 * 60 * 30;
+
+   /**
+    * Data manager.
+    */
+   protected final DataManager dataManager;
+
+   /**
+    * Run time lock time out.
+    */
+   protected long lockTimeOut;
+
+   /**
+    * Lock remover thread.
+    */
+   protected LockRemover lockRemover;
+
+   /**
+    * SessionLockManagers that uses this LockManager.
+    */
+   protected Map<String, CacheableSessionLockManager> sessionLockManagers;
+
+   /**
+    * The current Transaction Manager
+    */
+   protected TransactionManager tm;
+
+   /**
+    * Logger
+    */
+   private final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.AbstractCacheableLockManager");
+
+   protected LockActionNonTxAware<Integer, Object> getNumLocks;
+
+   protected LockActionNonTxAware<Boolean, Object> hasLocks;
+
+   protected LockActionNonTxAware<Boolean, String> isLockLive;
+
+   protected LockActionNonTxAware<Object, LockData> refresh;
+
+   protected LockActionNonTxAware<Boolean, String> lockExist;
+
+   protected LockActionNonTxAware<LockData, String> getLockDataById;
+
+   protected LockActionNonTxAware<List<LockData>, Object> getLockList;
+
+   /**
+    * Constructor.
+    * 
+    * @param dataManager - workspace persistent data manager
+    * @param config - workspace entry
+    * @param transactionManager 
+    *          the transaction manager
+    * @throws RepositoryConfigurationException 
+    */
+   public AbstractCacheableLockManager(WorkspacePersistentDataManager dataManager, WorkspaceEntry config,
+      TransactionManager transactionManager, LockRemoverHolder lockRemoverHolder)
+      throws RepositoryConfigurationException
+   {
+      if (config.getLockManager() != null)
+      {
+         if (config.getLockManager().getParameters() != null
+            && config.getLockManager().getParameterValue(TIME_OUT, null) != null)
+         {
+            long timeOut = config.getLockManager().getParameterTime(TIME_OUT);
+            lockTimeOut = timeOut > 0 ? timeOut : DEFAULT_LOCK_TIMEOUT;
+         }
+         else
+         {
+            lockTimeOut =
+               config.getLockManager().getTimeout() > 0 ? config.getLockManager().getTimeout() : DEFAULT_LOCK_TIMEOUT;
+         }
+      }
+      else
+      {
+         lockTimeOut = DEFAULT_LOCK_TIMEOUT;
+      }
+
+      this.dataManager = dataManager;
+      this.sessionLockManagers = new ConcurrentHashMap<String, CacheableSessionLockManager>();
+      this.tm = transactionManager;
+      this.lockRemover = lockRemoverHolder.getLockRemover(this);
+      dataManager.addItemPersistenceListener(this);
+   }
+
+   @Managed
+   @ManagedDescription("Remove the expired locks")
+   public void cleanExpiredLocks()
+   {
+      removeExpired();
+   }
+
+   public long getDefaultLockTimeOut()
+   {
+      return lockTimeOut;
+   }
+
+   @Managed
+   @ManagedDescription("The number of active locks")
+   public int getNumLocks()
+   {
+      try
+      {
+         return executeLockActionNonTxAware(getNumLocks, null);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return -1;
+   }
+
+   /**
+    * Indicates if some locks have already been created
+    */
+   protected boolean hasLocks()
+   {
+      try
+      {
+         return executeLockActionNonTxAware(hasLocks, null);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return true;
+   }
+
+   /**
+    * Return new instance of session lock manager.
+    */
+   public SessionLockManager getSessionLockManager(String sessionId, SessionDataManager transientManager)
+   {
+      CacheableSessionLockManager sessionManager = new CacheableSessionLockManager(sessionId, this, transientManager);
+      sessionLockManagers.put(sessionId, sessionManager);
+      return sessionManager;
+   }
+
+   /**
+    * Check is LockManager contains lock. No matter it is in pending or persistent state.
+    * 
+    * @param nodeId - locked node id
+    * @return 
+    */
+   public boolean isLockLive(String nodeId) throws LockException
+   {
+      try
+      {
+         return executeLockActionNonTxAware(isLockLive, nodeId);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return false;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isTXAware()
+   {
+      return true;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void onSaveItems(ItemStateChangesLog changesLog)
+   {
+      List<PlainChangesLog> chengesLogList = new ArrayList<PlainChangesLog>();
+      if (changesLog instanceof TransactionChangesLog)
+      {
+         ChangesLogIterator logIterator = ((TransactionChangesLog)changesLog).getLogIterator();
+
+         while (logIterator.hasNextLog())
+         {
+            chengesLogList.add(logIterator.nextLog());
+         }
+      }
+      else if (changesLog instanceof PlainChangesLog)
+      {
+         chengesLogList.add((PlainChangesLog)changesLog);
+      }
+      else if (changesLog instanceof CompositeChangesLog)
+      {
+         for (ChangesLogIterator iter = ((CompositeChangesLog)changesLog).getLogIterator(); iter.hasNextLog();)
+         {
+            chengesLogList.add(iter.nextLog());
+         }
+      }
+
+      List<LockOperationContainer> containers = new ArrayList<LockOperationContainer>();
+
+      for (PlainChangesLog currChangesLog : chengesLogList)
+      {
+         String sessionId = currChangesLog.getSessionId();
+
+         String nodeIdentifier;
+         try
+         {
+            switch (currChangesLog.getEventType())
+            {
+               case ExtendedEvent.LOCK :
+                  if (currChangesLog.getSize() < 2)
+                  {
+                     LOG.error("Incorrect changes log  of type ExtendedEvent.LOCK size=" + currChangesLog.getSize()
+                        + "<2 \n" + currChangesLog.dump());
+                     break;
+                  }
+                  nodeIdentifier = currChangesLog.getAllStates().get(0).getData().getParentIdentifier();
+
+                  CacheableSessionLockManager session = sessionLockManagers.get(sessionId);
+                  if (session != null && session.containsPendingLock(nodeIdentifier))
+                  {
+                     containers.add(new LockOperationContainer(nodeIdentifier, currChangesLog.getSessionId(),
+                        ExtendedEvent.LOCK));
+                  }
+                  else
+                  {
+                     LOG.error("Lock must exist in pending locks.");
+                  }
+                  break;
+               case ExtendedEvent.UNLOCK :
+                  if (currChangesLog.getSize() < 2)
+                  {
+                     LOG.error("Incorrect changes log  of type ExtendedEvent.UNLOCK size=" + currChangesLog.getSize()
+                        + "<2 \n" + currChangesLog.dump());
+                     break;
+                  }
+
+                  containers.add(new LockOperationContainer(currChangesLog.getAllStates().get(0).getData()
+                     .getParentIdentifier(), currChangesLog.getSessionId(), ExtendedEvent.UNLOCK));
+                  break;
+               default :
+                  HashSet<String> removedLock = new HashSet<String>();
+                  for (ItemState itemState : currChangesLog.getAllStates())
+                  {
+                     // this is a node and node is locked
+                     if (itemState.getData().isNode() && lockExist(itemState.getData().getIdentifier()))
+                     {
+                        nodeIdentifier = itemState.getData().getIdentifier();
+                        if (itemState.isDeleted())
+                        {
+                           removedLock.add(nodeIdentifier);
+                        }
+                        else if (itemState.isAdded() || itemState.isRenamed() || itemState.isUpdated())
+                        {
+                           removedLock.remove(nodeIdentifier);
+                        }
+                     }
+                  }
+                  for (String identifier : removedLock)
+                  {
+                     containers.add(new LockOperationContainer(identifier, currChangesLog.getSessionId(),
+                        ExtendedEvent.UNLOCK));
+                  }
+                  break;
+            }
+         }
+         catch (IllegalStateException e)
+         {
+            LOG.error(e.getLocalizedMessage(), e);
+         }
+      }
+
+      // sort locking and unlocking operations to avoid deadlocks
+      Collections.sort(containers);
+      for (LockOperationContainer container : containers)
+      {
+         try
+         {
+            container.apply();
+         }
+         catch (LockException e)
+         {
+            LOG.error(e.getMessage(), e);
+         }
+      }
+   }
+
+   /**
+    * Class containing operation type (LOCK or UNLOCK) and all the needed information like node uuid and session id.
+    */
+   private class LockOperationContainer implements Comparable<LockOperationContainer>
+   {
+
+      private String identifier;
+
+      private String sessionId;
+
+      private int type;
+
+      /**
+       * @param identifier node identifier 
+       * @param sessionId id of session
+       * @param type ExtendedEvent type specifying the operation (LOCK or UNLOCK)
+       */
+      public LockOperationContainer(String identifier, String sessionId, int type)
+      {
+         super();
+         this.identifier = identifier;
+         this.sessionId = sessionId;
+         this.type = type;
+      }
+
+      /**
+       * @return node identifier
+       */
+      public String getIdentifier()
+      {
+         return identifier;
+      }
+
+      public void apply() throws LockException
+      {
+         // invoke internalLock in LOCK operation
+         if (type == ExtendedEvent.LOCK)
+         {
+            internalLock(sessionId, identifier);
+         }
+         // invoke internalUnLock in UNLOCK operation
+         else if (type == ExtendedEvent.UNLOCK)
+         {
+            internalUnLock(sessionId, identifier);
+         }
+      }
+
+      /**
+       * @see java.lang.Comparable#compareTo(java.lang.Object)
+       */
+      public int compareTo(LockOperationContainer o)
+      {
+         return identifier.compareTo(o.getIdentifier());
+      }
+   }
+
+   /**
+    * Refreshed lock data in cache
+    * 
+    * @param newLockData
+    */
+   public void refreshLockData(LockData newLockData) throws LockException
+   {
+      executeLockActionNonTxAware(refresh, newLockData);
+   }
+
+   /**
+    * Remove expired locks. Used from LockRemover.
+    */
+   public synchronized void removeExpired()
+   {
+      final List<String> removeLockList = new ArrayList<String>();
+
+      for (LockData lock : getLockList())
+      {
+         if (!lock.isSessionScoped() && lock.getTimeToDeath() < 0)
+         {
+            removeLockList.add(lock.getNodeIdentifier());
+         }
+      }
+
+      Collections.sort(removeLockList);
+
+      for (String rLock : removeLockList)
+      {
+         removeLock(rLock);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void start()
+   {
+      lockRemover.start();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void stop()
+   {
+      lockRemover.stop();
+      sessionLockManagers.clear();
+   }
+
+   /**
+    * Copy <code>PropertyData prop<code> to new TransientItemData
+    * 
+    * @param prop
+    * @return
+    * @throws RepositoryException
+    */
+   protected TransientItemData copyItemData(PropertyData prop) throws RepositoryException
+   {
+      if (prop == null)
+      {
+         return null;
+      }
+
+      // make a copy, value may be null for deleting items
+      TransientPropertyData newData =
+         new TransientPropertyData(prop.getQPath(), prop.getIdentifier(), prop.getPersistedVersion(), prop.getType(),
+            prop.getParentIdentifier(), prop.isMultiValued(), prop.getValues());
+
+      return newData;
+   }
+
+   /**
+    * Internal lock
+    * 
+    * @param nodeIdentifier
+    * @throws LockException
+    */
+   protected abstract void internalLock(String sessionId, String nodeIdentifier) throws LockException;
+
+   /**
+    * Internal unlock.
+    * 
+    * @param sessionId
+    * @param nodeIdentifier
+    * @throws LockException
+    */
+   protected abstract void internalUnLock(String sessionId, String nodeIdentifier) throws LockException;
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean lockExist(String nodeId)
+   {
+      try
+      {
+         return executeLockActionNonTxAware(lockExist, nodeId);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return false;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getLockTokenHash(String token)
+   {
+      String hash = "";
+      try
+      {
+         MessageDigest m = MessageDigest.getInstance("MD5");
+         m.update(token.getBytes(), 0, token.length());
+         hash = new BigInteger(1, m.digest()).toString(16);
+      }
+      catch (NoSuchAlgorithmException e)
+      {
+         LOG.error("Can't get instanse of MD5 MessageDigest!", e);
+      }
+      return hash;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public LockData getExactNodeOrCloseParentLock(NodeData node) throws RepositoryException
+   {
+      return getExactNodeOrCloseParentLock(node, true);
+   }
+
+   private LockData getExactNodeOrCloseParentLock(NodeData node, boolean checkHasLocks) throws RepositoryException
+   {
+
+      if (node == null || (checkHasLocks && !hasLocks()))
+      {
+         return null;
+      }
+      LockData retval = null;
+      retval = getLockDataById(node.getIdentifier());
+      if (retval == null)
+      {
+         NodeData parentData = (NodeData)dataManager.getItemData(node.getParentIdentifier());
+         if (parentData != null)
+         {
+            retval = getExactNodeOrCloseParentLock(parentData, false);
+         }
+      }
+      return retval;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public LockData getExactNodeLock(NodeData node) throws RepositoryException
+   {
+      if (node == null || !hasLocks())
+      {
+         return null;
+      }
+
+      return getLockDataById(node.getIdentifier());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public LockData getClosedChild(NodeData node) throws RepositoryException
+   {
+      return getClosedChild(node, true);
+   }
+
+   private LockData getClosedChild(NodeData node, boolean checkHasLocks) throws RepositoryException
+   {
+
+      if (node == null || (checkHasLocks && !hasLocks()))
+      {
+         return null;
+      }
+      LockData retval = null;
+
+      List<NodeData> childData = dataManager.getChildNodesData(node);
+      for (NodeData nodeData : childData)
+      {
+         retval = getLockDataById(nodeData.getIdentifier());
+         if (retval != null)
+         {
+            return retval;
+         }
+      }
+      // child not found try to find dipper
+      for (NodeData nodeData : childData)
+      {
+         retval = getClosedChild(nodeData, false);
+         if (retval != null)
+         {
+            return retval;
+         }
+      }
+      return retval;
+   }
+
+   protected LockData getLockDataById(String nodeId)
+   {
+      try
+      {
+         return executeLockActionNonTxAware(getLockDataById, nodeId);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return null;
+   }
+
+   protected synchronized List<LockData> getLockList()
+   {
+      try
+      {
+         return executeLockActionNonTxAware(getLockList, null);
+      }
+      catch (LockException e)
+      {
+         // ignore me will never occur
+      }
+      return null;
+   }
+
+   /**
+    * Remove lock, used by Lock remover.
+    * 
+    * @param nodeIdentifier String
+    */
+   protected void removeLock(String nodeIdentifier)
+   {
+      try
+      {
+         NodeData nData = (NodeData)dataManager.getItemData(nodeIdentifier);
+
+         //TODO EXOJCR-412, should be refactored in future.
+         //Skip removing, because that node was removed in other node of cluster.  
+         if (nData == null)
+         {
+            return;
+         }
+
+         PlainChangesLog changesLog =
+            new PlainChangesLogImpl(new ArrayList<ItemState>(), IdentityConstants.SYSTEM, ExtendedEvent.UNLOCK);
+
+         ItemData lockOwner =
+            copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKOWNER, 1),
+               ItemType.PROPERTY));
+
+         //TODO EXOJCR-412, should be refactored in future.
+         //Skip removing, because that lock was removed in other node of cluster.  
+         if (lockOwner == null)
+         {
+            return;
+         }
+
+         changesLog.add(ItemState.createDeletedState(lockOwner));
+
+         ItemData lockIsDeep =
+            copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKISDEEP, 1),
+               ItemType.PROPERTY));
+
+         //TODO EXOJCR-412, should be refactored in future.
+         //Skip removing, because that lock was removed in other node of cluster.  
+         if (lockIsDeep == null)
+         {
+            return;
+         }
+
+         changesLog.add(ItemState.createDeletedState(lockIsDeep));
+
+         // lock probably removed by other thread
+         if (lockOwner == null && lockIsDeep == null)
+         {
+            return;
+         }
+
+         dataManager.save(new TransactionChangesLog(changesLog));
+      }
+      catch (JCRInvalidItemStateException e)
+      {
+         //TODO EXOJCR-412, should be refactored in future.
+         //Skip property not found in DB, because that lock property was removed in other node of cluster.
+         if (LOG.isDebugEnabled())
+         {
+            LOG.debug("The propperty was removed in other node of cluster.", e);
+         }
+
+      }
+      catch (RepositoryException e)
+      {
+         LOG.error("Error occur during removing lock" + e.getLocalizedMessage(), e);
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void closeSessionLockManager(String sessionID)
+   {
+      sessionLockManagers.remove(sessionID);
+   }
+
+   /**
+    * 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
+    * Author : Nicolas Filotto 
+    *          nicolas.filotto at exoplatform.com
+    * 21 janv. 2010
+    */
+   protected static interface LockActionNonTxAware<R, A>
+   {
+      R execute(A arg) throws LockException;
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.lock.cacheable;
+
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 
+ *
+ * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
+ * @version $Id: CacheLockImpl.java 111 2008-11-11 11:11:11Z serg $
+ */
+public class CacheLockImpl extends LockImpl
+{
+   private boolean live;
+
+   private LockData lockData;
+
+   private SessionImpl session;
+
+   private CacheableSessionLockManager lockManager;
+
+   /**
+    * Constructor.
+    * 
+    * @param session - session owner
+    * @param lockData - LockData
+    * @param lockManager - CacheableLockManager
+    */
+   public CacheLockImpl(SessionImpl session, LockData lockData, CacheableSessionLockManager lockManager)
+   {
+      this.lockData = lockData;
+      this.session = session;
+      this.lockManager = lockManager;
+      this.live = true;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getLockOwner()
+   {
+      return lockData.getOwner();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getLockToken()
+   {
+      return lockManager.getLockToken(lockData.getTokenHash());
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isLive() throws LockException
+   {
+      if (!live)
+      {
+         // it is already not alive
+         return false;
+      }
+      live = lockManager.isLockLive(lockData.getNodeIdentifier());
+      return live;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void refresh() throws LockException, RepositoryException
+   {
+      if (!isLive())
+         throw new LockException("Lock is not live");
+
+      LockData newLockData =
+         new LockData(lockData.getNodeIdentifier(), lockData.getTokenHash(), lockData.isDeep(), lockData
+            .isSessionScoped(), lockData.getOwner(), lockData.getTimeOut());
+
+      lockManager.refresh(newLockData);
+      lockData = newLockData;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Node getNode()
+   {
+      try
+      {
+         return (Node)session.getTransientNodesManager().getItemByIdentifier(lockData.getNodeIdentifier(), true);
+      }
+      catch (RepositoryException e)
+      {
+         //TODO
+         e.printStackTrace();
+      }
+      return null;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isDeep()
+   {
+
+      return lockData.isDeep();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isSessionScoped()
+   {
+      return lockData.isSessionScoped();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public long getTimeToDeath()
+   {
+      return lockData.getTimeToDeath();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected void setTimeOut(long timeOut) throws LockException
+   {
+      lockData.setTimeOut(timeOut);
+
+      //reset lock data
+      lockManager.refresh(lockData);
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableLockManager.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableLockManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.lock.cacheable;
+
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.impl.core.lock.WorkspaceLockManager;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 
+ *
+ * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
+ * @version $Id: CacheableLockManager.java 111 2008-11-11 11:11:11Z serg $
+ */
+public interface CacheableLockManager extends WorkspaceLockManager
+{
+   /**
+    * Is lock live for node by nodeIdentifier.
+    * 
+    * @param nodeIdentifier
+    * 
+    * @return boolean
+    * @throws LockException 
+    */
+   boolean isLockLive(String nodeIdentifier) throws LockException;
+
+   /**
+    * Replace old lockData with new one. Node ID, token can't be replaced.
+    * 
+    * @param newLockData
+    * @throws LockException
+    */
+   void refreshLockData(LockData newLockData) throws LockException;
+
+   /**
+    * Get default lock timeout.
+    * 
+    * @return long value of timeout
+    */
+   long getDefaultLockTimeOut();
+
+   /**
+    * Return hash for lock token.
+    * 
+    * @param lockToken - lock token string 
+    * @return - hash string
+    */
+   String getLockTokenHash(String lockToken);
+
+   /**
+    * Return Lock holding node or its parent.
+    * 
+    * @param node - NodeData
+    * @return LockData for node or null;
+    * @throws RepositoryException
+    */
+   LockData getExactNodeOrCloseParentLock(NodeData node) throws RepositoryException;
+
+   /**
+    * Return Lock holding any nodes child.
+    * 
+    * @param node - NodeData
+    * @return LockData for node or null;
+    * @throws RepositoryException
+    */
+   LockData getClosedChild(NodeData node) throws RepositoryException;
+
+   boolean lockExist(String nodeId) throws RepositoryException;
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableSessionLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableSessionLockManager.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheableSessionLockManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.lock.cacheable;
+
+import org.exoplatform.services.jcr.core.ExtendedSession;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.impl.core.SessionDataManager;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.jcr.impl.core.lock.AbstractSessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
+import org.exoplatform.services.jcr.util.IdGenerator;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.lock.Lock;
+import javax.jcr.lock.LockException;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * <br/>Date: 
+ *
+ * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
+ * @version $Id: CacheableSessionLockManager.java 2137 2010-03-25 15:31:56Z sergiykarpenko $
+ */
+public class CacheableSessionLockManager extends AbstractSessionLockManager
+{
+   /**
+    * Logger
+    */
+   private final Log log = ExoLogger.getLogger("exo.jcr.component.core.CacheableSessionLockManager");
+
+   /**
+    * Session identifier.
+    */
+   private final String sessionID;
+
+   /**
+    * Lock tokens held by this session.
+    * [token name, tokens hash]
+    */
+   private final Map<String, String> tokens;
+
+   /**
+    * Map of nodes locked in this session. Need to remove session scoped lock on session close.
+    * [node identifier, lock data]
+    */
+   private final Map<String, LockData> lockedNodes;
+
+   /**
+    * Set of pending locked nodes identifiers.
+    */
+   private final Set<String> pendingLocks;
+
+   /**
+    * Workspace lock manager
+    */
+   private final CacheableLockManager lockManager;
+
+   /**
+    * Constructor.
+    * 
+    * @param sessionID - session identifier
+    * @param lockManager - workspace lock manager
+    */
+   public CacheableSessionLockManager(String sessionID, CacheableLockManager lockManager,
+      SessionDataManager transientManager)
+   {
+      super(transientManager);
+      this.sessionID = sessionID;
+      this.tokens = new HashMap<String, String>();
+      this.lockedNodes = new HashMap<String, LockData>();
+      this.pendingLocks = new HashSet<String>();
+      this.lockManager = lockManager;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Lock addLock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeOut) throws LockException,
+      RepositoryException
+   {
+
+      String lockToken = IdGenerator.generate();
+
+      NodeData data = (NodeData)node.getData();
+
+      LockData lData = lockManager.getExactNodeOrCloseParentLock(data);
+      if (lData != null)
+      {
+         if (lData.getNodeIdentifier().equals(node.getIdentifier()))
+         {
+            throw new LockException("Node already locked: " + data.getQPath());
+         }
+         else if (lData.isDeep())
+         {
+            throw new LockException("Parent node has deep lock.");
+         }
+      }
+
+      if (isDeep && lockManager.getClosedChild(data) != null)
+      {
+         throw new LockException("Some child node is locked.");
+      }
+
+      String lockTokenHash = lockManager.getLockTokenHash(lockToken);
+
+      lData =
+         new LockData(node.getIdentifier(), lockTokenHash, isDeep, isSessionScoped, node.getSession().getUserID(),
+            timeOut > 0 ? timeOut : lockManager.getDefaultLockTimeOut());
+
+      lockedNodes.put(node.getInternalIdentifier(), lData);
+      pendingLocks.add(node.getInternalIdentifier());
+      tokens.put(lockToken, lData.getTokenHash());
+
+      LockImpl lock = new CacheLockImpl(node.getSession(), lData, this);
+
+      return lock;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void addLockToken(String lt)
+   {
+      tokens.put(lt, lockManager.getLockTokenHash(lt));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public LockImpl getLock(NodeImpl node) throws LockException, RepositoryException
+   {
+      LockData lData = lockManager.getExactNodeOrCloseParentLock((NodeData)node.getData());
+
+      if (lData == null || (!node.getInternalIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
+      {
+         throw new LockException("Node not locked: " + node.getData().getQPath());
+      }
+      return new CacheLockImpl(node.getSession(), lData, this);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String[] getLockTokens()
+   {
+      String[] arr = new String[tokens.size()];
+      tokens.keySet().toArray(arr);
+      return arr;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean holdsLock(NodeData node) throws RepositoryException
+   {
+      return lockManager.lockExist(node.getIdentifier());//.getExactNodeLock(node) != null;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected boolean isLockedPersisted(NodeData node) throws LockException
+   {
+      LockData lData = null;
+      try
+      {
+         lData = lockManager.getExactNodeOrCloseParentLock(node);
+      }
+      catch (RepositoryException e)
+      {
+         throw new LockException(e.getMessage(), e);
+      }
+
+      if (lData == null || (!node.getIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
+      {
+         return false;
+      }
+      return true;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected boolean isPersistedLockHolder(NodeData node) throws RepositoryException
+   {
+      LockData lData = lockManager.getExactNodeOrCloseParentLock(node);
+      return lData != null && isLockHolder(lData);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void onCloseSession(ExtendedSession session)
+   {
+      SessionImpl sessionImpl = (SessionImpl)session;
+
+      String[] nodeIds = new String[lockedNodes.size()];
+      lockedNodes.keySet().toArray(nodeIds);
+
+      for (String nodeId : nodeIds)
+      {
+         LockData lock = lockedNodes.remove(nodeId);
+
+         if (lock.isSessionScoped() && !pendingLocks.contains(nodeId))
+         {
+            try
+            {
+               NodeImpl node =
+                  ((NodeImpl)sessionImpl.getTransientNodesManager()
+                     .getItemByIdentifier(lock.getNodeIdentifier(), false));
+
+               if (node != null)
+               {
+                  node.unlock();
+               }
+
+            }
+            catch (UnsupportedRepositoryOperationException e)
+            {
+               log.error(e.getLocalizedMessage());
+            }
+            catch (LockException e)
+            {
+               log.error(e.getLocalizedMessage());
+            }
+            catch (AccessDeniedException e)
+            {
+               log.error(e.getLocalizedMessage());
+            }
+            catch (RepositoryException e)
+            {
+               log.error(e.getLocalizedMessage());
+            }
+         }
+      }
+
+      pendingLocks.clear();
+      tokens.clear();
+      lockedNodes.clear();
+
+      lockManager.closeSessionLockManager(sessionID);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void removeLockToken(String lt)
+   {
+      tokens.remove(lt);
+   }
+
+   /**
+    * Checks if session has token to this lock data or session is System.
+    * 
+    * @param lockData
+    * @return
+    */
+   private boolean isLockHolder(LockData lockData)
+   {
+      return tokens.containsValue(lockData.getTokenHash());
+   }
+
+   /**
+    * Is session contains pending lock for node by nodeId.
+    * @param nodeId - node ID string
+    * @return boolean
+    */
+   public boolean containsPendingLock(String nodeId)
+   {
+      return pendingLocks.contains(nodeId);
+   }
+
+   /**
+    * Returns real token, if session has it.
+    * 
+    * @param tokenHash - token hash string
+    * @return lock token string
+    */
+   protected String getLockToken(String tokenHash)
+   {
+      for (String token : tokens.keySet())
+      {
+         if (tokens.get(token).equals(tokenHash))
+         {
+            return token;
+         }
+      }
+      return null;
+   }
+
+   /**
+    * Return pending lock.
+    * 
+    * @param nodeId - ID of locked node
+    * @return pending lock or null
+    */
+   public LockData getPendingLock(String nodeId)
+   {
+      if (pendingLocks.contains(nodeId))
+      {
+         return lockedNodes.get(nodeId);
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    * Check is lock alive. That means lock must exist in LockManager storage (cache or map, etc). 
+    * 
+    * @param nodeIdentifier - locked node id
+    * @return
+    */
+   protected boolean isLockLive(String nodeIdentifier) throws LockException
+   {
+
+      if (lockManager.isLockLive(nodeIdentifier))
+      {
+         return true;
+      }
+      else
+      {
+         return pendingLocks.contains(nodeIdentifier);
+      }
+   }
+
+   public void notifyLockPersisted(String nodeIdentifier)
+   {
+      pendingLocks.remove(nodeIdentifier);
+   }
+
+   /**
+    * Notify SessionLockManager that node is unlocked.
+    * 
+    * @param nodeIdentifier - unlocked node identifier
+    */
+   public void notifyLockRemoved(String nodeIdentifier)
+   {
+      lockedNodes.remove(nodeIdentifier);
+   }
+
+   /**
+    * Refresh lockData. 
+    * 
+    * @param newLockData
+    * @throws LockException
+    */
+   protected void refresh(LockData newLockData) throws LockException
+   {
+      lockManager.refreshLockData(newLockData);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   protected boolean checkPersistedLocks(NodeData node) throws LockException
+   {
+      LockData lData = null;
+      try
+      {
+         lData = lockManager.getExactNodeOrCloseParentLock(node);
+      }
+      catch (RepositoryException e)
+      {
+         throw new LockException(e.getMessage(), e);
+      }
+
+      if (lData == null || (!node.getIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
+      {
+         return true;
+      }
+
+      // lock exist, so lets check is current session is LockHolder
+      return isLockHolder(lData);
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/LockData.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/LockData.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/LockData.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,264 @@
+/*
+ * 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.lock.cacheable;
+
+import org.exoplatform.services.jcr.impl.Constants;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Created by The eXo Platform SAS.
+ * 
+ * @author <a href="mailto:gennady.azarenkov at exoplatform.com">Gennady Azarenkov</a>
+ * @version $Id: LockData.java 787 2009-11-20 11:36:15Z nzamosenchuk $
+ */
+
+public class LockData implements Externalizable
+{
+   /**
+    * The time of birth. From this time we start count the time of death. death = birthday+TIME_OUT;
+    */
+   private long birthday;
+
+   /**
+    * If isDeep is true then the lock applies to this node and all its descendant nodes; if false,
+    * the lock applies only to this, the holding node.
+    */
+   private boolean deep;
+
+   /**
+    * A lock token is a string that uniquely identifies a particular lock and acts as a “key”
+    * allowing a user to alter a locked node. LockData stores only token hash.
+    */
+   private String tokenHash;
+
+   /**
+    * Identifier of locked node.
+    */
+   private String nodeIdentifier;
+
+   /**
+    * The owner of the locked node.
+    */
+   private String owner;
+
+   /**
+    * If isSessionScoped is true then this lock will expire upon the expiration of the current
+    * session (either through an automatic or explicit Session.logout); if false, this lock does not
+    * expire until explicitly unlocked or automatically unlocked due to a implementation-specific
+    * limitation, such as a timeout.
+    */
+   private boolean sessionScoped;
+
+   /**
+    * <B>8.4.9 Timing Out</B> An implementation may unlock any lock at any time due to
+    * implementation-specific criteria, such as time limits on locks.
+    */
+   private long timeOut;
+
+   // Need for Externalizable
+   public LockData()
+   {
+      this.sessionScoped = false;
+      this.deep = false;
+   }
+
+   /**
+    * @param nodeIdentifier
+    * @param lockToken
+    * @param deep
+    * @param sessionScoped
+    * @param owner
+    * @param timeOut
+    *       is seconds!
+    */
+   public LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean sessionScoped, String owner,
+      long timeOut)
+   {
+      this(nodeIdentifier, lockTokenHash, deep, sessionScoped, owner, timeOut, System.currentTimeMillis());
+   }
+   
+   /**
+    * @param nodeIdentifier
+    * @param lockToken
+    * @param deep
+    * @param sessionScoped
+    * @param owner
+    * @param timeOut
+    *       is seconds!
+    * @param birthday
+    */
+   public LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean sessionScoped, String owner,
+      long timeOut, long birthday)
+   {
+      this.nodeIdentifier = nodeIdentifier;
+      this.tokenHash = lockTokenHash;
+      this.deep = deep;
+      this.sessionScoped = sessionScoped;
+      this.owner = owner;
+      this.timeOut = timeOut;
+      this.birthday = birthday;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (super.equals(obj))
+      {
+         return true;
+      }
+      if (obj instanceof LockData)
+      {
+         return hashCode() == obj.hashCode();
+      }
+      return false;
+   }
+
+   /**
+    * @return the nodeIdentifier
+    */
+   public String getNodeIdentifier()
+   {
+      return nodeIdentifier;
+   }
+
+   /**
+    * @return
+    */
+   public String getOwner()
+   {
+      return owner;
+   }
+
+   /**
+    * @return The time to death in millis
+    */
+   public long getTimeToDeath()
+   {
+      return birthday + timeOut - System.currentTimeMillis();
+   }
+
+   public String getTokenHash()
+   {
+      return tokenHash;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      return tokenHash.hashCode();
+   }
+
+   public boolean isDeep()
+   {
+      return deep;
+   }
+
+   /**
+    * @return
+    */
+   public boolean isSessionScoped()
+   {
+      return sessionScoped;
+   }
+
+   /**
+    * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
+    */
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      // read boolean
+      this.deep = in.readBoolean();
+      this.sessionScoped = in.readBoolean();
+      // read long
+      this.birthday = in.readLong();
+      this.timeOut = in.readLong();
+      //read strings
+      // read uuid
+      byte[] buf;
+      buf = new byte[in.readInt()];
+      in.readFully(buf);
+      this.nodeIdentifier = new String(buf, Constants.DEFAULT_ENCODING);
+      // read owner
+      buf = new byte[in.readInt()];
+      in.readFully(buf);
+      this.owner = new String(buf, Constants.DEFAULT_ENCODING);
+      // read token
+      buf = new byte[in.readInt()];
+      in.readFully(buf);
+      this.tokenHash = new String(buf, Constants.DEFAULT_ENCODING);
+   }
+
+   /**
+    * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
+    */
+   public void writeExternal(ObjectOutput out) throws IOException
+   {
+      // write boolean
+      out.writeBoolean(deep);
+      out.writeBoolean(sessionScoped);
+      // write long
+      out.writeLong(birthday);
+      out.writeLong(timeOut);
+      // write string
+      // node uuid
+      byte[] ptbuf = nodeIdentifier.getBytes(Constants.DEFAULT_ENCODING);
+      out.writeInt(ptbuf.length);
+      out.write(ptbuf);
+      // node owner
+      ptbuf = owner.getBytes(Constants.DEFAULT_ENCODING);
+      out.writeInt(ptbuf.length);
+      out.write(ptbuf);
+      // node token
+      ptbuf = tokenHash.getBytes(Constants.DEFAULT_ENCODING);
+      out.writeInt(ptbuf.length);
+      out.write(ptbuf);
+
+   }
+
+   /**
+    * @return
+    */
+   public long getTimeOut()
+   {
+      return timeOut;
+   }
+
+   public long getBirthDay()
+   {
+      return birthday;
+   }
+
+   public void setTimeOut(long timeOut)
+   {
+      this.timeOut = timeOut;
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/infinispan/ISPNCacheableLockManagerImpl.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,395 @@
+/*
+ *
+ * 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.lock.infinispan;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.management.jmx.annotations.Property;
+import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.AbstractCacheableLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.CacheableSessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.LockData;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
+import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
+import org.exoplatform.services.jcr.infinispan.PrivilegedISPNCacheHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.services.naming.InitialContextInitializer;
+import org.exoplatform.services.transaction.TransactionService;
+import org.infinispan.Cache;
+
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: InfinispanLockManagerImpl.java 111 2010-11-11 11:11:11Z tolusha $
+ */
+ at Managed
+ at NameTemplate(@Property(key = "service", value = "lockmanager"))
+public class ISPNCacheableLockManagerImpl extends AbstractCacheableLockManager
+{
+
+   /**
+    *  The name to property cache configuration. 
+    */
+   public static final String INFINISPAN_JDBC_CL_DATASOURCE = "infinispan-cl-cache.jdbc.datasource";
+
+   public static final String INFINISPAN_JDBC_CL_DATA_COLUMN = "infinispan-cl-cache.jdbc.data.type";
+
+   public static final String INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN = "infinispan-cl-cache.jdbc.timestamp.type";
+
+   public static final String INFINISPAN_JDBC_CL_ID_COLUMN = "infinispan-cl-cache.jdbc.id.type";
+
+   public static final String INFINISPAN_JDBC_CL_AUTO = "auto";
+
+   /**
+    * Logger
+    */
+   private final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.InfinispanLockManagerImpl");
+
+   private Cache<Serializable, Object> cache;
+
+   public ISPNCacheableLockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config,
+      InitialContextInitializer context, TransactionService transactionService, ConfigurationManager cfm, LockRemoverHolder lockRemoverHolder)
+      throws RepositoryConfigurationException, RepositoryException
+   {
+      this(dataManager, config, context, transactionService.getTransactionManager(), cfm, lockRemoverHolder);
+   }
+
+   public ISPNCacheableLockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config,
+      InitialContextInitializer context, ConfigurationManager cfm, LockRemoverHolder lockRemoverHolder) throws RepositoryConfigurationException,
+      RepositoryException
+   {
+      this(dataManager, config, context, (TransactionManager)null, cfm, lockRemoverHolder);
+   }
+
+   public ISPNCacheableLockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config,
+      InitialContextInitializer context, TransactionManager transactionManager, ConfigurationManager cfm, LockRemoverHolder lockRemoverHolder)
+      throws RepositoryConfigurationException, RepositoryException
+   {
+      super(dataManager, config, transactionManager, lockRemoverHolder);
+
+      // make cache
+      if (config.getLockManager() != null)
+      {
+         // create cache using custom factory
+         ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+
+         // configure cache loader parameters with correct DB data-types
+         configureJDBCCacheLoader(config.getLockManager());
+
+         cache = factory.createCache("Lock-" + config.getUniqueName(), config.getLockManager());
+
+         // Context recall is a workaround of JDBCCacheLoader starting. 
+         context.recall();
+      }
+      else
+      {
+         throw new RepositoryConfigurationException("Cache configuration not found");
+      }
+
+      this.getNumLocks = new LockActionNonTxAware<Integer, Object>()
+      {
+         public Integer execute(Object arg)
+         {
+            return cache.size();
+         }
+      };
+
+      this.hasLocks = new LockActionNonTxAware<Boolean, Object>()
+      {
+         public Boolean execute(Object arg)
+         {
+            return !cache.isEmpty();
+         }
+      };
+
+      this.isLockLive = new LockActionNonTxAware<Boolean, String>()
+      {
+         public Boolean execute(String nodeId)
+         {
+            return cache.containsKey(nodeId);
+         }
+      };
+
+      this.refresh = new LockActionNonTxAware<Object, LockData>()
+      {
+         public Object execute(LockData newLockData) throws LockException
+         {
+            Object oldValue = PrivilegedISPNCacheHelper.put(cache, newLockData.getNodeIdentifier(), newLockData);
+            if (oldValue == null)
+            {
+               throw new LockException("Can't refresh lock for node " + newLockData.getNodeIdentifier()
+                  + " since lock is not exist");
+            }
+            return null;
+         }
+      };
+
+      this.lockExist = this.isLockLive;
+
+      this.getLockDataById = new LockActionNonTxAware<LockData, String>()
+      {
+         public LockData execute(String nodeId) throws LockException
+         {
+            return (LockData)cache.get(nodeId);
+         }
+      };
+
+      this.getLockList = new LockActionNonTxAware<List<LockData>, Object>()
+      {
+         public List<LockData> execute(Object arg) throws LockException
+         {
+            Collection<Object> datas = cache.values();
+
+            List<LockData> locksData = new ArrayList<LockData>();
+            for (Object lockData : datas)
+            {
+               if (lockData != null)
+               {
+                  locksData.add((LockData)lockData);
+               }
+            }
+            return locksData;
+         }
+      };
+   }
+
+   /**
+    * If JDBC cache loader is used, then fills-in column types. If column type configured from jcr-configuration file,
+    * then nothing is overridden. Parameters are injected into the given parameterEntry.
+    */
+   private void configureJDBCCacheLoader(MappedParametrizedObjectEntry parameterEntry) throws RepositoryException
+   {
+      String dataSourceName = parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_DATASOURCE, null);
+      // if data source is defined, then inject correct data-types.
+      // Also it cans be not defined and nothing should be injected (i.e. no cache loader is used (possibly pattern is changed, to used another cache loader))
+      if (dataSourceName != null)
+      {
+         String dialect;
+         // detect dialect of data-source
+         try
+         {
+            final DataSource dataSource = (DataSource)new InitialContext().lookup(dataSourceName);
+            if (dataSource == null)
+            {
+               throw new RepositoryException("DataSource (" + dataSourceName + ") can't be null");
+            }
+
+            Connection jdbcConn = null;
+            try
+            {
+               PrivilegedExceptionAction<Connection> action = new PrivilegedExceptionAction<Connection>()
+               {
+                  public Connection run() throws Exception
+                  {
+                     return dataSource.getConnection();
+                  }
+               };
+               try
+               {
+                  jdbcConn = AccessController.doPrivileged(action);
+               }
+               catch (PrivilegedActionException pae)
+               {
+                  Throwable cause = pae.getCause();
+                  if (cause instanceof SQLException)
+                  {
+                     throw (SQLException)cause;
+                  }
+                  else if (cause instanceof RuntimeException)
+                  {
+                     throw (RuntimeException)cause;
+                  }
+                  else
+                  {
+                     throw new RuntimeException(cause);
+                  }
+               }
+
+               dialect = DialectDetecter.detect(jdbcConn.getMetaData());
+            }
+            finally
+            {
+               if (jdbcConn != null && !jdbcConn.isClosed())
+               {
+                  try
+                  {
+                     jdbcConn.close();
+                  }
+                  catch (SQLException e)
+                  {
+                     throw new RepositoryException("Error of connection close", e);
+                  }
+               }
+            }
+         }
+         catch (Exception e)
+         {
+            throw new RepositoryException("Error configuring JDBC cache loader", e);
+         }
+
+         // default values, will be overridden with types suitable for concrete data base.
+         String blobType = "BLOB";
+         String charType = "VARCHAR(512)";
+         String timeStampType = "BIGINT";
+         // HSSQL
+         if (dialect.equals(DBConstants.DB_DIALECT_HSQLDB))
+         {
+            blobType = "OBJECT";
+         }
+         // MYSQL
+         else if (dialect.equals(DBConstants.DB_DIALECT_MYSQL) || dialect.equals(DBConstants.DB_DIALECT_MYSQL_UTF8))
+         {
+            blobType = "LONGBLOB";
+         }
+         // ORACLE
+         else if (dialect.equals(DBConstants.DB_DIALECT_ORACLE) || dialect.equals(DBConstants.DB_DIALECT_ORACLEOCI))
+         {
+            // Oracle suggests the use VARCHAR2 instead of VARCHAR while declaring data type.
+            charType = "VARCHAR2(512)";
+            timeStampType = "NUMBER(19, 0)";
+         }
+         // POSTGRE SQL
+         else if (dialect.equals(DBConstants.DB_DIALECT_PGSQL))
+         {
+            blobType = "bytea";
+         }
+         // Microsoft SQL
+         else if (dialect.equals(DBConstants.DB_DIALECT_MSSQL))
+         {
+            blobType = "VARBINARY(MAX)";
+         }
+         // SYBASE
+         else if (dialect.equals(DBConstants.DB_DIALECT_SYBASE))
+         {
+            blobType = "IMAGE";
+         }
+         // INGRES
+         else if (dialect.equals(DBConstants.DB_DIALECT_INGRES))
+         {
+            blobType = "long byte";
+         }
+         // else GENERIC, DB2 etc
+
+         // set parameters if not defined
+         // if parameter is missing in configuration, then getParameterValue(INFINISPAN_JDBC_CL_DATA_COLUMN, INFINISPAN_JDBC_CL_AUTO) 
+         // will return INFINISPAN_JDBC_CL_AUTO. If parameter is present in configuration and equals to "auto", then it should be replaced 
+         // with correct value for given database
+         if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_DATA_COLUMN, INFINISPAN_JDBC_CL_AUTO)
+            .equalsIgnoreCase(INFINISPAN_JDBC_CL_AUTO))
+         {
+            parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_DATA_COLUMN, blobType);
+         }
+
+         if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_ID_COLUMN, INFINISPAN_JDBC_CL_AUTO).equalsIgnoreCase(
+            INFINISPAN_JDBC_CL_AUTO))
+         {
+            parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_ID_COLUMN, charType);
+         }
+
+         if (parameterEntry.getParameterValue(INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN, INFINISPAN_JDBC_CL_AUTO)
+            .equalsIgnoreCase(INFINISPAN_JDBC_CL_AUTO))
+         {
+            parameterEntry.putParameterValue(INFINISPAN_JDBC_CL_TIMESTAMP_COLUMN, timeStampType);
+         }
+      }
+      else
+      {
+         LOG.warn("CacheLoader DataSource " + INFINISPAN_JDBC_CL_DATASOURCE + " is not configured.");
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void stop()
+   {
+      super.stop();
+      PrivilegedISPNCacheHelper.stop(cache);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected synchronized void internalLock(String sessionId, String nodeIdentifier) throws LockException
+   {
+      CacheableSessionLockManager session = sessionLockManagers.get(sessionId);
+      if (session != null && session.containsPendingLock(nodeIdentifier))
+      {
+         LockData lockData = session.getPendingLock(nodeIdentifier);
+
+         // this will return null if success. And old data if something exists...
+         LockData oldLockData = (LockData)PrivilegedISPNCacheHelper.putIfAbsent(cache, nodeIdentifier, lockData);
+
+         if (oldLockData != null)
+         {
+            throw new LockException("Unable to write LockData. Node [" + lockData.getNodeIdentifier()
+               + "] already has LockData!");
+         }
+
+         session.notifyLockPersisted(nodeIdentifier);
+      }
+      else
+      {
+         throw new LockException("No lock in pending locks");
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   protected synchronized void internalUnLock(String sessionId, String nodeIdentifier) throws LockException
+   {
+      LockData lData = getLockDataById(nodeIdentifier);
+
+      if (lData != null)
+      {
+         cache.remove(nodeIdentifier);
+
+         CacheableSessionLockManager sessMgr = sessionLockManagers.get(sessionId);
+         if (sessMgr != null)
+         {
+            sessMgr.notifyLockRemoved(nodeIdentifier);
+         }
+      }
+   }
+}

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheLockImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheLockImpl.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheLockImpl.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2003-2010 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.core.lock.jbosscache;
-
-import org.exoplatform.services.jcr.impl.core.SessionImpl;
-import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- * 
- * <br/>Date: 
- *
- * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
- * @version $Id: CacheLockImpl.java 111 2008-11-11 11:11:11Z serg $
- */
-public class CacheLockImpl extends LockImpl
-{
-   private boolean live;
-
-   private LockData lockData;
-
-   private SessionImpl session;
-
-   private CacheableSessionLockManager lockManager;
-
-   /**
-    * Constructor.
-    * 
-    * @param session - session owner
-    * @param lockData - LockData
-    * @param lockManager - CacheableLockManager
-    */
-   public CacheLockImpl(SessionImpl session, LockData lockData, CacheableSessionLockManager lockManager)
-   {
-      this.lockData = lockData;
-      this.session = session;
-      this.lockManager = lockManager;
-      this.live = true;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public String getLockOwner()
-   {
-      return lockData.getOwner();
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public String getLockToken()
-   {
-      return lockManager.getLockToken(lockData.getTokenHash());
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean isLive() throws LockException
-   {
-      if (!live)
-      {
-         // it is already not alive
-         return false;
-      }
-      live = lockManager.isLockLive(lockData.getNodeIdentifier());
-      return live;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void refresh() throws LockException, RepositoryException
-   {
-      if (!isLive())
-         throw new LockException("Lock is not live");
-
-      LockData newLockData =
-         new LockData(lockData.getNodeIdentifier(), lockData.getTokenHash(), lockData.isDeep(), lockData
-            .isSessionScoped(), lockData.getOwner(), lockData.getTimeOut());
-
-      lockManager.refresh(newLockData);
-      lockData = newLockData;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public Node getNode()
-   {
-      try
-      {
-         return (Node)session.getTransientNodesManager().getItemByIdentifier(lockData.getNodeIdentifier(), true);
-      }
-      catch (RepositoryException e)
-      {
-         //TODO
-         e.printStackTrace();
-      }
-      return null;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean isDeep()
-   {
-
-      return lockData.isDeep();
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean isSessionScoped()
-   {
-      return lockData.isSessionScoped();
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public long getTimeToDeath()
-   {
-      return lockData.getTimeToDeath();
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   protected void setTimeOut(long timeOut) throws LockException
-   {
-      lockData.setTimeOut(timeOut);
-
-      //reset lock data
-      lockManager.refresh(lockData);
-   }
-}

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2003-2010 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.core.lock.jbosscache;
-
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.impl.core.lock.WorkspaceLockManager;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- * 
- * <br/>Date: 
- *
- * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
- * @version $Id: CacheableLockManager.java 111 2008-11-11 11:11:11Z serg $
- */
-public interface CacheableLockManager extends WorkspaceLockManager
-{
-   /**
-    * Is lock live for node by nodeIdentifier.
-    * 
-    * @param nodeIdentifier
-    * 
-    * @return boolean
-    * @throws LockException 
-    */
-   boolean isLockLive(String nodeIdentifier) throws LockException;
-
-   /**
-    * Replace old lockData with new one. Node ID, token can't be replaced.
-    * 
-    * @param newLockData
-    * @throws LockException
-    */
-   void refreshLockData(LockData newLockData) throws LockException;
-
-   /**
-    * Get default lock timeout.
-    * 
-    * @return long value of timeout
-    */
-   long getDefaultLockTimeOut();
-
-   /**
-    * Return hash for lock token.
-    * 
-    * @param lockToken - lock token string 
-    * @return - hash string
-    */
-   String getLockTokenHash(String lockToken);
-
-   /**
-    * Return Lock holding node or its parent.
-    * 
-    * @param node - NodeData
-    * @return LockData for node or null;
-    * @throws RepositoryException
-    */
-   LockData getExactNodeOrCloseParentLock(NodeData node) throws RepositoryException;
-
-   /**
-    * Return Lock holding any nodes child.
-    * 
-    * @param node - NodeData
-    * @return LockData for node or null;
-    * @throws RepositoryException
-    */
-   LockData getClosedChild(NodeData node) throws RepositoryException;
-
-   boolean lockExist(String nodeId) throws RepositoryException;
-
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManagerImpl.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -16,49 +16,26 @@
  */
 package org.exoplatform.services.jcr.impl.core.lock.jbosscache;
 
-import org.exoplatform.commons.utils.SecurityHelper;
 import org.exoplatform.container.configuration.ConfigurationManager;
 import org.exoplatform.management.annotations.Managed;
-import org.exoplatform.management.annotations.ManagedDescription;
 import org.exoplatform.management.jmx.annotations.NameTemplate;
 import org.exoplatform.management.jmx.annotations.Property;
 import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
 import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
-import org.exoplatform.services.jcr.config.SimpleParameterEntry;
 import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
-import org.exoplatform.services.jcr.dataflow.CompositeChangesLog;
-import org.exoplatform.services.jcr.dataflow.DataManager;
-import org.exoplatform.services.jcr.dataflow.ItemState;
-import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
-import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
-import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
-import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
-import org.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener;
-import org.exoplatform.services.jcr.datamodel.ItemData;
-import org.exoplatform.services.jcr.datamodel.ItemType;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.datamodel.PropertyData;
-import org.exoplatform.services.jcr.datamodel.QPathEntry;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.SessionDataManager;
-import org.exoplatform.services.jcr.impl.core.lock.LockRemover;
 import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
-import org.exoplatform.services.jcr.impl.core.lock.SessionLockManager;
-import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
-import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.AbstractCacheableLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.CacheableSessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.LockData;
 import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
-import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
 import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
 import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
-import org.exoplatform.services.jcr.impl.util.PrivilegedCacheHelper;
 import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory;
+import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
 import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory.CacheType;
-import org.exoplatform.services.jcr.observation.ExtendedEvent;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.exoplatform.services.naming.InitialContextInitializer;
-import org.exoplatform.services.security.IdentityConstants;
 import org.exoplatform.services.transaction.TransactionService;
 import org.jboss.cache.Cache;
 import org.jboss.cache.CacheSPI;
@@ -69,31 +46,21 @@
 import org.jboss.cache.loader.CacheLoader;
 import org.jboss.cache.loader.CacheLoaderManager;
 import org.jboss.cache.lock.TimeoutException;
-import org.picocontainer.Startable;
 
 import java.io.Serializable;
-import java.math.BigInteger;
 import java.security.AccessController;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.lock.LockException;
 import javax.naming.InitialContext;
 import javax.sql.DataSource;
-import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 
 /**
@@ -106,18 +73,9 @@
  */
 @Managed
 @NameTemplate(@Property(key = "service", value = "lockmanager"))
-public class CacheableLockManagerImpl implements CacheableLockManager, ItemsPersistenceListener, Startable
+public class CacheableLockManagerImpl extends AbstractCacheableLockManager
 {
-   /**
-    *  The name to property time out.  
-    */
-   public static final String TIME_OUT = "time-out";
 
-   /**
-    *  The name to property cache configuration. 
-    */
-   public static final String JBOSSCACCHE_CONFIG = "jbosscache-configuration";
-
    public static final String JBOSSCACHE_JDBC_CL_DATASOURCE = "jbosscache-cl-cache.jdbc.datasource";
 
    public static final String JBOSSCACHE_JDBC_CL_NODE_COLUMN = "jbosscache-cl-cache.jdbc.node.type";
@@ -134,11 +92,6 @@
    public static final String JBOSSCACHE_JDBC_CL_AUTO = "auto";
 
    /**
-    * Default lock time out. 30min
-    */
-   public static final long DEFAULT_LOCK_TIMEOUT = 1000 * 60 * 30;
-
-   /**
     * Name of lock root in jboss-cache.
     */
    public static final String LOCKS = "$LOCKS";
@@ -153,26 +106,6 @@
     */
    private final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.CacheableLockManagerImpl");
 
-   /**
-    * Data manager.
-    */
-   private final DataManager dataManager;
-
-   /**
-    * Run time lock time out.
-    */
-   private long lockTimeOut;
-
-   /**
-    * Lock remover thread.
-    */
-   private LockRemover lockRemover;
-
-   /**
-    * The current Transaction Manager
-    */
-   private TransactionManager tm;
-
    private Cache<Serializable, Object> cache;
 
    private final Fqn<String> lockRoot;
@@ -180,11 +113,6 @@
    private final boolean shareable;
 
    /**
-    * SessionLockManagers that uses this LockManager.
-    */
-   private Map<String, CacheableSessionLockManager> sessionLockManagers;
-
-   /**
     * Constructor.
     * 
     * @param dataManager - workspace persistent data manager
@@ -214,7 +142,6 @@
       throws RepositoryConfigurationException, RepositoryException
    {
       this(dataManager, config, context, (TransactionManager)null, cfm, lockRemoverHolder);
-
    }
 
    /**
@@ -231,38 +158,13 @@
       InitialContextInitializer context, TransactionManager transactionManager, ConfigurationManager cfm,
       LockRemoverHolder lockRemoverHolder) throws RepositoryConfigurationException, RepositoryException
    {
-      lockRoot = Fqn.fromElements(config.getUniqueName(), LOCKS);
+      super(dataManager, config, transactionManager, lockRemoverHolder);
 
-      List<SimpleParameterEntry> paramenerts = config.getLockManager().getParameters();
+      lockRoot = Fqn.fromElements(LOCKS);
 
-      this.dataManager = dataManager;
-      if (config.getLockManager() != null)
-      {
-         if (paramenerts != null && config.getLockManager().getParameterValue(TIME_OUT, null) != null)
-         {
-            long timeOut = config.getLockManager().getParameterTime(TIME_OUT);
-            lockTimeOut = timeOut > 0 ? timeOut : DEFAULT_LOCK_TIMEOUT;
-         }
-         else
-         {
-            lockTimeOut =
-               config.getLockManager().getTimeout() > 0 ? config.getLockManager().getTimeout() : DEFAULT_LOCK_TIMEOUT;
-         }
-      }
-      else
-      {
-         lockTimeOut = DEFAULT_LOCK_TIMEOUT;
-      }
-
-      sessionLockManagers = new ConcurrentHashMap<String, CacheableSessionLockManager>();
-
-      dataManager.addItemPersistenceListener(this);
-
       // make cache
       if (config.getLockManager() != null)
       {
-         this.tm = transactionManager;
-
          // create cache using custom factory
          ExoJBossCacheFactory<Serializable, Object> factory =
             new ExoJBossCacheFactory<Serializable, Object>(cfm, transactionManager);
@@ -271,19 +173,18 @@
          configureJDBCCacheLoader(config.getLockManager());
 
          cache = factory.createCache(config.getLockManager());
-
+        
          Fqn<String> rootFqn = Fqn.fromElements(config.getUniqueName());
-
          shareable =
             config.getLockManager().getParameterBoolean(JBOSSCACHE_SHAREABLE, JBOSSCACHE_SHAREABLE_DEFAULT)
                .booleanValue();
          cache = ExoJBossCacheFactory.getUniqueInstance(CacheType.LOCK_CACHE, rootFqn, cache, shareable);
-         PrivilegedCacheHelper.create(cache);
+         PrivilegedJBossCacheHelper.create(cache);
          if (cache.getCacheStatus().startAllowed())
          {
             // Add the cache loader needed to prevent TimeoutException
             addCacheLoader();
-            PrivilegedCacheHelper.start(cache);
+            PrivilegedJBossCacheHelper.start(cache);
          }
 
          createStructuredNode(lockRoot);
@@ -296,14 +197,91 @@
          throw new RepositoryConfigurationException("Cache configuration not found");
       }
 
-      lockRemover = lockRemoverHolder.getLockRemover(this);
+      this.getNumLocks = new LockActionNonTxAware<Integer, Object>()
+      {
+         public Integer execute(Object arg)
+         {
+            return ((CacheSPI<Serializable, Object>)cache).getNumberOfNodes() - 1;
+         }
+      };
+
+      this.hasLocks = new LockActionNonTxAware<Boolean, Object>()
+      {
+         public Boolean execute(Object arg)
+         {
+            return ((CacheSPI<Serializable, Object>)cache).getNode(lockRoot).hasChildrenDirect();
+         }
+      };
+
+      this.isLockLive = new LockActionNonTxAware<Boolean, String>()
+      {
+         public Boolean execute(String nodeId)
+         {
+            if (cache.get(makeLockFqn(nodeId), LOCK_DATA) != null) //pendingLocks.containsKey(nodeId) || 
+            {
+               return true;
+            }
+
+            return false;
+         }
+      };
+
+      this.refresh = new LockActionNonTxAware<Object, LockData>()
+      {
+         public Object execute(LockData newLockData) throws LockException
+         {
+            Fqn<String> fqn = makeLockFqn(newLockData.getNodeIdentifier());
+            Object oldValue = PrivilegedJBossCacheHelper.put(cache, fqn, LOCK_DATA, newLockData);
+            if (oldValue == null)
+            {
+               throw new LockException("Can't refresh lock for node " + newLockData.getNodeIdentifier()
+                  + " since lock is not exist");
+            }
+            return null;
+         }
+      };
+
+      this.lockExist = new LockActionNonTxAware<Boolean, String>()
+      {
+         public Boolean execute(String nodeId) throws LockException
+         {
+            return cache.get(makeLockFqn(nodeId), LOCK_DATA) != null;
+         }
+      };
+
+      this.getLockDataById = new LockActionNonTxAware<LockData, String>()
+      {
+         public LockData execute(String nodeId) throws LockException
+         {
+            return (LockData)cache.get(makeLockFqn(nodeId), LOCK_DATA);
+         }
+      };
+
+      this.getLockList = new LockActionNonTxAware<List<LockData>, Object>()
+      {
+         public List<LockData> execute(Object arg) throws LockException
+         {
+            Set<Object> nodesId = cache.getChildrenNames(lockRoot);
+
+            List<LockData> locksData = new ArrayList<LockData>();
+            for (Object nodeId : nodesId)
+            {
+               LockData lockData = (LockData)cache.get(makeLockFqn((String)nodeId), LOCK_DATA);
+               if (lockData != null)
+               {
+                  locksData.add(lockData);
+               }
+            }
+            return locksData;
+         }
+      };
    }
 
    /**
     * If JDBC cache loader is used, then fills-in column types. If column type configured from jcr-configuration file,
     * then nothing is overridden. Parameters are injected into the given parameterEntry.
     */
-   public void configureJDBCCacheLoader(MappedParametrizedObjectEntry parameterEntry) throws RepositoryException
+   private void configureJDBCCacheLoader(MappedParametrizedObjectEntry parameterEntry) throws RepositoryException
    {
       String dataSourceName = parameterEntry.getParameterValue(JBOSSCACHE_JDBC_CL_DATASOURCE, null);
       // if data source is defined, then inject correct data-types.
@@ -487,355 +465,13 @@
       }
    }
 
-   @Managed
-   @ManagedDescription("Remove the expired locks")
-   public void cleanExpiredLocks()
-   {
-      removeExpired();
-   }
-
-   public long getDefaultLockTimeOut()
-   {
-      return lockTimeOut;
-   }
-
-   private final LockActionNonTxAware<Integer, Object> getNumLocks = new LockActionNonTxAware<Integer, Object>()
-   {
-      public Integer execute(Object arg)
-      {
-         return ((CacheSPI<Serializable, Object>)cache).getNode(lockRoot).getChildrenDirect().size();
-      }
-   };
-
-   @Managed
-   @ManagedDescription("The number of active locks")
-   public int getNumLocks()
-   {
-      try
-      {
-         return executeLockActionNonTxAware(getNumLocks, null);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return -1;
-   }
-
-   private final LockActionNonTxAware<Boolean, Object> hasLocks = new LockActionNonTxAware<Boolean, Object>()
-   {
-      public Boolean execute(Object arg)
-      {
-         return ((CacheSPI<Serializable, Object>)cache).getNode(lockRoot).hasChildrenDirect();
-      }
-   };
-
    /**
-    * Indicates if some locks have already been created
-    */
-   private boolean hasLocks()
-   {
-      try
-      {
-         return executeLockActionNonTxAware(hasLocks, null);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return true;
-   }
-
-   /**
-    * Return new instance of session lock manager.
-    */
-   public SessionLockManager getSessionLockManager(String sessionId, SessionDataManager transientManager)
-   {
-      CacheableSessionLockManager sessionManager = new CacheableSessionLockManager(sessionId, this, transientManager);
-      sessionLockManagers.put(sessionId, sessionManager);
-      return sessionManager;
-   }
-
-   private final LockActionNonTxAware<Boolean, String> isLockLive = new LockActionNonTxAware<Boolean, String>()
-   {
-      public Boolean execute(String nodeId)
-      {
-         if (cache.get(makeLockFqn(nodeId), LOCK_DATA) != null) //pendingLocks.containsKey(nodeId) || 
-         {
-            return true;
-         }
-
-         return false;
-      }
-   };
-
-   /**
-    * Check is LockManager contains lock. No matter it is in pending or persistent state.
-    * 
-    * @param nodeId - locked node id
-    * @return 
-    */
-   public boolean isLockLive(String nodeId) throws LockException
-   {
-      try
-      {
-         return executeLockActionNonTxAware(isLockLive, nodeId);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return false;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean isTXAware()
-   {
-      return true;
-   }
-
-   /*
-    * (non-Javadoc)
-    * @seeorg.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener#onSaveItems(org.
-    * exoplatform.services.jcr.dataflow.ItemStateChangesLog)
-    */
-   public void onSaveItems(ItemStateChangesLog changesLog)
-   {
-      List<PlainChangesLog> chengesLogList = new ArrayList<PlainChangesLog>();
-      if (changesLog instanceof TransactionChangesLog)
-      {
-         ChangesLogIterator logIterator = ((TransactionChangesLog)changesLog).getLogIterator();
-
-         while (logIterator.hasNextLog())
-         {
-            chengesLogList.add(logIterator.nextLog());
-         }
-      }
-      else if (changesLog instanceof PlainChangesLog)
-      {
-         chengesLogList.add((PlainChangesLog)changesLog);
-      }
-      else if (changesLog instanceof CompositeChangesLog)
-      {
-         for (ChangesLogIterator iter = ((CompositeChangesLog)changesLog).getLogIterator(); iter.hasNextLog();)
-         {
-            chengesLogList.add(iter.nextLog());
-         }
-      }
-
-      List<LockOperationContainer> containers = new ArrayList<LockOperationContainer>();
-
-      for (PlainChangesLog currChangesLog : chengesLogList)
-      {
-         String sessionId = currChangesLog.getSessionId();
-
-         String nodeIdentifier;
-         try
-         {
-            switch (currChangesLog.getEventType())
-            {
-               case ExtendedEvent.LOCK :
-                  if (currChangesLog.getSize() < 2)
-                  {
-                     LOG.error("Incorrect changes log  of type ExtendedEvent.LOCK size=" + currChangesLog.getSize()
-                        + "<2 \n" + currChangesLog.dump());
-                     break;
-                  }
-                  nodeIdentifier = currChangesLog.getAllStates().get(0).getData().getParentIdentifier();
-
-                  CacheableSessionLockManager session = sessionLockManagers.get(sessionId);
-                  if (session != null && session.containsPendingLock(nodeIdentifier))
-                  {
-                     containers.add(new LockOperationContainer(nodeIdentifier, currChangesLog.getSessionId(),
-                        ExtendedEvent.LOCK));
-                  }
-                  else
-                  {
-                     LOG.error("Lock must exist in pending locks.");
-                  }
-                  break;
-               case ExtendedEvent.UNLOCK :
-                  if (currChangesLog.getSize() < 2)
-                  {
-                     LOG.error("Incorrect changes log  of type ExtendedEvent.UNLOCK size=" + currChangesLog.getSize()
-                        + "<2 \n" + currChangesLog.dump());
-                     break;
-                  }
-
-                  containers.add(new LockOperationContainer(currChangesLog.getAllStates().get(0).getData()
-                     .getParentIdentifier(), currChangesLog.getSessionId(), ExtendedEvent.UNLOCK));
-                  break;
-               default :
-                  HashSet<String> removedLock = new HashSet<String>();
-                  for (ItemState itemState : currChangesLog.getAllStates())
-                  {
-                     // this is a node and node is locked
-                     if (itemState.getData().isNode() && lockExist(itemState.getData().getIdentifier()))
-                     {
-                        nodeIdentifier = itemState.getData().getIdentifier();
-                        if (itemState.isDeleted())
-                        {
-                           removedLock.add(nodeIdentifier);
-                        }
-                        else if (itemState.isAdded() || itemState.isRenamed() || itemState.isUpdated())
-                        {
-                           removedLock.remove(nodeIdentifier);
-                        }
-                     }
-                  }
-                  for (String identifier : removedLock)
-                  {
-                     containers.add(new LockOperationContainer(identifier, currChangesLog.getSessionId(),
-                        ExtendedEvent.UNLOCK));
-                  }
-                  break;
-            }
-         }
-         catch (IllegalStateException e)
-         {
-            LOG.error(e.getLocalizedMessage(), e);
-         }
-      }
-
-      // sort locking and unlocking operations to avoid deadlocks in JBossCache
-      Collections.sort(containers);
-      for (LockOperationContainer container : containers)
-      {
-         try
-         {
-            container.apply();
-         }
-         catch (LockException e)
-         {
-            LOG.error(e.getMessage(), e);
-         }
-      }
-   }
-
-   /**
-    * Class containing operation type (LOCK or UNLOCK) and all the needed information like node uuid and session id.
-    */
-   private class LockOperationContainer implements Comparable<LockOperationContainer>
-   {
-
-      private String identifier;
-
-      private String sessionId;
-
-      private int type;
-
-      /**
-       * @param identifier node identifier 
-       * @param sessionId id of session
-       * @param type ExtendedEvent type specifying the operation (LOCK or UNLOCK)
-       */
-      public LockOperationContainer(String identifier, String sessionId, int type)
-      {
-         super();
-         this.identifier = identifier;
-         this.sessionId = sessionId;
-         this.type = type;
-      }
-
-      /**
-       * @return node identifier
-       */
-      public String getIdentifier()
-      {
-         return identifier;
-      }
-
-      public void apply() throws LockException
-      {
-         // invoke internalLock in LOCK operation
-         if (type == ExtendedEvent.LOCK)
-         {
-            internalLock(sessionId, identifier);
-         }
-         // invoke internalUnLock in UNLOCK operation
-         else if (type == ExtendedEvent.UNLOCK)
-         {
-            internalUnLock(sessionId, identifier);
-         }
-      }
-
-      /**
-       * @see java.lang.Comparable#compareTo(java.lang.Object)
-       */
-      public int compareTo(LockOperationContainer o)
-      {
-         return identifier.compareTo(o.getIdentifier());
-      }
-   }
-
-   private final LockActionNonTxAware<Object, LockData> refresh = new LockActionNonTxAware<Object, LockData>()
-   {
-      public Object execute(LockData newLockData) throws LockException
-      {
-         Fqn<String> fqn = makeLockFqn(newLockData.getNodeIdentifier());
-         Object oldValue = PrivilegedCacheHelper.put(cache, fqn, LOCK_DATA, newLockData);
-         if (oldValue == null)
-         {
-            throw new LockException("Can't refresh lock for node " + newLockData.getNodeIdentifier()
-               + " since lock is not exist");
-         }
-         return null;
-      }
-   };
-
-   /**
-    * Refreshed lock data in cache
-    * 
-    * @param newLockData
-    */
-   public void refreshLockData(LockData newLockData) throws LockException
-   {
-      executeLockActionNonTxAware(refresh, newLockData);
-   }
-
-   /**
-    * Remove expired locks. Used from LockRemover.
-    */
-   public synchronized void removeExpired()
-   {
-      final List<String> removeLockList = new ArrayList<String>();
-
-      for (LockData lock : getLockList())
-      {
-         if (!lock.isSessionScoped() && lock.getTimeToDeath() < 0)
-         {
-            removeLockList.add(lock.getNodeIdentifier());
-         }
-      }
-
-      Collections.sort(removeLockList);
-
-      for (String rLock : removeLockList)
-      {
-         removeLock(rLock);
-      }
-   }
-
-   /*
-    * (non-Javadoc)
-    * @see org.picocontainer.Startable#start()
-    */
-   public void start()
-   {
-      lockRemover.start();
-   }
-
-   /*
-    * (non-Javadoc)
-    * @see org.picocontainer.Startable#stop()
-    */
+   * {@inheritDoc}
+   */
+   @Override
    public void stop()
    {
-      lockRemover.stop();
-
-      sessionLockManagers.clear();
+      super.stop();
       if (shareable)
       {
          // The cache cannot be stopped since it can be shared so we evict the root node instead
@@ -843,40 +479,16 @@
       }
       else
       {
-         PrivilegedCacheHelper.stop(cache);
+         PrivilegedJBossCacheHelper.stop(cache);
       }
    }
 
    /**
-    * Copy <code>PropertyData prop<code> to new TransientItemData
-    * 
-    * @param prop
-    * @return
-    * @throws RepositoryException
+    * {@inheritDoc}
     */
-   private TransientItemData copyItemData(PropertyData prop) throws RepositoryException
+   @Override
+   protected synchronized void internalLock(String sessionId, String nodeIdentifier) throws LockException
    {
-      if (prop == null)
-      {
-         return null;
-      }
-
-      // make a copy, value may be null for deleting items
-      TransientPropertyData newData =
-         new TransientPropertyData(prop.getQPath(), prop.getIdentifier(), prop.getPersistedVersion(), prop.getType(),
-            prop.getParentIdentifier(), prop.isMultiValued(), prop.getValues());
-
-      return newData;
-   }
-
-   /**
-    * Internal lock
-    * 
-    * @param nodeIdentifier
-    * @throws LockException
-    */
-   private synchronized void internalLock(String sessionId, String nodeIdentifier) throws LockException
-   {
       CacheableSessionLockManager session = sessionLockManagers.get(sessionId);
       if (session != null && session.containsPendingLock(nodeIdentifier))
       {
@@ -904,13 +516,10 @@
    }
 
    /**
-    * Internal unlock.
-    * 
-    * @param sessionId
-    * @param nodeIdentifier
-    * @throws LockException
+    * {@inheritDoc}
     */
-   private synchronized void internalUnLock(String sessionId, String nodeIdentifier) throws LockException
+   @Override
+   protected synchronized void internalUnLock(String sessionId, String nodeIdentifier) throws LockException
    {
       LockData lData = getLockDataById(nodeIdentifier);
 
@@ -926,258 +535,7 @@
       }
    }
 
-   private final LockActionNonTxAware<Boolean, String> lockExist = new LockActionNonTxAware<Boolean, String>()
-   {
-      public Boolean execute(String nodeId) throws LockException
-      {
-         return cache.get(makeLockFqn(nodeId), LOCK_DATA) != null;
-      }
-   };
-
    /**
-    * {@inheritDoc}
-    */
-   public boolean lockExist(String nodeId)
-   {
-      try
-      {
-         return executeLockActionNonTxAware(lockExist, nodeId);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return false;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public String getLockTokenHash(String token)
-   {
-      String hash = "";
-      try
-      {
-         MessageDigest m = MessageDigest.getInstance("MD5");
-         m.update(token.getBytes(), 0, token.length());
-         hash = new BigInteger(1, m.digest()).toString(16);
-      }
-      catch (NoSuchAlgorithmException e)
-      {
-         LOG.error("Can't get instanse of MD5 MessageDigest!", e);
-      }
-      return hash;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public LockData getExactNodeOrCloseParentLock(NodeData node) throws RepositoryException
-   {
-      return getExactNodeOrCloseParentLock(node, true);
-   }
-
-   private LockData getExactNodeOrCloseParentLock(NodeData node, boolean checkHasLocks) throws RepositoryException
-   {
-
-      if (node == null || (checkHasLocks && !hasLocks()))
-      {
-         return null;
-      }
-      LockData retval = null;
-      retval = getLockDataById(node.getIdentifier());
-      if (retval == null)
-      {
-         NodeData parentData = (NodeData)dataManager.getItemData(node.getParentIdentifier());
-         if (parentData != null)
-         {
-            retval = getExactNodeOrCloseParentLock(parentData, false);
-         }
-      }
-      return retval;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public LockData getExactNodeLock(NodeData node) throws RepositoryException
-   {
-      if (node == null || !hasLocks())
-      {
-         return null;
-      }
-
-      return getLockDataById(node.getIdentifier());
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public LockData getClosedChild(NodeData node) throws RepositoryException
-   {
-      return getClosedChild(node, true);
-   }
-
-   private LockData getClosedChild(NodeData node, boolean checkHasLocks) throws RepositoryException
-   {
-
-      if (node == null || (checkHasLocks && !hasLocks()))
-      {
-         return null;
-      }
-      LockData retval = null;
-
-      List<NodeData> childData = dataManager.getChildNodesData(node);
-      for (NodeData nodeData : childData)
-      {
-         retval = getLockDataById(nodeData.getIdentifier());
-         if (retval != null)
-            return retval;
-      }
-      // child not found try to find dipper
-      for (NodeData nodeData : childData)
-      {
-         retval = getClosedChild(nodeData, false);
-         if (retval != null)
-            return retval;
-      }
-      return retval;
-   }
-
-   private final LockActionNonTxAware<LockData, String> getLockDataById = new LockActionNonTxAware<LockData, String>()
-   {
-      public LockData execute(String nodeId) throws LockException
-      {
-         return (LockData)cache.get(makeLockFqn(nodeId), LOCK_DATA);
-      }
-   };
-
-   protected LockData getLockDataById(String nodeId)
-   {
-      try
-      {
-         return executeLockActionNonTxAware(getLockDataById, nodeId);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return null;
-   }
-
-   private final LockActionNonTxAware<List<LockData>, Object> getLockList =
-      new LockActionNonTxAware<List<LockData>, Object>()
-      {
-         public List<LockData> execute(Object arg) throws LockException
-         {
-            Set<Object> nodesId = cache.getChildrenNames(lockRoot);
-
-            List<LockData> locksData = new ArrayList<LockData>();
-            for (Object nodeId : nodesId)
-            {
-               LockData lockData = (LockData)cache.get(makeLockFqn((String)nodeId), LOCK_DATA);
-               if (lockData != null)
-               {
-                  locksData.add(lockData);
-               }
-            }
-            return locksData;
-         }
-      };
-
-   protected synchronized List<LockData> getLockList()
-   {
-      try
-      {
-         return executeLockActionNonTxAware(getLockList, null);
-      }
-      catch (LockException e)
-      {
-         // ignore me will never occur
-      }
-      return null;
-   }
-
-   /**
-    * Remove lock, used by Lock remover.
-    * 
-    * @param nodeIdentifier String
-    */
-   protected void removeLock(String nodeIdentifier)
-   {
-      try
-      {
-         NodeData nData = (NodeData)dataManager.getItemData(nodeIdentifier);
-
-         //TODO EXOJCR-412, should be refactored in future.
-         //Skip removing, because that node was removed in other node of cluster.  
-         if (nData == null)
-         {
-            return;
-         }
-
-         PlainChangesLog changesLog =
-            new PlainChangesLogImpl(new ArrayList<ItemState>(), IdentityConstants.SYSTEM, ExtendedEvent.UNLOCK);
-
-         ItemData lockOwner =
-            copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKOWNER, 1),
-               ItemType.PROPERTY));
-
-         //TODO EXOJCR-412, should be refactored in future.
-         //Skip removing, because that lock was removed in other node of cluster.  
-         if (lockOwner == null)
-         {
-            return;
-         }
-
-         changesLog.add(ItemState.createDeletedState(lockOwner));
-
-         ItemData lockIsDeep =
-            copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKISDEEP, 1),
-               ItemType.PROPERTY));
-
-         //TODO EXOJCR-412, should be refactored in future.
-         //Skip removing, because that lock was removed in other node of cluster.  
-         if (lockIsDeep == null)
-         {
-            return;
-         }
-
-         changesLog.add(ItemState.createDeletedState(lockIsDeep));
-
-         // lock probably removed by other thread
-         if (lockOwner == null && lockIsDeep == null)
-         {
-            return;
-         }
-
-         dataManager.save(new TransactionChangesLog(changesLog));
-      }
-      catch (JCRInvalidItemStateException e)
-      {
-         //TODO EXOJCR-412, should be refactored in future.
-         //Skip property not found in DB, because that lock property was removed in other node of cluster.
-         if (LOG.isDebugEnabled())
-         {
-            LOG.debug("The propperty was removed in other node of cluster.", e);
-         }
-
-      }
-      catch (RepositoryException e)
-      {
-         LOG.error("Error occur during removing lock" + e.getLocalizedMessage(), e);
-      }
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void closeSessionLockManager(String sessionID)
-   {
-      sessionLockManagers.remove(sessionID);
-   }
-
-   /**
     * Make lock absolute Fqn, i.e. /$LOCKS/nodeID.
     *
     * @param itemId String
@@ -1191,73 +549,14 @@
    /**
     *  Will be created structured node in cache, like /$LOCKS
     */
-   private void createStructuredNode(final Fqn<String> fqn)
+   private void createStructuredNode(Fqn<String> fqn)
    {
       Node<Serializable, Object> node = cache.getRoot().getChild(fqn);
       if (node == null)
       {
          cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
-         node = SecurityHelper.doPriviledgedAction(new PrivilegedAction<Node<Serializable, Object>>()
-         {
-            public Node<Serializable, Object> run()
-            {
-               return cache.getRoot().addChild(fqn);
-            }
-         }); 
+         node = cache.getRoot().addChild(fqn);
       }
       node.setResident(true);
    }
-
-   /**
-    * Execute the given action outside a transaction. This is needed since the {@link Cache} used by {@link CacheableLockManagerImpl}
-    * manages the persistence of its locks thanks to a {@link CacheLoader} and a {@link CacheLoader} lock the JBoss 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
-    * Author : Nicolas Filotto 
-    *          nicolas.filotto at exoplatform.com
-    * 21 janv. 2010
-    */
-   private static interface LockActionNonTxAware<R, A>
-   {
-      R execute(A arg) throws LockException;
-   }
 }

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableSessionLockManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableSessionLockManager.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableSessionLockManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 2003-2010 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.core.lock.jbosscache;
-
-import org.exoplatform.services.jcr.core.ExtendedSession;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.impl.core.NodeImpl;
-import org.exoplatform.services.jcr.impl.core.SessionDataManager;
-import org.exoplatform.services.jcr.impl.core.SessionImpl;
-import org.exoplatform.services.jcr.impl.core.lock.AbstractSessionLockManager;
-import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
-import org.exoplatform.services.jcr.util.IdGenerator;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.lock.Lock;
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- * 
- * <br/>Date: 
- *
- * @author <a href="karpenko.sergiy at gmail.com">Karpenko Sergiy</a> 
- * @version $Id$
- */
-public class CacheableSessionLockManager extends AbstractSessionLockManager
-{
-   /**
-    * Logger
-    */
-   private final Log log = ExoLogger.getLogger("exo.jcr.component.core.CacheableSessionLockManager");
-
-   /**
-    * Session identifier.
-    */
-   private final String sessionID;
-
-   /**
-    * Lock tokens held by this session.
-    * [token name, tokens hash]
-    */
-   private final Map<String, String> tokens;
-
-   /**
-    * Map of nodes locked in this session. Need to remove session scoped lock on session close.
-    * [node identifier, lock data]
-    */
-   private final Map<String, LockData> lockedNodes;
-
-   /**
-    * Set of pending locked nodes identifiers.
-    */
-   private final Set<String> pendingLocks;
-
-   /**
-    * Workspace lock manager
-    */
-   private final CacheableLockManager lockManager;
-
-   /**
-    * Constructor.
-    * 
-    * @param sessionID - session identifier
-    * @param lockManager - workspace lock manager
-    */
-   public CacheableSessionLockManager(String sessionID, CacheableLockManager lockManager,
-      SessionDataManager transientManager)
-   {
-      super(transientManager);
-      this.sessionID = sessionID;
-      this.tokens = new HashMap<String, String>();
-      this.lockedNodes = new HashMap<String, LockData>();
-      this.pendingLocks = new HashSet<String>();
-      this.lockManager = lockManager;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public Lock addLock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeOut) throws LockException,
-      RepositoryException
-   {
-
-      String lockToken = IdGenerator.generate();
-
-      NodeData data = (NodeData)node.getData();
-
-      LockData lData = lockManager.getExactNodeOrCloseParentLock(data);
-      if (lData != null)
-      {
-         if (lData.getNodeIdentifier().equals(node.getIdentifier()))
-         {
-            throw new LockException("Node already locked: " + data.getQPath());
-         }
-         else if (lData.isDeep())
-         {
-            throw new LockException("Parent node has deep lock.");
-         }
-      }
-
-      if (isDeep && lockManager.getClosedChild(data) != null)
-      {
-         throw new LockException("Some child node is locked.");
-      }
-
-      String lockTokenHash = lockManager.getLockTokenHash(lockToken);
-
-      lData =
-         new LockData(node.getIdentifier(), lockTokenHash, isDeep, isSessionScoped, node.getSession().getUserID(),
-            timeOut > 0 ? timeOut : lockManager.getDefaultLockTimeOut());
-
-      lockedNodes.put(node.getInternalIdentifier(), lData);
-      pendingLocks.add(node.getInternalIdentifier());
-      tokens.put(lockToken, lData.getTokenHash());
-
-      LockImpl lock = new CacheLockImpl(node.getSession(), lData, this);
-
-      return lock;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void addLockToken(String lt)
-   {
-      tokens.put(lt, lockManager.getLockTokenHash(lt));
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public LockImpl getLock(NodeImpl node) throws LockException, RepositoryException
-   {
-      LockData lData = lockManager.getExactNodeOrCloseParentLock((NodeData)node.getData());
-
-      if (lData == null || (!node.getInternalIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
-      {
-         throw new LockException("Node not locked: " + node.getData().getQPath());
-      }
-      return new CacheLockImpl(node.getSession(), lData, this);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public String[] getLockTokens()
-   {
-      String[] arr = new String[tokens.size()];
-      tokens.keySet().toArray(arr);
-      return arr;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public boolean holdsLock(NodeData node) throws RepositoryException
-   {
-      return lockManager.lockExist(node.getIdentifier());//.getExactNodeLock(node) != null;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   protected boolean isLockedPersisted(NodeData node) throws LockException
-   {
-      LockData lData = null;
-      try
-      {
-         lData = lockManager.getExactNodeOrCloseParentLock(node);
-      }
-      catch (RepositoryException e)
-      {
-         throw new LockException(e.getMessage(), e);
-      }
-
-      if (lData == null || (!node.getIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
-      {
-         return false;
-      }
-      return true;
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   protected boolean isPersistedLockHolder(NodeData node) throws RepositoryException
-   {
-      LockData lData = lockManager.getExactNodeOrCloseParentLock(node);
-      return lData != null && isLockHolder(lData);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void onCloseSession(ExtendedSession session)
-   {
-      SessionImpl sessionImpl = (SessionImpl)session;
-
-      String[] nodeIds = new String[lockedNodes.size()];
-      lockedNodes.keySet().toArray(nodeIds);
-
-      for (String nodeId : nodeIds)
-      {
-         LockData lock = lockedNodes.remove(nodeId);
-
-         if (lock.isSessionScoped() && !pendingLocks.contains(nodeId))
-         {
-            try
-            {
-               NodeImpl node =
-                  ((NodeImpl)sessionImpl.getTransientNodesManager()
-                     .getItemByIdentifier(lock.getNodeIdentifier(), false));
-
-               if (node != null)
-               {
-                  node.unlock();
-               }
-
-            }
-            catch (UnsupportedRepositoryOperationException e)
-            {
-               log.error(e.getLocalizedMessage());
-            }
-            catch (LockException e)
-            {
-               log.error(e.getLocalizedMessage());
-            }
-            catch (AccessDeniedException e)
-            {
-               log.error(e.getLocalizedMessage());
-            }
-            catch (RepositoryException e)
-            {
-               log.error(e.getLocalizedMessage());
-            }
-         }
-      }
-
-      pendingLocks.clear();
-      tokens.clear();
-      lockedNodes.clear();
-
-      lockManager.closeSessionLockManager(sessionID);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   public void removeLockToken(String lt)
-   {
-      tokens.remove(lt);
-   }
-
-   /**
-    * Checks if session has token to this lock data or session is System.
-    * 
-    * @param lockData
-    * @return
-    */
-   private boolean isLockHolder(LockData lockData)
-   {
-      return tokens.containsValue(lockData.getTokenHash());
-   }
-
-   /**
-    * Is session contains pending lock for node by nodeId.
-    * @param nodeId - node ID string
-    * @return boolean
-    */
-   public boolean containsPendingLock(String nodeId)
-   {
-      return pendingLocks.contains(nodeId);
-   }
-
-   /**
-    * Returns real token, if session has it.
-    * 
-    * @param tokenHash - token hash string
-    * @return lock token string
-    */
-   protected String getLockToken(String tokenHash)
-   {
-      for (String token : tokens.keySet())
-      {
-         if (tokens.get(token).equals(tokenHash))
-         {
-            return token;
-         }
-      }
-      return null;
-   }
-
-   /**
-    * Return pending lock.
-    * 
-    * @param nodeId - ID of locked node
-    * @return pending lock or null
-    */
-   public LockData getPendingLock(String nodeId)
-   {
-      if (pendingLocks.contains(nodeId))
-      {
-         return lockedNodes.get(nodeId);
-      }
-      else
-      {
-         return null;
-      }
-   }
-
-   /**
-    * Check is lock alive. That means lock must exist in LockManager storage (cache or map, etc). 
-    * 
-    * @param nodeIdentifier - locked node id
-    * @return
-    */
-   protected boolean isLockLive(String nodeIdentifier) throws LockException
-   {
-
-      if (lockManager.isLockLive(nodeIdentifier))
-      {
-         return true;
-      }
-      else
-      {
-         return pendingLocks.contains(nodeIdentifier);
-      }
-   }
-
-   public void notifyLockPersisted(String nodeIdentifier)
-   {
-      pendingLocks.remove(nodeIdentifier);
-   }
-
-   /**
-    * Notify SessionLockManager that node is unlocked.
-    * 
-    * @param nodeIdentifier - unlocked node identifier
-    */
-   public void notifyLockRemoved(String nodeIdentifier)
-   {
-      lockedNodes.remove(nodeIdentifier);
-   }
-
-   /**
-    * Refresh lockData. 
-    * 
-    * @param newLockData
-    * @throws LockException
-    */
-   protected void refresh(LockData newLockData) throws LockException
-   {
-      lockManager.refreshLockData(newLockData);
-   }
-
-   /**
-    * {@inheritDoc}
-    */
-   protected boolean checkPersistedLocks(NodeData node) throws LockException
-   {
-      LockData lData = null;
-      try
-      {
-         lData = lockManager.getExactNodeOrCloseParentLock(node);
-      }
-      catch (RepositoryException e)
-      {
-         throw new LockException(e.getMessage(), e);
-      }
-
-      if (lData == null || (!node.getIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
-      {
-         return true;
-      }
-
-      // lock exist, so lets check is current session is LockHolder
-      return isLockHolder(lData);
-   }
-
-}

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,264 +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.lock.jbosscache;
-
-import org.exoplatform.services.jcr.impl.Constants;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-/**
- * Created by The eXo Platform SAS.
- * 
- * @author <a href="mailto:gennady.azarenkov at exoplatform.com">Gennady Azarenkov</a>
- * @version $Id: LockData.java 787 2009-11-20 11:36:15Z nzamosenchuk $
- */
-
-public class LockData implements Externalizable
-{
-   /**
-    * The time of birth. From this time we start count the time of death. death = birthday+TIME_OUT;
-    */
-   private long birthday;
-
-   /**
-    * If isDeep is true then the lock applies to this node and all its descendant nodes; if false,
-    * the lock applies only to this, the holding node.
-    */
-   private boolean deep;
-
-   /**
-    * A lock token is a string that uniquely identifies a particular lock and acts as a “key”
-    * allowing a user to alter a locked node. LockData stores only token hash.
-    */
-   private String tokenHash;
-
-   /**
-    * Identifier of locked node.
-    */
-   private String nodeIdentifier;
-
-   /**
-    * The owner of the locked node.
-    */
-   private String owner;
-
-   /**
-    * If isSessionScoped is true then this lock will expire upon the expiration of the current
-    * session (either through an automatic or explicit Session.logout); if false, this lock does not
-    * expire until explicitly unlocked or automatically unlocked due to a implementation-specific
-    * limitation, such as a timeout.
-    */
-   private boolean sessionScoped;
-
-   /**
-    * <B>8.4.9 Timing Out</B> An implementation may unlock any lock at any time due to
-    * implementation-specific criteria, such as time limits on locks.
-    */
-   private long timeOut;
-
-   // Need for Externalizable
-   public LockData()
-   {
-      this.sessionScoped = false;
-      this.deep = false;
-   }
-
-   /**
-    * @param nodeIdentifier
-    * @param lockToken
-    * @param deep
-    * @param sessionScoped
-    * @param owner
-    * @param timeOut
-    *       is seconds!
-    */
-   public LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean sessionScoped, String owner,
-      long timeOut)
-   {
-      this(nodeIdentifier, lockTokenHash, deep, sessionScoped, owner, timeOut, System.currentTimeMillis());
-   }
-   
-   /**
-    * @param nodeIdentifier
-    * @param lockToken
-    * @param deep
-    * @param sessionScoped
-    * @param owner
-    * @param timeOut
-    *       is seconds!
-    * @param birthday
-    */
-   public LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean sessionScoped, String owner,
-      long timeOut, long birthday)
-   {
-      this.nodeIdentifier = nodeIdentifier;
-      this.tokenHash = lockTokenHash;
-      this.deep = deep;
-      this.sessionScoped = sessionScoped;
-      this.owner = owner;
-      this.timeOut = timeOut;
-      this.birthday = birthday;
-   }
-
-   /*
-    * (non-Javadoc)
-    * @see java.lang.Object#equals(java.lang.Object)
-    */
-   @Override
-   public boolean equals(Object obj)
-   {
-      if (super.equals(obj))
-      {
-         return true;
-      }
-      if (obj instanceof LockData)
-      {
-         return hashCode() == obj.hashCode();
-      }
-      return false;
-   }
-
-   /**
-    * @return the nodeIdentifier
-    */
-   public String getNodeIdentifier()
-   {
-      return nodeIdentifier;
-   }
-
-   /**
-    * @return
-    */
-   public String getOwner()
-   {
-      return owner;
-   }
-
-   /**
-    * @return The time to death in millis
-    */
-   public long getTimeToDeath()
-   {
-      return birthday + timeOut - System.currentTimeMillis();
-   }
-
-   public String getTokenHash()
-   {
-      return tokenHash;
-   }
-
-   /*
-    * (non-Javadoc)
-    * @see java.lang.Object#hashCode()
-    */
-   @Override
-   public int hashCode()
-   {
-      return tokenHash.hashCode();
-   }
-
-   public boolean isDeep()
-   {
-      return deep;
-   }
-
-   /**
-    * @return
-    */
-   public boolean isSessionScoped()
-   {
-      return sessionScoped;
-   }
-
-   /**
-    * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
-    */
-   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
-   {
-      // read boolean
-      this.deep = in.readBoolean();
-      this.sessionScoped = in.readBoolean();
-      // read long
-      this.birthday = in.readLong();
-      this.timeOut = in.readLong();
-      //read strings
-      // read uuid
-      byte[] buf;
-      buf = new byte[in.readInt()];
-      in.readFully(buf);
-      this.nodeIdentifier = new String(buf, Constants.DEFAULT_ENCODING);
-      // read owner
-      buf = new byte[in.readInt()];
-      in.readFully(buf);
-      this.owner = new String(buf, Constants.DEFAULT_ENCODING);
-      // read token
-      buf = new byte[in.readInt()];
-      in.readFully(buf);
-      this.tokenHash = new String(buf, Constants.DEFAULT_ENCODING);
-   }
-
-   /**
-    * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
-    */
-   public void writeExternal(ObjectOutput out) throws IOException
-   {
-      // write boolean
-      out.writeBoolean(deep);
-      out.writeBoolean(sessionScoped);
-      // write long
-      out.writeLong(birthday);
-      out.writeLong(timeOut);
-      // write string
-      // node uuid
-      byte[] ptbuf = nodeIdentifier.getBytes(Constants.DEFAULT_ENCODING);
-      out.writeInt(ptbuf.length);
-      out.write(ptbuf);
-      // node owner
-      ptbuf = owner.getBytes(Constants.DEFAULT_ENCODING);
-      out.writeInt(ptbuf.length);
-      out.write(ptbuf);
-      // node token
-      ptbuf = tokenHash.getBytes(Constants.DEFAULT_ENCODING);
-      out.writeInt(ptbuf.length);
-      out.write(ptbuf);
-
-   }
-
-   /**
-    * @return
-    */
-   public long getTimeOut()
-   {
-      return timeOut;
-   }
-
-   public long getBirthDay()
-   {
-      return birthday;
-   }
-
-   public void setTimeOut(long timeOut)
-   {
-      this.timeOut = timeOut;
-   }
-
-}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/CacheableJDBCLockManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/CacheableJDBCLockManagerImpl.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/CacheableJDBCLockManagerImpl.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -43,9 +43,9 @@
 import org.exoplatform.services.jcr.impl.core.lock.LockRemover;
 import org.exoplatform.services.jcr.impl.core.lock.LockRemoverHolder;
 import org.exoplatform.services.jcr.impl.core.lock.SessionLockManager;
-import org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableLockManager;
-import org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableSessionLockManager;
-import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockData;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.CacheableLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.CacheableSessionLockManager;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.LockData;
 import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
 import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
 import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
@@ -814,7 +814,9 @@
    public LockData getExactNodeOrCloseParentLock(NodeData node) throws RepositoryException
    {
       if (node == null)
+      {
          return null;
+      }
       LockData retval = null;
       retval = getLockDataById(node.getIdentifier());
       if (retval == null)
@@ -840,14 +842,18 @@
       {
          retval = getLockDataById(nodeData.getIdentifier());
          if (retval != null)
+         {
             return retval;
+         }
       }
       // child not found try to find dipper
       for (NodeData nodeData : childData)
       {
          retval = getClosedChild(nodeData);
          if (retval != null)
+         {
             return retval;
+         }
       }
       return retval;
    }

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/LockJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/LockJDBCConnection.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/jdbc/LockJDBCConnection.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -16,7 +16,7 @@
  */
 package org.exoplatform.services.jcr.impl.core.lock.jbosscache.jdbc;
 
-import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockData;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.LockData;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexChangesFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexChangesFilter.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexChangesFilter.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -27,8 +27,8 @@
 import org.exoplatform.services.jcr.impl.core.query.IndexingTree;
 import org.exoplatform.services.jcr.impl.core.query.QueryHandler;
 import org.exoplatform.services.jcr.impl.core.query.SearchManager;
-import org.exoplatform.services.jcr.impl.util.PrivilegedCacheHelper;
 import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory;
+import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
 import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory.CacheType;
 import org.exoplatform.services.jcr.util.IdGenerator;
 import org.exoplatform.services.log.ExoLogger;
@@ -136,8 +136,8 @@
          ExoJBossCacheFactory.getUniqueInstance(CacheType.INDEX_CACHE, rootFqn, initCache, config.getParameterBoolean(
             PARAM_JBOSSCACHE_SHAREABLE, PARAM_JBOSSCACHE_SHAREABLE_DEFAULT));
 
-      PrivilegedCacheHelper.create(cache);
-      PrivilegedCacheHelper.start(cache);
+      PrivilegedJBossCacheHelper.create(cache);
+      PrivilegedJBossCacheHelper.start(cache);
 
       // start will invoke cache listener which will notify handler that mode is changed
       IndexerIoMode ioMode =
@@ -192,7 +192,7 @@
       String id = IdGenerator.generate();
       try
       {
-         PrivilegedCacheHelper.put(cache, Fqn.fromRelativeElements(rootFqn, id), LISTWRAPPER,
+         PrivilegedJBossCacheHelper.put(cache, Fqn.fromRelativeElements(rootFqn, id), LISTWRAPPER,
             new ChangesFilterListsWrapper(addedNodes, removedNodes, parentAddedNodes, parentRemovedNodes));
       }
       catch (CacheException e)

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexInfos.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -23,7 +23,7 @@
 import org.exoplatform.services.jcr.impl.core.query.IndexerIoModeListener;
 import org.exoplatform.services.jcr.impl.core.query.lucene.IndexInfos;
 import org.exoplatform.services.jcr.impl.core.query.lucene.MultiIndex;
-import org.exoplatform.services.jcr.impl.util.PrivilegedCacheHelper;
+import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.jboss.cache.Cache;
@@ -84,7 +84,8 @@
    /**
     * @param cache instance of JbossCache that is used to deliver index names
     */
-   public JBossCacheIndexInfos(Fqn<String> rootFqn, Cache<Serializable, Object> cache, boolean system, IndexerIoModeHandler modeHandler)
+   public JBossCacheIndexInfos(Fqn<String> rootFqn, Cache<Serializable, Object> cache, boolean system,
+      IndexerIoModeHandler modeHandler)
    {
       this(rootFqn, DEFALUT_NAME, cache, system, modeHandler);
    }
@@ -159,7 +160,7 @@
          // write to FS
          super.write();
          // write to cache
-         PrivilegedCacheHelper.put(cache, namesFqn, LIST_KEY, getNames());
+         PrivilegedJBossCacheHelper.put(cache, namesFqn, LIST_KEY, getNames());
       }
    }
 

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/jbosscache/JBossCacheIndexUpdateMonitor.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -24,7 +24,7 @@
 import org.exoplatform.services.jcr.impl.core.query.lucene.IndexInfos;
 import org.exoplatform.services.jcr.impl.core.query.lucene.IndexUpdateMonitor;
 import org.exoplatform.services.jcr.impl.core.query.lucene.IndexUpdateMonitorListener;
-import org.exoplatform.services.jcr.impl.util.PrivilegedCacheHelper;
+import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.jboss.cache.Cache;
@@ -157,7 +157,7 @@
          localUpdateInProgress = updateInProgress;
          if (persitentUpdate)
          {
-            PrivilegedCacheHelper.put(cache, parametersFqn, PARAMETER_NAME, new Boolean(updateInProgress));
+            PrivilegedJBossCacheHelper.put(cache, parametersFqn, PARAMETER_NAME, new Boolean(updateInProgress));
 
          }
          for (IndexUpdateMonitorListener listener : listeners)

Added: 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	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,1021 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.AdvancedCache;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.Configuration.CacheMode;
+import org.infinispan.context.Flag;
+import org.infinispan.lifecycle.ComponentStatus;
+import org.infinispan.manager.CacheContainer;
+import org.infinispan.util.concurrent.NotifyingFuture;
+
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.transaction.TransactionManager;
+
+/**
+ * Decorator over the Infinispan Cache that stores changes in buffer, then sorts and applies it.
+ * 
+ * @author <a href="mailto:Sergey.Kabashnyuk at exoplatform.org">Sergey Kabashnyuk</a>
+ * @version $Id: BufferedISPNCache.java 3514 2010-11-22 16:14:36Z nzamosenchuk $
+ * 
+ */
+ at SuppressWarnings("unchecked")
+public class BufferedISPNCache implements Cache<Serializable, Object>
+{
+   /**
+    * Parent cache.
+    */
+   private final AdvancedCache<Serializable, Object> parentCache;
+
+   private final ThreadLocal<CompressedISPNChangesBuffer> changesList = new ThreadLocal<CompressedISPNChangesBuffer>();
+
+   private ThreadLocal<Boolean> local = new ThreadLocal<Boolean>();
+
+   /**
+    * Allow to perform local cache changes.
+    */
+   private final Boolean allowLocalChanges;
+
+   protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.BufferedISPNCache");
+
+   public static enum ChangesType {
+      REMOVE, PUT;
+   }
+
+   /**
+    * Container for changes
+    */
+   public static abstract class ChangesContainer implements Comparable<ChangesContainer>
+   {
+      protected final CacheKey key;
+
+      protected final ChangesType changesType;
+
+      protected final AdvancedCache<Serializable, Object> cache;
+
+      protected final int historicalIndex;
+
+      protected final boolean localMode;
+
+      private final Boolean allowLocalChanges;
+
+      public ChangesContainer(CacheKey key, ChangesType changesType, AdvancedCache<Serializable, Object> cache,
+         int historicalIndex, boolean localMode, Boolean allowLocalChanges)
+      {
+         this.key = key;
+         this.changesType = changesType;
+         this.cache = cache;
+         this.historicalIndex = historicalIndex;
+         this.localMode = localMode;
+         this.allowLocalChanges = allowLocalChanges;
+      }
+
+      /**
+       * @return the key
+       */
+      public CacheKey getKey()
+      {
+         return key;
+      }
+
+      /**
+       * @return the index of change in original sequence
+       */
+      public int getHistoricalIndex()
+      {
+         return historicalIndex;
+      }
+
+      /**
+       * @return the changesType
+       */
+      public ChangesType getChangesType()
+      {
+         return changesType;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      public String toString()
+      {
+         return key.toString() + " type=" + changesType + " historysIndex=" + historicalIndex;
+      }
+
+      /**
+       * {@inheritDoc}
+       */
+      public int compareTo(ChangesContainer o)
+      {
+         int result = key.compareTo(o.getKey());
+         return result == 0 ? historicalIndex - o.getHistoricalIndex() : result;
+      }
+
+      protected void setCacheLocalMode()
+      {
+         if (localMode)
+         {
+            if (allowLocalChanges == null)
+            {
+               CacheMode cacheMode = cache.getConfiguration().getCacheMode();
+               if (cacheMode != CacheMode.DIST_ASYNC && cacheMode != CacheMode.DIST_SYNC)
+               {
+                  cache.withFlags(Flag.CACHE_MODE_LOCAL);
+               }
+            }
+            else if (allowLocalChanges)
+            {
+               cache.withFlags(Flag.CACHE_MODE_LOCAL);
+            }
+         }
+      }
+
+      public abstract void apply();
+   }
+
+   /**
+    * Put object container;
+    */
+   public static class PutObjectContainer extends ChangesContainer
+   {
+      private final Object value;
+
+      public PutObjectContainer(CacheKey key, Object value, AdvancedCache<Serializable, Object> cache,
+         int historicalIndex, boolean local, Boolean allowLocalChanges)
+      {
+         super(key, ChangesType.PUT, cache, historicalIndex, local, allowLocalChanges);
+
+         this.value = value;
+      }
+
+      @Override
+      public void apply()
+      {
+         setCacheLocalMode();
+         cache.put(key, value);
+      }
+   }
+
+   /**
+    * It tries to get Set by given key. If it is Set then adds new value and puts new set back. If
+    * null found, then new Set created (ordinary cache does).
+    */
+   public static class AddToListContainer extends ChangesContainer
+   {
+      private final Object value;
+
+      private final boolean forceModify;
+
+      public AddToListContainer(CacheKey key, Object value, AdvancedCache<Serializable, Object> cache,
+         boolean forceModify, int historicalIndex, boolean local, Boolean allowLocalChanges)
+      {
+         super(key, ChangesType.PUT, cache, historicalIndex, local, allowLocalChanges);
+         this.value = value;
+         this.forceModify = forceModify;
+      }
+
+      @Override
+      public void apply()
+      {
+         // force writeLock on next read
+         cache.withFlags(Flag.FORCE_WRITE_LOCK);
+
+         Object existingObject = cache.get(key);
+         Set<Object> newSet = new HashSet<Object>();
+
+         // if set found of null, perform add
+         if (existingObject instanceof Set || (existingObject == null && forceModify))
+         {
+            // set found
+            if (existingObject instanceof Set)
+            {
+               newSet.addAll((Set<Object>)existingObject);
+            }
+            newSet.add(value);
+
+            setCacheLocalMode();
+            cache.put(key, newSet);
+         }
+         else if (existingObject != null)
+         {
+            LOG.error("Unexpected object found by key " + key.toString() + ". Expected Set, but found:"
+               + existingObject.getClass().getName());
+         }
+      }
+   }
+
+   /**
+    * It tries to get set by given key. If it is set then removes value and puts new modified set
+    * back.
+    */
+   public static class RemoveFromListContainer extends ChangesContainer
+   {
+      private final Object value;
+
+      public RemoveFromListContainer(CacheKey key, Object value, AdvancedCache<Serializable, Object> cache,
+         int historicalIndex, boolean local, Boolean allowLocalChanges)
+      {
+         super(key, ChangesType.REMOVE, cache, historicalIndex, local, allowLocalChanges);
+         this.value = value;
+      }
+
+      @Override
+      public void apply()
+      {
+         // force writeLock on next read
+         cache.withFlags(Flag.FORCE_WRITE_LOCK);
+
+         setCacheLocalMode();
+         Object existingObject = cache.get(key);
+
+         // if found value is really set! add to it.
+         if (existingObject instanceof Set)
+         {
+            Set<Object> newSet = new HashSet<Object>((Set<Object>)existingObject);
+            newSet.remove(value);
+
+            setCacheLocalMode();
+            cache.put(key, newSet);
+         }
+      }
+   }
+
+   /**
+    * Remove container.
+    */
+   public static class RemoveObjectContainer extends ChangesContainer
+   {
+      public RemoveObjectContainer(CacheKey key, AdvancedCache<Serializable, Object> cache, int historicalIndex,
+         boolean local, Boolean allowLocalChanges)
+      {
+         super(key, ChangesType.REMOVE, cache, historicalIndex, local, allowLocalChanges);
+      }
+
+      @Override
+      public void apply()
+      {
+         setCacheLocalMode();
+         cache.remove(key);
+      }
+   }
+
+   public BufferedISPNCache(Cache<Serializable, Object> parentCache, Boolean allowLocalChanges)
+   {
+      this.parentCache = parentCache.getAdvancedCache();
+      this.allowLocalChanges = allowLocalChanges;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Void> clearAsync()
+   {
+      return parentCache.clearAsync();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void compact()
+   {
+      parentCache.compact();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void endBatch(boolean successful)
+   {
+      parentCache.endBatch(successful);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Set<java.util.Map.Entry<Serializable, Object>> entrySet()
+   {
+      return parentCache.entrySet();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void evict(Serializable key)
+   {
+      parentCache.evict(key);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public AdvancedCache<Serializable, Object> getAdvancedCache()
+   {
+      return parentCache.getAdvancedCache();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public CacheContainer getCacheManager()
+   {
+      return parentCache.getCacheManager();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Configuration getConfiguration()
+   {
+      return parentCache.getConfiguration();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getName()
+   {
+      return parentCache.getName();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ComponentStatus getStatus()
+   {
+      return parentCache.getStatus();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public String getVersion()
+   {
+      return parentCache.getVersion();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Set<Serializable> keySet()
+   {
+      return parentCache.keySet();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object put(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.put(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object put(Serializable key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime,
+      TimeUnit maxIdleTimeUnit)
+   {
+      return parentCache.put(key, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void putAll(Map<? extends Serializable, ? extends Object> map, long lifespan, TimeUnit unit)
+   {
+      parentCache.putAll(map, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void putAll(Map<? extends Serializable, ? extends Object> map, long lifespan, TimeUnit lifespanUnit,
+      long maxIdleTime, TimeUnit maxIdleTimeUnit)
+   {
+      parentCache.putAll(map, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Void> putAllAsync(Map<? extends Serializable, ? extends Object> data)
+   {
+      return parentCache.putAllAsync(data);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Void> putAllAsync(Map<? extends Serializable, ? extends Object> data, long lifespan,
+      TimeUnit unit)
+   {
+      return parentCache.putAllAsync(data, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Void> putAllAsync(Map<? extends Serializable, ? extends Object> data, long lifespan,
+      TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit)
+   {
+      return parentCache.putAllAsync(data, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putAsync(Serializable key, Object value)
+   {
+      return parentCache.putAsync(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putAsync(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.putAsync(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putAsync(Serializable key, Object value, long lifespan, TimeUnit lifespanUnit,
+      long maxIdle, TimeUnit maxIdleUnit)
+   {
+      return parentCache.putAsync(key, value, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void putForExternalRead(Serializable key, Object value)
+   {
+      parentCache.putForExternalRead(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object putIfAbsent(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.putIfAbsent(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object putIfAbsent(Serializable key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime,
+      TimeUnit maxIdleTimeUnit)
+   {
+      return parentCache.putIfAbsent(key, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putIfAbsentAsync(Serializable key, Object value)
+   {
+      return parentCache.putIfAbsentAsync(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putIfAbsentAsync(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.putIfAbsentAsync(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> putIfAbsentAsync(Serializable key, Object value, long lifespan,
+      TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit)
+   {
+      return parentCache.putIfAbsentAsync(key, value, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> removeAsync(Object key)
+   {
+      return parentCache.removeAsync(key);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Boolean> removeAsync(Object key, Object value)
+   {
+      return parentCache.removeAsync(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object replace(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.replace(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean replace(Serializable key, Object oldValue, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.replace(key, oldValue, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object replace(Serializable key, Object value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime,
+      TimeUnit maxIdleTimeUnit)
+   {
+      return parentCache.replace(key, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean replace(Serializable key, Object oldValue, Object value, long lifespan, TimeUnit lifespanUnit,
+      long maxIdleTime, TimeUnit maxIdleTimeUnit)
+   {
+      return parentCache.replace(key, oldValue, value, lifespan, lifespanUnit, maxIdleTime, maxIdleTimeUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> replaceAsync(Serializable key, Object value)
+   {
+      return parentCache.replaceAsync(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Boolean> replaceAsync(Serializable key, Object oldValue, Object newValue)
+   {
+      return parentCache.replaceAsync(key, oldValue, newValue);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> replaceAsync(Serializable key, Object value, long lifespan, TimeUnit unit)
+   {
+      return parentCache.replaceAsync(key, value, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Boolean> replaceAsync(Serializable key, Object oldValue, Object newValue, long lifespan,
+      TimeUnit unit)
+   {
+      return parentCache.replaceAsync(key, oldValue, newValue, lifespan, unit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Object> replaceAsync(Serializable key, Object value, long lifespan, TimeUnit lifespanUnit,
+      long maxIdle, TimeUnit maxIdleUnit)
+   {
+      return parentCache.replaceAsync(key, value, lifespan, lifespanUnit, maxIdle, maxIdleUnit);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NotifyingFuture<Boolean> replaceAsync(Serializable key, Object oldValue, Object newValue, long lifespan,
+      TimeUnit lifespanUnit, long maxIdle, TimeUnit maxIdleUnit)
+   {
+      return parentCache.replaceAsync(key, oldValue, newValue);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean startBatch()
+   {
+      return parentCache.startBatch();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Collection<Object> values()
+   {
+      return parentCache.values();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object putIfAbsent(Serializable key, Object value)
+   {
+      return parentCache.putIfAbsent(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean remove(Object key, Object value)
+   {
+      return parentCache.remove(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object replace(Serializable key, Object value)
+   {
+      return parentCache.replace(key, value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean replace(Serializable key, Object oldValue, Object newValue)
+   {
+      return parentCache.replace(key, oldValue, newValue);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void clear()
+   {
+      parentCache.clear();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean containsKey(Object key)
+   {
+      return parentCache.containsKey(key);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean containsValue(Object value)
+   {
+      return parentCache.containsValue(value);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object get(Object key)
+   {
+      return parentCache.get(key);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isEmpty()
+   {
+      return parentCache.isEmpty();
+   }
+
+   /**
+    * Put object in cache.
+    * 
+    * @param key
+    *          cache key
+    * @param value
+    *          cache value
+    * @return
+    *          always returns null  
+    */
+   public Object put(CacheKey key, Object value)
+   {
+      return put(key, value, false);
+   }
+
+   /**
+    * Put object in cache.
+    * @param key
+    *          cache key
+    * @param value
+    *          cache value
+    * @param withReturnValue
+    *          indicates if a return value is expected
+    * @return <code>null</code> if <code>withReturnValue</code> has been set to <code>false</code>
+    * the previous value otherwise
+    */
+   public Object put(final CacheKey key, Object value, final boolean withReturnValue)
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+      changesContainer.add(new PutObjectContainer(key, value, parentCache, changesContainer.getHistoryIndex(), local
+         .get(), allowLocalChanges));
+
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            return withReturnValue ? parentCache.get(key) : null;
+         }
+      };
+      return AccessController.doPrivileged(action);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object put(Serializable key, Object value)
+   {
+      throw new UnsupportedOperationException("Unexpected method call use put(CacheKey key, Object value)");
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void putAll(Map<? extends Serializable, ? extends Object> m)
+   {
+      parentCache.putAll(m);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Object remove(Object key)
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+      changesContainer.add(new RemoveObjectContainer((CacheKey)key, parentCache, changesContainer.getHistoryIndex(),
+         local.get(), allowLocalChanges));
+
+      // return null as we never used result
+      return null;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int size()
+   {
+      return parentCache.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void start()
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            parentCache.start();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void stop()
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            parentCache.stop();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void addListener(Object listener)
+   {
+      parentCache.addListener(listener);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public Set<Object> getListeners()
+   {
+      return parentCache.getListeners();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void removeListener(Object listener)
+   {
+      parentCache.removeListener(listener);
+   }
+
+   /**
+    * Start buffering process.
+    */
+   public void beginTransaction()
+   {
+      changesList.set(new CompressedISPNChangesBuffer());
+      local.set(false);
+   }
+
+   /**
+    * 
+    * @return status of the cache transaction
+    */
+   public boolean isTransactionActive()
+   {
+      return changesList.get() != null;
+   }
+
+   /**
+    * Sort changes and commit data to the cache.
+    */
+   public void commitTransaction()
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+      try
+      {
+         List<ChangesContainer> containers = changesContainer.getSortedList();
+         for (ChangesContainer cacheChange : containers)
+         {
+            cacheChange.apply();
+         }
+      }
+      finally
+      {
+         changesList.set(null);
+         changesContainer = null;
+      }
+   }
+
+   /**
+    * Forget about changes
+    */
+   public void rollbackTransaction()
+   {
+      changesList.set(null);
+   }
+
+   /**
+    * Creates all ChangesBuffers with given parameter
+    * 
+    * @param local
+    */
+   public void setLocal(boolean local)
+   {
+      // start local transaction
+      if (local && changesList.get() == null)
+      {
+         beginTransaction();
+      }
+      if (!local && this.local.get())
+      {
+
+      }
+      this.local.set(local);
+   }
+
+   /**
+    * Tries to get buffer and if it is null throws an exception otherwise returns buffer.
+    * 
+    * @return
+    */
+   private CompressedISPNChangesBuffer getChangesBufferSafe()
+   {
+      CompressedISPNChangesBuffer changesContainer = changesList.get();
+      if (changesContainer == null)
+      {
+         throw new IllegalStateException("changesContainer should not be empty");
+      }
+      return changesContainer;
+   }
+
+   public TransactionManager getTransactionManager()
+   {
+      return parentCache.getTransactionManager();
+   }
+
+   /**
+    * 
+    * @param key
+    * @param value
+    */
+   public void addToList(CacheKey key, Object value, boolean forceModify)
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+      changesContainer.add(new AddToListContainer(key, value, parentCache, forceModify, changesContainer
+         .getHistoryIndex(), local.get(), allowLocalChanges));
+   }
+
+   /**
+    * 
+    * @param string
+    * @param node
+    * @return
+    */
+   public Object putInBuffer(CacheKey key, Object value)
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+
+      // take Object from buffer for first 
+      Object prevObject = getObjectFromChangesContainer(changesContainer, key);
+
+      changesContainer.add(new PutObjectContainer(key, value, parentCache, changesContainer.getHistoryIndex(), local
+         .get(), allowLocalChanges));
+
+      if (prevObject != null)
+      {
+         return prevObject;
+      }
+      else
+      {
+         return parentCache.get(key);
+      }
+   }
+
+   private Object getObjectFromChangesContainer(CompressedISPNChangesBuffer changesContainer, CacheKey key)
+   {
+      List<ChangesContainer> changes = changesContainer.getSortedList();
+      Object object = null;
+
+      for (ChangesContainer change : changes)
+      {
+         if (change.getChangesType().equals(ChangesType.PUT) && change.getKey().equals(key))
+         {
+            object = ((PutObjectContainer)change).value;
+         }
+      }
+
+      return object;
+   }
+
+   /**
+    * 
+    * @param key
+    * @param value
+    */
+   public void removeFromList(CacheKey key, Object value)
+   {
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+      changesContainer.add(new RemoveFromListContainer(key, value, parentCache, changesContainer.getHistoryIndex(),
+         local.get(), allowLocalChanges));
+   }
+
+   public Object getFromBuffer(CacheKey key)
+   {
+      //look at buffer for first
+      CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+
+      Object objectFromBuffer = getObjectFromChangesContainer(changesContainer, key);
+
+      if (objectFromBuffer != null)
+      {
+         return objectFromBuffer;
+      }
+      else
+      {
+         return parentCache.get(key);
+      }
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheId.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheId.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,55 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+/**
+ * 
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: CacheId.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public class CacheId extends CacheKey
+{
+
+   /**
+    * CacheId constructor.
+    * 
+    * @param id
+    */
+   CacheId(String id)
+   {
+      super(id);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof CacheId)
+      {
+         CacheId cacheId = (CacheId)obj;
+         return (cacheId.hash == hash && cacheId.id.equals(id));
+      }
+      else
+      {
+         return false;
+      }
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheKey.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheKey.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheKey.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,71 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+import java.io.Serializable;
+
+/**
+ * Created by The eXo Platform SAS. <br/>
+ * 
+ * Base class for WorkspaceCache keys.<br/>
+ * 
+ * Date: 10.06.2008<br/>
+ * 
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
+ * @version $Id: CacheKey.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public abstract class CacheKey implements Serializable, Comparable<CacheKey>
+{
+
+   protected final String id;
+
+   protected final int hash;
+
+   CacheKey(String id)
+   {
+      this.id = id;
+      this.hash = id.hashCode();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public int hashCode()
+   {
+      return this.hash;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public String toString()
+   {
+      return this.id.toString();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int compareTo(CacheKey o)
+   {
+      return id.compareTo(o.id);
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheNodesId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheNodesId.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheNodesId.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,57 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+/**
+ * Created by The eXo Platform SAS
+ * 
+ * Date: 10.06.2008
+ * 
+ * Cache record used to store item Id key.
+ * 
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
+ * @version $Id: CacheNodesId.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public class CacheNodesId extends CacheKey
+{
+
+   public static final String PREFIX = "N";
+
+   CacheNodesId(String id)
+   {
+      super(PREFIX + id);
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof CacheNodesId)
+      {
+         CacheNodesId cacheNodesId = (CacheNodesId)obj;
+         return (cacheNodesId.hash == hash && cacheNodesId.id.equals(id));
+      }
+      else
+      {
+         return false;
+      }
+   }
+
+   // check is this descendant of prevRootPath
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePropsId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePropsId.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePropsId.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,54 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+/**
+ * Created by The eXo Platform SAS
+ * 
+ * Date: 10.06.2008
+ * 
+ * Cache record used to store item Id key.
+ * 
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
+ * @version $Id: CachePropsId.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public class CachePropsId extends CacheKey
+{
+
+   public static final String PREFIX = "P";
+
+   CachePropsId(String id)
+   {
+      super(PREFIX + id);
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof CachePropsId)
+      {
+         CachePropsId cachePropsId = (CachePropsId)obj;
+         return (cachePropsId.hash == hash && cachePropsId.id.equals(id));
+      }
+      else
+      {
+         return false;
+      }
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheQPath.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheQPath.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheQPath.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,87 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+import org.exoplatform.services.jcr.datamodel.ItemType;
+import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+
+/**
+ * Created by The eXo Platform SAS. <br/>
+ * 
+ * Store QPath as key in cache.
+ * 
+ * 15.06.07
+ * 
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
+ * @version $Id: CacheQPath.java 3393 2010-11-04 07:54:54Z tolusha $
+ */
+class CacheQPath extends CacheKey
+{
+
+   private final String parentId;
+
+   private final QPath path;
+
+   CacheQPath(String parentId, QPath path, ItemType itemType)
+   {
+      super(new StringBuilder().append(parentId != null ? parentId : Constants.ROOT_PARENT_UUID)
+         .append(path.getEntries()[path.getEntries().length - 1].getAsString(true)).append(itemType.toString())
+         .toString());
+
+      this.parentId = parentId;
+      this.path = path;
+   }
+
+   CacheQPath(String parentId, QPathEntry name, ItemType itemType)
+   {
+      super(new StringBuilder().append(parentId != null ? parentId : Constants.ROOT_PARENT_UUID)
+         .append(name.getAsString(true)).append(itemType.toString()).toString());
+
+      this.parentId = parentId;
+      this.path = null;
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof CacheQPath)
+      {
+         CacheQPath cacheQPath = (CacheQPath)obj;
+         return (cacheQPath.hashCode() == hash && cacheQPath.id.equals(id));
+      }
+      else
+      {
+         return false;
+      }
+   }
+
+   @Override
+   public String toString()
+   {
+      final StringBuilder s = new StringBuilder();
+      s.append((this.parentId != null ? this.parentId : Constants.ROOT_PARENT_UUID));
+      s.append((path != null ? path.getEntries()[path.getEntries().length - 1] : "null"));
+      s.append(", ");
+      s.append(id);
+      return s.toString();
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheRefsId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheRefsId.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CacheRefsId.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,54 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+/**
+ * Created by The eXo Platform SAS
+ * 
+ * Date: 10.06.2008
+ * 
+ * Cache record used to store item Id key.
+ * 
+ * @author <a href="mailto:peter.nedonosko at exoplatform.com.ua">Peter Nedonosko</a>
+ * @version $Id: CachePropsId.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public class CacheRefsId extends CacheKey
+{
+
+   public static final String PREFIX = "R";
+
+   CacheRefsId(String id)
+   {
+      super(PREFIX + id);
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj instanceof CacheRefsId)
+      {
+         CacheRefsId cachePropsId = (CacheRefsId)obj;
+         return (cachePropsId.hash == hash && cachePropsId.id.equals(id));
+      }
+      else
+      {
+         return false;
+      }
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CompressedISPNChangesBuffer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CompressedISPNChangesBuffer.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CompressedISPNChangesBuffer.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,73 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+import org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.BufferedISPNCache.ChangesContainer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Sorting cache modification
+ * 
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: CompressedISPNChangesBuffer.java 2845 2010-07-30 13:29:37Z tolusha $
+ */
+public class CompressedISPNChangesBuffer
+{
+   private int historyIndex = 0;
+
+   List<ChangesContainer> changes = new ArrayList<ChangesContainer>();
+
+   /**
+    * Adds new modification container to buffer and performs optimization if needed. Optimization doesn't iterate
+    * over lists and uses HashMaps. So each optimization duration doesn't depend on list size.  
+    * 
+    * @param container
+    */
+   public void add(ChangesContainer container)
+   {
+      changes.add(container);
+   }
+
+   /**
+    * After each invocation of the method increments internal field. 
+    * Designed to be used as history order index in each {@link ChangesContainer}
+    * @return
+    */
+   public int getHistoryIndex()
+   {
+      historyIndex++;
+      return historyIndex;
+   }
+
+   /**
+    * Builds single list of modifications from internal structures and sorts it.
+    * 
+    * @return
+    */
+   public List<ChangesContainer> getSortedList()
+   {
+      List<ChangesContainer> changesContainers = new ArrayList<ChangesContainer>(changes);
+      Collections.sort(changesContainers);
+      return changesContainers;
+   }
+
+}

Added: 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	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,1136 @@
+/*
+ * 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.dataflow.persistent.infinispan;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.access.AccessControlList;
+import org.exoplatform.services.jcr.config.CacheEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
+import org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache;
+import org.exoplatform.services.jcr.datamodel.IllegalPathException;
+import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.ItemType;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.NullItemData;
+import org.exoplatform.services.jcr.datamodel.NullNodeData;
+import org.exoplatform.services.jcr.datamodel.NullPropertyData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.Cache;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * Created by The eXo Platform SAS.<p/>
+ * 
+ * Cache based on Infinispan.<p/>
+ *
+ * <ul>
+ * <li>cache transparent: or item cached or not, we should not generate "not found" Exceptions </li>
+ * 
+ * This cache implementation stores items by UUID and parent UUID with QPathEntry.
+ * Except this cache stores list of children UUID.
+ * 
+ * <p/>
+ * Current state notes (subject of change):
+ * <ul>
+ * <li>cache implements WorkspaceStorageCache, without any stuff about references and locks</li>
+ * <li>transaction style implemented via batches, do with JTA (i.e. via exo's TransactionService + JBoss TM)</li>
+ * </ul>
+ * 
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: ISPNCacheWorkspaceStorageCache.java 3514 2010-11-22 16:14:36Z nzamosenchuk $
+ */
+public class ISPNCacheWorkspaceStorageCache implements WorkspaceStorageCache
+{
+
+   private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.ISPNCacheWorkspaceStorageCache");
+
+   protected final BufferedISPNCache cache;
+
+   /**
+    * Node order comparator for getChildNodes().
+    */
+   class NodesOrderComparator<N extends NodeData> implements Comparator<NodeData>
+   {
+      /**
+       * {@inheritDoc}
+       */
+      public int compare(NodeData n1, NodeData n2)
+      {
+         return n1.getOrderNumber() - n2.getOrderNumber();
+      }
+   }
+
+   class ChildItemsIterator<T extends ItemData> implements Iterator<T>
+   {
+
+      final Iterator<String> childs;
+
+      T next;
+
+      ChildItemsIterator(CacheKey key)
+      {
+         Set<String> set = (Set<String>)cache.get(key);
+         if (set != null)
+         {
+            childs = ((Set<String>)cache.get(key)).iterator();
+            fetchNext();
+         }
+         else
+         {
+            childs = null;
+            next = null;
+         }
+      }
+
+      protected void fetchNext()
+      {
+         if (childs.hasNext())
+         {
+            // traverse to the first existing or the end of children
+            T n = null;
+            do
+            {
+               n = (T)cache.get(new CacheId(childs.next()));
+            }
+            while (n == null && childs.hasNext());
+            next = n;
+         }
+         else
+         {
+            next = null;
+         }
+      }
+
+      public boolean hasNext()
+      {
+         return next != null;
+      }
+
+      public T next()
+      {
+         if (next == null)
+         {
+            throw new NoSuchElementException();
+         }
+
+         final T current = next;
+         fetchNext();
+         return current;
+      }
+
+      public void remove()
+      {
+         throw new IllegalArgumentException("Not implemented");
+      }
+   }
+
+   class ChildNodesIterator<N extends NodeData> extends ChildItemsIterator<N>
+   {
+      ChildNodesIterator(String parentId)
+      {
+         super(new CacheNodesId(parentId));
+      }
+
+      @Override
+      public N next()
+      {
+         return super.next();
+      }
+   }
+
+   class ChildPropertiesIterator<P extends PropertyData> extends ChildItemsIterator<P>
+   {
+
+      ChildPropertiesIterator(String parentId)
+      {
+         super(new CachePropsId(parentId));
+      }
+
+      @Override
+      public P next()
+      {
+         return super.next();
+      }
+   }
+
+   /**
+    * Cache constructor with eXo TransactionService support.
+    * 
+    * @param wsConfig WorkspaceEntry workspace config
+    * @throws RepositoryException if error of initialization
+    * @throws RepositoryConfigurationException if error of configuration
+    */
+   public ISPNCacheWorkspaceStorageCache(WorkspaceEntry wsConfig, ConfigurationManager cfm) throws RepositoryException,
+      RepositoryConfigurationException
+   {
+      if (wsConfig.getCache() == null)
+      {
+         throw new RepositoryConfigurationException("Cache configuration not found");
+      }
+
+      // create cache using custom factory
+      ISPNCacheFactory<Serializable, Object> factory = new ISPNCacheFactory<Serializable, Object>(cfm);
+
+      // create parent Infinispan instance
+      CacheEntry cacheEntry = wsConfig.getCache();
+      Cache<Serializable, Object> parentCache = factory.createCache("Data-" + wsConfig.getUniqueName(), cacheEntry);
+
+      Boolean allowLocalChanges = null;
+      try
+      {
+         allowLocalChanges = cacheEntry.getParameterBoolean("allow-local-changes");
+      }
+      catch (RepositoryConfigurationException e)
+      {
+         // do n't nothing
+      }
+      this.cache = new BufferedISPNCache(parentCache, allowLocalChanges);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void put(ItemData item)
+   {
+      // There is different commit processing for NullNodeData and ordinary ItemData.
+      if (item instanceof NullItemData)
+      {
+         putNullItem((NullItemData)item);
+         return;
+      }
+
+      boolean inTransaction = cache.isTransactionActive();
+      try
+      {
+         if (!inTransaction)
+         {
+            cache.beginTransaction();
+         }
+         cache.setLocal(true);
+         if (item.isNode())
+         {
+            putNode((NodeData)item, ModifyChildOption.NOT_MODIFY);
+         }
+         else
+         {
+            putProperty((PropertyData)item, ModifyChildOption.NOT_MODIFY);
+         }
+      }
+      finally
+      {
+         cache.setLocal(false);
+         if (!inTransaction)
+         {
+            cache.commitTransaction();
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void remove(ItemData item)
+   {
+      removeItem(item);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void onSaveItems(final ItemStateChangesLog itemStates)
+   {
+      //  if something happen we will rollback changes
+      boolean rollback = true;
+      try
+      {
+         cache.beginTransaction();
+         for (ItemState state : itemStates.getAllStates())
+         {
+            if (state.isAdded())
+            {
+               if (state.isPersisted())
+               {
+                  putItem(state.getData());
+               }
+            }
+            else if (state.isUpdated())
+            {
+               if (state.isPersisted())
+               {
+                  // There was a problem with removing a list of samename siblings in on transaction,
+                  // so putItemInBufferedCache(..) and updateInBufferedCache(..) used instead put(..) and update (..) methods.
+                  ItemData prevItem = putItemInBufferedCache(state.getData());
+                  if (prevItem != null && state.isNode())
+                  {
+                     // nodes reordered, if previous is null it's InvalidItemState case
+                     updateInBuffer((NodeData)state.getData(), (NodeData)prevItem);
+                  }
+               }
+            }
+            else if (state.isDeleted())
+            {
+               removeItem(state.getData());
+            }
+            else if (state.isRenamed())
+            {
+               putItem(state.getData());
+            }
+            else if (state.isMixinChanged())
+            {
+               if (state.isPersisted())
+               {
+                  // update subtree ACLs
+                  updateMixin((NodeData)state.getData());
+               }
+            }
+         }
+
+         cache.commitTransaction();
+         rollback = false;
+      }
+      finally
+      {
+         if (rollback)
+         {
+            cache.rollbackTransaction();
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void addChildNodes(NodeData parent, List<NodeData> childs)
+   {
+      boolean inTransaction = cache.isTransactionActive();
+      try
+      {
+         if (!inTransaction)
+         {
+            cache.beginTransaction();
+         }
+
+         cache.setLocal(true);
+
+         // remove previous all (to be sure about consistency)
+         cache.remove(new CacheNodesId(parent.getIdentifier()));
+
+         if (childs.size() > 0)
+         {
+            Set<Object> set = new HashSet<Object>();
+            for (NodeData child : childs)
+            {
+               putNode(child, ModifyChildOption.NOT_MODIFY);
+               set.add(child.getIdentifier());
+            }
+            cache.put(new CacheNodesId(parent.getIdentifier()), set);
+         }
+         else
+         {
+            // cache fact of empty childs list
+            cache.put(new CacheNodesId(parent.getIdentifier()), new HashSet<Object>());
+         }
+      }
+      finally
+      {
+         cache.setLocal(false);
+         if (!inTransaction)
+         {
+            cache.commitTransaction();
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void addChildProperties(NodeData parent, List<PropertyData> childs)
+   {
+      boolean inTransaction = cache.isTransactionActive();
+      try
+      {
+         if (!inTransaction)
+         {
+            cache.beginTransaction();
+         }
+         cache.setLocal(true);
+         // remove previous all (to be sure about consistency)
+         cache.remove(new CachePropsId(parent.getIdentifier()));
+         if (childs.size() > 0)
+         {
+            // add all new
+            Set<Object> set = new HashSet<Object>();
+            for (PropertyData child : childs)
+            {
+               putProperty(child, ModifyChildOption.NOT_MODIFY);
+               set.add(child.getIdentifier());
+            }
+            cache.put(new CachePropsId(parent.getIdentifier()), set);
+
+         }
+         else
+         {
+            LOG.warn("Empty properties list cached " + (parent != null ? parent.getQPath().getAsString() : parent));
+         }
+      }
+      finally
+      {
+         cache.setLocal(false);
+         if (!inTransaction)
+         {
+            cache.commitTransaction();
+         }
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public void addChildPropertiesList(NodeData parent, List<PropertyData> childProperties)
+   {
+      // TODO not implemented, will force read from DB
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ItemData get(String parentId, QPathEntry name)
+   {
+      return get(parentId, name, ItemType.UNKNOWN);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   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))
+         {
+            // this NullNodeData object will not be placed at cache, so we can use unsafe constructor 
+            return new NullNodeData(parentIdentifier, name);
+         }
+         else
+         {
+            return get(itemId);
+         }
+      }
+      return null;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public ItemData get(String id)
+   {
+      return id == null ? null : (ItemData)cache.get(new CacheId(id));
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   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;
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public int getChildNodesCount(NodeData parent)
+   {
+      Set<String> list = (Set<String>)cache.get(new CacheNodesId(parent.getIdentifier()));
+      return list != null ? list.size() : -1;
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public List<PropertyData> getChildProperties(NodeData parent)
+   {
+      return getChildProps(parent.getIdentifier(), true);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public List<PropertyData> listChildProperties(NodeData parent)
+   {
+      return getChildProps(parent.getIdentifier(), false);
+   }
+
+   /**
+    * Internal get child properties.
+    *
+    * @param parentId String
+    * @param withValue boolean, if true only "full" Propeties can be returned
+    * @return List of PropertyData
+    */
+   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;
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public long getSize()
+   {
+      return cache.size();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isEnabled()
+   {
+      return true;
+   }
+
+   /**
+    * Internal put Item.
+    *
+    * @param item ItemData, new data to put in the cache
+    * @return ItemData, previous data or null
+    */
+   protected ItemData putItem(ItemData item)
+   {
+      if (item.isNode())
+      {
+         return putNode((NodeData)item, ModifyChildOption.MODIFY);
+      }
+      else
+      {
+         return putProperty((PropertyData)item, ModifyChildOption.MODIFY);
+      }
+   }
+
+   protected ItemData putItemInBufferedCache(ItemData item)
+   {
+      if (item.isNode())
+      {
+         return putNodeInBufferedCache((NodeData)item, ModifyChildOption.MODIFY);
+      }
+      else
+      {
+         return putProperty((PropertyData)item, ModifyChildOption.MODIFY);
+      }
+
+   }
+
+   /**
+    * Internal put Node.
+    *
+    * @param node, NodeData, new data to put in the cache
+    * @return NodeData, previous data or null
+    */
+   protected ItemData putNode(NodeData node, ModifyChildOption modifyListsOfChild)
+   {
+      if (node.getParentIdentifier() != null)
+      {
+         cache.put(new CacheQPath(node.getParentIdentifier(), node.getQPath(), ItemType.NODE), node.getIdentifier());
+
+         // if MODIFY and List present OR FORCE_MODIFY, then write
+         if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
+         {
+            cache.addToList(new CacheNodesId(node.getParentIdentifier()), node.getIdentifier(),
+               modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+         }
+      }
+
+      return (ItemData)cache.put(new CacheId(node.getIdentifier()), node, true);
+   }
+
+   protected ItemData putNodeInBufferedCache(NodeData node, ModifyChildOption modifyListsOfChild)
+   {
+      if (node.getParentIdentifier() != null)
+      {
+         cache.put(new CacheQPath(node.getParentIdentifier(), node.getQPath(), ItemType.NODE), node.getIdentifier());
+
+         // if MODIFY and List present OR FORCE_MODIFY, then write
+         if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
+         {
+            cache.addToList(new CacheNodesId(node.getParentIdentifier()), node.getIdentifier(),
+               modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+         }
+      }
+
+      // NullNodeData must never be returned inside internal cache operations. 
+      ItemData itemData = (ItemData)cache.putInBuffer(new CacheId(node.getIdentifier()), node);
+      return (itemData instanceof NullItemData) ? null : itemData;
+   }
+
+   /**
+    * Internal put NullNode.
+    *
+    * @param node, NodeData, new data to put in the cache
+    */
+   protected void putNullItem(NullItemData node)
+   {
+      boolean inTransaction = cache.isTransactionActive();
+      try
+      {
+         if (!inTransaction)
+         {
+            cache.beginTransaction();
+         }
+         cache.setLocal(true);
+
+         if (node.getQPath() == null)
+         {
+            //put in $ITEMS
+            cache.put(new CacheId(node.getIdentifier()), node);
+         }
+         else
+         {
+
+            cache.put(new CacheQPath(node.getParentIdentifier(), node.getQPath(), (node.isNode() ? ItemType.NODE
+               : ItemType.PROPERTY)), node.getIdentifier());
+         }
+      }
+      finally
+      {
+         cache.setLocal(false);
+         if (!inTransaction)
+         {
+            dedicatedTxCommit();
+         }
+      }
+   }
+
+   /**
+    * Internal put Property.
+    *
+    * @param node, PropertyData, new data to put in the cache
+    * @return PropertyData, previous data or null
+    */
+   protected PropertyData putProperty(PropertyData prop, ModifyChildOption modifyListsOfChild)
+   {
+      // if MODIFY and List present OR FORCE_MODIFY, then write
+      if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
+      {
+         cache.addToList(new CachePropsId(prop.getParentIdentifier()), prop.getIdentifier(),
+            modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+      }
+
+      cache.put(new CacheQPath(prop.getParentIdentifier(), prop.getQPath(), ItemType.PROPERTY), prop.getIdentifier());
+
+      // add referenced property
+      if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY && prop.getType() == PropertyType.REFERENCE)
+      {
+         List<ValueData> lData = prop.getValues();
+         for (int i = 0, length = lData.size(); i < length; i++)
+         {
+            ValueData vdata = lData.get(i);
+            String nodeIdentifier = null;
+            try
+            {
+               nodeIdentifier = new String(vdata.getAsByteArray(), Constants.DEFAULT_ENCODING);
+            }
+            catch (IllegalStateException e)
+            {
+               // Do nothing. Never happens.
+            }
+            catch (IOException e)
+            {
+               // Do nothing. Never happens.
+            }
+            cache.addToList(new CacheRefsId(nodeIdentifier), prop.getIdentifier(),
+               modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+         }
+      }
+      // NullItemData must never be returned inside internal cache operations. 
+      PropertyData propData = (PropertyData)cache.put(new CacheId(prop.getIdentifier()), prop, true);
+      return (propData instanceof NullPropertyData) ? null : propData;
+   }
+
+   protected void removeItem(ItemData item)
+   {
+      cache.remove(new CacheId(item.getIdentifier()));
+      cache.remove(new CacheQPath(item.getParentIdentifier(), item.getQPath(), ItemType.getItemType(item)));
+
+      if (item.getParentIdentifier() != null)
+      {
+         if (item.isNode())
+         {
+            cache.remove(new CacheNodesId(item.getIdentifier()));
+            cache.remove(new CachePropsId(item.getIdentifier()));
+
+            cache.removeFromList(new CacheNodesId(item.getParentIdentifier()), item.getIdentifier());
+            cache.remove(new CacheRefsId(item.getIdentifier()));
+         }
+         else
+         {
+            cache.removeFromList(new CachePropsId(item.getParentIdentifier()), item.getIdentifier());
+         }
+      }
+   }
+
+   /**
+    * Update Node's mixin and ACL.
+    *
+    * @param node NodeData
+    */
+   protected void updateMixin(NodeData node)
+   {
+      NodeData prevData = (NodeData)cache.put(new CacheId(node.getIdentifier()), node, true);
+      // prevent update NullNodeData
+      if (!(prevData instanceof NullNodeData))
+      {
+         if (prevData != null)
+         {
+            // do update ACL if needed
+            if (prevData.getACL() == null || !prevData.getACL().equals(node.getACL()))
+            {
+               updateChildsACL(node.getIdentifier(), node.getACL());
+            }
+         }
+         else if (LOG.isDebugEnabled())
+         {
+            LOG.debug("Previous NodeData not found for mixin update " + node.getQPath().getAsString());
+         }
+      }
+   }
+
+   /**
+    * Update Node hierachy in case of same-name siblings reorder.
+    * Assumes the new (updated) nodes already putted in the cache. Previous name of updated nodes will be calculated
+    * and that node will be deleted (if has same id as the new node). Childs paths will be updated to a new node path.
+    *
+    * @param node NodeData
+    * @param prevNode NodeData
+    */
+   protected void updateInBuffer(final NodeData node, final NodeData prevNode)
+   {
+      // I expect that NullNodeData will never update existing NodeData.
+      CacheQPath prevKey = new CacheQPath(node.getParentIdentifier(), prevNode.getQPath(), ItemType.NODE);
+      if (node.getIdentifier().equals(cache.getFromBuffer(prevKey)))
+      {
+         cache.remove(prevKey);
+      }
+
+      // update childs paths if index changed
+      int nodeIndex = node.getQPath().getEntries()[node.getQPath().getEntries().length - 1].getIndex();
+      int prevNodeIndex = prevNode.getQPath().getEntries()[prevNode.getQPath().getEntries().length - 1].getIndex();
+      if (nodeIndex != prevNodeIndex)
+      {
+         // its a samename reordering
+         updateTreePath(prevNode.getQPath(), node.getQPath(), null); // don't change ACL, it's same parent
+      }
+   }
+
+   /**
+    * Check all items in cache - is it descendant of prevRootPath, and update path according newRootPath.
+    * 
+    * @param prevRootPath
+    * @param newRootPath
+    * @param acl
+    */
+   protected void updateTreePath(final QPath prevRootPath, final QPath newRootPath, final AccessControlList acl)
+   {
+      boolean inheritACL = acl != null;
+
+      // check all ITEMS in cache 
+      Iterator<Serializable> keys = cache.keySet().iterator();
+
+      while (keys.hasNext())
+      {
+         CacheKey key = (CacheKey)keys.next();
+         if (key instanceof CacheId)
+         {
+            ItemData data = (ItemData)cache.get(key);
+
+            if (data != null)
+            {
+               // check is this descendant of prevRootPath
+               QPath nodeQPath = data.getQPath();
+               // NullNodeData's qPath==null;
+               if (nodeQPath != null && nodeQPath.isDescendantOf(prevRootPath))
+               {
+
+                  //make relative path
+                  QPathEntry[] relativePath = null;
+                  try
+                  {
+                     relativePath = nodeQPath.getRelPath(nodeQPath.getDepth() - prevRootPath.getDepth());
+                  }
+                  catch (IllegalPathException e)
+                  {
+                     // Do nothing. Never happens.
+                  }
+
+                  // make new path - no matter  node or property
+                  QPath newPath = QPath.makeChildPath(newRootPath, relativePath);
+
+                  if (data.isNode())
+                  {
+                     // update node
+                     NodeData prevNode = (NodeData)data;
+
+                     TransientNodeData newNode =
+                        new TransientNodeData(newPath, prevNode.getIdentifier(), prevNode.getPersistedVersion(),
+                           prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(),
+                           prevNode.getParentIdentifier(), inheritACL ? acl : prevNode.getACL());
+
+                     // update this node
+                     cache.put(new CacheId(newNode.getIdentifier()), newNode);
+                  }
+                  else
+                  {
+                     //update property
+                     PropertyData prevProp = (PropertyData)data;
+
+                     if (inheritACL
+                        && (prevProp.getQPath().getName().equals(Constants.EXO_PERMISSIONS) || prevProp.getQPath()
+                           .getName().equals(Constants.EXO_OWNER)))
+                     {
+                        inheritACL = false;
+                     }
+
+                     TransientPropertyData newProp =
+                        new TransientPropertyData(newPath, prevProp.getIdentifier(), prevProp.getPersistedVersion(),
+                           prevProp.getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(), prevProp
+                              .getValues());
+
+                     // update this property
+                     cache.put(new CacheId(newProp.getIdentifier()), newProp);
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   /**
+    * Update child Nodes ACLs.
+    *
+    * @param parentId String - root node id of JCR subtree.
+    * @param acl AccessControlList
+    */
+   protected void updateChildsACL(final String parentId, final AccessControlList acl)
+   {
+      for (Iterator<NodeData> iter = new ChildNodesIterator<NodeData>(parentId); iter.hasNext();)
+      {
+         NodeData prevNode = iter.next();
+
+         // is ACL changes on this node (i.e. ACL inheritance brokes)
+         for (InternalQName mixin : prevNode.getMixinTypeNames())
+         {
+            if (mixin.equals(Constants.EXO_PRIVILEGEABLE) || mixin.equals(Constants.EXO_OWNEABLE))
+            {
+               continue;
+            }
+         }
+
+         // recreate with new path for child Nodes only
+         TransientNodeData newNode =
+            new TransientNodeData(prevNode.getQPath(), prevNode.getIdentifier(), prevNode.getPersistedVersion(),
+               prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(), prevNode
+                  .getParentIdentifier(), acl);
+
+         // update this node
+         cache.put(new CacheId(newNode.getIdentifier()), newNode);
+
+         // update childs recursive
+         updateChildsACL(newNode.getIdentifier(), acl);
+      }
+   }
+
+   public void beginTransaction()
+   {
+      cache.beginTransaction();
+   }
+
+   public void commitTransaction()
+   {
+      cache.commitTransaction();
+   }
+
+   public void rollbackTransaction()
+   {
+      cache.rollbackTransaction();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public boolean isTXAware()
+   {
+      return true;
+   }
+
+   /**
+    * <li>NOT_MODIFY - node(property) is not added to the parent's list (no persistent changes performed, cache used as cache)</li>
+    * <li>MODIFY - node(property) is added to the parent's list if parent in the cache (new item is added to persistent, add to list if it is present)</li>
+    * <li>FORCE_MODIFY - node(property) is added to the parent's list anyway (when list is read from DB, forcing write)</li>
+    */
+   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
+    */
+   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.doPriviledgedExceptionAction(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.doPriviledgedExceptionAction(new PrivilegedExceptionAction<Object>()
+               {
+                  public Object run() throws Exception
+                  {
+                     tm.resume(privilegedTx);
+                     return null;
+                  }
+               });
+            }
+            catch (Exception e)
+            {
+               LOG.warn("Cannot resume the current transaction", e);
+            }
+         }
+      }
+   }
+
+   /**
+    * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#addReferencedProperties(java.lang.String, java.util.List)
+    */
+   public void addReferencedProperties(String identifier, List<PropertyData> refProperties)
+   {
+      boolean inTransaction = cache.isTransactionActive();
+      try
+      {
+         if (!inTransaction)
+         {
+            cache.beginTransaction();
+         }
+         cache.setLocal(true);
+         // remove previous all (to be sure about consistency)
+         cache.remove(new CacheRefsId(identifier));
+
+         Set<Object> set = new HashSet<Object>();
+         for (PropertyData prop : refProperties)
+         {
+            putProperty(prop, ModifyChildOption.NOT_MODIFY);
+            set.add(prop.getIdentifier());
+         }
+         cache.put(new CacheRefsId(identifier), set);
+      }
+      finally
+      {
+         cache.setLocal(false);
+         if (!inTransaction)
+         {
+            cache.commitTransaction();
+         }
+      }
+   }
+
+   /**
+    * @see org.exoplatform.services.jcr.dataflow.persistent.WorkspaceStorageCache#getReferencedProperties(java.lang.String)
+    */
+   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;
+      }
+   }
+}

Deleted: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/PrivilegedCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/PrivilegedCacheHelper.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/util/PrivilegedCacheHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -1,275 +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.util;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.CacheFactory;
-import org.jboss.cache.DefaultCacheFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.config.ConfigurationException;
-
-import java.io.InputStream;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
- * @version $Id: PrivilegedCacheHelper.java 111 2010-11-11 11:11:11Z tolusha $
- *
- */
-public class PrivilegedCacheHelper
-{
-   /**
-    * Start cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> void start(final Cache<K, V> cache)
-   {
-      PrivilegedAction<Void> action = new PrivilegedAction<Void>()
-      {
-         public Void run()
-         {
-            cache.start();
-            return null;
-         }
-      };
-      AccessController.doPrivileged(action);
-   }
-
-   /**
-    * Stop cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> void stop(final Cache<K, V> cache)
-   {
-      PrivilegedAction<Void> action = new PrivilegedAction<Void>()
-      {
-         public Void run()
-         {
-            cache.stop();
-            return null;
-         }
-      };
-      AccessController.doPrivileged(action);
-   }
-
-   /**
-    * Create cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> void create(final Cache<K, V> cache)
-   {
-      PrivilegedAction<Void> action = new PrivilegedAction<Void>()
-      {
-         public Void run()
-         {
-            cache.create();
-            return null;
-         }
-      };
-      AccessController.doPrivileged(action);
-   }
-
-   /**
-    * End batch in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> void endBatch(final Cache<K, V> cache, final boolean successful)
-   {
-      PrivilegedAction<Void> action = new PrivilegedAction<Void>()
-      {
-         public Void run()
-         {
-            cache.endBatch(successful);
-            return null;
-         }
-      };
-      AccessController.doPrivileged(action);
-   }
-
-   /**
-    * Create cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> Cache<K, V> createCache(final CacheFactory<K, V> factory, final InputStream is,
-      final boolean start)
-   {
-      PrivilegedExceptionAction<Cache<K, V>> action = new PrivilegedExceptionAction<Cache<K, V>>()
-      {
-         public Cache<K, V> run() throws Exception
-         {
-            return factory.createCache(is, start);
-         }
-      };
-      try
-      {
-         return AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof ConfigurationException)
-         {
-            throw (ConfigurationException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   /**
-    * Put in cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> V put(final Cache<K, V> cache, final String fqn, final K key, final V value)
-      throws CacheException
-   {
-      PrivilegedExceptionAction<V> action = new PrivilegedExceptionAction<V>()
-      {
-         public V run() throws Exception
-         {
-            return cache.put(fqn, key, value);
-         }
-      };
-      try
-      {
-         return AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof IllegalStateException)
-         {
-            throw (IllegalStateException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   /**
-    * Remove fomr cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> boolean removeNode(final Cache<K, V> cache, final Fqn fqn) throws CacheException
-   {
-      PrivilegedExceptionAction<Boolean> action = new PrivilegedExceptionAction<Boolean>()
-      {
-         public Boolean run() throws Exception
-         {
-            return cache.removeNode(fqn);
-         }
-      };
-      try
-      {
-         return AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof IllegalStateException)
-         {
-            throw (IllegalStateException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   /**
-    * Put in cache in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> V put(final Cache<K, V> cache, final Fqn fqn, final K key, final V value) throws CacheException
-   {
-      PrivilegedExceptionAction<V> action = new PrivilegedExceptionAction<V>()
-      {
-         public V run() throws Exception
-         {
-            return cache.put(fqn, key, value);
-         }
-      };
-      try
-      {
-         return AccessController.doPrivileged(action);
-      }
-      catch (PrivilegedActionException pae)
-      {
-         Throwable cause = pae.getCause();
-         if (cause instanceof IllegalStateException)
-         {
-            throw (IllegalStateException)cause;
-         }
-         else if (cause instanceof RuntimeException)
-         {
-            throw (RuntimeException)cause;
-         }
-         else
-         {
-            throw new RuntimeException(cause);
-         }
-      }
-   }
-
-   /**
-    * Create cache factory in privileged mode.
-    * 
-    * @param cache
-    */
-   public static <K, V> DefaultCacheFactory<K, V> createCacheFactory() throws CacheException
-   {
-      PrivilegedAction<DefaultCacheFactory<K, V>> action = new PrivilegedAction<DefaultCacheFactory<K, V>>()
-      {
-         public DefaultCacheFactory<K, V> run()
-         {
-            return new DefaultCacheFactory<K, V>();
-         }
-      };
-      return AccessController.doPrivileged(action);
-   }
-}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheFactory.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheFactory.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,182 @@
+/*
+ * 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.infinispan;
+
+import org.exoplatform.commons.utils.SecurityHelper;
+import org.exoplatform.container.ExoContainer;
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
+import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
+import org.exoplatform.services.jcr.config.TemplateConfigurationHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.GlobalConfiguration;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Factory that creates and starts pre-configured instances of Infinispan.
+ * Path to Infinispan configuration or template and cache name should be 
+ * provided as "infinispan-configuration" and "infinispan-cache-name" properties 
+ * in parameterEntry instance respectively. 
+ * 
+ * @author <a href="mailto:nikolazius at gmail.com">Nikolay Zamosenchuk</a>
+ * @version $Id: InfinispanCacheFactory.java 3001 2010-08-30 06:56:05Z tolusha $
+ *
+ */
+public class ISPNCacheFactory<K, V>
+{
+
+   public static final String INFINISPAN_CONFIG = "infinispan-configuration";
+
+   private final TemplateConfigurationHelper configurationHelper;
+
+   private static final Log log = ExoLogger.getLogger("exo.jcr.component.core.InfinispanCacheFactory");
+
+   /**
+    * A Map that contains all the registered CacheManager order by {@link ExoContainer} 
+    * instances and {@link GlobalConfiguration}.
+    */
+   private static Map<GlobalConfiguration, EmbeddedCacheManager> CACHE_MANAGERS =
+      new HashMap<GlobalConfiguration, EmbeddedCacheManager>();
+
+   /**
+    * Creates InfinispanCacheFactory with provided configuration transaction managers.
+    * Transaction manager will later be injected to cache instance. 
+    * 
+    * @param configurationManager
+    */
+   public ISPNCacheFactory(ConfigurationManager configurationManager)
+   {
+      this.configurationHelper = new ISPNCacheHelper(configurationManager);
+   }
+
+   /**
+   * Factory that creates and starts pre-configured instances of Infinispan.
+   * Path to Infinispan configuration or template should be provided as 
+   * "infinispan-configuration" property in parameterEntry instance. 
+   * <br>
+   * 
+   * @param regionId the unique id of the cache region to create
+   * @param parameterEntry
+   * @return
+   * @throws RepositoryConfigurationException
+   */
+   public Cache<K, V> createCache(final String regionId, MappedParametrizedObjectEntry parameterEntry)
+      throws RepositoryConfigurationException
+   {
+      // get Infinispan configuration file path
+      final String configurationPath = parameterEntry.getParameterValue(INFINISPAN_CONFIG);
+      log.info("Infinispan Cache configuration used: " + configurationPath);
+
+      // prepare configuration
+      final InputStream configStream;
+      try
+      {
+         // fill template
+         configStream = configurationHelper.fillTemplate(configurationPath, parameterEntry.getParameters());
+      }
+      catch (IOException e)
+      {
+         throw new RepositoryConfigurationException(e);
+      }
+
+      // create cache
+      final EmbeddedCacheManager manager;
+      try
+      {
+         // creating new CacheManager using SecurityHelper
+
+         manager = SecurityHelper.doPriviledgedIOExceptionAction(new PrivilegedExceptionAction<EmbeddedCacheManager>()
+         {
+            public EmbeddedCacheManager run() throws IOException
+            {
+               return getUniqueInstance(regionId, new DefaultCacheManager(configStream));
+            }
+         });
+
+      }
+      catch (IOException e)
+      {
+         throw new RepositoryConfigurationException(e);
+      }
+
+      PrivilegedAction<Cache<K, V>> action = new PrivilegedAction<Cache<K, V>>()
+      {
+         public Cache<K, V> run()
+         {
+            return manager.getCache(regionId);
+         }
+      };
+      Cache<K, V> cache = AccessController.doPrivileged(action);
+
+      return cache;
+   }
+
+   /**
+    * Try to find if a {@link EmbeddedCacheManager} of the same type (i.e. their {@link GlobalConfiguration} are equals)
+    * has already been registered for the same current container.
+    * If no cache manager has been registered, we register the given cache manager otherwise we
+    * use the previously registered cache manager and we define a dedicated region for the related cache.
+    * @param regionId the unique id of the cache region to create
+    * @param manager the current cache manager of the cache to create
+    * @return the given cache manager if it has not been registered otherwise the cache manager of the same
+    * type that has already been registered..
+    */
+   private static synchronized EmbeddedCacheManager getUniqueInstance(String regionId, EmbeddedCacheManager manager)
+   {
+      GlobalConfiguration gc = manager.getGlobalConfiguration();
+      ExoContainer container = ExoContainerContext.getCurrentContainer();
+      // Ensure that the cluster name won't be used between 2 ExoContainers
+      gc.setClusterName(gc.getClusterName() + "-" + container.getContext().getName());
+      Configuration conf = manager.getDefaultConfiguration();
+      if (CACHE_MANAGERS.containsKey(gc))
+      {
+         manager = CACHE_MANAGERS.get(gc);
+      }
+      else
+      {
+         CACHE_MANAGERS.put(gc, manager);
+         if (log.isInfoEnabled())
+         {
+            log.info("A new JBoss Cache instance has been registered for the region " + regionId
+               + " and the container " + container.getContext().getName());
+         }
+      }
+      // Define the configuration of the cache
+      manager.defineConfiguration(regionId, conf);
+      if (log.isInfoEnabled())
+      {
+         log.info("The region " + regionId + " has been registered for the container "
+            + container.getContext().getName());
+      }
+      return manager;
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheHelper.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/ISPNCacheHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,44 @@
+/*
+ * 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.infinispan;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.config.TemplateConfigurationHelper;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: ISPNCacheHelper.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+public class ISPNCacheHelper extends TemplateConfigurationHelper
+{
+
+   /**
+    * Creates configuration cache helper with pre-configured for Infinispan cache parameters,<br>
+    * including: "infinispan-*" and "jgroups-configuration", and excluding "infinispan-configuration"
+    * 
+    * @param cfm
+    *          instance for looking up resources
+    */
+   public ISPNCacheHelper(ConfigurationManager cfm)
+   {
+      super(new String[]{"^jgroups-configuration", "^infinispan-.*"}, new String[]{"^infinispan-configuration"}, cfm);
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/infinispan/PrivilegedISPNCacheHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,105 @@
+/*
+ * 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.infinispan;
+
+import org.infinispan.Cache;
+
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: PrivilegedCacheHelper.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+public class PrivilegedISPNCacheHelper
+{
+
+   /**
+    * Start Infinispan cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static void start(final org.infinispan.Cache<Serializable, Object> cache)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            cache.start();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Stop Infinispan cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static void stop(final Cache<Serializable, Object> cache)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            cache.stop();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Put in Infinispan cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static Object putIfAbsent(final Cache<Serializable, Object> cache, final Serializable key, final Object value)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            return cache.putIfAbsent(key, value);
+         }
+      };
+      return AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Put in Infinispan cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static Object put(final Cache<Serializable, Object> cache, final Serializable key, final Object value)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            return cache.put(key, value);
+         }
+      };
+      return AccessController.doPrivileged(action);
+   }
+
+}

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/ExoJBossCacheFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/ExoJBossCacheFactory.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/ExoJBossCacheFactory.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -25,7 +25,6 @@
 import org.exoplatform.services.jcr.config.MappedParametrizedObjectEntry;
 import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
 import org.exoplatform.services.jcr.config.TemplateConfigurationHelper;
-import org.exoplatform.services.jcr.impl.util.PrivilegedCacheHelper;
 import org.exoplatform.services.log.ExoLogger;
 import org.exoplatform.services.log.Log;
 import org.jboss.cache.Cache;
@@ -110,7 +109,7 @@
    public ExoJBossCacheFactory(ConfigurationManager configurationManager, TransactionManager transactionManager)
    {
       this.configurationManager = configurationManager;
-      this.configurationHelper = TemplateConfigurationHelper.createJBossCacheHelper(configurationManager);
+      this.configurationHelper = new JBossCacheHelper(configurationManager);
       this.transactionManager = transactionManager;
    }
 

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/JBossCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/JBossCacheHelper.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/JBossCacheHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,43 @@
+/*
+ * 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.jbosscache;
+
+import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.services.jcr.config.TemplateConfigurationHelper;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: ISPNCacheHelper.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+public class JBossCacheHelper extends TemplateConfigurationHelper
+{
+
+   /**
+    * Creates configuration cache helper with pre-configured for JBossCache parameters,<br>
+    * including: "jbosscache-*" and "jgroups-configuration", and excluding "jbosscache-configuration"
+    * 
+    * @param cfm
+    *          instance for looking up resources
+    */
+   public JBossCacheHelper(ConfigurationManager cfm)
+   {
+      super(new String[]{"^jbosscache-.*", "^jgroups-configuration"}, new String[]{"^jbosscache-configuration"}, cfm);
+   }
+}

Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/jbosscache/PrivilegedJBossCacheHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,167 @@
+/*
+ * 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.jbosscache;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: PrivilegedCacheHelper.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+public class PrivilegedJBossCacheHelper
+{
+   /**
+    * Start JBoss cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static void start(final Cache<Serializable, Object> cache)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            cache.start();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Stop JBoss cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static void stop(final Cache<Serializable, Object> cache)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            cache.stop();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Create JBoss cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static void create(final Cache<Serializable, Object> cache)
+   {
+      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
+      {
+         public Object run()
+         {
+            cache.create();
+            return null;
+         }
+      };
+      AccessController.doPrivileged(action);
+   }
+
+   /**
+    * Put in JBoss cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static Object put(final Cache<Serializable, Object> cache, final String fqn, final Serializable key,
+      final Object value) throws CacheException
+   {
+      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
+      {
+         public Object run() throws Exception
+         {
+            return cache.put(fqn, key, value);
+
+         }
+      };
+      try
+      {
+         return AccessController.doPrivileged(action);
+      }
+      catch (PrivilegedActionException pae)
+      {
+         Throwable cause = pae.getCause();
+         if (cause instanceof CacheException)
+         {
+            throw (CacheException)cause;
+         }
+         else if (cause instanceof RuntimeException)
+         {
+            throw (RuntimeException)cause;
+         }
+         else
+         {
+            throw new RuntimeException(cause);
+         }
+      }
+   }
+
+   /**
+    * Put in JBoss cache in privileged mode.
+    * 
+    * @param cache
+    */
+   public static Object put(final Cache<Serializable, Object> cache, final Fqn fqn, final Serializable key,
+      final Object value) throws CacheException
+   {
+      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
+      {
+         public Object run() throws Exception
+         {
+            return cache.put(fqn, key, value);
+         }
+      };
+      try
+      {
+         return AccessController.doPrivileged(action);
+      }
+      catch (PrivilegedActionException pae)
+      {
+         Throwable cause = pae.getCause();
+         if (cause instanceof CacheException)
+         {
+            throw (CacheException)cause;
+         }
+         else if (cause instanceof RuntimeException)
+         {
+            throw (RuntimeException)cause;
+         }
+         else
+         {
+            throw new RuntimeException(cause);
+         }
+      }
+   }
+
+}

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	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/xa/TestUserTransaction.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -115,7 +115,7 @@
       ut.begin();
       log.info("after begin");
       // we need to create the session within the transaction to ensure that it will be enlisted
-      Session session = (SessionImpl)repository.login(credentials, "ws");
+      Session session = repository.login(credentials, "ws");
       session.getRootNode().addNode("txcommit");
       session.save();
       assertNotNull(session.getItem("/txcommit"));
@@ -143,7 +143,7 @@
 
       ut.begin();
       // we need to create the session within the transaction to ensure that it will be enlisted
-      Session session = (SessionImpl)repository.login(credentials, "ws");
+      Session session = repository.login(credentials, "ws");
       session.getRootNode().addNode("txrollback");
       session.save();
       assertNotNull(session.getItem("/txrollback"));
@@ -254,6 +254,9 @@
          assertNotNull(((XASession) s1).getCommitException());
       }
 
+      s1.logout();
+      s2.logout();      
+      
       try {
          session.getItem("/pretx/tx1");
          fail("PathNotFoundException should be thrown");

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/config/TestTemplateConfigurationHelper.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/config/TestTemplateConfigurationHelper.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/config/TestTemplateConfigurationHelper.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -18,10 +18,11 @@
  */
 package org.exoplatform.services.jcr.config;
 
+import junit.framework.TestCase;
+
 import org.exoplatform.container.configuration.ConfigurationManagerImpl;
+import org.exoplatform.services.jcr.jbosscache.JBossCacheHelper;
 
-import junit.framework.TestCase;
-
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -40,7 +41,7 @@
    {
       // create helper with predefined include and exclude patterns
       TemplateConfigurationHelper helper =
-         TemplateConfigurationHelper.createJBossCacheHelper(new ConfigurationManagerImpl());
+         new JBossCacheHelper(new ConfigurationManagerImpl());
       Map<String, String> parameters = new HashMap<String, String>();
       parameters.put("jbosscache-configuration", "");
       parameters.put("jbosscache-cache.loader", "");
@@ -58,7 +59,7 @@
    public void testFilters2()
    {
       // create helper with predefined include and exclude patterns
-      TemplateConfigurationHelper helper = TemplateConfigurationHelper.createJBossCacheHelper(new ConfigurationManagerImpl());
+      TemplateConfigurationHelper helper =  new JBossCacheHelper(new ConfigurationManagerImpl());
       Map<String, String> parameters = new HashMap<String, String>();
       parameters.put("jgroups-configuration", "");
       parameters.put("jbosscache-cache.loader", "");
@@ -74,7 +75,7 @@
 
    public void testTemplating() throws IOException
    {
-      TemplateConfigurationHelper helper = TemplateConfigurationHelper.createJBossCacheHelper(new ConfigurationManagerImpl());
+      TemplateConfigurationHelper helper =  new JBossCacheHelper(new ConfigurationManagerImpl());
       String template = "configuration in any format, containing ${jbosscache-template-variable} and many others";
       String expectedConfig = "configuration in any format, containing pretty good parameter and many others";
 

Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java	2010-11-25 15:28:39 UTC (rev 3570)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -19,7 +19,7 @@
 package org.exoplatform.services.jcr.impl.core.lock;
 
 import org.exoplatform.services.jcr.JcrImplBaseTest;
-import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockData;
+import org.exoplatform.services.jcr.impl.core.lock.cacheable.LockData;
 import org.exoplatform.services.jcr.impl.core.lock.jbosscache.jdbc.LockJDBCConnection;
 import org.exoplatform.services.jcr.impl.core.lock.jbosscache.jdbc.LockJDBCContainer;
 

Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/lab/infinispan/TestISPNCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/lab/infinispan/TestISPNCache.java	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/lab/infinispan/TestISPNCache.java	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,128 @@
+/*
+ * 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.lab.infinispan;
+
+import junit.framework.TestCase;
+
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.GlobalConfiguration;
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author <a href="anatoliy.bazko at exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: TestINSPCache.java 111 2010-11-11 11:11:11Z tolusha $
+ *
+ */
+public class TestISPNCache extends TestCase
+{
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void setUp() throws Exception
+   {
+      super.setUp();
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public void tearDown() throws Exception
+   {
+      super.tearDown();
+   }
+
+   /**
+    * Test default cache and base operation.
+    * 
+    * @throws Exception
+    */
+   public void testGetCache() throws Exception
+   {
+      // Create cache manager
+      GlobalConfiguration myGlobalConfig = new GlobalConfiguration();
+      EmbeddedCacheManager manager = new DefaultCacheManager(myGlobalConfig);
+
+      // Create a cache
+      Configuration config = new Configuration();
+      manager.defineConfiguration("cache", config);
+      Cache cache = manager.getCache("cache");
+
+      cache.put("key", "value");
+      assertTrue(cache.size() == 1);
+      assertTrue(cache.containsKey("key"));
+
+      String value = (String)cache.remove("key");
+      assertTrue(value.equals("value"));
+      assertTrue(cache.isEmpty());
+
+      cache.put("key", "value");
+      cache.putIfAbsent("key", "newValue");
+      assertTrue("value".equals(cache.get("key")));
+
+      cache.clear();
+      assertTrue(cache.isEmpty());
+
+      cache.put("key", "value", 2, TimeUnit.SECONDS);
+      assertTrue(cache.containsKey("key"));
+      Thread.sleep(2000 + 500);
+      assertFalse(cache.containsKey("key"));
+   }
+
+   /**
+    * Test cluster cache and base operation.
+    * 
+    * @throws Exception
+    */
+   public void testGetClusterCache() throws Exception
+   {
+      // Create cache manager
+      EmbeddedCacheManager manager = new DefaultCacheManager(GlobalConfiguration.getClusteredDefault());
+
+      // Create a cache
+      Cache cache = manager.getCache();
+
+      cache.put("key", "value");
+      assertTrue(cache.size() == 1);
+      assertTrue(cache.containsKey("key"));
+
+      String value = (String)cache.remove("key");
+      assertTrue(value.equals("value"));
+      assertTrue(cache.isEmpty());
+
+      cache.put("key", "value");
+      cache.putIfAbsent("key", "newValue");
+      assertTrue("value".equals(cache.get("key")));
+
+      cache.clear();
+      assertTrue(cache.isEmpty());
+
+      cache.put("key", "value", 2, TimeUnit.SECONDS);
+      assertTrue(cache.containsKey("key"));
+      Thread.sleep(2000 + 500);
+      assertFalse(cache.containsKey("key"));
+   }
+
+}

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-config.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<infinispan
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+      xsi:schemaLocation="urn:infinispan:config:4.0 http://www.infinispan.org/schemas/infinispan-config-4.0.xsd" 
+      xmlns="urn:infinispan:config:4.0">
+
+    <global>
+      <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+        <properties>
+          <property name="threadNamePrefix" value="EvictionThread"/>
+        </properties>
+      </evictionScheduledExecutor>
+
+      <globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
+
+      <transport transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport" clusterName="${infinispan-cluster-name}" distributedSyncTimeout="20000">
+        <properties>
+          <property name="configurationFile" value="${jgroups-configuration}"/>
+        </properties>
+      </transport>
+    </global>
+
+    <default>
+      <locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
+      <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
+      <jmxStatistics enabled="true"/>
+      <deadlockDetection enabled="true" spinDuration="100"/>
+      <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="5000"/>
+   </default>
+</infinispan>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-infinispan-lock.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<infinispan
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+      xsi:schemaLocation="urn:infinispan:config:4.0 http://www.infinispan.org/schemas/infinispan-config-4.0.xsd" 
+      xmlns="urn:infinispan:config:4.0">
+
+    <global>
+      <globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
+
+      <transport transportClass="org.infinispan.remoting.transport.jgroups.JGroupsTransport" clusterName="${infinispan-cluster-name}" distributedSyncTimeout="20000">
+        <properties>
+          <property name="configurationFile" value="${jgroups-configuration}"/>
+        </properties>
+      </transport>
+    </global>
+
+    <default>
+      <locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
+      <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
+      <jmxStatistics enabled="true"/>
+      <deadlockDetection enabled="true" spinDuration="100"/>
+
+      <loaders passivation="false" shared="true" preload="true">
+        <loader class="org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore" fetchPersistentState="false" ignoreModifications="false" purgeOnStartup="false">
+          <properties>
+             <property name="stringsTableNamePrefix" value="${infinispan-cl-cache.jdbc.table.name}"/>
+             <property name="idColumnName" value="${infinispan-cl-cache.jdbc.id.column}"/>
+             <property name="dataColumnName" value="${infinispan-cl-cache.jdbc.data.column}"/>
+             <property name="timestampColumnName" value="${infinispan-cl-cache.jdbc.timestamp.column}"/>
+             <property name="idColumnType" value="${infinispan-cl-cache.jdbc.id.type}"/>
+             <property name="dataColumnType" value="${infinispan-cl-cache.jdbc.data.type}"/>
+             <property name="timestampColumnType" value="${infinispan-cl-cache.jdbc.timestamp.type}"/>
+             <property name="dropTableOnExit" value="${infinispan-cl-cache.jdbc.table.drop}"/>
+             <property name="createTableOnStart" value="${infinispan-cl-cache.jdbc.table.create}"/>
+             <property name="connectionFactoryClass" value="${infinispan-cl-cache.jdbc.connectionFactory}"/>
+             <property name="datasourceJndiLocation" value="${infinispan-cl-cache.jdbc.datasource}"/>
+          </properties>
+          <async enabled="false"/>
+        </loader>
+      </loaders>
+   </default>
+
+</infinispan>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-config.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-config.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-config.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<infinispan
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+      xsi:schemaLocation="urn:infinispan:config:4.0 http://www.infinispan.org/schemas/infinispan-config-4.0.xsd" 
+      xmlns="urn:infinispan:config:4.0">
+
+    <global>
+      <evictionScheduledExecutor factory="org.infinispan.executors.DefaultScheduledExecutorFactory">
+        <properties>
+          <property name="threadNamePrefix" value="EvictionThread"/>
+        </properties>
+      </evictionScheduledExecutor>
+
+      <globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
+    </global>
+
+    <default>
+      <locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
+      <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
+      <jmxStatistics enabled="true"/>
+      <deadlockDetection enabled="true" spinDuration="100"/>
+      <eviction strategy="LRU" wakeUpInterval="5000" threadPolicy="DEFAULT" maxEntries="5000"/>
+   </default>
+</infinispan>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-infinispan-lock.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<infinispan
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+      xsi:schemaLocation="urn:infinispan:config:4.0 http://www.infinispan.org/schemas/infinispan-config-4.0.xsd" 
+      xmlns="urn:infinispan:config:4.0">
+
+    <global>
+      <globalJmxStatistics jmxDomain="infinispan" enabled="true" allowDuplicateDomains="true"/>
+    </global>
+
+    <default>
+      <locking isolationLevel="READ_COMMITTED" lockAcquisitionTimeout="20000" writeSkewCheck="false" concurrencyLevel="500"/>
+      <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" syncRollbackPhase="false" syncCommitPhase="false"/>
+      <jmxStatistics enabled="true"/>
+      <deadlockDetection enabled="true" spinDuration="100"/>
+
+      <loaders passivation="false" shared="true" preload="true">
+        <loader class="org.infinispan.loaders.jdbc.stringbased.JdbcStringBasedCacheStore" fetchPersistentState="false" ignoreModifications="false" purgeOnStartup="false">
+          <properties>
+             <property name="stringsTableNamePrefix" value="${infinispan-cl-cache.jdbc.table.name}"/>
+             <property name="idColumnName" value="${infinispan-cl-cache.jdbc.id.column}"/>
+             <property name="dataColumnName" value="${infinispan-cl-cache.jdbc.data.column}"/>
+             <property name="timestampColumnName" value="${infinispan-cl-cache.jdbc.timestamp.column}"/>
+             <property name="idColumnType" value="${infinispan-cl-cache.jdbc.id.type}"/>
+             <property name="dataColumnType" value="${infinispan-cl-cache.jdbc.data.type}"/>
+             <property name="timestampColumnType" value="${infinispan-cl-cache.jdbc.timestamp.type}"/>
+             <property name="dropTableOnExit" value="${infinispan-cl-cache.jdbc.table.drop}"/>
+             <property name="createTableOnStart" value="${infinispan-cl-cache.jdbc.table.create}"/>
+             <property name="connectionFactoryClass" value="${infinispan-cl-cache.jdbc.connectionFactory}"/>
+             <property name="datasourceJndiLocation" value="${infinispan-cl-cache.jdbc.datasource}"/>
+          </properties>
+          <async enabled="false"/>
+        </loader>
+      </loaders>
+   </default>
+
+</infinispan>

Added: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config-ispn.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config-ispn.xml	                        (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/standalone/test-jcr-config-ispn.xml	2010-11-26 13:07:26 UTC (rev 3571)
@@ -0,0 +1,587 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+
+    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.
+
+-->
+<repository-service default-repository="db1">
+   <repositories>
+      <repository name="db1" system-workspace="ws" default-workspace="ws">
+         <security-domain>exo-domain</security-domain>
+         <!-- access-control>optional</access-control -->
+         <!-- access-control>disable</access-control -->
+         <session-max-age>1h</session-max-age>
+         <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>
+         <workspaces>
+            <workspace name="ws">
+               <!-- for system storage -->
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws" />
+                           <property name="digest-algo" value="MD5" />
+                           <property name="vcas-type" value="org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImpl" />
+                           <property name="jdbc-source-name" value="jdbcjcr" />
+                           <property name="jdbc-dialect" value="auto" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                  </properties>
+               </initializer>
+               <!-- initializer class="org.exoplatform.services.jcr.impl.core.RestoreWorkspaceInitializer">
+                  <properties>
+                     <property name="restore-path" value="./sv_export_root.xml" />
+                     <property name="restore-path" value="./src/test/resources/import-export/restore_db1_ws1.xml" />
+                  </properties>
+               </initializer -->
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1/ws" />
+                     <!-- property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.jbosscache.JbossCacheIndexChangesFilter" />
+                     <property name="jbosscache-configuration" value="conf/standalone/test-jbosscache-config.xml" /-->
+                     
+                   </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>            
+            </workspace>
+
+            <workspace name="ws1">
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr1" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws1" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws1" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws1" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1/ws1" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws1" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr1" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                            
+            </workspace>
+
+            <workspace name="ws2" lazy-read-threshold="1">
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr2" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws2" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws2" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws2" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1/ws2" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws2" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr2" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                              
+            </workspace>
+            
+            <workspace name="ws3">
+               <!-- for system storage -->
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr3" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws3" />
+                  </properties>
+                  <value-storages>
+                      <!--
+                      This storage is used to check whether properties are removed
+                      correctly from each value-storage
+                      (TestRemoveFromValueStorage.java)
+                      -->
+                     <value-storage id="ws3_big" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws3_big" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="1024K" />
+                        </filters>
+                     </value-storage>
+                     <value-storage id="ws3" class="org.exoplatform.services.jcr.impl.storage.value.fs.CASableTreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws3" />
+                           <property name="digest-algo" value="MD5" />
+                           <property name="vcas-type" value="org.exoplatform.services.jcr.impl.storage.value.cas.JDBCValueContentAddressStorageImpl" />
+                           <property name="jdbc-source-name" value="jdbcjcr" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1/ws3" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws3" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr3" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                               
+            </workspace>
+         </workspaces>
+      </repository>
+
+      <repository name="db2" system-workspace="ws" default-workspace="ws">
+         <security-domain>exo-domain</security-domain>
+         <!-- access-control>optional</access-control -->
+         <!-- access-control>disable</access-control -->
+         <session-max-age>1h</session-max-age>
+         <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>
+         <workspaces>
+            <workspace name="ws">
+               <!-- for system storage -->
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcrdb2" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/wsdb2" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/wsdb2" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="100K" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                     <property name="root-permissions" value="*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db2/ws" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db2_ws" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcrdb2" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                              
+            </workspace>
+
+            <workspace name="ws1">
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr1db2" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws1db2" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws1" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws1db2" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="100K" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                     <property name="root-permissions" value="any read;any add_node;any set_property;any remove" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db2/ws1" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db2_ws1" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr1db2" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>  
+            </workspace>
+         </workspaces>
+      </repository>
+
+      <repository name="db1tck" system-workspace="ws" default-workspace="ws">
+         <security-domain>exo-domain</security-domain>
+         <!-- access-control>optional</access-control -->
+         <!-- access-control>disable</access-control -->
+         <session-max-age>1h</session-max-age>
+         <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>
+         <workspaces>
+            <workspace name="ws">
+               <!-- for system storage -->
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcrtck" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/wstck" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/wstck" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="100K" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                     <property name="root-permissions" value="any read;*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1tck/ws" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="excerptprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.WeightedHTMLExcerpt" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1tck_ws" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcrtck" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                
+            </workspace>
+
+            <workspace name="ws1">
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr1tck" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws1tck" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws1" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws1tck" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="100K" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                     <property name="root-permissions" value="any read;*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1tck/ws1" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1tck_ws1" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr1tck" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>  
+            </workspace>
+
+            <workspace name="ws2">
+               <container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer">
+                  <properties>
+                     <property name="source-name" value="jdbcjcr2tck" />
+                     <property name="dialect" value="auto" />
+                     <property name="multi-db" value="true" />
+                     <property name="update-storage" value="false" />
+                     <property name="max-buffer-size" value="200k" />
+                     <property name="swap-directory" value="target/temp/swap/ws2tck" />
+                  </properties>
+                  <value-storages>
+                     <value-storage id="ws2" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+                        <properties>
+                           <property name="path" value="target/temp/values/ws2tck" />
+                        </properties>
+                        <filters>
+                           <filter property-type="Binary" min-value-size="100K" />
+                        </filters>
+                     </value-storage>
+                  </value-storages>
+               </container>
+               <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+                  <properties>
+                     <property name="root-nodetype" value="nt:unstructured" />
+                     <property name="root-permissions" value="any read;*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove" />
+                  </properties>
+               </initializer>
+               <cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan.ISPNCacheWorkspaceStorageCache">
+                  <properties>
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                  </properties>
+               </cache>
+               <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+                  <properties>
+                     <property name="index-dir" value="target/temp/index/db1tck/ws2" />
+                     <property name="synonymprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.PropertiesSynonymProvider" />
+                     <property name="synonymprovider-config-path" value="../../synonyms.properties" />
+                     <property name="support-highlighting" value="true" />
+                     <property name="indexing-configuration-path" value="../../indexing-configuration.xml" />
+                     <property name="query-class" value="org.exoplatform.services.jcr.impl.core.query.QueryImpl" />
+                     <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" />
+                     <property name="excerptprovider-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.WeightedHTMLExcerpt"/>
+                     <property name="extractorPoolSize" value="2"/>
+                     <property name="extractorTimeout" value="10"/>
+                  </properties>
+               </query-handler>
+               <lock-manager class="org.exoplatform.services.jcr.impl.core.lock.infinispan.ISPNCacheableLockManagerImpl">
+                  <properties>
+                     <property name="time-out" value="15m" />
+                     <property name="infinispan-configuration" value="conf/standalone/cluster/test-infinispan-config.xml" />
+                     <property name="infinispan-cl-cache.jdbc.table.name" value="jcrlocks_db1tck_ws2" />
+                     <property name="infinispan-cl-cache.jdbc.table.create" value="true" />
+                     <property name="infinispan-cl-cache.jdbc.table.drop" value="false" />
+                     <property name="infinispan-cl-cache.jdbc.id.column" value="id" />
+                     <property name="infinispan-cl-cache.jdbc.data.column" value="data" />
+                     <property name="infinispan-cl-cache.jdbc.timestamp.column" value="timestamp" />
+                     <property name="infinispan-cl-cache.jdbc.datasource" value="jdbcjcr2tck" />
+                     <property name="infinispan-cl-cache.jdbc.connectionFactory" value="org.infinispan.loaders.jdbc.connectionfactory.ManagedConnectionFactory" />
+                  </properties>
+               </lock-manager>                  
+            </workspace>
+         </workspaces>
+      </repository>
+   </repositories>
+</repository-service>



More information about the exo-jcr-commits mailing list