You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/05/19 12:02:52 UTC
svn commit: r776256 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
RepositoryCopier.java persistence/PersistenceCopier.java
Author: jukka
Date: Tue May 19 10:02:51 2009
New Revision: 776256
URL: http://svn.apache.org/viewvc?rev=776256&view=rev
Log:
JCR-422: Implement a backup tool
Document and clean up the initial backup code. Add better logging and some TODO markers.
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java?rev=776256&r1=776255&r2=776256&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Tue May 19 10:02:51 2009
@@ -24,8 +24,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
import javax.jcr.NamespaceRegistry;
import javax.jcr.RepositoryException;
@@ -39,13 +37,46 @@
import org.apache.jackrabbit.core.state.ItemStateException;
import org.apache.jackrabbit.core.version.VersionManagerImpl;
import org.apache.jackrabbit.spi.Name;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * Tool for backing up or migrating the entire contents (workspaces,
+ * version histories, namespaces, node types, etc.) of a repository to
+ * a new repository. The target repository (if it exists) is overwritten.
+ *
+ * @since Apache Jackrabbit 1.6
+ */
public class RepositoryCopier {
- private final RepositoryImpl source;
-
- private final RepositoryImpl target;
-
+ /**
+ * Logger instance
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(RepositoryCopier.class);
+
+ /**
+ * Source repository configuration
+ */
+ private final RepositoryConfig sourceConfig;
+
+ /**
+ * Target repository configuration
+ */
+ private final RepositoryConfig targetConfig;
+
+ /**
+ * Creates a tool for copying the full contents of the source repository.
+ * The given source repository directory is expected to contain the
+ * repository configuration as a <code>repository.xml</code> file.
+ * The target repository directory must not already exist. It will be
+ * automatically created with default repository configuration.
+ *
+ * @param source source repository directory
+ * @param target target repository directory
+ * @throws RepositoryException if the repositories can not be accessed
+ * @throws IOException if the target directory can not be initialized
+ */
public RepositoryCopier(File source, File target)
throws RepositoryException, IOException {
if (!source.isDirectory()) {
@@ -77,79 +108,110 @@
output.close();
}
- this.source = RepositoryImpl.create(
- RepositoryConfig.create(sx.getPath(), source.getPath()));
- this.target = RepositoryImpl.create(
- RepositoryConfig.create(tx.getPath(), target.getPath()));
+ sourceConfig = RepositoryConfig.create(sx.getPath(), source.getPath());
+ targetConfig = RepositoryConfig.create(tx.getPath(), target.getPath());
}
+ /**
+ * Creates a tool for copying the full contents of the source repository
+ * to the given target repository. Any existing content in the target
+ * repository will be overwritten.
+ *
+ * @param source source repository configuration
+ * @param target target repository configuration
+ * @throws RepositoryException if the repositories can not be accessed
+ */
public RepositoryCopier(RepositoryConfig source, RepositoryConfig target)
throws RepositoryException {
- this.source = RepositoryImpl.create(source);
- this.target = RepositoryImpl.create(target);
+ sourceConfig = source;
+ targetConfig = target;
}
- public void copy() throws Exception {
- System.out.println(
- "Copying repository " + source.getConfig().getHomeDir());
- copyNamespaces();
- copyNodeTypes();
- copyVersionStore();
- copyWorkspaces();
-
- target.shutdown();
- source.shutdown();
-
- System.out.println(" Done.");
- }
-
- private void copyNamespaces() throws RepositoryException {
- NamespaceRegistry sourceRegistry = source.getNamespaceRegistry();
- NamespaceRegistry targetRegistry = target.getNamespaceRegistry();
- Set<String> existing = new HashSet<String>(Arrays.asList(
- targetRegistry.getURIs()));
- for (String uri : sourceRegistry.getURIs()) {
+ /**
+ * Copies the full content from the source to the target repository.
+ * Note that both the source and the target repository must be closed
+ * during the copy operation as this method requires exclusive access
+ * to the repositories.
+ *
+ * @throws RepositoryException if the copy operation fails
+ */
+ public void copy() throws RepositoryException {
+ logger.info(
+ "Copying repository content from {} to {}",
+ sourceConfig.getHomeDir(), targetConfig.getHomeDir());
+
+ RepositoryImpl source = RepositoryImpl.create(sourceConfig);
+ try {
+ RepositoryImpl target = RepositoryImpl.create(targetConfig);
+ try {
+ copyNamespaces(
+ source.getNamespaceRegistry(),
+ target.getNamespaceRegistry());
+ copyNodeTypes(
+ source.getNodeTypeRegistry(),
+ target.getNodeTypeRegistry());
+ copyVersionStore(
+ source.getVersionManagerImpl(),
+ target.getVersionManagerImpl());
+ copyWorkspaces(source, target);
+ } catch (InvalidNodeTypeDefException e) {
+ throw new RepositoryException("Failed to copy node types", e);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Failed to copy item states", e);
+ } finally {
+ target.shutdown();
+ }
+ } finally {
+ source.shutdown();
+ }
+ }
+
+ private void copyNamespaces(
+ NamespaceRegistry source, NamespaceRegistry target)
+ throws RepositoryException {
+ logger.info("Copying registered namespaces");
+
+ Collection<String> existing = Arrays.asList(target.getURIs());
+ for (String uri : source.getURIs()) {
if (!existing.contains(uri)) {
// TODO: what if the prefix is already taken?
- targetRegistry.registerNamespace(
- sourceRegistry.getPrefix(uri), uri);
+ target.registerNamespace(source.getPrefix(uri), uri);
}
}
}
- private void copyNodeTypes()
+ private void copyNodeTypes(NodeTypeRegistry source, NodeTypeRegistry target)
throws RepositoryException, InvalidNodeTypeDefException {
- NodeTypeRegistry sourceRegistry = source.getNodeTypeRegistry();
- NodeTypeRegistry targetRegistry = target.getNodeTypeRegistry();
- Set<Name> existing = new HashSet<Name>(Arrays.asList(
- targetRegistry.getRegisteredNodeTypes()));
+ logger.info("Copying registered node types");
+
+ Collection<Name> existing =
+ Arrays.asList(target.getRegisteredNodeTypes());
Collection<NodeTypeDef> register = new ArrayList<NodeTypeDef>();
- for (Name name : sourceRegistry.getRegisteredNodeTypes()) {
+ for (Name name : source.getRegisteredNodeTypes()) {
// TODO: what about modified node types?
if (!existing.contains(name)) {
- register.add(sourceRegistry.getNodeTypeDef(name));
+ register.add(source.getNodeTypeDef(name));
}
}
- targetRegistry.registerNodeTypes(register);
+ target.registerNodeTypes(register);
}
- private void copyVersionStore()
+ private void copyVersionStore(
+ VersionManagerImpl source, VersionManagerImpl target)
throws RepositoryException, ItemStateException {
- System.out.println(" Copying version histories...");
- VersionManagerImpl sourceManager = source.getVersionManagerImpl();
- VersionManagerImpl targetManager = target.getVersionManagerImpl();
+ logger.info("Copying version histories");
+
PersistenceCopier copier = new PersistenceCopier(
- sourceManager.getPersistenceManager(),
- targetManager.getPersistenceManager());
+ source.getPersistenceManager(),
+ target.getPersistenceManager());
copier.copy(RepositoryImpl.VERSION_STORAGE_NODE_ID);
}
- private void copyWorkspaces()
+ private void copyWorkspaces(RepositoryImpl source, RepositoryImpl target)
throws RepositoryException, ItemStateException {
- Set<String> existing = new HashSet<String>(Arrays.asList(
- target.getWorkspaceNames()));
+ Collection<String> existing = Arrays.asList(target.getWorkspaceNames());
for (String name : source.getWorkspaceNames()) {
- System.out.println(" Copying workspace " + name + "...");
+ logger.info("Copying workspace {}" , name);
if (!existing.contains(name)) {
target.createWorkspace(name);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java?rev=776256&r1=776255&r2=776256&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java Tue May 19 10:02:51 2009
@@ -29,26 +29,62 @@
import org.apache.jackrabbit.spi.Name;
/**
- *
+ * Tool for copying item states from one persistence manager to another.
+ * Used for backing up or migrating repository content.
+ *
+ * @since Apache Jackrabbit 1.6
*/
public class PersistenceCopier {
+ /**
+ * Source persistence manager.
+ */
private final PersistenceManager source;
+ /**
+ * Target persistence manager.
+ */
private final PersistenceManager target;
+ /**
+ * Identifiers of the nodes that have already been copied or that
+ * should explicitly not be copied. Used to avoid duplicate copies
+ * of shareable nodes and to avoid trying to copy "missing" nodes
+ * like the virtual "/jcr:system" node.
+ */
private final Set<NodeId> exclude = new HashSet<NodeId>();
+ /**
+ * Creates a tool for copying content from one persistence manager
+ * to another.
+ *
+ * @param source source persistence manager
+ * @param target target persistence manager
+ */
public PersistenceCopier(
PersistenceManager source, PersistenceManager target) {
this.source = source;
this.target = target;
}
+ /**
+ * Explicitly exclude the identified node from being copied. Used for
+ * excluding virtual nodes like "/jcr:system" from the copy process.
+ *
+ * @param id identifier of the node to be excluded
+ */
public void excludeNode(NodeId id) {
exclude.add(id);
}
+ /**
+ * Recursively copies the identified node and all its descendants.
+ * Explicitly excluded nodes and nodes that have already been copied
+ * are automatically skipped.
+ *
+ * @param id identifier of the node to be copied
+ * @throws ItemStateException if the copy operation fails
+ */
public void copy(NodeId id) throws ItemStateException {
if (!exclude.contains(id)) {
NodeState node = source.load(id);
@@ -58,12 +94,21 @@
}
copy(node);
+ exclude.add(id);
}
}
+ /**
+ * Copies the given node state and all associated property states
+ * to the target persistence manager.
+ *
+ * @param sourceNode source node state
+ * @throws ItemStateException if the copy operation fails
+ */
private void copy(NodeState sourceNode) throws ItemStateException {
ChangeLog changes = new ChangeLog();
+ // Copy the node state
NodeState targetNode = target.createNew(sourceNode.getNodeId());
targetNode.setParentId(sourceNode.getParentId());
targetNode.setDefinitionId(sourceNode.getDefinitionId());
@@ -77,6 +122,7 @@
changes.added(targetNode);
}
+ // Copy all associated property states
for (Name name : sourceNode.getPropertyNames()) {
PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
PropertyState sourceState = source.load(id);
@@ -93,6 +139,9 @@
}
}
+ // TODO: Copy node references?
+
+ // Persist the copied states
target.store(changes);
}