exo-jcr SVN: r3578 - jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2010-11-30 04:44:44 -0500 (Tue, 30 Nov 2010)
New Revision: 3578
Modified:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java
Log:
EXOJCR-1083: NewGroupListener.preSave() and preDelete() now uses groupId from incoming Croup object instead generating it using parentId
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java 2010-11-30 09:41:20 UTC (rev 3577)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java 2010-11-30 09:44:44 UTC (rev 3578)
@@ -63,14 +63,24 @@
groupsPath_ = nodeHierarchyCreatorService.getJcrPath(GROUPS_PATH);
}
+ /**
+ * {@inheritDoc}
+ */
public void preSave(Group group, boolean isNew) throws Exception
{
String groupId = null;
- String parentId = group.getParentId();
- if (parentId == null || parentId.length() == 0)
- groupId = "/" + group.getGroupName();
+ if (group.getId() != null)
+ {
+ groupId = group.getId();
+ }
else
- groupId = parentId + "/" + group.getGroupName();
+ {
+ String parentId = group.getParentId();
+ if (parentId == null || parentId.length() == 0)
+ groupId = "/" + group.getGroupName();
+ else
+ groupId = parentId + "/" + group.getGroupName();
+ }
List<RepositoryEntry> repositories = jcrService_.getConfig().getRepositoryConfigurations();
if (isNew)
{
@@ -81,14 +91,24 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public void preDelete(Group group) throws Exception
{
String groupId = null;
- String parentId = group.getParentId();
- if (parentId == null || parentId.length() == 0)
- groupId = "/" + group.getGroupName();
+ if (group.getId() != null)
+ {
+ groupId = group.getId();
+ }
else
- groupId = parentId + "/" + group.getGroupName();
+ {
+ String parentId = group.getParentId();
+ if (parentId == null || parentId.length() == 0)
+ groupId = "/" + group.getGroupName();
+ else
+ groupId = parentId + "/" + group.getGroupName();
+ }
List<RepositoryEntry> repositories = jcrService_.getConfig().getRepositoryConfigurations();
for (RepositoryEntry repo : repositories)
{
13 years, 5 months
exo-jcr SVN: r3577 - in jcr/branches/1.14-IMPR: applications and 24 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-11-30 04:41:20 -0500 (Tue, 30 Nov 2010)
New Revision: 3577
Modified:
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.backupconsole/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.browser/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.config/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.fckeditor/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jboss/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jetty/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jonas/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.rest/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.applications.tomcat/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.cluster.testclient/pom.xml
jcr/branches/1.14-IMPR/applications/exo.jcr.ear/pom.xml
jcr/branches/1.14-IMPR/applications/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.component.core/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.component.ext/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.component.ftp/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.component.statistics/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.component.webdav/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.connectors.localadapter/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/en/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.docs/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.framework.command/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.framework.ftpclient/pom.xml
jcr/branches/1.14-IMPR/exo.jcr.framework.web/pom.xml
jcr/branches/1.14-IMPR/packaging/module/pom.xml
jcr/branches/1.14-IMPR/pom.xml
Log:
EXOJCR-1080: set version
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.backupconsole/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.backupconsole/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.backupconsole/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.applications.backupconsole</artifactId>
<name>eXo JCR :: Applications :: Backup Console</name>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.browser/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.browser/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.browser/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.applications.browser</artifactId>
<packaging>war</packaging>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.config/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.config/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.config/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.applications.config</artifactId>
<packaging>pom</packaging>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.fckeditor/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.fckeditor/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.fckeditor/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.applications.fckeditor</artifactId>
<packaging>war</packaging>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jboss/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jboss/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jboss/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.applications.config</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.ear</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<type>ear</type>
<scope>runtime</scope>
</dependency>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jetty/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jetty/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jetty/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.applications.config</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<relativePath>exo.jcr.applications.config</relativePath>
</parent>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jonas/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jonas/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.jonas/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.applications.config</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -40,7 +40,7 @@
<dependency>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.ear</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<type>ear</type>
<scope>runtime</scope>
</dependency>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.rest/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.rest/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.rest/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.applications.rest</artifactId>
<packaging>war</packaging>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.applications.tomcat/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.applications.tomcat/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.applications.tomcat/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.applications.config</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<relativePath>exo.jcr.applications.config</relativePath>
</parent>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.cluster.testclient/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.cluster.testclient/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.cluster.testclient/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.cluster.testclient</artifactId>
<name>eXo JCR :: Cluster :: Test Client</name>
Modified: jcr/branches/1.14-IMPR/applications/exo.jcr.ear/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/exo.jcr.ear/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/exo.jcr.ear/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.ear</artifactId>
<packaging>ear</packaging>
Modified: jcr/branches/1.14-IMPR/applications/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/applications/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/applications/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,12 +22,12 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jcr-applications-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<name>eXo JCR :: Applications :: Reactor</name>
<packaging>pom</packaging>
Modified: jcr/branches/1.14-IMPR/exo.jcr.component.core/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.component.core/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.component.core/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.component.core</artifactId>
<name>eXo JCR :: Component :: Core Service</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.component.ext/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.component.ext/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.component.ext/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.component.ext</artifactId>
<name>eXo JCR :: Component :: Extension Service</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.component.ftp/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.component.ftp/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.component.ftp/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.component.ftp</artifactId>
<name>eXo JCR :: Component :: FTP Service</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.component.statistics/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.component.statistics/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.component.statistics/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.component.statistics</artifactId>
<name>eXo JCR :: Component :: Statistics Provider</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.component.webdav/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.component.webdav/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.component.webdav/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.component.webdav</artifactId>
<name>eXo JCR :: Component :: Webdav Service</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.connectors.localadapter/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.connectors.localadapter/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.connectors.localadapter/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.connectors.localadapter</artifactId>
<packaging>rar</packaging>
Modified: jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/en/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/en/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/en/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.docs.developer</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
Modified: jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.docs/exo.jcr.docs.developer/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>exo.jcr.docs</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
Modified: jcr/branches/1.14-IMPR/exo.jcr.docs/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.docs/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.docs/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -22,7 +22,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
Modified: jcr/branches/1.14-IMPR/exo.jcr.framework.command/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.framework.command/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.framework.command/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -12,7 +12,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.framework.command</artifactId>
<name>eXo JCR :: Framework :: Command</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.framework.ftpclient/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.framework.ftpclient/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.framework.ftpclient/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.framework.ftpclient</artifactId>
<name>eXo JCR :: Framework :: FTP Client</name>
Modified: jcr/branches/1.14-IMPR/exo.jcr.framework.web/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/exo.jcr.framework.web/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/exo.jcr.framework.web/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -24,7 +24,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>exo.jcr.framework.web</artifactId>
<name>eXo JCR :: Framework :: Web</name>
Modified: jcr/branches/1.14-IMPR/packaging/module/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/packaging/module/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/packaging/module/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -4,7 +4,7 @@
<parent>
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
</parent>
<artifactId>jcr.packaging.module</artifactId>
<packaging>pom</packaging>
Modified: jcr/branches/1.14-IMPR/pom.xml
===================================================================
--- jcr/branches/1.14-IMPR/pom.xml 2010-11-30 08:46:00 UTC (rev 3576)
+++ jcr/branches/1.14-IMPR/pom.xml 2010-11-30 09:41:20 UTC (rev 3577)
@@ -29,7 +29,7 @@
<groupId>org.exoplatform.jcr</groupId>
<artifactId>jcr-parent</artifactId>
- <version>1.14.0-Beta02</version>
+ <version>1.14-IMPR-SNAPSHOT</version>
<packaging>pom</packaging>
<name>eXo JCR</name>
13 years, 5 months
exo-jcr SVN: r3576 - jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2010-11-30 03:46:00 -0500 (Tue, 30 Nov 2010)
New Revision: 3576
Modified:
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java
Log:
JCR-1527: NewGroupListener.preSave() and preDelete() now uses groupId from incoming Croup object instead generating it using parentId
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java 2010-11-29 07:27:57 UTC (rev 3575)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/hierarchy/impl/NewGroupListener.java 2010-11-30 08:46:00 UTC (rev 3576)
@@ -63,14 +63,24 @@
groupsPath_ = nodeHierarchyCreatorService.getJcrPath(GROUPS_PATH);
}
+ /**
+ * {@inheritDoc}
+ */
public void preSave(Group group, boolean isNew) throws Exception
{
String groupId = null;
- String parentId = group.getParentId();
- if (parentId == null || parentId.length() == 0)
- groupId = "/" + group.getGroupName();
+ if (group.getId() != null)
+ {
+ groupId = group.getId();
+ }
else
- groupId = parentId + "/" + group.getGroupName();
+ {
+ String parentId = group.getParentId();
+ if (parentId == null || parentId.length() == 0)
+ groupId = "/" + group.getGroupName();
+ else
+ groupId = parentId + "/" + group.getGroupName();
+ }
List<RepositoryEntry> repositories = jcrService_.getConfig().getRepositoryConfigurations();
if (isNew)
{
@@ -81,14 +91,24 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
public void preDelete(Group group) throws Exception
{
String groupId = null;
- String parentId = group.getParentId();
- if (parentId == null || parentId.length() == 0)
- groupId = "/" + group.getGroupName();
+ if (group.getId() != null)
+ {
+ groupId = group.getId();
+ }
else
- groupId = parentId + "/" + group.getGroupName();
+ {
+ String parentId = group.getParentId();
+ if (parentId == null || parentId.length() == 0)
+ groupId = "/" + group.getGroupName();
+ else
+ groupId = parentId + "/" + group.getGroupName();
+ }
List<RepositoryEntry> repositories = jcrService_.getConfig().getRepositoryConfigurations();
for (RepositoryEntry repo : repositories)
{
13 years, 5 months
exo-jcr SVN: r3575 - in jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules: jcr and 1 other directory.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2010-11-29 02:27:57 -0500 (Mon, 29 Nov 2010)
New Revision: 3575
Added:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/repository-creation-service.xml
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml
Log:
EXOJCR-929: RepositoryCreationService documentation added
Added: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/repository-creation-service.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/repository-creation-service.xml (rev 0)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/repository-creation-service.xml 2010-11-29 07:27:57 UTC (rev 3575)
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.RepositoryCreationService">
+ <?dbhtml filename="ch-repository-creation-service.html"?>
+
+ <title>RepositoryCreationService</title>
+
+ <section>
+ <title>Intro</title>
+
+ <para>RepositoryCreationService is the service for creation repositories
+ in runtime. The service can be used in standalone or cluster
+ environment.</para>
+ </section>
+
+ <section>
+ <title>Dependencies</title>
+
+ <para>RepositoryConfigurationService depends to next components:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><link linkend="Core.DBCreatorService">DBCreator</link> -
+ DBCreator used to create new database for each unbinded datasource.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="JCR.BackupService">BackupManager</link> -
+ BackupManager used to created repository from backup.</para>
+ </listitem>
+
+ <listitem>
+ <para><link linkend="Kernel.RPCService">RPCService</link> - RPCService
+ used for communication between cluster-nodes </para>
+
+ <note>
+ <para>RPCService may not be configured - in this case,
+ RepositoryService will work as standalone service.</para>
+ </note>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <title>How it works</title>
+
+ <itemizedlist>
+ <listitem>
+ <para> User executes reserveRepositoryName(String repositoryName) -
+ client-node calls coordinator-node to reserve repositoryName. If this
+ name is already reserved or repository with this name exist,
+ client-node will fetch RepositoryCreationException. If not Client will
+ get token string. </para>
+ </listitem>
+
+ <listitem>
+ <para>than user executes createRepository(String backupId,
+ RepositoryEntry rEntry, String token). Coordinator-node checks the
+ token, and creates Repository. </para>
+ </listitem>
+
+ <listitem>
+ <para> whan repository become created - user-node broadcast message to
+ all clusterNodes with RepositoryEntry, so each cluster node starts new
+ Repository. </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>There is two ways to create repositry: make it in single step - just
+ call createRepository(String backupId, RepositoryEntry); or reserve
+ repositoryName at first (reserveRepositoryName(String repositoryName)),
+ than create reserved repository (createRepository(String backupId,
+ RepositoryEntry rEntry, String token)). </para>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <para>RepositoryCreationService configuration</para>
+
+ <programlisting><component>
+ <key>org.exoplatform.services.jcr.ext.backup.BackupManager</key>
+ <type>org.exoplatform.services.jcr.ext.backup.impl.BackupManagerImpl</type>
+ <init-params>
+ <properties-param>
+ <name>backup-properties</name>
+ <property name="default-incremental-job-period" value="3600" /><!-- set default incremental periond = 60 minutes -->
+ <property name="full-backup-type" value="org.exoplatform.services.jcr.ext.backup.impl.fs.FullBackupJob" />
+ <property name="incremental-backup-type" value="org.exoplatform.services.jcr.ext.backup.impl.fs.IncrementalBackupJob" />
+ <property name="backup-dir" value="target/backup" />
+ </properties-param>
+ </init-params>
+</component>
+
+<component>
+ <key>org.exoplatform.services.database.creator.DBCreator</key>
+ <type>org.exoplatform.services.database.creator.DBCreator</type>
+ <init-params>
+ <properties-param>
+ <name>db-connection</name>
+ <description>database connection properties</description>
+ <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
+ <property name="url" value="jdbc:hsqldb:file:target/temp/data/" />
+ <property name="username" value="sa" />
+ <property name="password" value="" />
+ </properties-param>
+ <properties-param>
+ <name>db-creation</name>
+ <description>database creation properties</description>
+ <property name="scriptPath" value="src/test/resources/test.sql" />
+ <property name="username" value="sa" />
+ <property name="password" value="" />
+ </properties-param>
+ </init-params>
+</component>
+
+<component>
+ <key>org.exoplatform.services.rpc.RPCService</key>
+ <type>org.exoplatform.services.rpc.impl.RPCServiceImpl</type>
+ <init-params>
+ <value-param>
+ <name>jgroups-configuration</name>
+ <value>jar:/conf/standalone/udp-mux.xml</value>
+ </value-param>
+ <value-param>
+ <name>jgroups-cluster-name</name>
+ <value>RPCService-Cluster</value>
+ </value-param>
+ <value-param>
+ <name>jgroups-default-timeout</name>
+ <value>0</value>
+ </value-param>
+ </init-params>
+</component>
+
+<component>
+ <key>org.exoplatform.services.jcr.ext.repository.creation.RepositoryCreationService</key>
+ <type>
+ org.exoplatform.services.jcr.ext.repository.creation.RepositoryCreationServiceImpl
+ </type>
+</component></programlisting>
+ </section>
+
+ <section>
+ <title>Repsitory Interface</title>
+
+ <programlisting>public interface RepositoryCreationService
+{
+ /**
+ * Reserves, validates and creates repository in a simplified form.
+ *
+ * @param rEntry - repository Entry - note that datasource must not exist.
+ * @param backupId - backup id
+ * @throws RepositoryConfigurationException
+ * if some exception occurred during repository creation or repository name is absent in reserved list
+ * @throws RepositoryCreationServiceException
+ * if some exception occurred during repository creation or repository name is absent in reserved list
+ */
+ void createRepository(String backupId, RepositoryEntry rEntry) throws RepositoryConfigurationException,
+ RepositoryCreationException;
+
+ /**
+ * Reserve repository name to prevent repository creation with same name from other place in same time
+ * via this service.
+ *
+ * @param repositoryName - repositoryName
+ * @return repository token. Anyone obtaining a token can later create a repository of reserved name.
+ * @throws RepositoryCreationServiceException if can't reserve name
+ */
+ String reserveRepositoryName(String repositoryName) throws RepositoryCreationException;
+
+ /**
+ * Creates repository, using token of already reserved repository name. Good for cases, when repository creation should be delayed or
+ * made asynchronously in dedicated thread.
+ *
+ * @param rEntry - repository entry - note, that datasource must not exist
+ * @param backupId - backup id
+ * @param rToken - token
+ * @throws RepositoryConfigurationException
+ * if some exception occurred during repository creation or repository name is absent in reserved list
+ * @throws RepositoryCreationServiceException
+ * if some exception occurred during repository creation or repository name is absent in reserved list
+ */
+ void createRepository(String backupId, RepositoryEntry rEntry, String rToken)
+ throws RepositoryConfigurationException, RepositoryCreationException;
+}</programlisting>
+ </section>
+
+ <section>
+ <title>Conclusions and restrictions</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Each datasource in RepositoryEntry of new Repository must have
+ unbinded datasources. Thats mean, such datasource must have not
+ databases behind them. This restriction exists to avoid corruption of
+ existing repositories data. </para>
+ </listitem>
+
+ <listitem>
+ <para>RPCService is optional component, but without it,
+ RepositoryCreatorService can not communicate with other cluster-nodes
+ and works as standalone.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</chapter>
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml 2010-11-26 15:02:32 UTC (rev 3574)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.xml 2010-11-29 07:27:57 UTC (rev 3575)
@@ -89,7 +89,11 @@
<xi:include href="jcr/transaction-manager-lookup.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="jcr/repository-creation-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+
<!-- search -->
<xi:include href="jcr/searching/jcr-query-usecases.xml"
13 years, 5 months
exo-jcr SVN: r3574 - jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/repository/creation.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2010-11-26 10:02:32 -0500 (Fri, 26 Nov 2010)
New Revision: 3574
Modified:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/repository/creation/RepositoryCreationServiceImpl.java
Log:
EXOJCR-929: RepositoryCreationServiceImpl made as Startable
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/repository/creation/RepositoryCreationServiceImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/repository/creation/RepositoryCreationServiceImpl.java 2010-11-26 14:03:02 UTC (rev 3573)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/repository/creation/RepositoryCreationServiceImpl.java 2010-11-26 15:02:32 UTC (rev 3574)
@@ -45,6 +45,7 @@
import org.exoplatform.ws.frameworks.json.impl.JsonGeneratorImpl;
import org.exoplatform.ws.frameworks.json.impl.JsonParserImpl;
import org.exoplatform.ws.frameworks.json.value.JsonValue;
+import org.picocontainer.Startable;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -72,7 +73,7 @@
* @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
* @version $Id: RepositoryCreationServiceImpl.java 111 2008-11-11 11:11:11Z serg $
*/
-public class RepositoryCreationServiceImpl implements RepositoryCreationService
+public class RepositoryCreationServiceImpl implements RepositoryCreationService, Startable
{
/**
* The logger.
@@ -624,4 +625,22 @@
return new BeanBuilder().createObject(cl, jsonValue);
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start()
+ {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop()
+ {
+ this.rpcService.unregisterCommand(reserveRepositoryName);
+ this.rpcService.unregisterCommand(createRepository);
+ this.rpcService.unregisterCommand(startRepository);
+ }
}
13 years, 5 months
exo-jcr SVN: r3573 - jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup.
by do-not-reply@jboss.org
Author: tolusha
Date: 2010-11-26 09:03:02 -0500 (Fri, 26 Nov 2010)
New Revision: 3573
Modified:
jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java
Log:
EXOJCR-896: fix test
Modified: jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java 2010-11-26 13:26:11 UTC (rev 3572)
+++ jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java 2010-11-26 14:03:02 UTC (rev 3573)
@@ -491,7 +491,7 @@
final BackupChain bch = backup.startBackup(config);
- Thread.sleep(30000);
+ Thread.sleep(40000);
assertTrue(bch.isFinished());
13 years, 5 months
exo-jcr SVN: r3572 - in jcr/trunk: exo.jcr.component.ext and 1 other directory.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2010-11-26 08:26:11 -0500 (Fri, 26 Nov 2010)
New Revision: 3572
Modified:
jcr/trunk/exo.jcr.component.ext/pom.xml
jcr/trunk/pom.xml
Log:
EXOJCR-1054 : updating parent pom and ext's pom with new dependencies
Modified: jcr/trunk/exo.jcr.component.ext/pom.xml
===================================================================
--- jcr/trunk/exo.jcr.component.ext/pom.xml 2010-11-26 13:07:26 UTC (rev 3571)
+++ jcr/trunk/exo.jcr.component.ext/pom.xml 2010-11-26 13:26:11 UTC (rev 3572)
@@ -109,7 +109,7 @@
<artifactId>commons-chain</artifactId>
</dependency>
<dependency>
- <groupId>jgroups</groupId>
+ <groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
</dependency>
<dependency>
Modified: jcr/trunk/pom.xml
===================================================================
--- jcr/trunk/pom.xml 2010-11-26 13:07:26 UTC (rev 3571)
+++ jcr/trunk/pom.xml 2010-11-26 13:26:11 UTC (rev 3572)
@@ -354,9 +354,9 @@
<version>1.8.0.7</version>
</dependency>
<dependency>
- <groupId>jgroups</groupId>
+ <groupId>org.jgroups</groupId>
<artifactId>jgroups</artifactId>
- <version>2.6.13.GA</version>
+ <version>2.10.0.GA</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
@@ -398,6 +398,16 @@
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>4.1.0.FINAL</version>
+ </dependency>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-cachestore-jdbc</artifactId>
+ <version>4.1.0.FINAL</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
13 years, 5 months
exo-jcr SVN: r3571 - in jcr/trunk/exo.jcr.component.core: src/main/java/org/exoplatform/services/jcr and 19 other directories.
by do-not-reply@jboss.org
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@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@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(a)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(a)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(a)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(a)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(a)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@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(a)exoplatform.org">Anatoliy Bazko</a>
+ * @version $Id: InfinispanLockManagerImpl.java 111 2010-11-11 11:11:11Z tolusha $
+ */
+@Managed
+@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(a)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(a)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(a)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(a)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@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@exoplatform.org">Sergey Kabashnyuk</a>
+ * @version $Id: BufferedISPNCache.java 3514 2010-11-22 16:14:36Z nzamosenchuk $
+ *
+ */
+@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(a)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@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@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@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@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@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(a)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(a)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(a)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@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(a)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(a)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(a)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(a)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(a)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>
13 years, 5 months
exo-jcr SVN: r3570 - jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/backup.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-11-25 10:28:39 -0500 (Thu, 25 Nov 2010)
New Revision: 3570
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml
Log:
JCR-1502 : Changes for "The JCR backupset should be fully independent" was committed.
Modified: jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml 2010-11-25 15:27:54 UTC (rev 3569)
+++ jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/backup/exojcr-backup-service.xml 2010-11-25 15:28:39 UTC (rev 3570)
@@ -473,5 +473,55 @@
reinitialization, the task will have new time values for the backup
operation cycle as the chainPeriod and incrementalPeriod will be applied
again. That behaviour may be changed in the future.</para>
+
+ <para></para>
+
+ <section>
+ <title>Restore a workspace or a repository using original
+ configuration</title>
+
+ <para>The Backup manager allows you to restore a repository or a
+ workspace using the original configuration stored into the backup
+ log:</para>
+
+ <programlisting> /**
+ * WorkspaceEntry for restore should be contains in BackupChainLog.
+ *
+ * @param workspaceBackupIdentifier
+ * identifier to workspace backup.
+ * @param asynchronous
+ * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ * @throws BackupOperationException
+ * if backup operation exception occurred
+ * @throws BackupConfigurationException
+ * if configuration exception occurred
+ */
+ void restoreWorkspace(String workspaceBackupIdentifier, boolean asynchronous) throws BackupOperationException,
+ BackupConfigurationException;
+
+ /**
+ * ReprositoryEntry for restore should be contains in BackupChainLog.
+ *
+ * @param repositoryBackupIdentifier
+ * identifier to repository backup.
+ * @param asynchronous
+ * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ * @throws BackupOperationException
+ * if backup operation exception occurred
+ * @throws BackupConfigurationException
+ * if configuration exception occurred
+ */
+ void restoreRepository(String repositoryBackupIdentifier, boolean asynchronous) throws BackupOperationException,
+ BackupConfigurationException;</programlisting>
+ </section>
+
+ <section>
+ <title>Backup set portability</title>
+
+ <para>The Backup log is stored during the Backup operation into two
+ different locations: backup-dir directory of BackupService to support
+ interactive operations via Backup API (e.g. console) and backup set
+ files for portability (e.g. on another server).</para>
+ </section>
</section>
</chapter>
13 years, 5 months
exo-jcr SVN: r3569 - in jcr/branches/1.12.x/exo.jcr.component.ext/src: main/java/org/exoplatform/services/jcr/ext/backup/impl and 1 other directories.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2010-11-25 10:27:54 -0500 (Thu, 25 Nov 2010)
New Revision: 3569
Added:
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/ExtendedBackupManager.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/WorkspaceRestoreException.java
Modified:
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/BackupChainLog.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/RepositoryBackupChainLog.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupChainImpl.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/RepositoryBackupChainImpl.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/AbstractBackupTestCase.java
jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java
Log:
JCR-1502 : Changes for "The JCR backupset should be fully independent" was committed.
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/BackupChainLog.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/BackupChainLog.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/BackupChainLog.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -18,15 +18,14 @@
*/
package org.exoplatform.services.jcr.ext.backup;
-import org.exoplatform.services.jcr.impl.util.JCRDateFormat;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -44,6 +43,20 @@
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.StartElement;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.util.JCRDateFormat;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.exoplatform.ws.frameworks.json.JsonHandler;
+import org.exoplatform.ws.frameworks.json.JsonParser;
+import org.exoplatform.ws.frameworks.json.impl.BeanBuilder;
+import org.exoplatform.ws.frameworks.json.impl.JsonDefaultHandler;
+import org.exoplatform.ws.frameworks.json.impl.JsonException;
+import org.exoplatform.ws.frameworks.json.impl.JsonGeneratorImpl;
+import org.exoplatform.ws.frameworks.json.impl.JsonParserImpl;
+import org.exoplatform.ws.frameworks.json.value.JsonValue;
+
/**
* Created by The eXo Platform SARL .<br/>
*
@@ -53,6 +66,11 @@
public class BackupChainLog
{
+ /**
+ * Start for 1.1 version log will be stored relative paths.
+ */
+ protected static String VERSION_LOG_1_1 = "1.1";
+
protected static Log logger = ExoLogger.getLogger("exo.jcr.component.ext.BackupChainLog");
public static final String PREFIX = "backup-";
@@ -79,6 +97,12 @@
private boolean finalized;
+ private WorkspaceEntry originalWorkspaceEntry;
+
+ private final String versionLog;
+
+ private File rootDir;
+
/**
* BackupChainLog constructor.
*
@@ -92,24 +116,30 @@
* Sting, FQN for incremental backup
* @param backupId
* String, the identifier of backup
+ * @param wEntry
+ * original workspace config
* @throws BackupOperationException
* will be generate the exception BackupOperationException
*/
public BackupChainLog(File logDir, BackupConfig config, String fullBackupType, String incrementalBackupType,
- String backupId) throws BackupOperationException
+ String backupId, WorkspaceEntry wEntry, File rootDir) throws BackupOperationException
{
try
{
this.finalized = false;
+ this.versionLog = VERSION_LOG_1_1;
this.log = new File(logDir.getCanonicalPath() + File.separator + (PREFIX + backupId + SUFFIX));
+ this.rootDir = rootDir;
this.log.createNewFile();
this.backupId = backupId;
this.config = config;
this.jobEntries = new ArrayList<JobEntryInfo>();
+ this.originalWorkspaceEntry = wEntry;
// write config info here
logWriter = new LogWriter(log);
logWriter.write(config, fullBackupType, incrementalBackupType);
+ logWriter.writeWorkspaceEntry(originalWorkspaceEntry);
}
catch (IOException e)
{
@@ -123,6 +153,10 @@
{
throw new BackupOperationException(e);
}
+ catch (JsonException e)
+ {
+ throw new BackupOperationException(e);
+ }
}
/**
@@ -144,10 +178,12 @@
logReader.readLogFile();
logReader.jobEntrysNormalize();
+ this.versionLog = logReader.getVersionLog();
this.config = logReader.getBackupConfig();
this.startedTime = logReader.getBeginTime();
this.finishedTime = logReader.getEndTime();
this.jobEntries = logReader.getJobEntryInfoNormalizeList();
+ this.originalWorkspaceEntry = logReader.getOriginalWorkspaceEntry();
for (JobEntryInfo info : jobEntries)
{
@@ -178,6 +214,10 @@
{
throw new BackupOperationException(e);
}
+ catch (Exception e)
+ {
+ throw new BackupOperationException(e);
+ }
}
/**
@@ -197,7 +237,7 @@
info.setState(job.getState());
info.setURL(job.getStorageURL());
- logWriter.write(info);
+ logWriter.write(info, config);
}
catch (Exception e)
{
@@ -246,6 +286,33 @@
{
finalized = true;
logWriter.writeEndLog();
+
+ //copy backup chain log file in into Backupset files itself for portability (e.g. on another server)
+ try
+ {
+ InputStream in = new FileInputStream(log);
+
+ File dest = new File(config.getBackupDir() + File.separator + log.getName());
+ if (!dest.exists())
+ {
+ OutputStream out = new FileOutputStream(dest);
+
+ byte[] buf = new byte[(int) (log.length())];
+ in.read(buf);
+
+ String sConfig = new String(buf, Constants.DEFAULT_ENCODING);
+ sConfig = sConfig.replaceAll("<backup-dir>.+</backup-dir>", "<backup-dir>.</backup-dir>");
+
+ out.write(sConfig.getBytes(Constants.DEFAULT_ENCODING));
+ in.close();
+ out.close();
+ }
+ }
+ catch (Exception e)
+ {
+ logger.error("Can't write log", e);
+ }
+
}
/**
@@ -309,6 +376,17 @@
return finishedTime;
}
+ /**
+ * Getting original workspace configuration
+ *
+ * @return WorkspaceEntry
+ * return the original workspace configuration
+ */
+ public WorkspaceEntry getOriginalWorkspaceEntry()
+ {
+ return originalWorkspaceEntry;
+ }
+
private class LogReader
{
protected Log logger = ExoLogger.getLogger("exo.jcr.component.ext.LogReader");
@@ -322,15 +400,31 @@
private List<JobEntryInfo> jobEntries;
private List<JobEntryInfo> jobEntriesNormalize;
+
+ private WorkspaceEntry originalWorkspaceEntry;
+
+ private String version;
public LogReader(File logFile) throws FileNotFoundException, XMLStreamException, FactoryConfigurationError
{
this.logFile = logFile;
jobEntries = new ArrayList<JobEntryInfo>();
- reader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(this.logFile));
+ reader =
+ XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(this.logFile),
+ Constants.DEFAULT_ENCODING);
}
+ public String getVersionLog()
+ {
+ return version;
+ }
+
+ public WorkspaceEntry getOriginalWorkspaceEntry()
+ {
+ return originalWorkspaceEntry;
+ }
+
public BackupConfig getBackupConfig()
{
return config;
@@ -356,7 +450,7 @@
return jobEntries.get(jobEntries.size() - 1).getDate();
}
- public void readLogFile() throws XMLStreamException, MalformedURLException, ValueFormatException
+ public void readLogFile() throws Exception
{
boolean endDocument = false;
@@ -375,6 +469,14 @@
if (name.equals("job-entry-info"))
jobEntries.add(readJobEntryInfo());
+ if (name.equals("original-workspace-config"))
+ this.originalWorkspaceEntry = readWorkspaceEntry();
+
+ if (name.equals("version-log"))
+ {
+ this.version = readContent();
+ }
+
break;
case StartElement.END_DOCUMENT :
@@ -384,8 +486,38 @@
}
}
- private JobEntryInfo readJobEntryInfo() throws XMLStreamException, MalformedURLException, ValueFormatException
+ private WorkspaceEntry readWorkspaceEntry() throws Exception
{
+ String jsonRepositoryEntry = reader.getElementText();
+
+ return (WorkspaceEntry) (getObject(WorkspaceEntry.class, jsonRepositoryEntry
+ .getBytes(Constants.DEFAULT_ENCODING)));
+ }
+
+ /**
+ * Will be created the Object from JSON binary data.
+ *
+ * @param cl
+ * Class
+ * @param data
+ * binary data (JSON)
+ * @return Object
+ * @throws Exception
+ * will be generated Exception
+ */
+ private Object getObject(Class cl, byte[] data) throws Exception
+ {
+ JsonHandler jsonHandler = new JsonDefaultHandler();
+ JsonParser jsonParser = new JsonParserImpl();
+ InputStream inputStream = new ByteArrayInputStream(data);
+ jsonParser.parse(inputStream, jsonHandler);
+ JsonValue jsonValue = jsonHandler.getJsonObject();
+
+ return new BeanBuilder().createObject(cl, jsonValue);
+ }
+
+ private JobEntryInfo readJobEntryInfo() throws XMLStreamException, ValueFormatException, IOException
+ {
JobEntryInfo info = new JobEntryInfo();
boolean endJobEntryInfo = false;
@@ -406,8 +538,22 @@
info.setState(getState(readContent()));
if (name.equals("url"))
- info.setURL(new URL(readContent()));
+ {
+ if (version != null && version.equals(VERSION_LOG_1_1))
+ {
+ String path =
+ readContent().replace("file:",
+ "file:" + config.getBackupDir().getCanonicalPath()
+ + File.separator);
+ info.setURL(new URL(path));
+ }
+ else
+ {
+ info.setURL(new URL(readContent()));
+ }
+ }
+
if (name.equals("date"))
info.setDate(JCRDateFormat.parse(readContent()));
@@ -457,7 +603,7 @@
return type;
}
- private BackupConfig readBackupConfig() throws XMLStreamException
+ private BackupConfig readBackupConfig() throws XMLStreamException, IOException
{
BackupConfig conf = new BackupConfig();
@@ -473,8 +619,27 @@
String name = reader.getLocalName();
if (name.equals("backup-dir"))
- conf.setBackupDir(new File(readContent()));
+ {
+ if (version != null && version.equals(VERSION_LOG_1_1))
+ {
+ String dir = readContent();
+ if (dir.equals("."))
+ {
+ String path = logFile.getParentFile().getCanonicalPath();
+ conf.setBackupDir(new File(path));
+ }
+ else
+ {
+ conf.setBackupDir(new File(dir));
+ }
+ }
+ else
+ {
+ conf.setBackupDir(new File(readContent()));
+ }
+ }
+
if (name.equals("repository"))
conf.setRepository(readContent());
@@ -546,15 +711,32 @@
{
this.logFile = logFile;
- writer = XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(this.logFile));
+ writer =
+ XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(this.logFile),
+ Constants.DEFAULT_ENCODING);
writer.writeStartDocument();
- writer.writeStartElement("backup-cain-log");
+ writer.writeStartElement("backup-chain-log");
+
+ writer.writeStartElement("version-log");
+ writer.writeCharacters(versionLog);
+ writer.writeEndElement();
+
writer.flush();
}
+ public void writeWorkspaceEntry(WorkspaceEntry originalWorkspaceEntry) throws JsonException, XMLStreamException
+ {
+ JsonGeneratorImpl generatorImpl = new JsonGeneratorImpl();
+ JsonValue json = generatorImpl.createJsonObject(originalWorkspaceEntry);
+
+ writer.writeStartElement("original-workspace-config");
+ writer.writeCData(json.toString());
+ writer.writeEndElement();
+ }
+
public synchronized void write(BackupConfig config, String fullBackupType, String incrementalBackupType)
- throws XMLStreamException
+ throws XMLStreamException, IOException
{
writer.writeStartElement("backup-config");
@@ -569,7 +751,14 @@
if (config.getBackupDir() != null)
{
writer.writeStartElement("backup-dir");
- writer.writeCharacters(config.getBackupDir().getAbsolutePath());
+
+ String path =
+ (isRootBackupManagerDir(logFile) ? config.getBackupDir().getCanonicalPath() : config
+ .getBackupDir().getCanonicalPath()
+ .replace(logFile.getParentFile().getCanonicalPath(), ""));
+
+
+ writer.writeCharacters(path.equals("") ? "." : path);
writer.writeEndElement();
}
@@ -600,7 +789,7 @@
writer.flush();
}
- public synchronized void write(JobEntryInfo info) throws XMLStreamException
+ public synchronized void write(JobEntryInfo info, BackupConfig config) throws XMLStreamException, IOException
{
writer.writeStartElement("job-entry-info");
@@ -613,7 +802,7 @@
writer.writeEndElement();
writer.writeStartElement("url");
- writer.writeCharacters(info.getURL().toString());
+ writer.writeCharacters(getRelativeUrl(info.getURL(), config.getBackupDir()));
writer.writeEndElement();
writer.writeStartElement("date");
@@ -625,6 +814,18 @@
writer.flush();
}
+ private String getRelativeUrl(URL url, File backupDir) throws IOException
+ {
+ String str = new File(url.getFile()).getCanonicalPath();
+
+ return url.getProtocol() + ":" + str.replace(config.getBackupDir().getCanonicalPath() + File.separator, "");
+ }
+
+ private boolean isRootBackupManagerDir(File log) throws IOException
+ {
+ return (log.getCanonicalFile().getParentFile().getCanonicalPath().equals(rootDir.getCanonicalPath()));
+ }
+
public synchronized void writeEndLog()
{
try
Added: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/ExtendedBackupManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/ExtendedBackupManager.java (rev 0)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/ExtendedBackupManager.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -0,0 +1,98 @@
+/*
+ * 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.ext.backup;
+
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date: 2010
+ *
+ * @author <a href="mailto:alex.reshetnyak@exoplatform.com.ua">Alex Reshetnyak</a>
+ * @version $Id: ExtendedBackupManager.java 3545 2010-11-24 15:35:31Z areshetnyak $
+ */
+public interface ExtendedBackupManager
+ extends BackupManager
+{
+
+ // TODO Will be uncommented after fix issue JCR-1054
+ // /**
+ // * Restore existing workspace. Previous data will be deleted.
+ // * For getting status of workspace restore can use
+ // * BackupManager.getLastRestore(String repositoryName, String workspaceName) method
+ // * WorkspaceEntry for restore should be contains in BackupChainLog.
+ // *
+ // * @param workspaceBackupIdentifier
+ // * identifier to workspace backup.
+ // * @param asynchronous
+ // * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ // * @throws BackupOperationException
+ // * if backup operation exception occurred
+ // * @throws BackupConfigurationException
+ // * if configuration exception occurred
+ // */
+ // void restoreExistingWorkspace(String workspaceBackupIdentifier, boolean asynchronous)
+ // throws BackupOperationException, BackupConfigurationException;
+ //
+ // /**
+ // * Restore existing repository. Previous data will be deleted.
+ // * For getting status of repository restore can use
+ // * BackupManager.getLastRestore(String repositoryName) method.
+ // * ReprositoryEntry for restore should be contains in BackupChainLog.
+ // *
+ // * @param repositoryBackupIdentifier
+ // * identifier to repository backup.
+ // * @param asynchronous
+ // * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ // * @throws BackupOperationException
+ // * if backup operation exception occurred
+ // * @throws BackupConfigurationException
+ // * if configuration exception occurred
+ // */
+ // void restoreExistingRepository(String repositoryBackupIdentifier, boolean asynchronous)
+ // throws BackupOperationException, BackupConfigurationException;
+
+ /**
+ * WorkspaceEntry for restore should be contains in BackupChainLog.
+ *
+ * @param workspaceBackupIdentifier
+ * identifier to workspace backup.
+ * @param asynchronous
+ * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ * @throws BackupOperationException
+ * if backup operation exception occurred
+ * @throws BackupConfigurationException
+ * if configuration exception occurred
+ */
+ void restoreWorkspace(String workspaceBackupIdentifier, boolean asynchronous) throws BackupOperationException,
+ BackupConfigurationException;
+
+ /**
+ * ReprositoryEntry for restore should be contains in BackupChainLog.
+ *
+ * @param repositoryBackupIdentifier
+ * identifier to repository backup.
+ * @param asynchronous
+ * if 'true' restore will be in asynchronous mode (i.e. in separated thread)
+ * @throws BackupOperationException
+ * if backup operation exception occurred
+ * @throws BackupConfigurationException
+ * if configuration exception occurred
+ */
+ void restoreRepository(String repositoryBackupIdentifier, boolean asynchronous) throws BackupOperationException,
+ BackupConfigurationException;
+}
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/RepositoryBackupChainLog.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/RepositoryBackupChainLog.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/RepositoryBackupChainLog.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -16,18 +16,19 @@
*/
package org.exoplatform.services.jcr.ext.backup;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
-import javax.jcr.ValueFormatException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
@@ -36,9 +37,19 @@
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.events.StartElement;
+import org.exoplatform.services.jcr.config.RepositoryEntry;
+import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.util.JCRDateFormat;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import org.exoplatform.ws.frameworks.json.JsonHandler;
+import org.exoplatform.ws.frameworks.json.JsonParser;
+import org.exoplatform.ws.frameworks.json.impl.BeanBuilder;
+import org.exoplatform.ws.frameworks.json.impl.JsonDefaultHandler;
+import org.exoplatform.ws.frameworks.json.impl.JsonException;
+import org.exoplatform.ws.frameworks.json.impl.JsonGeneratorImpl;
+import org.exoplatform.ws.frameworks.json.impl.JsonParserImpl;
+import org.exoplatform.ws.frameworks.json.value.JsonValue;
/**
* Created by The eXo Platform SAS.
@@ -63,15 +74,22 @@
{
this.logFile = logFile;
- writer = XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(this.logFile));
+ writer =
+ XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(this.logFile),
+ Constants.DEFAULT_ENCODING);
writer.writeStartDocument();
writer.writeStartElement("repository-backup-chain-log");
- writer.flush();
+ writer.writeStartElement("version-log");
+ writer.writeCharacters(versionLog);
+ writer.writeEndElement();
+
writer.writeStartElement("start-time");
writer.writeCharacters(JCRDateFormat.format(startedTime));
writer.writeEndElement();
+
+ writer.flush();
}
public void writeSystemWorkspaceName(String wsName) throws XMLStreamException
@@ -82,14 +100,16 @@
writer.flush();
}
- public void writeBackupsPath(List<String> wsLogFilePathList) throws XMLStreamException
+ public void writeBackupsPath(List<String> wsLogFilePathList, RepositoryBackupConfig config)
+ throws XMLStreamException,
+ IOException
{
writer.writeStartElement("workspaces-backup-info");
for (String path : wsLogFilePathList)
{
writer.writeStartElement("url");
- writer.writeCharacters(path);
+ writer.writeCharacters(path.replace(config.getBackupDir().getCanonicalPath() + File.separator, ""));
writer.writeEndElement();
}
@@ -99,7 +119,7 @@
}
public synchronized void write(RepositoryBackupConfig config, String fullBackupType, String incrementalBackupType)
- throws XMLStreamException
+ throws XMLStreamException, IOException
{
writer.writeStartElement("repository-backup-config");
@@ -118,7 +138,7 @@
if (config.getBackupDir() != null)
{
writer.writeStartElement("backup-dir");
- writer.writeCharacters(config.getBackupDir().getAbsolutePath());
+ writer.writeCharacters(config.getBackupDir().getCanonicalPath());
writer.writeEndElement();
}
@@ -159,6 +179,17 @@
logger.error("Can't write end log", e);
}
}
+
+ public synchronized void writeRepositoryEntry(RepositoryEntry rEntry) throws JsonException, XMLStreamException
+ {
+
+ JsonGeneratorImpl generatorImpl = new JsonGeneratorImpl();
+ JsonValue json = generatorImpl.createJsonObject(rEntry);
+
+ writer.writeStartElement("original-repository-config");
+ writer.writeCData(json.toString());
+ writer.writeEndElement();
+ }
}
private class LogReader
@@ -169,13 +200,17 @@
private XMLStreamReader reader;
+ private String version;
+
public LogReader(File logFile) throws FileNotFoundException, XMLStreamException, FactoryConfigurationError
{
this.logFile = logFile;
- reader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(logFile));
+ reader =
+ XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(logFile),
+ Constants.DEFAULT_ENCODING);
}
- public void readLogFile() throws XMLStreamException, MalformedURLException, ValueFormatException
+ public void readLogFile() throws UnsupportedEncodingException, Exception
{
boolean endDocument = false;
@@ -206,6 +241,15 @@
if (name.equals("finish-time"))
finishedTime = JCRDateFormat.parse(readContent());
+ if (name.equals("original-repository-config"))
+ originalRepositoryEntry = readRepositoryEntry();
+
+ if (name.equals("version-log"))
+ {
+ this.version = readContent();
+ }
+
+
break;
case StartElement.END_DOCUMENT :
@@ -215,8 +259,38 @@
}
}
- private List<String> readWorkspaceBackupInfo() throws XMLStreamException
+ private RepositoryEntry readRepositoryEntry() throws UnsupportedEncodingException, Exception
{
+ String jsonRepositoryEntry = reader.getElementText();
+
+ return (RepositoryEntry) (getObject(RepositoryEntry.class, jsonRepositoryEntry
+ .getBytes(Constants.DEFAULT_ENCODING)));
+ }
+
+ /**
+ * Will be created the Object from JSON binary data.
+ *
+ * @param cl
+ * Class
+ * @param data
+ * binary data (JSON)
+ * @return Object
+ * @throws Exception
+ * will be generated Exception
+ */
+ private Object getObject(Class cl, byte[] data) throws Exception
+ {
+ JsonHandler jsonHandler = new JsonDefaultHandler();
+ JsonParser jsonParser = new JsonParserImpl();
+ InputStream inputStream = new ByteArrayInputStream(data);
+ jsonParser.parse(inputStream, jsonHandler);
+ JsonValue jsonValue = jsonHandler.getJsonObject();
+
+ return new BeanBuilder().createObject(cl, jsonValue);
+ }
+
+ private List<String> readWorkspaceBackupInfo() throws XMLStreamException, IOException
+ {
List<String> wsBackupInfo = new ArrayList<String>();
boolean endWorkspaceBackupInfo = false;
@@ -231,7 +305,17 @@
String name = reader.getLocalName();
if (name.equals("url"))
- wsBackupInfo.add(readContent());
+ {
+ if (version != null && version.equals(VERSION_LOG_1_1))
+ {
+ String path = config.getBackupDir().getCanonicalPath() + File.separator + readContent();
+ wsBackupInfo.add(path);
+ }
+ else
+ {
+ wsBackupInfo.add(readContent());
+ }
+ }
break;
@@ -247,7 +331,7 @@
return wsBackupInfo;
}
- private BackupConfig readBackupConfig() throws XMLStreamException
+ private BackupConfig readBackupConfig() throws XMLStreamException, IOException
{
BackupConfig conf = new BackupConfig();
@@ -263,8 +347,27 @@
String name = reader.getLocalName();
if (name.equals("backup-dir"))
- conf.setBackupDir(new File(readContent()));
+ {
+ if (version != null && version.equals(VERSION_LOG_1_1))
+ {
+ String dir = readContent();
+ if (dir.equals("."))
+ {
+ String path = logFile.getParentFile().getCanonicalPath();
+ conf.setBackupDir(new File(path));
+ }
+ else
+ {
+ conf.setBackupDir(new File(dir));
+ }
+ }
+ else
+ {
+ conf.setBackupDir(new File(readContent()));
+ }
+ }
+
if (name.equals("backup-type"))
conf.setBackupType(Integer.valueOf(readContent()));
@@ -312,82 +415,19 @@
return content;
}
- private JobEntryInfo readJobEntryInfo() throws XMLStreamException, MalformedURLException, ValueFormatException
+ public String getVersionLog()
{
- JobEntryInfo info = new JobEntryInfo();
-
- boolean endJobEntryInfo = false;
-
- while (!endJobEntryInfo)
- {
- int eventCode = reader.next();
- switch (eventCode)
- {
-
- case StartElement.START_ELEMENT :
- String name = reader.getLocalName();
-
- if (name.equals("type"))
- info.setType(getType(readContent()));
-
- if (name.equals("state"))
- info.setState(getState(readContent()));
-
- if (name.equals("url"))
- info.setURL(new URL(readContent()));
-
- if (name.equals("date"))
- info.setDate(JCRDateFormat.parse(readContent()));
-
- break;
-
- case StartElement.END_ELEMENT :
- String tagName = reader.getLocalName();
-
- if (tagName.equals("job-entry-info"))
- endJobEntryInfo = true;
- break;
- }
- }
-
- return info;
+ return version;
}
-
- private int getState(String content)
- {
- int state = -1;
-
- if (content.equals("FINISHED"))
- state = BackupJob.FINISHED;
-
- if (content.equals("STARTING"))
- state = BackupJob.STARTING;
-
- if (content.equals("WAITING"))
- state = BackupJob.WAITING;
-
- if (content.equals("WORKING"))
- state = BackupJob.WORKING;
-
- return state;
- }
-
- private int getType(String content)
- {
- int type = -1;
-
- if (content.equals("FULL"))
- type = BackupJob.FULL;
-
- if (content.equals("INCREMENTAL"))
- type = BackupJob.INCREMENTAL;
-
- return type;
- }
}
protected static Log logger = ExoLogger.getLogger("exo.jcr.component.ext.BackupChainLog");
+ /**
+ * Start for 1.1 version log will be stored relative paths.
+ */
+ protected static String VERSION_LOG_1_1 = "1.1";
+
public static final String PREFIX = "repository-backup-";
private static final String SUFFIX = ".xml";
@@ -416,6 +456,10 @@
private String increnetalBackupType;
+ private RepositoryEntry originalRepositoryEntry;
+
+ private final String versionLog;
+
/**
* @param logDirectory
* @param config
@@ -423,15 +467,17 @@
* @param wsLogFilePathList
* @param backupId
* @param startTime
+ * @param rEntry
* @throws BackupOperationException
*/
public RepositoryBackupChainLog(File logDirectory, RepositoryBackupConfig config, String fullBackupType,
String incrementalBackupType, String systemWorkspace, List<String> wsLogFilePathList, String backupId,
- Calendar startTime) throws BackupOperationException
+ Calendar startTime, RepositoryEntry rEntry) throws BackupOperationException
{
try
{
this.finalized = false;
+ this.versionLog = VERSION_LOG_1_1;
this.log = new File(logDirectory.getCanonicalPath() + File.separator + (PREFIX + backupId + SUFFIX));
this.log.createNewFile();
this.backupId = backupId;
@@ -439,11 +485,13 @@
this.startedTime = Calendar.getInstance();
this.fullBackupType = fullBackupType;
this.increnetalBackupType = incrementalBackupType;
+ this.originalRepositoryEntry = rEntry;
logWriter = new LogWriter(log);
logWriter.write(config, fullBackupType, incrementalBackupType);
logWriter.writeSystemWorkspaceName(systemWorkspace);
- logWriter.writeBackupsPath(wsLogFilePathList);
+ logWriter.writeBackupsPath(wsLogFilePathList, config);
+ logWriter.writeRepositoryEntry(rEntry);
this.workspaceBackupsInfo = wsLogFilePathList;
this.workspaceSystem = systemWorkspace;
@@ -460,6 +508,10 @@
{
throw new BackupOperationException("Can not create backup log ...", e);
}
+ catch (JsonException e)
+ {
+ throw new BackupOperationException("Can not create backup log ...", e);
+ }
}
/**
@@ -475,6 +527,7 @@
{
logReader = new LogReader(log);
logReader.readLogFile();
+ this.versionLog = logReader.getVersionLog();
}
catch (FileNotFoundException e)
{
@@ -486,21 +539,16 @@
throw new BackupOperationException(
"Can not read RepositoryBackupChainLog from file :" + log.getAbsolutePath(), e);
}
- catch (FactoryConfigurationError e)
+ catch (UnsupportedEncodingException e)
{
throw new BackupOperationException(
"Can not read RepositoryBackupChainLog from file :" + log.getAbsolutePath(), e);
}
- catch (MalformedURLException e)
+ catch (Exception e)
{
throw new BackupOperationException(
"Can not read RepositoryBackupChainLog from file :" + log.getAbsolutePath(), e);
}
- catch (ValueFormatException e)
- {
- throw new BackupOperationException(
- "Can not read RepositoryBackupChainLog from file :" + log.getAbsolutePath(), e);
- }
}
/**
@@ -563,6 +611,33 @@
finishedTime = Calendar.getInstance();
finalized = true;
logWriter.writeEndLog();
+
+ //copy backup chain log file in into Backupset files itself for portability (e.g. on another server)
+ try
+ {
+ InputStream in = new FileInputStream(log);
+
+ File dest = new File(config.getBackupDir() + File.separator + log.getName());
+ if (!dest.exists())
+ {
+ OutputStream out = new FileOutputStream(dest);
+
+ byte[] buf = new byte[(int) (log.length())];
+ in.read(buf);
+
+ String sConfig = new String(buf, Constants.DEFAULT_ENCODING);
+ sConfig = sConfig.replaceAll("<backup-dir>.+</backup-dir>", "<backup-dir>.</backup-dir>");
+
+ out.write(sConfig.getBytes(Constants.DEFAULT_ENCODING));
+
+ in.close();
+ out.close();
+ }
+ }
+ catch (Exception e)
+ {
+ logger.error("Can't write log", e);
+ }
}
}
@@ -599,4 +674,15 @@
return backupId;
}
+ /**
+ * Getting original repository configuration
+ *
+ * @return RepositoryEntry
+ * return the original repository configuration
+ */
+ public RepositoryEntry getOriginalRepositoryEntry()
+ {
+ return originalRepositoryEntry;
+ }
+
}
Added: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/WorkspaceRestoreException.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/WorkspaceRestoreException.java (rev 0)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/WorkspaceRestoreException.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -0,0 +1,54 @@
+/*
+ * 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.ext.backup;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date: 2010
+ *
+ * @author <a href="mailto:alex.reshetnyak@exoplatform.com.ua">Alex Reshetnyak</a>
+ * @version $Id: WorkspaceRestoreException.java 3210 2010-09-28 12:01:50Z areshetnyak $
+ */
+public class WorkspaceRestoreException
+ extends BackupConfigurationException
+{
+
+ /**
+ * WorkspaceRestoreException constructor.
+ *
+ * @param message
+ * String, the exception message
+ */
+ public WorkspaceRestoreException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * WorkspaceRestoreException constructor.
+ *
+ * @param message
+ * String, the exception message
+ * @param e
+ * Throwable, the cause exception
+ */
+ public WorkspaceRestoreException(String message, Throwable e)
+ {
+ super(message, e);
+ }
+}
\ No newline at end of file
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupChainImpl.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupChainImpl.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupChainImpl.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -18,6 +18,18 @@
*/
package org.exoplatform.services.jcr.ext.backup.impl;
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.backup.BackupChain;
import org.exoplatform.services.jcr.ext.backup.BackupChainLog;
@@ -30,17 +42,6 @@
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
-
/**
* Created by The eXo Platform SARL .<br/>
*
@@ -74,12 +75,16 @@
private Set<BackupJobListener> listeners = new LinkedHashSet<BackupJobListener>();
public BackupChainImpl(BackupConfig config, File logDirectory, ManageableRepository repository,
- String fullBackupType, String incrementalBackupType, String backupId) throws BackupOperationException,
+ String fullBackupType, String incrementalBackupType, String backupId, File rootDir)
+ throws BackupOperationException,
BackupConfigurationException
{
this.config = config;
this.jobs = new ArrayList<BackupJob>();
- this.chainLog = new BackupChainLog(logDirectory, config, fullBackupType, incrementalBackupType, backupId);
+
+ this.chainLog =
+ new BackupChainLog(logDirectory, config, fullBackupType, incrementalBackupType, backupId,
+ getWorkspaceEntry(config.getWorkspace(), repository), rootDir);
this.timeStamp = Calendar.getInstance();
this.backupId = backupId;
@@ -113,6 +118,29 @@
+ "_PeriodTimer_" + new SimpleDateFormat("yyyyMMdd.HHmmss.SSS").format(new Date()), true);
}
+ private WorkspaceEntry getWorkspaceEntry(String workspace, ManageableRepository repository)
+ throws BackupOperationException
+ {
+ WorkspaceEntry wEntry = null;
+
+ for (WorkspaceEntry entry : repository.getConfiguration().getWorkspaceEntries())
+ {
+ if (entry.getName().equals(workspace))
+ {
+ wEntry = entry;
+ break;
+ }
+ }
+
+ if (wEntry == null)
+ {
+ throw new BackupOperationException("Worksapce \"" + workspace + "\" was not exsisted in repository \""
+ + repository.getConfiguration().getName() + "\".");
+ }
+
+ return wEntry;
+ }
+
/**
* Add all listeners to a given job. Used in startBackup() which itself is synchronized.
*
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -66,10 +66,13 @@
import org.exoplatform.services.jcr.ext.backup.BackupJobListener;
import org.exoplatform.services.jcr.ext.backup.BackupManager;
import org.exoplatform.services.jcr.ext.backup.BackupOperationException;
+import org.exoplatform.services.jcr.ext.backup.ExtendedBackupManager;
import org.exoplatform.services.jcr.ext.backup.JobEntryInfo;
import org.exoplatform.services.jcr.ext.backup.RepositoryBackupChain;
import org.exoplatform.services.jcr.ext.backup.RepositoryBackupChainLog;
import org.exoplatform.services.jcr.ext.backup.RepositoryBackupConfig;
+import org.exoplatform.services.jcr.ext.backup.RepositoryRestoreExeption;
+import org.exoplatform.services.jcr.ext.backup.WorkspaceRestoreException;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.ext.registry.RegistryEntry;
import org.exoplatform.services.jcr.ext.registry.RegistryService;
@@ -98,7 +101,8 @@
* @version $Id: $
*/
-public class BackupManagerImpl implements BackupManager, Startable
+public class BackupManagerImpl
+ implements ExtendedBackupManager, Startable
{
protected static Log log = ExoLogger.getLogger("exo.jcr.component.ext.BackupManagerImpl");
@@ -592,7 +596,7 @@
String reposytoryName = (repositoryName == null ? config.getRepository() : repositoryName);
String workspaceName = workspaceEntry.getName();
- // ws should be registered not created
+ // ws should not exists.
if (!workspaceAlreadyExist(reposytoryName, workspaceName))
{
@@ -639,7 +643,7 @@
}
}
else
- throw new BackupConfigurationException("Workspace should exists " + workspaceName);
+ throw new BackupConfigurationException("Workspace \"" + workspaceName + "\" should not exists.");
}
private boolean workspaceAlreadyExist(String repository, String workspace) throws RepositoryException,
@@ -680,8 +684,8 @@
validateBackupConfig(config);
BackupChain bchain =
- new BackupChainImpl(config, logsDirectory, repoService.getRepository(config.getRepository()), fullBackupType,
- incrementalBackupType, IdGenerator.generate());
+ new BackupChainImpl(config, logsDirectory, repoService.getRepository(config.getRepository()),
+ fullBackupType, incrementalBackupType, IdGenerator.generate(), logsDirectory);
bchain.addListener(messagesListener);
bchain.addListener(jobListener);
@@ -1498,7 +1502,7 @@
RepositoryBackupChain repositoryBackupChain =
new RepositoryBackupChainImpl(config, logsDirectory, repository, fullBackupType, incrementalBackupType,
- IdGenerator.generate());
+ IdGenerator.generate());
repositoryBackupChain.startBackup();
@@ -1553,4 +1557,142 @@
}
return null;
}
+
+ // TODO Will be uncommented after fix issue JCR-1054
+ // /**
+ // * {@inheritDoc}
+ // */
+ // public void restoreExistingRepository(String repositoryBackupIdentifier, boolean asynchronous)
+ // throws BackupOperationException, BackupConfigurationException
+ // {
+ // RepositoryBackupChainLog backupChainLog = null;
+ //
+ // for (RepositoryBackupChainLog chainLog : getRepositoryBackupsLogs())
+ // {
+ // if (chainLog.getBackupId().equals(repositoryBackupIdentifier))
+ // {
+ // backupChainLog = chainLog;
+ // break;
+ // }
+ // }
+ //
+ // if (backupChainLog == null)
+ // {
+ // throw new BackupConfigurationException("Can not founf backup of repository with id \""
+ // + repositoryBackupIdentifier + "\"");
+ // }
+ //
+ // this.restoreExistingRepository(backupChainLog, backupChainLog.getOriginalRepositoryEntry(), asynchronous);
+ //
+ // }
+
+ // TODO Will be uncommented after fix issue JCR-1054
+ // /**
+ // * {@inheritDoc}
+ // */
+ // public void restoreExistingWorkspace(String workspaceBackupIdentifier, boolean asynchronous)
+ // throws BackupOperationException, BackupConfigurationException
+ // {
+ // BackupChainLog backupChainLog = null;
+ //
+ // for (BackupChainLog chainLog : getBackupsLogs())
+ // {
+ // if (chainLog.getBackupId().equals(workspaceBackupIdentifier))
+ // {
+ // backupChainLog = chainLog;
+ // break;
+ // }
+ // }
+ //
+ // if (backupChainLog == null)
+ // {
+ // throw new BackupConfigurationException("Can not founf backup of workspace with id \""
+ // + workspaceBackupIdentifier + "\"");
+ // }
+ //
+ // this.restoreExistingWorkspace(backupChainLog, backupChainLog.getBackupConfig().getRepository(), backupChainLog
+ // .getOriginalWorkspaceEntry(), asynchronous);
+ //
+ // }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restoreRepository(String repositoryBackupIdentifier, boolean asynchronous)
+ throws BackupOperationException, BackupConfigurationException
+ {
+ RepositoryBackupChainLog backupChainLog = null;
+
+ for (RepositoryBackupChainLog chainLog : getRepositoryBackupsLogs())
+ {
+ if (chainLog.getBackupId().equals(repositoryBackupIdentifier))
+ {
+ backupChainLog = chainLog;
+ break;
+ }
+ }
+
+ if (backupChainLog == null)
+ {
+ throw new BackupConfigurationException("Can not founf backup of repository with id \""
+ + repositoryBackupIdentifier + "\"");
+ }
+
+ try
+ {
+ this.restore(backupChainLog, backupChainLog.getOriginalRepositoryEntry(), asynchronous);
+ }
+ catch (RepositoryException e)
+ {
+ throw new RepositoryRestoreExeption("Repository \"" + backupChainLog.getOriginalRepositoryEntry().getName()
+ + "\" was not restored", e);
+ }
+ catch (RepositoryConfigurationException e)
+ {
+ throw new RepositoryRestoreExeption("Repository \"" + backupChainLog.getOriginalRepositoryEntry().getName()
+ + "\" was not restored", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void restoreWorkspace(String workspaceBackupIdentifier, boolean asynchronous)
+ throws BackupOperationException, BackupConfigurationException
+ {
+ BackupChainLog backupChainLog = null;
+
+ for (BackupChainLog chainLog : getBackupsLogs())
+ {
+ if (chainLog.getBackupId().equals(workspaceBackupIdentifier))
+ {
+ backupChainLog = chainLog;
+ break;
+ }
+ }
+
+ if (backupChainLog == null)
+ {
+ throw new BackupConfigurationException("Can not founf backup of workspace with id \""
+ + workspaceBackupIdentifier + "\"");
+ }
+
+ try
+ {
+ this.restore(backupChainLog, backupChainLog.getBackupConfig().getRepository(), backupChainLog
+ .getOriginalWorkspaceEntry(), asynchronous);
+ }
+ catch (RepositoryException e)
+ {
+ throw new WorkspaceRestoreException("Workapce \"" + backupChainLog.getOriginalWorkspaceEntry().getName()
+ + "\" was not restored in repository \"" + backupChainLog.getBackupConfig().getRepository() + "\"", e);
+ }
+ catch (RepositoryConfigurationException e)
+ {
+
+ throw new WorkspaceRestoreException("Workapce \"" + backupChainLog.getOriginalWorkspaceEntry().getName()
+ + "\" was not restored in repository \"" + backupChainLog.getBackupConfig().getRepository() + "\"", e);
+ }
+
+ }
}
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/RepositoryBackupChainImpl.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/RepositoryBackupChainImpl.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/RepositoryBackupChainImpl.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -68,7 +68,8 @@
private int state;
public RepositoryBackupChainImpl(RepositoryBackupConfig config, File logDirectory, ManageableRepository repository,
- String fullBackupType, String incrementalBackupType, String repositoryBackupId) throws BackupOperationException,
+ String fullBackupType, String incrementalBackupType, String repositoryBackupId)
+ throws BackupOperationException,
BackupConfigurationException
{
this.config = config;
@@ -89,8 +90,8 @@
wsBackupConfig.setIncrementalJobPeriod(config.getIncrementalJobPeriod());
BackupChain bchain =
- new BackupChainImpl(wsBackupConfig, config.getBackupDir(), repository,
- fullBackupType, incrementalBackupType, IdGenerator.generate());
+ new BackupChainImpl(wsBackupConfig, config.getBackupDir(), repository, fullBackupType,
+ incrementalBackupType, IdGenerator.generate(), logDirectory);
wsLogFilePathList.add(bchain.getLogFilePath());
workspaceBackups.add(bchain);
@@ -103,7 +104,8 @@
repository.getConfiguration().getSystemWorkspaceName(),
wsLogFilePathList,
this.repositoryBackupId,
- startTime);
+ startTime,
+ repository.getConfiguration());
state = INITIALIZED;
}
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/AbstractBackupTestCase.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/AbstractBackupTestCase.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/AbstractBackupTestCase.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -52,7 +52,8 @@
* @author <a href="mailto:peter.nedonosko@exoplatform.com.ua">Peter Nedonosko</a>
* @version $Id: AbstractBackupTestCase.java 760 2008-02-07 15:08:07Z pnedonosko $
*/
-public class AbstractBackupTestCase extends BaseStandaloneTest
+public class AbstractBackupTestCase
+ extends BaseStandaloneTest
{
protected SessionImpl ws1Session;
@@ -63,7 +64,24 @@
protected BackupManager backup;
- class LogFilter implements FileFilter
+ // TODO Will be uncommented after fix issue JCR-1054
+ // /**
+ // * Database cleaner.
+ // */
+ // private DBCleanerService dbCleanerService = new DBCleanerService();
+ //
+ // /**
+ // * Value storage cleaner.
+ // */
+ // private ValueStorageCleanHelper valueStorageCleanHelper = new ValueStorageCleanHelper();
+ //
+ // /**
+ // * Index storage cleaner.
+ // */
+ // private IndexCleanHelper indexCleanHelper = new IndexCleanHelper();
+
+ class LogFilter
+ implements FileFilter
{
public boolean accept(File pathname)
@@ -94,7 +112,7 @@
ws1TestRoot = ws1Session.getRootNode().addNode("backupTest");
ws1Session.save();
addContent(ws1TestRoot, 1, 10, 1);
-
+
}
else
{
@@ -106,7 +124,7 @@
}
// ws2
- ws2Session = (SessionImpl)repository.login(credentials, "ws2");
+ ws2Session = (SessionImpl) repository.login(credentials, "ws2");
}
@Override
@@ -115,17 +133,24 @@
for (String wsName : repository.getWorkspaceNames())
{
- if ("ws1".equals(wsName))
+ try
{
- ws1Session = (SessionImpl) repository.login(credentials, "ws1");
- ws1Session.getRootNode().getNode("backupTest").remove();
- ws1Session.save();
+ if ("ws1".equals(wsName))
+ {
+ ws1Session = (SessionImpl) repository.login(credentials, "ws1");
+ ws1Session.getRootNode().getNode("backupTest").remove();
+ ws1Session.save();
+ }
+ else
+ {
+ SessionImpl ws = (SessionImpl) repository.login(credentials, wsName);
+ ws.getRootNode().getNode("backupTest").remove();
+ ws.save();
+ }
}
- else
+ catch (PathNotFoundException e)
{
- SessionImpl ws = (SessionImpl)repository.login(credentials, wsName);
- ws.getRootNode().getNode("backupTest").remove();
- ws.save();
+ //skip
}
}
@@ -134,13 +159,13 @@
protected WorkspaceEntry makeWorkspaceEntry(String name, String sourceName)
{
- WorkspaceEntry ws1e = (WorkspaceEntry)ws1Session.getContainer().getComponentInstanceOfType(WorkspaceEntry.class);
+ WorkspaceEntry ws1e = (WorkspaceEntry) ws1Session.getContainer().getComponentInstanceOfType(WorkspaceEntry.class);
WorkspaceEntry ws1back = new WorkspaceEntry();
ws1back.setName(name);
// RepositoryContainer rcontainer = (RepositoryContainer)
// container.getComponentInstanceOfType(RepositoryContainer.class);
- ws1back.setUniqueName(((RepositoryImpl)ws1Session.getRepository()).getName() + "_" + ws1back.getName()); // EXOMAN
+ ws1back.setUniqueName(((RepositoryImpl) ws1Session.getRepository()).getName() + "_" + ws1back.getName()); // EXOMAN
ws1back.setAccessManager(ws1e.getAccessManager());
ws1back.setCache(ws1e.getCache());
@@ -173,45 +198,49 @@
}
ContainerEntry ce =
- new ContainerEntry("org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer", params);
+ new ContainerEntry("org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer", params);
ws1back.setContainer(ce);
return ws1back;
}
-
- protected RepositoryEntry makeRepositoryEntry(String repoName, RepositoryEntry baseRepoEntry, String sourceName, Map<String, String> workspaceMapping)
+
+ protected RepositoryEntry makeRepositoryEntry(String repoName, RepositoryEntry baseRepoEntry, String sourceName,
+ Map<String, String> workspaceMapping)
{
ArrayList<WorkspaceEntry> wsEntries = new ArrayList<WorkspaceEntry>();
-
+
for (WorkspaceEntry wsEntry : baseRepoEntry.getWorkspaceEntries())
{
- String newWorkspaceName = wsEntry.getName();
+ String newWorkspaceName = wsEntry.getName();
if (workspaceMapping != null)
{
newWorkspaceName = workspaceMapping.get(wsEntry.getName());
}
-
+
WorkspaceEntry newWSEntry = makeWorkspaceEntry(wsEntry, newWorkspaceName, repoName, sourceName);
-
+
wsEntries.add(newWSEntry);
}
-
+
RepositoryEntry newRepositoryEntry = new RepositoryEntry();
-
- newRepositoryEntry.setSystemWorkspaceName(workspaceMapping == null ? baseRepoEntry.getSystemWorkspaceName() : workspaceMapping.get(baseRepoEntry.getSystemWorkspaceName()));
+
+ newRepositoryEntry.setSystemWorkspaceName(workspaceMapping == null ? baseRepoEntry.getSystemWorkspaceName()
+ : workspaceMapping.get(baseRepoEntry.getSystemWorkspaceName()));
newRepositoryEntry.setAccessControl(baseRepoEntry.getAccessControl());
newRepositoryEntry.setAuthenticationPolicy(baseRepoEntry.getAuthenticationPolicy());
- newRepositoryEntry.setDefaultWorkspaceName(workspaceMapping == null ? baseRepoEntry.getDefaultWorkspaceName() : workspaceMapping.get(baseRepoEntry.getDefaultWorkspaceName()));
+ newRepositoryEntry.setDefaultWorkspaceName(workspaceMapping == null ? baseRepoEntry.getDefaultWorkspaceName()
+ : workspaceMapping.get(baseRepoEntry.getDefaultWorkspaceName()));
newRepositoryEntry.setName(repoName);
newRepositoryEntry.setSecurityDomain(baseRepoEntry.getSecurityDomain());
newRepositoryEntry.setSessionTimeOut(baseRepoEntry.getSessionTimeOut());
-
+
newRepositoryEntry.setWorkspaceEntries(wsEntries);
-
+
return newRepositoryEntry;
}
-
- protected WorkspaceEntry makeWorkspaceEntry(WorkspaceEntry baseWorkspaceEntry, String wsName, String repoName, String sourceName)
+
+ protected WorkspaceEntry makeWorkspaceEntry(WorkspaceEntry baseWorkspaceEntry, String wsName, String repoName,
+ String sourceName)
{
WorkspaceEntry ws1back = new WorkspaceEntry();
ws1back.setName(wsName);
@@ -240,7 +269,7 @@
if (newp.getName().equals("source-name"))
newp.setValue(sourceName);
else if (newp.getName().equals("swap-directory"))
- newp.setValue("target/temp/swap/" + repoName + "_" + wsName);
+ newp.setValue("target/temp/swap/" + repoName + "_" + wsName);
else if (newp.getName().equals("multi-db"))
newp.setValue("false");
@@ -248,18 +277,19 @@
}
ContainerEntry ce =
- new ContainerEntry("org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer", params);
+ new ContainerEntry("org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer", params);
ws1back.setContainer(ce);
return ws1back;
}
protected void restoreAndCheck(String workspaceName, String datasourceName, String backupLogFilePath, File backDir,
- int startIndex, int stopIndex) throws RepositoryConfigurationException, RepositoryException,
- BackupOperationException, BackupConfigurationException
+ int startIndex, int stopIndex) throws RepositoryConfigurationException, RepositoryException,
+ BackupOperationException, BackupConfigurationException
{
// restore
- RepositoryEntry re = (RepositoryEntry)ws1Session.getContainer().getComponentInstanceOfType(RepositoryEntry.class);
+ RepositoryEntry re =
+ (RepositoryEntry) ws1Session.getContainer().getComponentInstanceOfType(RepositoryEntry.class);
WorkspaceEntry ws1back = makeWorkspaceEntry(workspaceName, datasourceName);
repository.configWorkspace(ws1back);
@@ -274,12 +304,12 @@
SessionImpl back1 = null;
try
{
- back1 = (SessionImpl)repository.login(credentials, ws1back.getName());
+ back1 = (SessionImpl) repository.login(credentials, ws1back.getName());
Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
for (int i = startIndex; i < stopIndex; i++)
{
assertEquals("Restored content should be same", "property-" + i, ws1backTestRoot.getNode("node_" + i)
- .getProperty("exo:data").getString());
+ .getProperty("exo:data").getString());
}
}
catch (Exception e)
@@ -298,8 +328,8 @@
}
protected void addContent(Node node, int startIndex, int stopIndex, long sleepTime) throws ValueFormatException,
- VersionException, LockException, ConstraintViolationException, ItemExistsException, PathNotFoundException,
- RepositoryException, InterruptedException
+ VersionException, LockException, ConstraintViolationException, ItemExistsException, PathNotFoundException,
+ RepositoryException, InterruptedException
{
for (int i = startIndex; i <= stopIndex; i++)
{
Modified: jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java 2010-11-25 15:11:40 UTC (rev 3568)
+++ jcr/branches/1.12.x/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/backup/TestBackupManager.java 2010-11-25 15:27:54 UTC (rev 3569)
@@ -18,14 +18,6 @@
*/
package org.exoplatform.services.jcr.ext.backup;
-import org.apache.commons.collections.map.HashedMap;
-import org.exoplatform.services.jcr.config.RepositoryEntry;
-import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.core.ManageableRepository;
-import org.exoplatform.services.jcr.ext.backup.impl.JobRepositoryRestore;
-import org.exoplatform.services.jcr.ext.backup.impl.JobWorkspaceRestore;
-import org.exoplatform.services.jcr.impl.core.SessionImpl;
-
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -36,6 +28,15 @@
import javax.jcr.RepositoryException;
import javax.jcr.lock.Lock;
+import org.apache.commons.collections.map.HashedMap;
+import org.exoplatform.services.jcr.config.RepositoryEntry;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.core.ManageableRepository;
+import org.exoplatform.services.jcr.ext.backup.impl.JobRepositoryRestore;
+import org.exoplatform.services.jcr.ext.backup.impl.JobWorkspaceRestore;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+
/**
* Created by The eXo Platform SAS.
* Author : Peter Nedonosko peter.nedonosko(a)exoplatform.com.ua
@@ -48,74 +49,74 @@
{
public void testFullBackupRestore() throws Exception
- {
- // backup
- File backDir = new File("target/backup/ws1");
- backDir.mkdirs();
+ {
+ // backup
+ File backDir = new File("target/backup/ws1");
+ backDir.mkdirs();
- BackupConfig config = new BackupConfig();
- config.setRepository(repository.getName());
- config.setWorkspace("ws1");
- config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
+ BackupConfig config = new BackupConfig();
+ config.setRepository(repository.getName());
+ config.setWorkspace("ws1");
+ config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
- config.setBackupDir(backDir);
+ config.setBackupDir(backDir);
- backup.startBackup(config);
+ backup.startBackup(config);
- BackupChain bch = backup.findBackup(repository.getName(), "ws1");
+ BackupChain bch = backup.findBackup(repository.getName(), "ws1");
- // wait till full backup will be stopped
- while (bch.getFullBackupState() != BackupJob.FINISHED)
- {
- Thread.yield();
- Thread.sleep(50);
- }
+ // wait till full backup will be stopped
+ while (bch.getFullBackupState() != BackupJob.FINISHED)
+ {
+ Thread.yield();
+ Thread.sleep(50);
+ }
- // stop fullBackup
+ // stop fullBackup
- if (bch != null)
- backup.stopBackup(bch);
- else
- fail("Can't get fullBackup chain");
+ if (bch != null)
+ backup.stopBackup(bch);
+ else
+ fail("Can't get fullBackup chain");
- // restore
- RepositoryEntry re = (RepositoryEntry)ws1Session.getContainer().getComponentInstanceOfType(RepositoryEntry.class);
- WorkspaceEntry ws1back = makeWorkspaceEntry("ws1back", "jdbcjcr_backup_only_use_1");
+ // restore
+ RepositoryEntry re = (RepositoryEntry)ws1Session.getContainer().getComponentInstanceOfType(RepositoryEntry.class);
+ WorkspaceEntry ws1back = makeWorkspaceEntry("ws1back", "jdbcjcr_backup_only_use_1");
- // BackupChainLog bchLog = new BackupChainLog(backDir, rconfig);
- File backLog = new File(bch.getLogFilePath());
- if (backLog.exists())
- {
- BackupChainLog bchLog = new BackupChainLog(backLog);
+ // BackupChainLog bchLog = new BackupChainLog(backDir, rconfig);
+ File backLog = new File(bch.getLogFilePath());
+ if (backLog.exists())
+ {
+ BackupChainLog bchLog = new BackupChainLog(backLog);
- assertNotNull(bchLog.getStartedTime());
- assertNotNull(bchLog.getFinishedTime());
+ assertNotNull(bchLog.getStartedTime());
+ assertNotNull(bchLog.getFinishedTime());
- backup.restore(bchLog, re.getName(), ws1back, false);
+ backup.restore(bchLog, re.getName(), ws1back, false);
- // check
- SessionImpl back1 = null;
- try
- {
- back1 = (SessionImpl)repository.login(credentials, "ws1back");
- Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
- assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
- .getProperty("exo:data").getString());
+ // check
+ SessionImpl back1 = null;
+ try
+ {
+ back1 = (SessionImpl)repository.login(credentials, "ws1back");
+ Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
+ assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
+ .getProperty("exo:data").getString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ finally
+ {
+ if (back1 != null)
+ back1.logout();
+ }
}
- catch (Exception e)
- {
- e.printStackTrace();
- fail(e.getMessage());
- }
- finally
- {
- if (back1 != null)
- back1.logout();
- }
+ else
+ fail("There are no backup files in " + backDir.getAbsolutePath());
}
- else
- fail("There are no backup files in " + backDir.getAbsolutePath());
- }
public void testIncrementalBackupRestore() throws Exception
{
@@ -1221,4 +1222,288 @@
else
fail("There are no backup files in " + backDir.getAbsolutePath());
}
+
+ // TODO Will be uncommented after fix issue JCR-1054
+ /*public void testExistedWorkspaceRestoreWithConfig() throws Exception
+ {
+ // backup
+ File backDir = new File("target/backup/ws1");
+ backDir.mkdirs();
+
+ BackupConfig config = new BackupConfig();
+ config.setRepository(repository.getName());
+ config.setWorkspace("ws1");
+ config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
+
+ config.setBackupDir(backDir);
+
+ backup.startBackup(config);
+
+ BackupChain bch = backup.findBackup(repository.getName(), "ws1");
+
+ // wait till full backup will be stopped
+ while (bch.getFullBackupState() != BackupJob.FINISHED)
+ {
+ Thread.yield();
+ Thread.sleep(50);
+ }
+
+ // stop fullBackup
+ if (bch != null)
+ backup.stopBackup(bch);
+ else
+ fail("Can't get fullBackup chain");
+
+ super.tearDown();
+
+ File backLog = new File(bch.getLogFilePath());
+ if (backLog.exists())
+ {
+ BackupChainLog bchLog = new BackupChainLog(backLog);
+
+ assertNotNull(bchLog.getStartedTime());
+ assertNotNull(bchLog.getFinishedTime());
+
+ backup.restoreExistingWorkspace(bchLog.getBackupId(), false);
+
+ // check
+ SessionImpl back1 = null;
+ try
+ {
+ back1 = (SessionImpl) repository.login(credentials, "ws1");
+ Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
+ assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
+ .getProperty("exo:data").getString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ finally
+ {
+ if (back1 != null)
+ back1.logout();
+ }
+ }
+ else
+ fail("There are no backup files in " + backDir.getAbsolutePath());
+ }
+
+ public void testExistedRepositoryRestoreWithConfig() throws Exception
+ {
+ // backup
+ File backDir = new File("target/backup/db1");
+ backDir.mkdirs();
+
+ RepositoryBackupConfig config = new RepositoryBackupConfig();
+ String repoName = repository.getName();
+ config.setRepository(repoName);
+ config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
+
+ config.setBackupDir(backDir);
+
+ backup.startBackup(config);
+
+ RepositoryBackupChain bch = backup.findRepositoryBackup(repository.getName());
+
+ // wait till full backup will be stopped
+ while (bch.getState() != RepositoryBackupChain.FINISHED)
+ {
+ Thread.yield();
+ Thread.sleep(50);
+ }
+
+ // stop fullBackup
+ backup.stopBackup(bch);
+
+ // check
+ super.tearDown();
+
+ // restore
+ File backLog = new File(bch.getLogFilePath());
+ if (backLog.exists())
+ {
+ RepositoryBackupChainLog bchLog = new RepositoryBackupChainLog(backLog);
+
+ assertNotNull(bchLog.getStartedTime());
+ assertNotNull(bchLog.getFinishedTime());
+
+ backup.restoreExistingRepository(bchLog.getBackupId(), false);
+
+ assertEquals(JobWorkspaceRestore.RESTORE_SUCCESSFUL, backup.getLastRepositoryRestore(repoName)
+ .getStateRestore());
+
+ // check
+ ManageableRepository restoredRepository = repositoryService.getRepository(repoName);
+
+ for (String wsName : restoredRepository.getWorkspaceNames())
+ {
+ SessionImpl back1 = null;
+ try
+ {
+ back1 = (SessionImpl) restoredRepository.login(credentials, wsName);
+ Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
+ assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
+ .getProperty("exo:data").getString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ finally
+ {
+ if (back1 != null)
+ back1.logout();
+ }
+ }
+ }
+ else
+ fail("There are no backup files in " + backDir.getAbsolutePath());
+ }
+
+ public void testWorkspaceRestoreWithConfig() throws Exception
+ {
+ // backup
+ File backDir = new File("target/backup/ws1");
+ backDir.mkdirs();
+
+ BackupConfig config = new BackupConfig();
+ config.setRepository(repository.getName());
+ config.setWorkspace("ws1");
+ config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
+
+ config.setBackupDir(backDir);
+
+ backup.startBackup(config);
+
+ BackupChain bch = backup.findBackup(repository.getName(), "ws1");
+
+ // wait till full backup will be stopped
+ while (bch.getFullBackupState() != BackupJob.FINISHED)
+ {
+ Thread.yield();
+ Thread.sleep(50);
+ }
+
+ // stop fullBackup
+
+ if (bch != null)
+ backup.stopBackup(bch);
+ else
+ fail("Can't get fullBackup chain");
+
+ //TODO
+ super.tearDown();
+ removeWorkspaceFully(repository.getName(), "ws1");
+
+ File backLog = new File(bch.getLogFilePath());
+ if (backLog.exists())
+ {
+ BackupChainLog bchLog = new BackupChainLog(backLog);
+
+ assertNotNull(bchLog.getStartedTime());
+ assertNotNull(bchLog.getFinishedTime());
+
+ backup.restoreWorkspace(bchLog.getBackupId(), false);
+
+ // check
+ SessionImpl back1 = null;
+ try
+ {
+ back1 = (SessionImpl) repository.login(credentials, "ws1");
+ Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
+ assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
+ .getProperty("exo:data").getString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ finally
+ {
+ if (back1 != null)
+ back1.logout();
+ }
+ }
+ else
+ fail("There are no backup files in " + backDir.getAbsolutePath());
+ }
+
+ public void testRepositoryRestoreWithConfig() throws Exception
+ {
+ // backup
+ File backDir = new File("target/backup");
+ backDir.mkdirs();
+
+ RepositoryBackupConfig config = new RepositoryBackupConfig();
+ String repoName = repository.getName();
+ config.setRepository(repoName);
+ config.setBackupType(BackupManager.FULL_BACKUP_ONLY);
+
+ config.setBackupDir(backDir);
+
+ backup.startBackup(config);
+
+ RepositoryBackupChain bch = backup.findRepositoryBackup(repository.getName());
+
+ // wait till full backup will be stopped
+ while (bch.getState() != RepositoryBackupChain.FINISHED)
+ {
+ Thread.yield();
+ Thread.sleep(50);
+ }
+
+ // stop fullBackup
+
+ backup.stopBackup(bch);
+
+ //TODO
+ super.tearDown();
+ removeRepositoryFully(repository.getName());
+
+ // restore
+ File backLog = new File(bch.getLogFilePath());
+ if (backLog.exists())
+ {
+ RepositoryBackupChainLog bchLog = new RepositoryBackupChainLog(backLog);
+
+ assertNotNull(bchLog.getStartedTime());
+ assertNotNull(bchLog.getFinishedTime());
+
+ backup.restoreRepository(bchLog.getBackupId(), false);
+
+ assertEquals(JobWorkspaceRestore.RESTORE_SUCCESSFUL, backup.getLastRepositoryRestore(repoName)
+ .getStateRestore());
+
+ // check
+ ManageableRepository restoredRepository = repositoryService.getRepository(repoName);
+
+ for (String wsName : restoredRepository.getWorkspaceNames())
+ {
+ SessionImpl back1 = null;
+ try
+ {
+ back1 = (SessionImpl) restoredRepository.login(credentials, wsName);
+ Node ws1backTestRoot = back1.getRootNode().getNode("backupTest");
+ assertEquals("Restored content should be same", "property-5", ws1backTestRoot.getNode("node_5")
+ .getProperty("exo:data").getString());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ finally
+ {
+ if (back1 != null)
+ back1.logout();
+ }
+ }
+ }
+ else
+ fail("There are no backup files in " + backDir.getAbsolutePath());
+ }*/
}
13 years, 5 months