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/20 18:19:10 UTC
svn commit: r776753 - in /jackrabbit/branches/1.x: ./
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/
jackr...
Author: jukka
Date: Wed May 20 16:19:10 2009
New Revision: 776753
URL: http://svn.apache.org/viewvc?rev=776753&view=rev
Log:
1.x: Merged revisions 775833, 776256, 776356, 776362, 776373, 776310, 7776313 and 776332 (JCR-442 and JCR-2119)
Added:
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
- copied, changed from r775833, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java
- copied, changed from r775833, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java
Modified:
jackrabbit/branches/1.x/ (props changed)
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java
jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java
jackrabbit/branches/1.x/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java
Propchange: jackrabbit/branches/1.x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed May 20 16:19:10 2009
@@ -1 +1 @@
-/jackrabbit/trunk:770143-773197,773525-773554,773584,773588,773828,773835-775756,775836,775840,775981,775986,776036,776321-776322,776357,776650-776693,776737
+/jackrabbit/trunk:770143-773197,773525-773554,773584,773588,773828,773835-775756,775833,775836,775840,775981,775986,776036,776256,776310,776313,776321-776322,776332,776356-776357,776362,776373,776650-776693,776737
Copied: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (from r775833, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java)
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java?p2=jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java&p1=jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java&r1=775833&r2=776753&rev=776753&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Wed May 20 16:19:10 2009
@@ -17,20 +17,15 @@
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.commons.io.FileUtils;
import org.apache.jackrabbit.core.config.RepositoryConfig;
import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
@@ -39,125 +34,171 @@
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 should 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 repository can not be initialized
+ */
public RepositoryCopier(File source, File target)
throws RepositoryException, IOException {
- if (!source.isDirectory()) {
- throw new RepositoryException("Not a directory: " + source);
- }
+ this(RepositoryConfig.create(source), RepositoryConfig.install(target));
+ }
- File sx = new File(source, "repository.xml");
- if (!sx.isFile()) {
- throw new RepositoryException(
- "Not a repository directory: " + source);
- }
+ /**
+ * 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 {
+ sourceConfig = source;
+ targetConfig = target;
+ }
- if (target.exists()) {
- throw new RepositoryException("Target directory exists: " + target);
- }
- target.mkdirs();
+ /**
+ * 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());
- File tx = new File(target, "repository.xml");
- OutputStream output = new FileOutputStream(tx);
+ RepositoryImpl source = RepositoryImpl.create(sourceConfig);
try {
- InputStream input =
- RepositoryImpl.class.getResourceAsStream("repository.xml");
+ RepositoryImpl target = RepositoryImpl.create(targetConfig);
try {
- IOUtils.copy(input, output);
+ 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 {
- input.close();
+ target.shutdown();
+ }
+
+ // Remove index directories to force re-indexing on next startup
+ // TODO: There should be a cleaner way to do this
+ File targetDir = new File(targetConfig.getHomeDir());
+ File repoDir = new File(targetDir, "repository");
+ FileUtils.deleteQuietly(new File(repoDir, "index"));
+ File[] workspaces = new File(targetDir, "workspaces").listFiles();
+ for (int i = 0; workspaces != null && i < workspaces.length; i++) {
+ FileUtils.deleteQuietly(new File(workspaces[i], "index"));
}
} finally {
- output.close();
+ source.shutdown();
}
-
- 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)
+ private void copyNamespaces(
+ NamespaceRegistry source, NamespaceRegistry target)
throws RepositoryException {
- this.source = RepositoryImpl.create(source);
- this.target = RepositoryImpl.create(target);
- }
+ logger.info("Copying registered namespaces");
- 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)) {
+ Collection existing = Arrays.asList(target.getURIs());
+ String[] uris = source.getURIs();
+ for (int i = 0; i < uris.length; i++) {
+ if (!existing.contains(uris[i])) {
// TODO: what if the prefix is already taken?
- targetRegistry.registerNamespace(
- sourceRegistry.getPrefix(uri), uri);
+ target.registerNamespace(source.getPrefix(uris[i]), uris[i]);
}
}
}
- 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()));
- Collection<NodeTypeDef> register = new ArrayList<NodeTypeDef>();
- for (Name name : sourceRegistry.getRegisteredNodeTypes()) {
+ logger.info("Copying registered node types");
+
+ Collection existing = Arrays.asList(target.getRegisteredNodeTypes());
+ Collection register = new ArrayList();
+ Name[] names = source.getRegisteredNodeTypes();
+ for (int i = 0; i < names.length; i++) {
// TODO: what about modified node types?
- if (!existing.contains(name)) {
- register.add(sourceRegistry.getNodeTypeDef(name));
+ if (!existing.contains(names[i])) {
+ register.add(source.getNodeTypeDef(names[i]));
}
}
- 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()));
- for (String name : source.getWorkspaceNames()) {
- System.out.println(" Copying workspace " + name + "...");
+ Collection existing = Arrays.asList(target.getWorkspaceNames());
+ String[] names = source.getWorkspaceNames();
+ for (int i = 0; i < names.length; i++) {
+ logger.info("Copying workspace {}" , names[i]);
- if (!existing.contains(name)) {
- target.createWorkspace(name);
+ if (!existing.contains(names[i])) {
+ target.createWorkspace(names[i]);
}
PersistenceCopier copier = new PersistenceCopier(
- source.getWorkspaceInfo(name).getPersistenceManager(),
- target.getWorkspaceInfo(name).getPersistenceManager());
+ source.getWorkspaceInfo(names[i]).getPersistenceManager(),
+ target.getWorkspaceInfo(names[i]).getPersistenceManager());
copier.excludeNode(RepositoryImpl.SYSTEM_ROOT_NODE_ID);
copier.copy(RepositoryImpl.ROOT_NODE_ID);
}
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=776753&r1=776752&r2=776753&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Wed May 20 16:19:10 2009
@@ -2321,4 +2321,9 @@
return RepositoryImpl.this.getDataStore();
}
}
+
+ VersionManagerImpl getVersionManagerImpl() {
+ return vMgr;
+ }
+
}
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java?rev=776753&r1=776752&r2=776753&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java Wed May 20 16:19:10 2009
@@ -17,10 +17,8 @@
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.Collections;
import java.util.HashSet;
import java.util.Iterator;
@@ -34,7 +32,6 @@
import javax.jcr.Value;
import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.api.JackrabbitRepository;
import org.apache.jackrabbit.core.config.ConfigurationException;
import org.apache.jackrabbit.core.config.RepositoryConfig;
@@ -58,11 +55,6 @@
LoggerFactory.getLogger(TransientRepository.class);
/**
- * Resource path of the default repository configuration file.
- */
- private static final String DEFAULT_REPOSITORY_XML = "repository.xml";
-
- /**
* Name of the repository configuration file property.
*/
private static final String CONF_PROPERTY =
@@ -92,7 +84,7 @@
public interface RepositoryFactory {
/**
- * Creates and intializes a repository instance. The returned instance
+ * Creates and initializes a repository instance. The returned instance
* will be used and finally shut down by the caller of this method.
*
* @return initialized repository instance
@@ -133,9 +125,8 @@
* factory to initialize the underlying repository instances.
*
* @param factory repository factory
- * @throws IOException if the static repository descriptors cannot be loaded
*/
- public TransientRepository(RepositoryFactory factory) throws IOException {
+ public TransientRepository(RepositoryFactory factory) {
this.factory = factory;
this.repository = null;
this.descriptors = new Properties();
@@ -143,12 +134,16 @@
// FIXME: The current RepositoryImpl class does not allow static
// access to the repository descriptors, so we need to load them
// directly from the underlying property file.
- InputStream in =
- RepositoryImpl.class.getResourceAsStream("repository.properties");
try {
- descriptors.load(in);
- } finally {
- in.close();
+ InputStream in = RepositoryImpl.class.getResourceAsStream(
+ "repository.properties");
+ try {
+ descriptors.load(in);
+ } finally {
+ in.close();
+ }
+ } catch (IOException e) {
+ logger.warn("Unable to load static repository descriptors", e);
}
}
@@ -187,6 +182,32 @@
/**
* Creates a transient repository proxy that will use the given repository
* configuration file and home directory paths to initialize the underlying
+ * repository instances.
+ *
+ * @see #TransientRepository(File, File)
+ * @param config repository configuration file
+ * @param home repository home directory
+ * @throws IOException if the static repository descriptors cannot be loaded
+ */
+ public TransientRepository(String config, String home) {
+ this(new File(config), new File(home));
+ }
+
+ /**
+ * Creates a transient repository proxy based on the given repository
+ * home directory and the repository configuration file "repository.xml"
+ * contained in that directory.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param dir repository home directory
+ */
+ public TransientRepository(File dir) {
+ this(new File(dir, "repository.xml"), dir);
+ }
+
+ /**
+ * Creates a transient repository proxy that will use the given repository
+ * configuration file and home directory paths to initialize the underlying
* repository instances. The repository configuration file is reloaded
* whenever the repository is restarted, so it is safe to modify the
* configuration when all sessions have been closed.
@@ -198,48 +219,22 @@
* session starts. This is a convenience feature designed to reduce the
* need for manual configuration.
*
- * @param config repository configuration file
- * @param home repository home directory
- * @throws IOException if the static repository descriptors cannot be loaded
+ * @since Apache Jackrabbit 1.6
+ * @param xml repository configuration file
+ * @param dir repository home directory
*/
- public TransientRepository(final String config, final String home)
- throws IOException {
+ public TransientRepository(final File xml, final File dir) {
this(new RepositoryFactory() {
public RepositoryImpl getRepository() throws RepositoryException {
try {
- // Make sure that the repository configuration file exists
- File configFile = new File(config);
- if (!configFile.exists()) {
- logger.info("Copying default configuration to " + config);
- OutputStream output = new FileOutputStream(configFile);
- try {
- InputStream input =
- TransientRepository.class.getResourceAsStream(
- DEFAULT_REPOSITORY_XML);
- try {
- IOUtils.copy(input, output);
- } finally {
- input.close();
- }
- } finally {
- output.close();
- }
- }
- // Make sure that the repository home directory exists
- File homeDir = new File(home);
- if (!homeDir.exists()) {
- logger.info("Creating repository home directory " + home);
- homeDir.mkdirs();
- }
- // Load the configuration and create the repository
- RepositoryConfig rc = RepositoryConfig.create(config, home);
- return RepositoryImpl.create(rc);
+ return RepositoryImpl.create(
+ RepositoryConfig.install(xml, dir));
} catch (IOException e) {
throw new RepositoryException(
"Automatic repository configuration failed", e);
} catch (ConfigurationException e) {
throw new RepositoryException(
- "Invalid repository configuration: " + config, e);
+ "Invalid repository configuration file: " + xml, e);
}
}
});
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java?rev=776753&r1=776752&r2=776753&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java Wed May 20 16:19:10 2009
@@ -16,7 +16,8 @@
*/
package org.apache.jackrabbit.core.config;
-import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.data.DataStore;
import org.apache.jackrabbit.core.data.DataStoreFactory;
import org.apache.jackrabbit.core.fs.FileSystem;
@@ -41,10 +42,12 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringWriter;
@@ -71,10 +74,116 @@
/** the default logger */
private static Logger log = LoggerFactory.getLogger(RepositoryConfig.class);
+ /** Name of the default repository configuration file. */
+ private static final String REPOSITORY_XML = "repository.xml";
+
/** Name of the workspace configuration file. */
private static final String WORKSPACE_XML = "workspace.xml";
/**
+ * Returns the configuration of a repository in a given repository
+ * directory. The repository configuration is read from a "repository.xml"
+ * file inside the repository directory.
+ * <p>
+ * The directory is created if it does not exist. If the repository
+ * configuration file does not exist, then it is created using the
+ * default Jackrabbit configuration settings.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param dir repository home directory
+ * @return repository configuration
+ * @throws ConfigurationException on configuration errors
+ */
+ public static RepositoryConfig install(File dir)
+ throws IOException, ConfigurationException {
+ return install(new File(dir, REPOSITORY_XML), dir);
+ }
+
+ /**
+ * Returns the configuration of a repository with the given configuration
+ * file and repository home directory.
+ * <p>
+ * The directory is created if it does not exist. If the repository
+ * configuration file does not exist, then it is created using the
+ * default Jackrabbit configuration settings.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param dir repository home directory
+ * @return repository configuration
+ * @throws ConfigurationException on configuration errors
+ */
+ public static RepositoryConfig install(File xml, File dir)
+ throws IOException, ConfigurationException {
+ if (!dir.exists()) {
+ log.info("Creating repository directory {}", dir);
+ dir.mkdirs();
+ }
+
+ if (!xml.exists()) {
+ log.info("Installing default repository configuration to {}", xml);
+ OutputStream output = new FileOutputStream(xml);
+ try {
+ InputStream input =
+ RepositoryImpl.class.getResourceAsStream(REPOSITORY_XML);
+ try {
+ IOUtils.copy(input, output);
+ } finally {
+ input.close();
+ }
+ } finally {
+ output.close();
+ }
+ }
+
+ return create(xml, dir);
+ }
+
+ /**
+ * Returns the configuration of a repository in a given repository
+ * directory. The repository configuration is read from a "repository.xml"
+ * file inside the repository directory.
+ * <p>
+ * An exception is thrown if the directory does not exist or if
+ * the repository configuration file can not be read.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param dir repository home directory
+ * @return repository configuration
+ * @throws ConfigurationException on configuration errors
+ */
+ public static RepositoryConfig create(File dir)
+ throws ConfigurationException {
+ return create(new File(dir, REPOSITORY_XML), dir);
+ }
+
+ /**
+ * Returns the configuration of a repository with the given configuration
+ * file and repository home directory.
+ * <p>
+ * An exception is thrown if the directory does not exist or if
+ * the repository configuration file can not be read.
+ *
+ * @since Apache Jackrabbit 1.6
+ * @param dir repository home directory
+ * @return repository configuration
+ * @throws ConfigurationException on configuration errors
+ */
+ public static RepositoryConfig create(File xml, File dir)
+ throws ConfigurationException {
+ if (!dir.isDirectory()) {
+ throw new ConfigurationException(
+ "Repository directory " + dir + " does not exist");
+ }
+
+ if (!xml.isFile()) {
+ throw new ConfigurationException(
+ "Repository configuration file " + xml + " does not exist");
+ }
+
+ return create(new InputSource(xml.toURI().toString()), dir.getPath());
+ }
+
+ /**
* Convenience method that wraps the configuration file name into an
* {@link InputSource} and invokes the
* {@link #create(InputSource, String)} method.
Copied: jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java (from r775833, jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java)
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java?p2=jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java&p1=jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java&r1=775833&r2=776753&rev=776753&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java Wed May 20 16:19:10 2009
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.persistence;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
import org.apache.jackrabbit.core.NodeId;
@@ -24,46 +25,95 @@
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.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
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;
- private final Set<NodeId> exclude = new HashSet<NodeId>();
-
+ /**
+ * 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 exclude = new HashSet();
+
+ /**
+ * 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);
- for (ChildNodeEntry entry : node.getChildNodeEntries()) {
+ Iterator iterator = node.getChildNodeEntries().iterator();
+ while (iterator.hasNext()) {
+ ChildNodeEntry entry = (ChildNodeEntry) iterator.next();
copy(entry.getId());
}
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,7 +127,10 @@
changes.added(targetNode);
}
- for (Name name : sourceNode.getPropertyNames()) {
+ // Copy all associated property states
+ Iterator iterator = sourceNode.getPropertyNames().iterator();
+ while (iterator.hasNext()) {
+ Name name = (Name) iterator.next();
PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
PropertyState sourceState = source.load(id);
PropertyState targetState = target.createNew(id);
@@ -93,6 +146,17 @@
}
}
+ // Copy all node references
+ NodeReferencesId refsId = new NodeReferencesId(sourceNode.getNodeId());
+ if (source.exists(refsId)) {
+ changes.modified(source.load(refsId));
+ } else if (target.exists(refsId)) {
+ NodeReferences references = target.load(refsId);
+ references.clearAllReferences();
+ changes.modified(references);
+ }
+
+ // Persist the copied states
target.store(changes);
}
Modified: jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java?rev=776753&r1=776752&r2=776753&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/config/RepositoryConfigTest.java Wed May 20 16:19:10 2009
@@ -16,16 +16,16 @@
*/
package org.apache.jackrabbit.core.config;
-import junit.framework.TestCase;
+ import junit.framework.TestCase;
import org.xml.sax.InputSource;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.input.ClosedInputStream;
import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
@@ -34,54 +34,58 @@
*/
public class RepositoryConfigTest extends TestCase {
- private static final String REPOSITORY_XML = "target/repository_for_test.xml";
- private static final String REPOSITORY_HOME = "target/repository_for_test";
+ private static final File DIR =
+ new File("target", "RepositoryConfigTest");
- private static void deleteAll(File file) {
- if (file.exists()) {
- if (file.isDirectory()) {
- File[] children = file.listFiles();
- for (int i = 0; i < children.length; i++) {
- deleteAll(children[i]);
- }
- }
- file.delete();
- }
- }
+ private static final File XML =
+ new File(DIR, "repository.xml");
+
+ private RepositoryConfig config;
/**
* Sets up the test case by creating the repository home directory
* and copying the repository configuration file in place.
*/
protected void setUp() throws Exception {
- // Create the repository directory
- File home = new File(REPOSITORY_HOME);
- home.mkdirs();
-
- // Copy the repository configuration file in place
- ClassLoader loader = getClass().getClassLoader();
- InputStream input = loader.getResourceAsStream("org/apache/jackrabbit/core/repository.xml");
- try {
- OutputStream output = new FileOutputStream(REPOSITORY_XML);
- try {
- int n;
- byte[] buffer = new byte[1024];
- while ((n = input.read(buffer)) != -1) {
- output.write(buffer, 0, n);
- }
- } finally {
- output.close();
- }
- } finally {
- input.close();
- }
+ config = RepositoryConfig.install(DIR);
}
protected void tearDown() {
- File home = new File(REPOSITORY_HOME);
- deleteAll(home);
- File config = new File(REPOSITORY_XML);
- config.delete();
+ FileUtils.deleteQuietly(DIR);
+ }
+
+ public void testCreateWithRepositoryDirectory() {
+ try {
+ RepositoryConfig.create(DIR);
+ } catch (ConfigurationException e) {
+ fail("Valid repository directory");
+ }
+
+ try {
+ RepositoryConfig.create(new File(DIR, "invalid-repo-dir"));
+ fail("Invalid repository directory");
+ } catch (ConfigurationException e) {
+ }
+ }
+
+ public void testCreateWithRepositoryConfigAndDirectory() {
+ try {
+ RepositoryConfig.create(XML, DIR);
+ } catch (ConfigurationException e) {
+ fail("Valid repository configuration and directory");
+ }
+
+ try {
+ RepositoryConfig.create(XML, new File(DIR, "invalid-repo-dir"));
+ fail("Invalid repository directory");
+ } catch (ConfigurationException e) {
+ }
+
+ try {
+ RepositoryConfig.create(new File(DIR, "invalid.xml"), DIR);
+ fail("Invalid repository configuration");
+ } catch (ConfigurationException e) {
+ }
}
/**
@@ -89,12 +93,15 @@
*/
public void testRepositoryConfigCreateWithFileName() {
try {
- RepositoryConfig.create(REPOSITORY_XML, REPOSITORY_HOME);
+ RepositoryConfig.create(XML.getPath(), DIR.getPath());
} catch (ConfigurationException e) {
fail("Valid configuration file name");
}
+
try {
- RepositoryConfig.create("invalid-config-file", REPOSITORY_HOME);
+ RepositoryConfig.create(
+ new File(DIR, "invalid-config-file.xml").getPath(),
+ DIR.getPath());
fail("Invalid configuration file name");
} catch (ConfigurationException e) {
}
@@ -105,14 +112,23 @@
*/
public void testRepositoryConfigCreateWithURI() throws URISyntaxException {
try {
- URI uri = new File(REPOSITORY_XML).toURI();
- RepositoryConfig.create(uri, REPOSITORY_HOME);
+ RepositoryConfig.create(XML.toURI(), DIR.getPath());
} catch (ConfigurationException e) {
fail("Valid configuration URI");
}
+
+ try {
+ RepositoryConfig.create(
+ new File(DIR, "invalid-config-file.xml").toURI(),
+ DIR.getPath());
+ fail("Invalid configuration URI");
+ } catch (ConfigurationException e) {
+ }
+
try {
- URI uri = new URI("invalid://config/uri");
- RepositoryConfig.create(uri, REPOSITORY_HOME);
+ RepositoryConfig.create(
+ new URI("invalid://config/uri"),
+ DIR.getPath());
fail("Invalid configuration URI");
} catch (ConfigurationException e) {
}
@@ -122,25 +138,33 @@
* Tests that an input stream can be used for the configuration.
*/
public void testRepositoryConfigCreateWithInputStream() throws IOException {
- InputStream input = new FileInputStream(REPOSITORY_XML);
+ InputStream input = new FileInputStream(XML);
try {
- RepositoryConfig.create(input, REPOSITORY_HOME);
+ RepositoryConfig.create(input, DIR.getPath());
} catch (ConfigurationException e) {
fail("Valid configuration input stream");
} finally {
input.close();
}
- input = new InputStream() {
- public int read() throws IOException {
- throw new IOException("invalid input stream");
- }
- };
+
try {
- RepositoryConfig.create(input, REPOSITORY_HOME);
+ RepositoryConfig.create(
+ new InputStream() {
+ public int read() throws IOException {
+ throw new IOException("invalid input stream");
+ }
+ },
+ DIR.getPath());
+ fail("Invalid configuration input stream");
+ } catch (ConfigurationException e) {
+ }
+
+ try {
+ RepositoryConfig.create(
+ new ClosedInputStream(),
+ DIR.getPath());
fail("Invalid configuration input stream");
} catch (ConfigurationException e) {
- } finally {
- input.close();
}
}
@@ -149,16 +173,16 @@
*/
public void testRepositoryConfigCreateWithInputSource() throws IOException {
try {
- URI uri = new File(REPOSITORY_XML).toURI();
- InputSource source = new InputSource(uri.toString());
- RepositoryConfig.create(source, REPOSITORY_HOME);
+ InputSource source = new InputSource(XML.toURI().toString());
+ RepositoryConfig.create(source, DIR.getPath());
} catch (ConfigurationException e) {
fail("Valid configuration input source with file URI");
}
- InputStream stream = new FileInputStream(REPOSITORY_XML);
+
+ InputStream stream = new FileInputStream(XML);
try {
InputSource source = new InputSource(stream);
- RepositoryConfig.create(source, REPOSITORY_HOME);
+ RepositoryConfig.create(source, DIR.getPath());
} catch (ConfigurationException e) {
fail("Valid configuration input source with input stream");
} finally {
@@ -170,18 +194,16 @@
* Test that the repository configuration file is correctly parsed.
*/
public void testRepositoryConfig() throws Exception {
- RepositoryConfig config =
- RepositoryConfig.create(REPOSITORY_XML, REPOSITORY_HOME);
- assertEquals(REPOSITORY_HOME, config.getHomeDir());
+ assertEquals(DIR.getPath(), config.getHomeDir());
assertEquals("default", config.getDefaultWorkspaceName());
assertEquals(
- new File(REPOSITORY_HOME, "workspaces").getPath(),
+ new File(DIR, "workspaces").getPath(),
new File(config.getWorkspacesConfigRootDir()).getPath());
- assertEquals("Jackrabbit", config.getAppName());
assertEquals("Jackrabbit", config.getSecurityConfig().getAppName());
// SecurityManagerConfig
- SecurityManagerConfig smc = config.getSecurityConfig().getSecurityManagerConfig();
+ SecurityManagerConfig smc =
+ config.getSecurityConfig().getSecurityManagerConfig();
assertEquals(
"org.apache.jackrabbit.core.security.simple.SimpleSecurityManager",
smc.getClassName());
@@ -195,33 +217,30 @@
}
// AccessManagerConfig
- AccessManagerConfig amc = config.getAccessManagerConfig();
- amc = config.getSecurityConfig().getAccessManagerConfig();
+ AccessManagerConfig amc =
+ config.getSecurityConfig().getAccessManagerConfig();
assertEquals(
"org.apache.jackrabbit.core.security.simple.SimpleAccessManager",
amc.getClassName());
assertTrue(amc.getParameters().isEmpty());
VersioningConfig vc = config.getVersioningConfig();
- assertEquals(new File(REPOSITORY_HOME, "version"), vc.getHomeDir());
+ assertEquals(new File(DIR, "version"), vc.getHomeDir());
assertEquals(
"org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager",
vc.getPersistenceManagerConfig().getClassName());
}
public void testInit() throws Exception {
- RepositoryConfig.create(REPOSITORY_XML, REPOSITORY_HOME);
- File workspaces_dir = new File(REPOSITORY_HOME, "workspaces");
+ File workspaces_dir = new File(DIR, "workspaces");
File workspace_dir = new File(workspaces_dir, "default");
File workspace_xml = new File(workspace_dir, "workspace.xml");
assertTrue("Default workspace is created", workspace_xml.exists());
}
public void testCreateWorkspaceConfig() throws Exception {
- RepositoryConfig config =
- RepositoryConfig.create(REPOSITORY_XML, REPOSITORY_HOME);
- config.createWorkspaceConfig("test-workspace", (StringBuffer)null);
- File workspaces_dir = new File(REPOSITORY_HOME, "workspaces");
+ config.createWorkspaceConfig("test-workspace", (StringBuffer) null);
+ File workspaces_dir = new File(DIR, "workspaces");
File workspace_dir = new File(workspaces_dir, "test-workspace");
File workspace_xml = new File(workspace_dir, "workspace.xml");
assertTrue(workspace_xml.exists());
@@ -229,9 +248,7 @@
public void testCreateDuplicateWorkspaceConfig() throws Exception {
try {
- RepositoryConfig config =
- RepositoryConfig.create(REPOSITORY_XML, REPOSITORY_HOME);
- config.createWorkspaceConfig("default", (StringBuffer)null);
+ config.createWorkspaceConfig("default", (StringBuffer) null);
fail("No exception thrown when creating a duplicate workspace");
} catch (ConfigurationException e) {
// test passed
@@ -247,10 +264,11 @@
InputStream in = getClass().getResourceAsStream(
"/org/apache/jackrabbit/core/cluster/repository.xml");
- RepositoryConfig config = RepositoryConfig.create(in, REPOSITORY_HOME);
+ RepositoryConfig config = RepositoryConfig.create(in, DIR.getPath());
ClusterConfig clusterConfig = config.getClusterConfig();
assertEquals(id, clusterConfig.getId());
assertEquals(syncDelay, clusterConfig.getSyncDelay());
}
+
}
Modified: jackrabbit/branches/1.x/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.x/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java?rev=776753&r1=776752&r2=776753&view=diff
==============================================================================
--- jackrabbit/branches/1.x/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java (original)
+++ jackrabbit/branches/1.x/jackrabbit-standalone/src/main/java/org/apache/jackrabbit/standalone/Main.java Wed May 20 16:19:10 2009
@@ -19,7 +19,6 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.net.BindException;
import java.net.URL;
import org.apache.commons.cli.CommandLine;
@@ -28,6 +27,8 @@
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.RepositoryCopier;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
import org.apache.jackrabbit.servlet.jackrabbit.JackrabbitRepositoryServlet;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
@@ -70,6 +71,8 @@
options.addOption("?", "help", false, "print this message");
options.addOption("n", "notice", false, "print copyright notices");
options.addOption("l", "license", false, "print license information");
+ options.addOption(
+ "b", "backup", false, "create a backup of the repository");
options.addOption("q", "quiet", false, "disable console output");
options.addOption("d", "debug", false, "enable debug logging");
@@ -79,6 +82,12 @@
options.addOption("f", "file", true, "location of this jar file");
options.addOption("r", "repo", true, "repository directory (jackrabbit)");
options.addOption("c", "conf", true, "repository configuration file");
+ options.addOption(
+ "R", "backup-repo", true,
+ "backup repository directory (jackrabbit-backupN)");
+ options.addOption(
+ "C", "backup-conf", true,
+ "backup repository configuration file");
command = new GnuParser().parse(options, args);
}
@@ -118,32 +127,71 @@
message("Writing log messages to " + log);
prepareServerLog(log);
- message("Starting the server...");
- prepareWebapp(file, repository, tmp);
- accessLog.setHandler(webapp);
- prepareAccessLog(log);
- server.setHandler(accessLog);
- prepareConnector();
- server.addConnector(connector);
- prepareShutdown();
-
- try {
- server.start();
-
- String host = connector.getHost();
- if (host == null) {
- host = "localhost";
+ if (command.hasOption("backup")) {
+ backup(repository);
+ } else {
+ message("Starting the server...");
+ prepareWebapp(file, repository, tmp);
+ accessLog.setHandler(webapp);
+ prepareAccessLog(log);
+ server.setHandler(accessLog);
+ prepareConnector();
+ server.addConnector(connector);
+ prepareShutdown();
+
+ try {
+ server.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ message("Apache Jackrabbit is now running at "
+ +"http://" + host + ":" + connector.getPort() + "/");
+ } catch (Throwable t) {
+ System.err.println(
+ "Unable to start the server: " + t.getMessage());
+ System.exit(1);
}
- message("Apache Jackrabbit is now running at "
- +"http://" + host + ":" + connector.getPort() + "/");
- } catch (Throwable t) {
- System.err.println(
- "Unable to start the server: " + t.getMessage());
- System.exit(1);
}
}
}
+ private void backup(File sourceDir) throws Exception {
+ RepositoryConfig source;
+ if (command.hasOption("conf")) {
+ source = RepositoryConfig.create(
+ new File(command.getOptionValue("conf")), sourceDir);
+ } else {
+ source = RepositoryConfig.create(sourceDir);
+ }
+
+ File targetDir;
+ if (command.hasOption("backup-repo")) {
+ targetDir = new File(command.getOptionValue("backup-repo"));
+ } else {
+ int i = 1;
+ do {
+ targetDir = new File("jackrabbit-backup" + i++);
+ } while (targetDir.exists());
+ }
+
+ RepositoryConfig target;
+ if (command.hasOption("backup-conf")) {
+ target = RepositoryConfig.install(
+ new File(command.getOptionValue("backup-conf")), targetDir);
+ } else {
+ target = RepositoryConfig.install(targetDir);
+ }
+
+ message("Creating a repository copy in " + targetDir);
+
+ RepositoryCopier copier = new RepositoryCopier(source, target);
+ copier.copy();
+
+ message("The repository has been successfully copied.");
+ }
+
private void prepareServerLog(File log)
throws IOException {
Layout layout =