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/18 08:50:20 UTC
svn commit: r775833 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core:
RepositoryCopier.java RepositoryImpl.java persistence/PersistenceCopier.java
Author: jukka
Date: Mon May 18 06:50:16 2009
New Revision: 775833
URL: http://svn.apache.org/viewvc?rev=775833&view=rev
Log:
JCR-442: Implement a backup tool
Initial version of a repository copy mechanism that can also be used to migrate an entire repository (with namespaces, node types, and version histories) to a new configuration.
Be gentle, work in progress...
Added:
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/RepositoryImpl.java
Added: 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=775833&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Mon May 18 06:50:16 2009
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.core;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+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;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.persistence.PersistenceCopier;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.version.VersionManagerImpl;
+import org.apache.jackrabbit.spi.Name;
+
+public class RepositoryCopier {
+
+ private final RepositoryImpl source;
+
+ private final RepositoryImpl target;
+
+ public RepositoryCopier(File source, File target)
+ throws RepositoryException, IOException {
+ if (!source.isDirectory()) {
+ throw new RepositoryException("Not a directory: " + source);
+ }
+
+ File sx = new File(source, "repository.xml");
+ if (!sx.isFile()) {
+ throw new RepositoryException(
+ "Not a repository directory: " + source);
+ }
+
+ if (target.exists()) {
+ throw new RepositoryException("Target directory exists: " + target);
+ }
+ target.mkdirs();
+
+ File tx = new File(target, "repository.xml");
+ OutputStream output = new FileOutputStream(tx);
+ try {
+ InputStream input =
+ RepositoryImpl.class.getResourceAsStream("repository.xml");
+ try {
+ IOUtils.copy(input, output);
+ } finally {
+ input.close();
+ }
+ } finally {
+ output.close();
+ }
+
+ this.source = RepositoryImpl.create(
+ RepositoryConfig.create(sx.getPath(), source.getPath()));
+ this.target = RepositoryImpl.create(
+ RepositoryConfig.create(tx.getPath(), target.getPath()));
+ }
+
+ public RepositoryCopier(RepositoryConfig source, RepositoryConfig target)
+ throws RepositoryException {
+ this.source = RepositoryImpl.create(source);
+ this.target = RepositoryImpl.create(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()) {
+ if (!existing.contains(uri)) {
+ // TODO: what if the prefix is already taken?
+ targetRegistry.registerNamespace(
+ sourceRegistry.getPrefix(uri), uri);
+ }
+ }
+ }
+
+ private void copyNodeTypes()
+ throws RepositoryException, InvalidNodeTypeDefException {
+ NodeTypeRegistry sourceRegistry = source.getNodeTypeRegistry();
+ NodeTypeRegistry targetRegistry = target.getNodeTypeRegistry();
+ Set<Name> existing = new HashSet<Name>(Arrays.asList(
+ targetRegistry.getRegisteredNodeTypes()));
+ Collection<NodeTypeDef> register = new ArrayList<NodeTypeDef>();
+ for (Name name : sourceRegistry.getRegisteredNodeTypes()) {
+ // TODO: what about modified node types?
+ if (!existing.contains(name)) {
+ register.add(sourceRegistry.getNodeTypeDef(name));
+ }
+ }
+ targetRegistry.registerNodeTypes(register);
+ }
+
+ private void copyVersionStore()
+ throws RepositoryException, ItemStateException {
+ System.out.println(" Copying version histories...");
+ VersionManagerImpl sourceManager = source.getVersionManagerImpl();
+ VersionManagerImpl targetManager = target.getVersionManagerImpl();
+ PersistenceCopier copier = new PersistenceCopier(
+ sourceManager.getPersistenceManager(),
+ targetManager.getPersistenceManager());
+ copier.copy(RepositoryImpl.VERSION_STORAGE_NODE_ID);
+ }
+
+ private void copyWorkspaces()
+ throws RepositoryException, ItemStateException {
+ Set<String> existing = new HashSet<String>(Arrays.asList(
+ target.getWorkspaceNames()));
+ for (String name : source.getWorkspaceNames()) {
+ System.out.println(" Copying workspace " + name + "...");
+
+ if (!existing.contains(name)) {
+ target.createWorkspace(name);
+ }
+
+ PersistenceCopier copier = new PersistenceCopier(
+ source.getWorkspaceInfo(name).getPersistenceManager(),
+ target.getWorkspaceInfo(name).getPersistenceManager());
+ copier.excludeNode(RepositoryImpl.SYSTEM_ROOT_NODE_ID);
+ copier.copy(RepositoryImpl.ROOT_NODE_ID);
+ }
+ }
+
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=775833&r1=775832&r2=775833&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Mon May 18 06:50:16 2009
@@ -2321,4 +2321,9 @@
return RepositoryImpl.this.getDataStore();
}
}
+
+ VersionManagerImpl getVersionManagerImpl() {
+ return vMgr;
+ }
+
}
Added: 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=775833&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java Mon May 18 06:50:16 2009
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.core.persistence;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ChildNodeEntry;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.spi.Name;
+
+/**
+ *
+ */
+public class PersistenceCopier {
+
+ private final PersistenceManager source;
+
+ private final PersistenceManager target;
+
+ private final Set<NodeId> exclude = new HashSet<NodeId>();
+
+ public PersistenceCopier(
+ PersistenceManager source, PersistenceManager target) {
+ this.source = source;
+ this.target = target;
+ }
+
+ public void excludeNode(NodeId id) {
+ exclude.add(id);
+ }
+
+ public void copy(NodeId id) throws ItemStateException {
+ if (!exclude.contains(id)) {
+ NodeState node = source.load(id);
+
+ for (ChildNodeEntry entry : node.getChildNodeEntries()) {
+ copy(entry.getId());
+ }
+
+ copy(node);
+ }
+ }
+
+ private void copy(NodeState sourceNode) throws ItemStateException {
+ ChangeLog changes = new ChangeLog();
+
+ NodeState targetNode = target.createNew(sourceNode.getNodeId());
+ targetNode.setParentId(sourceNode.getParentId());
+ targetNode.setDefinitionId(sourceNode.getDefinitionId());
+ targetNode.setNodeTypeName(sourceNode.getNodeTypeName());
+ targetNode.setMixinTypeNames(sourceNode.getMixinTypeNames());
+ targetNode.setPropertyNames(sourceNode.getPropertyNames());
+ targetNode.setChildNodeEntries(sourceNode.getChildNodeEntries());
+ if (target.exists(targetNode.getNodeId())) {
+ changes.modified(targetNode);
+ } else {
+ changes.added(targetNode);
+ }
+
+ for (Name name : sourceNode.getPropertyNames()) {
+ PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
+ PropertyState sourceState = source.load(id);
+ PropertyState targetState = target.createNew(id);
+ targetState.setDefinitionId(sourceState.getDefinitionId());
+ targetState.setType(sourceState.getType());
+ targetState.setMultiValued(sourceState.isMultiValued());
+ // TODO: Copy binaries?
+ targetState.setValues(sourceState.getValues());
+ if (target.exists(targetState.getPropertyId())) {
+ changes.modified(targetState);
+ } else {
+ changes.added(targetState);
+ }
+ }
+
+ target.store(changes);
+ }
+
+}