]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - org.argeo.slc.support/src/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java
Move SLC Support
[gpl/argeo-slc.git] / org.argeo.slc.support / src / org / argeo / slc / lib / jcr / JcrRepositoryBackup.java
diff --git a/org.argeo.slc.support/src/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java b/org.argeo.slc.support/src/org/argeo/slc/lib/jcr/JcrRepositoryBackup.java
new file mode 100644 (file)
index 0000000..d2bb56b
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * 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.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;
+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.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSelectInfo;
+import org.apache.commons.vfs2.FileSelector;
+import org.apache.commons.vfs2.FileSystemException;
+import org.apache.commons.vfs2.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 sourceDatastore;
+       private String targetFile;
+
+       private String sourceWksp;
+
+       private String sourceUsername;
+       private char[] sourcePassword;
+
+       private RepositoryFactory repositoryFactory;
+       private FileSystemManager fileSystemManager;
+
+       public void run() {
+               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;
+                       if (sourceUsername != null)
+                               sourceCredentials = new SimpleCredentials(sourceUsername,
+                                               sourcePassword);
+
+                       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;
+                               Session sourceSession = null;
+                               JarOutputStream out = null;
+                               FileObject workspaceBackup = null;
+                               try {
+                                       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);
+                               } 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");
+               } catch (Exception e) {
+                       throw new SlcException("Cannot backup " + sourceRepo, e);
+               } finally {
+                       JcrUtils.logoutQuietly(sourceDefaultSession);
+               }
+       }
+
+       protected Boolean hasDatastore() {
+               return sourceDatastore != null && !sourceDatastore.trim().equals("");
+       }
+
+       protected void backupWorkspace(Session sourceSession, JarOutputStream out) {
+               try {
+                       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();
+                               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("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;
+       }
+
+       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;
+       }
+
+       public void setTargetFile(String targetFile) {
+               this.targetFile = targetFile;
+       }
+
+       public void setSourceDatastore(String sourceDatastore) {
+               this.sourceDatastore = sourceDatastore;
+       }
+
+}