JCR repository backup
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 4 Feb 2013 20:38:57 +0000 (20:38 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 4 Feb 2013 20:38:57 +0000 (20:38 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@6070 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

15 files changed:
dep/org.argeo.slc.dep.minimal/pom.xml
lib/org.argeo.slc.lib.jcr/.project [new file with mode: 0644]
lib/org.argeo.slc.lib.jcr/.settings/org.eclipse.pde.core.prefs [new file with mode: 0644]
lib/org.argeo.slc.lib.jcr/META-INF/spring/backup.xml [new file with mode: 0644]
lib/org.argeo.slc.lib.jcr/META-INF/spring/osgi.xml [new file with mode: 0644]
lib/org.argeo.slc.lib.jcr/build.properties [new file with mode: 0644]
lib/org.argeo.slc.lib.jcr/pom.xml [new file with mode: 0644]
lib/org.argeo.slc.lib.repo/pom.xml
lib/pom.xml
modules/org.argeo.slc.agent/META-INF/spring/common.xml
modules/org.argeo.slc.agent/META-INF/spring/osgi.xml
runtime/org.argeo.slc.repo/pom.xml
runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoSync.java
runtime/org.argeo.slc.support.simple/pom.xml
runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java [new file with mode: 0644]

index 2879e53b446b765dafec6440e3ff9e9bc5833752..680839f93db7d2c11c4f837c9f8d4173955ef237 100644 (file)
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.slc</groupId>
                        <version>${version.argeo-commons}</version>
                </dependency>
 
+               <!-- VFS -->
+               <dependency>
+                       <groupId>org.argeo.tp</groupId>
+                       <artifactId>org.apache.commons.vfs</artifactId>
+                       <exclusions>
+                               <exclusion>
+                                       <groupId>org.argeo.tp</groupId>
+                                       <artifactId>org.apache.xmlcommons</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+
                <!-- Xerces and Xalan -->
                <dependency>
                        <groupId>org.argeo.tp</groupId>
diff --git a/lib/org.argeo.slc.lib.jcr/.project b/lib/org.argeo.slc.lib.jcr/.project
new file mode 100644 (file)
index 0000000..8162314
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.slc.lib.jcr</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+       </natures>
+</projectDescription>
diff --git a/lib/org.argeo.slc.lib.jcr/.settings/org.eclipse.pde.core.prefs b/lib/org.argeo.slc.lib.jcr/.settings/org.eclipse.pde.core.prefs
new file mode 100644 (file)
index 0000000..f29e940
--- /dev/null
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/lib/org.argeo.slc.lib.jcr/META-INF/spring/backup.xml b/lib/org.argeo.slc.lib.jcr/META-INF/spring/backup.xml
new file mode 100644 (file)
index 0000000..d4186fd
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+       xsi:schemaLocation="\r
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+       http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-1.2.xsd">\r
+\r
+       <flow:flow name="backup">\r
+               <description>Backups a JCR repository as XML</description>\r
+               <flow:spec>\r
+                       <flow:primitive name="targetFile" value="file://${user.home}/node.zip" />\r
+                       <flow:primitive name="sourceRepo" value="vm:///node/" />\r
+                       <flow:primitive name="sourceWksp" value="" />\r
+                       <flow:primitive name="sourceUsername" value="${user.name}" />\r
+                       <flow:primitive name="sourcePassword" type="password"\r
+                               value="" />\r
+               </flow:spec>\r
+               <bean class="org.argeo.slc.lib.jcr.JcrRepositoryBackup">\r
+                       <flow:variable proxy-target-class="false" />\r
+                       <property name="targetFile" value="@{targetFile}" />\r
+                       <property name="sourceRepo" value="@{sourceRepo}" />\r
+                       <property name="sourceWksp" value="@{sourceWksp}" />\r
+                       <property name="sourceUsername" value="@{sourceUsername}" />\r
+                       <property name="sourcePassword" value="@{sourcePassword}" />\r
+                       <property name="repositoryFactory" ref="repositoryFactory" />\r
+                       <property name="fileSystemManager" ref="fileSystemManager" />\r
+               </bean>\r
+       </flow:flow>\r
+</beans>
\ No newline at end of file
diff --git a/lib/org.argeo.slc.lib.jcr/META-INF/spring/osgi.xml b/lib/org.argeo.slc.lib.jcr/META-INF/spring/osgi.xml
new file mode 100644 (file)
index 0000000..23ffca8
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/osgi  \r
+       http://www.springframework.org/schema/osgi/spring-osgi-1.1.xsd\r
+       http://www.springframework.org/schema/beans   \r
+       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+       <!-- IMPORTS -->\r
+       <beans:import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
+       <beans:import resource="classpath:org/argeo/slc/osgi/execution.xml" />\r
+\r
+       <!-- REFERENCES -->\r
+       <reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory" />\r
+       <reference id="fileSystemManager" interface="org.apache.commons.vfs.FileSystemManager" />\r
+</beans:beans>
\ No newline at end of file
diff --git a/lib/org.argeo.slc.lib.jcr/build.properties b/lib/org.argeo.slc.lib.jcr/build.properties
new file mode 100644 (file)
index 0000000..5f22cdd
--- /dev/null
@@ -0,0 +1 @@
+bin.includes = META-INF/
diff --git a/lib/org.argeo.slc.lib.jcr/pom.xml b/lib/org.argeo.slc.lib.jcr/pom.xml
new file mode 100644 (file)
index 0000000..4e7b17c
--- /dev/null
@@ -0,0 +1,12 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.slc</groupId>
+               <artifactId>lib</artifactId>
+               <version>1.1.12-SNAPSHOT</version>
+               <relativePath>..</relativePath>
+       </parent>
+       <artifactId>org.argeo.slc.lib.repo</artifactId>
+       <name>SLC Lib - Repository Utilities</name>
+       <description>Utilities to transfer, convert, manage software repositories</description>
+</project>
index 4e7b17cd020b4b9cfc9520a087ad9680f32dfc92..0a974be10a02e71900f8293dbc504bc6a86d2517 100644 (file)
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.slc</groupId>
@@ -6,7 +7,7 @@
                <version>1.1.12-SNAPSHOT</version>
                <relativePath>..</relativePath>
        </parent>
-       <artifactId>org.argeo.slc.lib.repo</artifactId>
+       <artifactId>org.argeo.slc.lib.jcr</artifactId>
        <name>SLC Lib - Repository Utilities</name>
-       <description>Utilities to transfer, convert, manage software repositories</description>
+       <description>Utilities related to JCR repositories</description>
 </project>
index 574012e0da9e0337d7f1f68952c2dc40afd24161..77f1cf6c8bac7f1c5ca5a755f0fb76f88da41bc5 100644 (file)
@@ -11,6 +11,7 @@
        <name>SLC Standard Libs</name>
        <description>SLC execution modules for generic tasks, to be used as parent pom</description>
        <modules>
+               <module>org.argeo.slc.lib.jcr</module>
                <module>org.argeo.slc.lib.repo</module>
        </modules>
        <properties>
index 2a3f36cfb8d8e631ea22c6f73679dedeabe87864..8345118f86e943e33cde8d2ee0a9258a2c3e93ee 100644 (file)
@@ -11,4 +11,8 @@
                        <value>osgibundle:agent.properties</value>
                </property>
        </bean>
+       
+               <bean name="fileSystemManager" class="org.apache.commons.vfs.impl.StandardFileSystemManager"
+               init-method="init" destroy-method="close" />
+       
 </beans>
\ No newline at end of file
index 027f184d970bd95ed2edb054bfdee28d8b03fa75..3858f9b31151de4d8338e9e0e3f6c3bf0144c1b4 100644 (file)
@@ -6,7 +6,7 @@
        http://www.springframework.org/schema/beans   \r
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
 \r
-<!--   <beans:import resource="classpath:org/argeo/slc/osgi/manager.xml" /> -->\r
+       <!-- <beans:import resource="classpath:org/argeo/slc/osgi/manager.xml" /> -->\r
 \r
        <!-- REFERENCES -->\r
        <list id="executionContexts" interface="org.argeo.slc.execution.ExecutionContext"\r
@@ -40,5 +40,7 @@
        <!-- SERVICES -->\r
        <service ref="modulesManager" interface="org.argeo.slc.execution.ExecutionModulesManager" />\r
 \r
+       <service ref="fileSystemManager" interface="org.apache.commons.vfs.FileSystemManager" />\r
+\r
 \r
 </beans:beans>
\ No newline at end of file
index dd34ce07b2b387ac3e0f3d1df166e2b48333b41f..223810e13a5faa86225d3e0d5506b12173e76b41 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.argeo.slc</groupId>
@@ -22,6 +23,7 @@
                                                </Export-Package>
                                                <Import-Package>
                                                        org.w3c.dom.*;version="0.0.0",
+                                                       org.xml.sax.*;version="0.0.0",
                                                        javax.xml.transform.*;version="0.0.0",
                                                        javax.xml.parsers.*;version="0.0.0",
                                                        javax.jcr.nodetype,
index bdde722dea68934c2b8cbe28b1cb1842f03ff0e9..3bcea12283a703bfc2a2d53f31ecf30d30e2f2b0 100644 (file)
@@ -279,4 +279,13 @@ public class RepoSync implements Runnable {
        public void setSourcePassword(char[] sourcePassword) {
                this.sourcePassword = sourcePassword;
        }
+
+       public void setTargetUsername(String targetUsername) {
+               this.targetUsername = targetUsername;
+       }
+
+       public void setTargetPassword(char[] targetPassword) {
+               this.targetPassword = targetPassword;
+       }
+
 }
index 8d9f3c69b6a02e87306ade39ccdcb5b46bdce8b3..bdbd589563fff80277e5164905a3a996f7df5a3e 100644 (file)
                        <artifactId>org.argeo.slc.core</artifactId>
                        <version>1.1.12-SNAPSHOT</version>
                </dependency>
+               <dependency>
+                       <groupId>org.argeo.commons.server</groupId>
+                       <artifactId>org.argeo.server.jcr</artifactId>
+                       <version>${version.argeo-commons}</version>
+               </dependency>
 
                <!-- SSH -->
                <dependency>
diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java
new file mode 100644 (file)
index 0000000..a6b7d28
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.slc.lib.jcr;
+
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.argeo.jcr.ArgeoJcrUtils;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+
+/** Backups a JCR repository */
+public class JcrRepositoryBackup implements Runnable {
+       private final static Log log = LogFactory.getLog(JcrRepositoryBackup.class);
+
+       private String sourceRepo;
+       private String targetFile;
+
+       private String sourceWksp;
+
+       private String sourceUsername;
+       private char[] sourcePassword;
+
+       private RepositoryFactory repositoryFactory;
+       private FileSystemManager fileSystemManager;
+
+       public void run() {
+               FileObject archiveFo = null;
+               Session sourceDefaultSession = null;
+               try {
+                       long begin = System.currentTimeMillis();
+
+                       Repository sourceRepository = ArgeoJcrUtils.getRepositoryByUri(
+                                       repositoryFactory, sourceRepo);
+                       Credentials sourceCredentials = null;
+                       if (sourceUsername != null)
+                               sourceCredentials = new SimpleCredentials(sourceUsername,
+                                               sourcePassword);
+
+                       archiveFo = fileSystemManager.resolveFile(targetFile);
+                       FileObject archiveRoot = fileSystemManager
+                                       .createFileSystem(archiveFo);
+
+                       Map<String, Exception> errors = new HashMap<String, Exception>();
+                       sourceDefaultSession = sourceRepository.login(sourceCredentials);
+                       for (String sourceWorkspaceName : sourceDefaultSession
+                                       .getWorkspace().getAccessibleWorkspaceNames()) {
+                               if (sourceWksp != null && !sourceWksp.trim().equals("")
+                                               && !sourceWorkspaceName.equals(sourceWksp))
+                                       continue;
+                               // if (sourceWorkspaceName.equals("security"))
+                               // continue;
+                               // if (sourceWorkspaceName.equals("localrepo"))
+                               // continue;
+                               Session sourceSession = null;
+                               OutputStream out = null;
+                               try {
+                                       FileObject workspaceXml = archiveRoot
+                                                       .getChild(sourceWorkspaceName + ".xml");
+                                       out = workspaceXml.getContent().getOutputStream();
+                                       sourceSession = sourceRepository.login(sourceCredentials,
+                                                       sourceWorkspaceName);
+                                       backupWorkspace(sourceSession, out);
+                                       workspaceXml.close();
+                               } catch (Exception e) {
+                                       errors.put("Could not sync workspace "
+                                                       + sourceWorkspaceName, e);
+                               } finally {
+                                       JcrUtils.logoutQuietly(sourceSession);
+                                       IOUtils.closeQuietly(out);
+                               }
+                       }
+
+                       long duration = (System.currentTimeMillis() - begin) / 1000;// s
+                       log.info("Backed-up " + sourceRepo + " in " + (duration / 60)
+                                       + "min " + (duration % 60) + "s");
+
+                       if (errors.size() > 0) {
+                               throw new SlcException("Sync failed " + errors);
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot backup " + sourceRepo, e);
+               } finally {
+                       JcrUtils.logoutQuietly(sourceDefaultSession);
+                       if (archiveFo != null)
+                               try {
+                                       archiveFo.close();
+                               } catch (FileSystemException e) {
+                                       // silent
+                               }
+               }
+       }
+
+       protected void backupWorkspace(Session sourceSession, OutputStream out) {
+               try {
+                       if (log.isDebugEnabled())
+                               log.debug("Syncing " + sourceSession.getWorkspace().getName()
+                                               + "...");
+                       for (NodeIterator it = sourceSession.getRootNode().getNodes(); it
+                                       .hasNext();) {
+                               Node node = it.nextNode();
+                               if (node.getName().equals("jcr:system"))
+                                       continue;
+
+                               sourceSession
+                                               .exportSystemView(node.getPath(), out, true, false);
+                               if (log.isDebugEnabled())
+                                       log.debug(" " + node.getPath());
+                       }
+                       if (log.isDebugEnabled())
+                               log.debug("Synced " + sourceSession.getWorkspace().getName());
+               } catch (Exception e) {
+                       throw new SlcException("Cannot backup "
+                                       + sourceSession.getWorkspace().getName(), e);
+               }
+       }
+
+       public void setSourceRepo(String sourceRepo) {
+               this.sourceRepo = sourceRepo;
+       }
+
+       public void setSourceWksp(String sourceWksp) {
+               this.sourceWksp = sourceWksp;
+       }
+
+       public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+               this.repositoryFactory = repositoryFactory;
+       }
+
+       public void setSourceUsername(String sourceUsername) {
+               this.sourceUsername = sourceUsername;
+       }
+
+       public void setSourcePassword(char[] sourcePassword) {
+               this.sourcePassword = sourcePassword;
+       }
+
+       public void setFileSystemManager(FileSystemManager fileSystemManager) {
+               this.fileSystemManager = fileSystemManager;
+       }
+
+}