]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.maintenance/src/org/argeo/maintenance/backup/LogicalBackup.java
Work on backups and file metadata indexing.
[lgpl/argeo-commons.git] / org.argeo.maintenance / src / org / argeo / maintenance / backup / LogicalBackup.java
diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/LogicalBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/LogicalBackup.java
new file mode 100644 (file)
index 0000000..d1b31b3
--- /dev/null
@@ -0,0 +1,223 @@
+package org.argeo.maintenance.backup;
+
+import java.io.BufferedWriter;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipOutputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.node.NodeUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.xml.sax.SAXException;
+
+public class LogicalBackup {
+       private final static Log log = LogFactory.getLog(LogicalBackup.class);
+
+       public final static String WORKSPACES_BASE = "workspaces/";
+       public final static String OSGI_BASE = "share/osgi/";
+       private final Repository repository;
+       private final BundleContext bundleContext;
+
+       private final ZipOutputStream zout;
+       private final Path basePath;
+
+       public LogicalBackup(BundleContext bundleContext, Repository repository, ZipOutputStream zout) {
+               this.repository = repository;
+               this.zout = zout;
+               this.basePath = null;
+               this.bundleContext = bundleContext;
+       }
+
+       public LogicalBackup(BundleContext bundleContext, Repository repository, Path basePath) {
+               this.repository = repository;
+               this.zout = null;
+               this.basePath = basePath;
+               this.bundleContext = bundleContext;
+       }
+
+       public void perform() throws RepositoryException, IOException {
+               for (Bundle bundle : bundleContext.getBundles()) {
+                       String relativePath = OSGI_BASE + "boot/" + bundle.getSymbolicName() + ".jar";
+                       Dictionary<String, String> headers = bundle.getHeaders();
+                       Manifest manifest = new Manifest();
+                       Enumeration<String> headerKeys = headers.keys();
+                       while (headerKeys.hasMoreElements()) {
+                               String headerKey = headerKeys.nextElement();
+                               String headerValue = headers.get(headerKey);
+                               manifest.getMainAttributes().putValue(headerKey, headerValue);
+                       }
+                       try (JarOutputStream jarOut = new JarOutputStream(openOutputStream(relativePath), manifest)) {
+//                             Enumeration<String> entryPaths = bundle.getEntryPaths("/");
+//                             while (entryPaths.hasMoreElements()) {
+//                                     String entryPath = entryPaths.nextElement();
+//                                     ZipEntry entry = new ZipEntry(entryPath);
+//                                     URL entryUrl = bundle.getEntry(entryPath);
+//                                     try (InputStream in = entryUrl.openStream()) {
+//                                             jarOut.putNextEntry(entry);
+//                                             IOUtils.copy(in, jarOut);
+//                                             jarOut.closeEntry();
+//                                     } catch (FileNotFoundException e) {
+//                                             log.warn(entryPath);
+//                                     }
+//                             }
+                               Enumeration<URL> resourcePaths = bundle.findEntries("/", "*", true);
+                               resources: while (resourcePaths.hasMoreElements()) {
+                                       URL entryUrl = resourcePaths.nextElement();
+                                       String entryPath = entryUrl.getPath();
+                                       if (entryPath.equals(""))
+                                               continue resources;
+                                       if (entryPath.endsWith("/"))
+                                               continue resources;
+                                       String entryName = entryPath.substring(1);// remove first '/'
+                                       if (entryUrl.getPath().equals("/META-INF/"))
+                                               continue resources;
+                                       if (entryUrl.getPath().equals("/META-INF/MANIFEST.MF"))
+                                               continue resources;
+                                       // dev
+                                       if (entryUrl.getPath().startsWith("/target"))
+                                               continue resources;
+                                       if (entryUrl.getPath().startsWith("/src"))
+                                               continue resources;
+                                       if (entryUrl.getPath().startsWith("/ext"))
+                                               continue resources;
+
+                                       if (entryName.startsWith("bin/")) {// dev
+                                               entryName = entryName.substring("bin/".length());
+                                       }
+
+                                       ZipEntry entry = new ZipEntry(entryName);
+                                       try (InputStream in = entryUrl.openStream()) {
+                                               try {
+                                                       jarOut.putNextEntry(entry);
+                                               } catch (ZipException e) {// duplicate
+                                                       continue resources;
+                                               }
+                                               IOUtils.copy(in, jarOut);
+                                               jarOut.closeEntry();
+//                                             log.info(entryUrl);
+                                       } catch (FileNotFoundException e) {
+                                               log.warn(entryUrl + ": " + e.getMessage());
+                                       }
+                               }
+                       }
+               }
+
+               Session defaultSession = login(null);
+               try {
+                       String[] workspaceNames = defaultSession.getWorkspace().getAccessibleWorkspaceNames();
+                       workspaces: for (String workspaceName : workspaceNames) {
+                               if ("security".equals(workspaceName))
+                                       continue workspaces;
+                               perform(workspaceName);
+                       }
+               } finally {
+                       JcrUtils.logoutQuietly(defaultSession);
+               }
+
+       }
+
+       public void perform(String workspaceName) throws RepositoryException, IOException {
+               Session session = login(workspaceName);
+               try {
+                       String relativePath = WORKSPACES_BASE + workspaceName + ".xml";
+                       OutputStream xmlOut = openOutputStream(relativePath);
+                       BackupContentHandler contentHandler;
+                       try (Writer writer = new BufferedWriter(new OutputStreamWriter(xmlOut, StandardCharsets.UTF_8))) {
+                               contentHandler = new BackupContentHandler(writer, session);
+                               try {
+                                       session.exportSystemView("/", contentHandler, true, false);
+                                       if (log.isDebugEnabled())
+                                               log.debug("Workspace " + workspaceName + ": metadata exported to " + relativePath);
+                               } catch (PathNotFoundException e) {
+                                       // TODO Auto-generated catch block
+                                       e.printStackTrace();
+                               } catch (SAXException e) {
+                                       // TODO Auto-generated catch block
+                                       e.printStackTrace();
+                               } catch (RepositoryException e) {
+                                       // TODO Auto-generated catch block
+                                       e.printStackTrace();
+                               }
+                       }
+                       for (String path : contentHandler.getContentPaths()) {
+                               Node contentNode = session.getNode(path);
+                               Binary binary = contentNode.getProperty(Property.JCR_DATA).getBinary();
+                               String fileRelativePath = WORKSPACES_BASE + workspaceName + contentNode.getParent().getPath();
+                               try (InputStream in = binary.getStream(); OutputStream out = openOutputStream(fileRelativePath)) {
+                                       IOUtils.copy(in, out);
+                                       if (log.isDebugEnabled())
+                                               log.debug("Workspace " + workspaceName + ": file content exported to " + fileRelativePath);
+                               } finally {
+
+                               }
+
+                       }
+
+//                     OutputStream xmlOut = openOutputStream(relativePath);
+//                     try {
+//                             session.exportSystemView("/", xmlOut, false, false);
+//                     } finally {
+//                             closeOutputStream(relativePath, xmlOut);
+//                     }
+
+                       // TODO scan all binaries
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       protected OutputStream openOutputStream(String relativePath) throws IOException {
+               if (zout != null) {
+                       ZipEntry entry = new ZipEntry(relativePath);
+                       zout.putNextEntry(entry);
+                       return zout;
+               } else if (basePath != null) {
+                       Path targetPath = basePath.resolve(Paths.get(relativePath));
+                       Files.createDirectories(targetPath.getParent());
+                       return Files.newOutputStream(targetPath);
+               } else {
+                       throw new UnsupportedOperationException();
+               }
+       }
+
+       protected void closeOutputStream(String relativePath, OutputStream out) throws IOException {
+               if (zout != null) {
+                       zout.closeEntry();
+               } else if (basePath != null) {
+                       out.close();
+               } else {
+                       throw new UnsupportedOperationException();
+               }
+       }
+
+       protected Session login(String workspaceName) {
+               return NodeUtils.openDataAdminSession(repository, workspaceName);
+       }
+}