import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.argeo.jcr.Jcr;
import org.argeo.jcr.JcrException;
import org.argeo.jcr.JcrUtils;
+import org.argeo.maintenance.backup.LogicalRestore;
import org.argeo.naming.LdapAttrs;
import org.argeo.osgi.useradmin.UserAdminConf;
import org.argeo.util.LangUtils;
// home
prepareDataModel(NodeConstants.NODE_REPOSITORY, deployedNodeRepository, publishAsLocalRepo);
+ // init from backup
+ Path restorePath = Paths.get(System.getProperty("user.dir"), "restore");
+ if (Files.exists(restorePath)) {
+ if (log.isDebugEnabled())
+ log.debug("Found backup " + restorePath + ", restoring it...");
+ LogicalRestore logicalRestore = new LogicalRestore(bc, deployedNodeRepository, restorePath);
+ KernelUtils.doAsDataAdmin(logicalRestore);
+ log.info("Restored backup from " + restorePath);
+ }
+
// init from repository
Collection<ServiceReference<Repository>> initRepositorySr;
try {
if (cn != null) {
List<String> publishAsLocalRepo = new ArrayList<>();
if (cn.equals(NodeConstants.NODE_REPOSITORY)) {
+// JackrabbitDataModelMigration.clearRepositoryCaches(repoContext.getRepositoryConfig());
prepareNodeRepository(repoContext.getRepository(), publishAsLocalRepo);
// TODO separate home repository
prepareHomeRepository(repoContext.getRepository());
import org.apache.commons.logging.Log;
import org.argeo.api.DataModelNamespace;
import org.argeo.api.NodeConstants;
-import org.argeo.cms.CmsException;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
}
static Session openAdminSession(final Repository repository, final String workspaceName) {
+ LoginContext loginContext = loginAsDataAdmin();
+ return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
+
+ @Override
+ public Session run() {
+ try {
+ return repository.login(workspaceName);
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot open admin session", e);
+ } finally {
+ try {
+ loginContext.logout();
+ } catch (LoginException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ });
+ }
+
+ static LoginContext loginAsDataAdmin() {
ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(KernelUtils.class.getClassLoader());
LoginContext loginContext;
} finally {
Thread.currentThread().setContextClassLoader(currentCl);
}
- return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
+ return loginContext;
+ }
+
+ static void doAsDataAdmin(Runnable action) {
+ LoginContext loginContext = loginAsDataAdmin();
+ Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {
@Override
- public Session run() {
+ public Void run() {
try {
- return repository.login(workspaceName);
- } catch (RepositoryException e) {
- throw new IllegalStateException("Cannot open admin session", e);
+ action.run();
+ return null;
+ } finally {
+ try {
+ loginContext.logout();
+ } catch (LoginException e) {
+ throw new IllegalStateException(e);
+ }
}
}
// new Thread(run, "Open service tracker " + st).start();
}
- /**
- * @return the {@link BundleContext} of the {@link Bundle} which provided this
- * class, never null.
- * @throws CmsException if the related bundle is not active
- */
-// static BundleContext getBundleContext(Class<?> clzz) {
-//// Bundle bundle = FrameworkUtil.getBundle(clzz);
-// BundleContext bc = Activator.getBundleContext();
-// if (bc == null)
-// throw new CmsException("Bundle " + bundle.getSymbolicName() + " is not active");
-// return bc;
-// }
-
static BundleContext getBundleContext() {
return Activator.getBundleContext();
}
package org.argeo.jackrabbit;
+import java.awt.geom.CubicCurve2D;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.jcr.Session;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.commons.cnd.CndImporter;
import org.apache.jackrabbit.commons.cnd.ParseException;
import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.argeo.jcr.JcrException;
+import org.apache.jackrabbit.core.fs.FileSystemException;
import org.argeo.jcr.JcrCallback;
+import org.argeo.jcr.JcrException;
import org.argeo.jcr.JcrUtils;
/** Migrate the data in a Jackrabbit repository. */
@Deprecated
public class JackrabbitDataModelMigration implements Comparable<JackrabbitDataModelMigration> {
-// private final static Log log = LogFactory.getLog(JackrabbitDataModelMigration.class);
+ private final static Log log = LogFactory.getLog(JackrabbitDataModelMigration.class);
private String dataModelNodePath;
private String targetVersion;
return true;
} catch (RepositoryException e) {
JcrUtils.discardQuietly(session);
- throw new JcrException(
- "Migration of data model " + dataModelNodePath + " to " + targetVersion + " failed.", e);
+ throw new JcrException("Migration of data model " + dataModelNodePath + " to " + targetVersion + " failed.",
+ e);
} catch (ParseException | IOException e) {
JcrUtils.discardQuietly(session);
throw new RuntimeException(
try {
String customeNodeTypesPath = "/nodetypes/custom_nodetypes.xml";
// FIXME causes weird error in Eclipse
-// repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
-// if (log.isDebugEnabled())
-// log.debug("Cleared " + customeNodeTypesPath);
+ repositoryConfig.getFileSystem().deleteFile(customeNodeTypesPath);
+ if (log.isDebugEnabled())
+ log.debug("Cleared " + customeNodeTypesPath);
} catch (RuntimeException e) {
throw e;
+ } catch (RepositoryException e) {
+ throw new JcrException(e);
+ } catch (FileSystemException e) {
+ throw new RuntimeException("Cannot clear node types cache.",e);
}
// File customNodeTypes = new File(home.getPath()
+++ /dev/null
-package org.argeo.maintenance;
-
-public class MaintenanceException extends RuntimeException {
- private static final long serialVersionUID = -4571088120514827735L;
-
- public MaintenanceException(String message) {
- super(message);
- }
-
- public MaintenanceException(String message, Throwable cause) {
- super(message, cause);
- }
-}
import javax.jcr.Session;
import org.apache.commons.io.IOUtils;
+import org.argeo.jcr.JcrException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
+/** XML handler serialising a JCR system view. */
public class BackupContentHandler extends DefaultHandler {
final static int MAX_DEPTH = 1024;
final static String SV_NAMESPACE_URI = "http://www.jcp.org/jcr/sv/1.0";
+ final static String SV_PREFIX = "sv";
// elements
final static String NODE = "node";
final static String PROPERTY = "property";
private Session session;
private Set<String> contentPaths = new TreeSet<>();
+ private boolean inSystem = false;
+
public BackupContentHandler(Writer out, Session session) {
super();
this.out = out;
if (currentDepth > 0)
currentPath[currentDepth - 1] = nodeName;
// System.out.println(getCurrentPath() + " , depth=" + currentDepth);
+ if ("jcr:system".equals(nodeName)) {
+ inSystem = true;
+ }
}
+ if (inSystem)
+ return;
if (SV_NAMESPACE_URI.equals(uri))
try {
out.write("<");
- out.write(localName);
+ out.write(SV_PREFIX + ":" + localName);
if (isProperty)
currentPropertyIsMultiple = false; // always reset
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.getLocalName(i);
String attrValue = attributes.getValue(i);
out.write(" ");
- out.write(attrName);
+ out.write(SV_PREFIX + ":" + attrName);
out.write("=");
out.write("\"");
out.write(attrValue);
}
}
}
- if (currentDepth == 0) {
- out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
+ if (isNode && currentDepth == 0) {
+ // out.write(" xmlns=\"" + SV_NAMESPACE_URI + "\"");
+ out.write(" xmlns:" + SV_PREFIX + "=\"" + SV_NAMESPACE_URI + "\"");
}
out.write(">");
if (isNode)
out.write("\n");
else if (isProperty && currentPropertyIsMultiple)
out.write("\n");
- } catch (IOException | RepositoryException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (RepositoryException e) {
+ throw new JcrException(e);
}
}
if (currentDepth > 0)
currentPath[currentDepth - 1] = null;
currentDepth = currentDepth - 1;
+ if (inSystem) {
+ // System.out.println("Skip " + getCurrentPath()+" ,
+ // currentDepth="+currentDepth);
+ if (currentDepth == 0) {
+ inSystem = false;
+ return;
+ }
+ }
}
+ if (inSystem)
+ return;
boolean isValue = localName.equals(VALUE);
if (SV_NAMESPACE_URI.equals(uri))
try {
}
currentEncoded = null;
out.write("</");
- out.write(localName);
+ out.write(SV_PREFIX + ":" + localName);
out.write(">");
if (!isValue)
out.write("\n");
out.write("\n");
}
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ throw new RuntimeException(e);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
+ if (inSystem)
+ return;
try {
out.write(ch, start, length);
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ throw new RuntimeException(e);
}
}
return contentPaths;
}
-
-
}
import javax.jcr.Binary;
import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
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();
+ throw new RuntimeException("Cannot perform backup of workspace " + workspaceName, e);
} catch (RepositoryException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ throw new JcrException("Cannot perform backup of workspace " + workspaceName, e);
}
}
for (String path : contentHandler.getContentPaths()) {
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);
+ if (log.isTraceEnabled())
+ log.trace("Workspace " + workspaceName + ": file content exported to " + fileRelativePath);
} finally {
}
--- /dev/null
+package org.argeo.maintenance.backup;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.FilenameUtils;
+import org.argeo.jcr.JcrException;
+import org.argeo.jcr.JcrUtils;
+import org.osgi.framework.BundleContext;
+
+/** Restores a backup in the format defined by {@link LogicalBackup}. */
+public class LogicalRestore implements Runnable {
+ private final Repository repository;
+ private final BundleContext bundleContext;
+ private final Path basePath;
+
+ public LogicalRestore(BundleContext bundleContext, Repository repository, Path basePath) {
+ this.repository = repository;
+ this.basePath = basePath;
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public void run() {
+ Path workspaces = basePath.resolve(LogicalBackup.WORKSPACES_BASE);
+ try (DirectoryStream<Path> xmls = Files.newDirectoryStream(workspaces, "*.xml")) {
+ for (Path workspacePath : xmls) {
+ String workspaceName = FilenameUtils.getBaseName(workspacePath.getFileName().toString());
+ Session session = JcrUtils.loginOrCreateWorkspace(repository, workspaceName);
+ try (InputStream in = Files.newInputStream(workspacePath)) {
+ session.getWorkspace().importXML("/", in,
+ ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+ } finally {
+ JcrUtils.logoutQuietly(session);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot restore backup from " + basePath, e);
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot restore backup from " + basePath, e);
+ }
+ }
+
+}