From 11e6f6d17d279a671f0d51d4db8d828e2e8aaf72 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Wed, 6 Feb 2013 16:22:45 +0000 Subject: [PATCH] JCR repository backup git-svn-id: https://svn.argeo.org/slc/trunk@6071 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../META-INF/spring/backup.xml | 7 +- lib/org.argeo.slc.lib.jcr/pom.xml | 4 +- lib/org.argeo.slc.lib.repo/pom.xml | 2 +- .../slc/lib/jcr/JcrRepositoryBackup.java | 151 +++++++++++++----- 4 files changed, 117 insertions(+), 47 deletions(-) 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 index d4186fd2c..7f33f5417 100644 --- a/lib/org.argeo.slc.lib.jcr/META-INF/spring/backup.xml +++ b/lib/org.argeo.slc.lib.jcr/META-INF/spring/backup.xml @@ -6,11 +6,13 @@ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-1.2.xsd"> - Backups a JCR repository as XML + Backups a JCR repository - + + @@ -20,6 +22,7 @@ + diff --git a/lib/org.argeo.slc.lib.jcr/pom.xml b/lib/org.argeo.slc.lib.jcr/pom.xml index 4e7b17cd0..3ce0ebb46 100644 --- a/lib/org.argeo.slc.lib.jcr/pom.xml +++ b/lib/org.argeo.slc.lib.jcr/pom.xml @@ -6,7 +6,7 @@ 1.1.12-SNAPSHOT .. - org.argeo.slc.lib.repo - SLC Lib - Repository Utilities + org.argeo.slc.lib.jcr + SLC Lib - JCR Utilities Utilities to transfer, convert, manage software repositories diff --git a/lib/org.argeo.slc.lib.repo/pom.xml b/lib/org.argeo.slc.lib.repo/pom.xml index 0a974be10..1e1bb44a5 100644 --- a/lib/org.argeo.slc.lib.repo/pom.xml +++ b/lib/org.argeo.slc.lib.repo/pom.xml @@ -7,7 +7,7 @@ 1.1.12-SNAPSHOT .. - org.argeo.slc.lib.jcr + org.argeo.slc.lib.repo SLC Lib - Repository Utilities Utilities related to JCR repositories 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 index a6b7d28ca..c63bdf026 100644 --- 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 @@ -15,9 +15,11 @@ */ package org.argeo.slc.lib.jcr; -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Map; +import java.util.UUID; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import javax.jcr.Credentials; import javax.jcr.Node; @@ -31,6 +33,8 @@ 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.FileSelectInfo; +import org.apache.commons.vfs.FileSelector; import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.FileSystemManager; import org.argeo.jcr.ArgeoJcrUtils; @@ -42,6 +46,7 @@ public class JcrRepositoryBackup implements Runnable { private final static Log log = LogFactory.getLog(JcrRepositoryBackup.class); private String sourceRepo; + private String sourceDatastore; private String targetFile; private String sourceWksp; @@ -53,11 +58,17 @@ public class JcrRepositoryBackup implements Runnable { private FileSystemManager fileSystemManager; public void run() { - FileObject archiveFo = null; Session sourceDefaultSession = null; try { long begin = System.currentTimeMillis(); + FileObject archiveRoot = fileSystemManager.resolveFile(targetFile); + archiveRoot.createFolder(); + + String datastoreFolderName = "datastore"; + if (hasDatastore()) + backupDataStore(archiveRoot.resolveFile(datastoreFolderName)); + Repository sourceRepository = ArgeoJcrUtils.getRepositoryByUri( repositoryFactory, sourceRepo); Credentials sourceCredentials = null; @@ -65,84 +76,132 @@ public class JcrRepositoryBackup implements Runnable { sourceCredentials = new SimpleCredentials(sourceUsername, sourcePassword); - archiveFo = fileSystemManager.resolveFile(targetFile); - FileObject archiveRoot = fileSystemManager - .createFileSystem(archiveFo); - - Map errors = new HashMap(); sourceDefaultSession = sourceRepository.login(sourceCredentials); for (String sourceWorkspaceName : sourceDefaultSession .getWorkspace().getAccessibleWorkspaceNames()) { + if (Thread.interrupted()) { + log.error("Workspace backup interrupted"); + Thread.currentThread().interrupt(); + return; + } + 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; + JarOutputStream out = null; + FileObject workspaceBackup = null; try { - FileObject workspaceXml = archiveRoot - .getChild(sourceWorkspaceName + ".xml"); - out = workspaceXml.getContent().getOutputStream(); + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put( + Attributes.Name.MANIFEST_VERSION, "1.0"); + manifest.getMainAttributes().putValue("Backup-UUID", + UUID.randomUUID().toString()); + manifest.getMainAttributes().putValue("Backup-Timestamp", + Long.toString(System.currentTimeMillis())); + manifest.getMainAttributes().putValue( + "Backup-JCR-Workspace", sourceWorkspaceName); + workspaceBackup = fileSystemManager.resolveFile(targetFile + + "/" + sourceWorkspaceName + ".jar"); + + out = new JarOutputStream(workspaceBackup.getContent() + .getOutputStream(), manifest); 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); + if (workspaceBackup != null) + workspaceBackup.close(); } } + // in case some binaries have been added during the backup + if (hasDatastore()) + backupDataStore(archiveRoot.resolveFile(datastoreFolderName)); + 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) { + protected Boolean hasDatastore() { + return sourceDatastore != null && !sourceDatastore.trim().equals(""); + } + + protected void backupWorkspace(Session sourceSession, JarOutputStream out) { try { - if (log.isDebugEnabled()) - log.debug("Syncing " + sourceSession.getWorkspace().getName() + if (log.isTraceEnabled()) + log.trace("Backup " + sourceSession.getWorkspace().getName() + "..."); + Boolean skipBinaries = hasDatastore(); for (NodeIterator it = sourceSession.getRootNode().getNodes(); it .hasNext();) { + if (Thread.interrupted()) { + log.error("Node backup interrupted"); + Thread.currentThread().interrupt(); + return; + } 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()); + JarEntry entry = new JarEntry(node.getPath()); + out.putNextEntry(entry); + sourceSession.exportSystemView(node.getPath(), out, + skipBinaries, false); + out.flush(); + out.closeEntry(); } if (log.isDebugEnabled()) - log.debug("Synced " + sourceSession.getWorkspace().getName()); + log.debug("Backed up " + sourceSession.getWorkspace().getName()); } catch (Exception e) { throw new SlcException("Cannot backup " + sourceSession.getWorkspace().getName(), e); } } + protected void backupDataStore(final FileObject targetDatastore) { + try { + targetDatastore.createFolder(); + final FileObject sourceDataStore = fileSystemManager + .resolveFile(sourceDatastore); + if (log.isDebugEnabled()) + log.debug("Backup " + sourceDatastore); + targetDatastore.copyFrom(sourceDataStore, new FileSelector() { + public boolean traverseDescendents(FileSelectInfo fileInfo) + throws Exception { + return true; + } + + public boolean includeFile(FileSelectInfo fileInfo) + throws Exception { + String relativeName = fileInfo + .getFile() + .getName() + .getPath() + .substring( + sourceDataStore.getName().getPath() + .length()); + FileObject target = targetDatastore + .resolveFile(relativeName); + if (target.exists()) { + return false; + } else { + return true; + } + } + }); + if (log.isDebugEnabled()) + log.debug("Backed-up " + sourceDatastore); + } catch (FileSystemException e) { + throw new SlcException("Cannot backup datastore", e); + } + } + public void setSourceRepo(String sourceRepo) { this.sourceRepo = sourceRepo; } @@ -167,4 +226,12 @@ public class JcrRepositoryBackup implements Runnable { this.fileSystemManager = fileSystemManager; } + public void setTargetFile(String targetFile) { + this.targetFile = targetFile; + } + + public void setSourceDatastore(String sourceDatastore) { + this.sourceDatastore = sourceDatastore; + } + } -- 2.30.2