Property changes on: /home/ntoper/workspace/backup ___________________________________________________________________ Name: svn:ignore - target + target repository *.settings *.classpath .project repository.xml dir_conflicts.prej myzip.zip Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/AllWorkspacesBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/AllWorkspacesBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/AllWorkspacesBackup.java (working copy) @@ -17,6 +17,9 @@ package org.apache.jackrabbit.backup; import java.io.IOException; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; import javax.jcr.LoginException; import javax.jcr.RepositoryException; @@ -37,8 +40,8 @@ * @throws RepositoryException * @throws LoginException */ - public AllWorkspacesBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); + public AllWorkspacesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); } public AllWorkspacesBackup() { @@ -44,7 +47,7 @@ public AllWorkspacesBackup() { super(); } - + /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) @@ -54,12 +57,13 @@ Session s = this.getSession(); Workspace wsp = s.getWorkspace(); String[] allWsp = wsp.getAccessibleWorkspaceNames(); - + String login = this.getCredentials().getUserID(); + String password = this.getCredentials().getPassword().toString(); + for (int i = 0; i < allWsp.length; i++) { - WorkspaceBackup wspb = new WorkspaceBackup(this.repo, this.conf, allWsp[i]); - wspb.backup(h); - - WorkspaceConfigBackup wspConfb = new WorkspaceConfigBackup(this.repo, this.conf, allWsp[i]); + WorkspaceBackup wspb = new WorkspaceBackup(this.getRepo(), this.getConf(), allWsp[i],login, password); + wspb.backup(h); + WorkspaceConfigBackup wspConfb = new WorkspaceConfigBackup(this.getRepo(), this.getConf(), allWsp[i], login, password); wspConfb.backup(h); } } @@ -67,9 +71,29 @@ /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub + public void restore(BackupIOHandler h) throws ZipException, IOException, LoginException, RepositoryException { + //Get All workspaces name in the zip + Enumeration entries = h.getEntries(); + while (entries.hasMoreElements()) { + String s = ((ZipEntry) entries.nextElement()).getName(); + if (s.contains("export_") && s.endsWith(".xml")) { + int begin = "export_".length(); + //Allow to manage is we backup 110 workspaces for instance + int end = s.length() - ".xml".length(); + String name = s.substring(begin, end); + String login = this.getCredentials().getUserID(); + String password = this.getCredentials().getPassword().toString(); + //No need to check if the config file is there: if not, we will throw an exception later. + //Restore the config + WorkspaceConfigBackup wspConfb = new WorkspaceConfigBackup(this.getRepo(), this.getConf(), name, login, password); + wspConfb.restore(h); + + //Restore the content + WorkspaceBackup wsb = new WorkspaceBackup(this.getRepo(), this.getConf(), name, login, password); + wsb.restore(h); + } + } } } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/Backup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/Backup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/Backup.java (working copy) @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.backup; +import java.io.FileNotFoundException; import java.io.IOException; import javax.jcr.LoginException; @@ -33,9 +34,10 @@ */ public abstract class Backup { - RepositoryImpl repo; - BackupConfig conf; - Session session; + private RepositoryImpl repo; + private BackupConfig conf; + private Session session;; + private SimpleCredentials credentials; /** * @@ -42,27 +44,30 @@ * @param repo The repository to backup * @param conf The specific BackupConfig object (usually a subset of backup.xml) * @param name Name of the resource to backup. Unique. Useful? - * @throws RepositoryException - * @throws LoginException + * @throws RepositoryException + * @throws LoginException + * */ //TODO Useful? - public Backup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { + public Backup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { this.repo = repo; this.conf = conf; - this.session = this.repo.login( - new SimpleCredentials(this.conf.getLogin(), this.conf.getPassword().toCharArray())); - + this.credentials = new SimpleCredentials(login, password.toCharArray()); + this.session = this.repo.login(this.credentials); + } + + protected Backup() { } - public Backup() { - + protected Backup(String login, String password) { + this.credentials = new SimpleCredentials(login, password.toCharArray()); } - - public void init(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { + + protected void init(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { this.repo = repo; this.conf = conf; - this.session = this.repo.login( - new SimpleCredentials(this.conf.getLogin(), this.conf.getPassword().toCharArray())); + this.credentials = new SimpleCredentials(login, password.toCharArray()); + this.session = this.repo.login(this.credentials); } public RepositoryImpl getRepo() { @@ -68,6 +73,10 @@ public RepositoryImpl getRepo() { return this.repo; } + + protected void setRepo(RepositoryImpl repo) { + this.repo = repo; + } /* * Each ResourceBackup is responsible to handle the backup. @@ -84,13 +93,30 @@ * Send it to out */ public abstract void backup(BackupIOHandler h) throws RepositoryException, IOException; - public abstract void restore(BackupIOHandler h); + public abstract void restore(BackupIOHandler h) throws FileNotFoundException, RepositoryException, IOException; - public Session getSession() { + protected Session getSession() { return this.session; } +// TODO call sesssion.logout or useless? + - //TODO call sesssion.logout or useless? + protected BackupConfig getConf() { + return conf; + } + protected void setConf(BackupConfig conf2) { + this.conf = conf2; + + } + protected SimpleCredentials getCredentials() { + return credentials; + } + + protected void setCredentials(SimpleCredentials cred) { + this.credentials = cred; + } + + } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfig.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfig.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfig.java (working copy) @@ -1,9 +1,9 @@ /* * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with + * contributor license agreements. See the NOTICE backupFile 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 ASF licenses this backupFile to You under the Apache License, Version 2.0 + * (the "License"); you may not use this backupFile except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -25,6 +25,7 @@ import org.apache.jackrabbit.core.config.ConfigurationException; import org.apache.jackrabbit.core.config.PersistenceManagerConfig; +import org.apache.jackrabbit.core.config.RepositoryConfig; import org.xml.sax.InputSource; @@ -37,17 +38,14 @@ * */ public class BackupConfig { - - //TODO Useful? - private PersistenceManagerConfig pmc; - //Tused to backup a workspace first in a file + + //used to backup a workspace first in a backupFile private File workFolder; private Collection allResources; - private File file; + private File backupFile; private File repoConfFile; - private String login; - private String password; - + + /** * Parses the given repository configuration document and returns the * parsed and initialized repository configuration. The given repository @@ -57,47 +55,38 @@ * method also initializes the configuration (creates the configured * directories, etc.). The {@link RepositoryConfigurationParser} class should be * used directly to just parse the configuration. - * @param repoConfFile + * @param repoConfFile * - * @param xml repository configuration document - * @param home repository home directory + * @param myFile repository configuration document + * @param repoConfFile repository file configuration * @return repository configuration * @throws ConfigurationException on configuration errors - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws IOException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + * @throws IOException */ - public static BackupConfig create(String myFile, String repoConfFile, String login, String password) + public static BackupConfig create(String myFile, String repoConfFile) throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { - URI uri = new File(myFile).toURI(); InputSource is = new InputSource(uri.toString()); - BackupConfigurationParser parser = new BackupConfigurationParser(new Properties()); - - BackupConfig config = parser.parseBackupConfig(is, myFile, repoConfFile, login, password); - + BackupConfig config = parser.parseBackupConfig(is, myFile, repoConfFile); return config; } - - + + //TODO if path not set in the conf file then create one as the current dir + public BackupConfig(File path, Collection allResources, String myFile, String repoConfFile) throws IOException { - //TODO see if path is really useful? - public BackupConfig(PersistenceManagerConfig pmc, File path, Collection allResources, String myFile, String repoConfFile, String login, String password) throws IOException { - //Logic application: not in the parser: this code has to be here if (!(path.isDirectory() && path.canWrite())) { throw new IOException(); - } - - this.pmc = pmc; + } + this.workFolder = path; this.allResources = allResources; - this.file = new File(myFile); + this.backupFile = new File(myFile); this.repoConfFile = new File(repoConfFile); - this.password = password; - this.login = login; } public Collection getAllResources() { @@ -104,6 +93,10 @@ return allResources; } + public void addResource(Backup b) { + this.allResources.add(b); + } + public File getWorkFolder() { return workFolder; } @@ -108,32 +101,12 @@ return workFolder; } - public PersistenceManagerConfig getPmc() { - return pmc; - } public File getFile() { - return this.file; + return this.backupFile; } - - public File getRepoConfFile() { return repoConfFile; } - - - - public String getPassword() { - return this.password; - } - - - - public String getLogin() { - return this.login; - } - - - } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationBackup.java (working copy) @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; +import java.util.zip.ZipException; import javax.jcr.LoginException; import javax.jcr.RepositoryException; @@ -38,16 +39,15 @@ * @throws RepositoryException * @throws LoginException */ - public BackupConfigurationBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); - + public BackupConfigurationBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); + } - + public BackupConfigurationBackup() { super(); } - - + /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) */ @@ -53,7 +53,7 @@ */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { - File file = conf.getFile(); + File file = this.getConf().getFile(); h.write("backup.xml", file); } @@ -58,11 +58,19 @@ } /* (non-Javadoc) + * This method is quite special. It is used to restore content from scratch. To break cyclic reference, we restore the file + * in the current directory (we don't have yet the temporary one). + * * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub + public void restore(BackupIOHandler h) throws ZipException, IOException { + File conf = new File("backup.xml"); + h.read("backup.xml", conf); + } - } + /* public File getBackupConfFile() { + // TODO Auto-generated method stub + return null; + }*/ } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationParser.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationParser.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationParser.java (working copy) @@ -44,6 +44,7 @@ private static final String RESOURCES = "Resources"; private static final String RESOURCE = "Resource"; private static final String SAVING_CLASS = "savingClass"; + //TODO Add parse to get the name if a specific wsp has to be backupped/restored. /** * @param variables @@ -70,29 +71,25 @@ * @see #parseBeanConfig(Element, String) * @see #parseVersioningConfig(Element) */ - public BackupConfig parseBackupConfig(InputSource xml, String myFile, String repoConfFile, String login, String password) + public BackupConfig parseBackupConfig(InputSource xml, String myFile, String repoConfFile) throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { //TODO refactor dependency between this method and BackupConfig Element root = parseXML(xml); - + //Working Folder Element workingFolder = getElement(root, WORKING_FOLDER); File path = new File(workingFolder.getAttribute(WORKING_FOLDER_ATTRIBUTE)); + - //Persistence Manager - PersistenceManagerConfig pmc = this.parsePersistenceManagerConfig(root); - - //Management of resources tag + //Management of resources tag Element resources = this.getElement(root, RESOURCES); - Collection allResources = this.parseResourcesConfig(resources); - - return new BackupConfig(pmc, path, allResources, myFile, repoConfFile, login, password); + Collection allResources = this.parseResourcesConfig(resources); + + return new BackupConfig(path, allResources, myFile, repoConfFile); } - + /** - * TODO: to put in ConfigurationParser? - * * Returns the named children of the given parent element. * * @param parent parent element @@ -149,17 +146,4 @@ return objects; } - - /** - * Parses the PersistenceManager config. - * - * @param parent parent of the PersistenceManager element - * @return persistence manager configuration - * @throws ConfigurationException if the configuration is broken - */ - protected PersistenceManagerConfig parsePersistenceManagerConfig( - Element parent) throws ConfigurationException { - return new PersistenceManagerConfig( - parseBeanConfig(parent, RepositoryConfigurationParser.PERSISTENCE_MANAGER_ELEMENT)); - } } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupIOHandler.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupIOHandler.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupIOHandler.java (working copy) @@ -16,18 +16,21 @@ */ package org.apache.jackrabbit.backup; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException;; +import java.io.IOException;import java.util.Enumeration; +import java.util.zip.ZipException; +; public interface BackupIOHandler { - + //TODO unify with input/output //Add reference to the file // How to precise if in or out... Maybe not needed? void close() throws IOException; - void initBackup() throws FileNotFoundException, IOException; - void initRestore() throws FileNotFoundException; void write(String name, File f) throws IOException; void write(String name, ByteArrayOutputStream fos) throws IOException; + byte[] read(String zipEntry) throws ZipException, IOException; + public void read(String zipEntry, File myFile) throws ZipException, IOException; + Enumeration getEntries() throws ZipException, IOException; } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupManager.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupManager.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupManager.java (working copy) @@ -38,22 +38,27 @@ * */ public class BackupManager extends Backup { - - public BackupManager(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); - + + + public BackupManager(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login , password); + + //Initiate correctly all objects in allResources - Iterator it = this.conf.getAllResources().iterator(); - - while(it.hasNext()) { + Iterator it = this.getConf().getAllResources().iterator(); + while ( it.hasNext() ) { Backup b = (Backup) it.next(); - b.init(repo, conf); + b.init(repo, conf, login, password); } } - - - public static BackupManager create(RepositoryImpl impl, BackupConfig conf2) throws LoginException, RepositoryException { - return new BackupManager(impl, conf2); + + public BackupManager() { + super(); + } + + + public static BackupManager create(RepositoryImpl impl, BackupConfig conf2, String login, String password) throws LoginException, RepositoryException { + return new BackupManager(impl, conf2, login, password); } /** * Used to backup the repository and all subclasses. Call all classes when needed. @@ -71,16 +76,16 @@ * It is responsible to initiate and close the zipFile. * Each backup method, use the BackupIOHandler to write the file directly. */ - - h.initBackup(); + + //We need to put those two Backup resources here for backup since they are handled differently + //for restore + this.addResource(new RepositoryBackup()); + this.addResource(new BackupConfigurationBackup()); + try { - - - Collection resources = this.conf.getAllResources(); - - + Collection resources = this.getConf().getAllResources(); Iterator it = resources.iterator(); - + while (it.hasNext()) { Backup b = (Backup) it.next(); b.backup(h); @@ -90,13 +95,51 @@ h.close(); } } - - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub - + /** + * TODO commment + * @param backup + * @throws RepositoryException + * @throws LoginException + */ + private void addResource(Backup backup) throws LoginException, RepositoryException { + String login = this.getCredentials().getUserID(); + String password = this.getCredentials().getPassword().toString(); + backup.init(this.getRepo(), this.getConf(), login, password); + this.getConf().addResource(backup); } - - + /** + * Same method as backup but for restore. + * TODO Comment + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + * + */ + public void restore(BackupIOHandler h) throws RepositoryException, IOException { + + /* + * There is a dissimetry in the restore operation compared to the backup one. + * It is because of the need to first restore the repository and launch it where during the backup we can + * backup the repository and the configuration file the same way as the other. + * + * (to make repository + backup file mandatory, they are added automatically in BAckupManager) + * + * + * Ignore any repository or backupConfig restore orders... + * + */ + try { + Collection resources = this.getConf().getAllResources(); + Iterator it = resources.iterator(); + while (it.hasNext()) { + Backup b = (Backup) it.next(); + b.restore(h); + } + } + finally { + h.close(); + } + } } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/LaunchBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/LaunchBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/LaunchBackup.java (working copy) @@ -16,6 +16,7 @@ */ package org.apache.jackrabbit.backup; +import java.io.File; import java.io.IOException; import javax.jcr.AccessDeniedException; @@ -23,6 +24,7 @@ import javax.jcr.RepositoryException; import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.ConfigurationException; import org.apache.jackrabbit.core.config.RepositoryConfig; /** @@ -34,14 +36,38 @@ * Date: 23-jun-06 */ public class LaunchBackup { + /** + * TODO where can I find the generic repository.xml? + * Path to the generic repository.xml + */ - static BackupIOHandler h; - RepositoryImpl repo; - BackupConfig conf; - RepositoryConfig repoConf; - BackupManager backup; - - + private static final String REPOSITORY_XML = "/home/ntoper/workspace/backup/"; + + /** + * The backupIOHandler used to handle IO + */ + private static BackupIOHandler h; + + /** + * Used to get a reference to the repository. + */ + private RepositoryImpl repo; + + /** + * The backupconfig object. + */ + private BackupConfig conf; + + /** + * The repositoryConfig object. + */ + private RepositoryConfig repoConf; + + /** + * The backupManager is used to launch all backup/restore operations. + */ + private BackupManager backup; + /** * The command line tool. @@ -46,29 +72,31 @@ /** * The command line tool. * - * LaunchBackup --zip myzip.zip --size 2 --conf backup.xml --login nico --password mlypass backup repository.xml repository/ - * LaunchBackup --zip ./myzip.zip --size 2 --conf backup.xml --login nico --password restore repository.xml repository/ + * LaunchBackup --zip myzip.zip --conf backup.xml --login nico --password mlypass backup repository.xml repository/ + * LaunchBackup --zip ./myzip.zip --login nico --password p repository.xml restore + * LaunchBackup --zip ./myzip.zip -- conf restore.xml --login nico --password p restore repository.xml repository/ + * + * If backup.xml for restore, no repository + backupConfig restore Only partial restore * * --zip: where is the zip file (only implemented way to backup for now) - * --size in Go - * * --conf: path to the config file for the backup tool - * + * * backup/restore: whether you want a backup or a restore - * + * * repository.xml: path to the config file of the repository - * + * * repository/ is the name of the repository - * + * * * --help for help option - * @throws RepositoryException - * @throws IOException - * @throws IOException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException * + * @throws RepositoryException + * @throws IOException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + * @throws AccessDeniedException + * @throws IOException */ public static void main(String[] args) throws RepositoryException, AccessDeniedException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { // I have to declare all var here so they are not resetted out of the for. @@ -82,52 +110,43 @@ //2 booleans in case the user specified nothing boolean isBackup = false; boolean isRestore = false; - + //Parse the command line. for (int i = 0; i < args.length; i++) { - + if ( args[i].equals("--help") || args.length == 0) { usage(); } - - if (args[i].equals("--zip")){ + + if (args[i].equals("--zip")) { zipFile = args[i + 1]; - //We put it here because later we might offer other possibilities than only zip - LaunchBackup.h = new ZipFileBackupIOHandler(zipFile); } - - if (args[i].equals("--conf")){ - + + if (args[i].equals("--conf")) { confFile = args[i + 1]; - } - - if (args[i].equals("--login")){ - + + if (args[i].equals("--login")) { login = args[i + 1]; - } - - if (args[i].equals("--password")){ - + + if (args[i].equals("--password")) { password = args[i + 1]; - } - - if (args[i].equals("backup") && isRestore == false ){ + + if (args[i].equals("backup") && !isRestore) { isBackup = true; repoConfFile = args[i + 1]; home = args[i + 2]; - } - - if (args[i].equals("restore") && isBackup == false ){ + + if (args[i].equals("restore") && !isBackup ) { isRestore = true; repoConfFile = args[i + 1]; home = args[i + 2]; - } + } } - + //Check if login and password are provided otherwise weird thing will happen if (login == null || password == null) { throw new LoginException(); @@ -132,19 +151,26 @@ if (login == null || password == null) { throw new LoginException(); } - + LaunchBackup launch = null; - + //We need to shutdown properly the repository whatever happens - try { + try { //Launch backup if (isBackup) { - launch = new LaunchBackup(repoConfFile, home, confFile, login, password); + launch = new LaunchBackup(repoConfFile, home, confFile, login, password); + LaunchBackup.h = new ZipBackupIOHandler(zipFile, true); launch.backup(h); - } + } //Launch restore + else if (isRestore && confFile == null) { + LaunchBackup.h = new ZipBackupIOHandler(zipFile, false); + launch = new LaunchBackup(repoConfFile, home, login, password); + launch.restore(h); + } else if (isRestore) { - launch = new LaunchBackup(); + LaunchBackup.h = new ZipBackupIOHandler(zipFile, false); + launch = new LaunchBackup(repoConfFile, home, confFile, login, password); launch.restore(h); } //Launch nothing (if nothing specified @@ -152,14 +178,14 @@ usage(); } } - finally - { - if (launch !=null) + finally { + if (launch != null) { launch.shutdown(); + } } } - + /** * Auxiliary method for main @@ -165,7 +191,7 @@ * Auxiliary method for main * */ - private static void usage(){ + private static void usage() { System.out.println("todo: cut and paste of the comment when the project is over"); System.exit(0); } @@ -173,14 +199,16 @@ /** * Constructor of LaunchBackup. Initiate the repository. * - * @param String filename: name of the configuration file - * @throws RepositoryException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws IOException + * @param String repoConfFile: name of the configuration file + * @throws RepositoryException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + * @throws IOException + * */ public LaunchBackup(String repoConfFile, String home, String backupConfFile, String login, String password) throws RepositoryException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { + //Launch first the repository this.repoConf = RepositoryConfig.create(repoConfFile, home); this.repo = RepositoryImpl.create(this.repoConf); @@ -186,21 +214,68 @@ this.repo = RepositoryImpl.create(this.repoConf); //Create the backupConfig object - this.conf = BackupConfig.create(backupConfFile, repoConfFile, login, password); - this.backup = BackupManager.create(this.repo, this.conf); - + this.conf = BackupConfig.create(backupConfFile, repoConfFile); + this.backup = BackupManager.create(this.repo, this.conf, login, password); } - + /** - * Used for restore operations only + * Used for restore operations only. + * + * This constructor restores the repository! I don't see any other options since to restore we + * need the repository and what is inside. + * + * + * @param password + * @param login + * @param home + * @throws RepositoryException + * @throws IOException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws ClassNotFoundException + * @throws * */ + public LaunchBackup(String repoConfFile, String home, String login, String password) throws RepositoryException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException { + /* + * There is a dissymetry there (due to design constraint: we wanted to be close of JR's way of working). + * We need to restore BackupConfiguration and the Repository and we need each other to create them. + */ - public LaunchBackup() { - // TODO Auto-generated constructor stub - } + //Extract BackupConfig + BackupConfigurationBackup b = new BackupConfigurationBackup(); + b.restore(h); + //RepoConfFile isn't the right one. We know it + BackupConfig bc; + try { + //We know we have restored it to backup.xml + //There is no other way, except to break the abstract class and create + //another restore methods. This seems fine and this way is unique/ + // If we have the issue again, we will evolve the design. + bc = BackupConfig.create("backup.xml", repoConfFile); + } catch (ConfigurationException e) { + throw new RepositoryException(); + } catch (ClassNotFoundException e) { + throw new RepositoryException(); + } catch (InstantiationException e) { + throw new RepositoryException(); + } + finally { + //We need to delete it anyway + File f = new File("backup.xml"); + f.delete(); + } + //Restore repository + RepositoryBackup br = new RepositoryBackup(repoConfFile, home);; + br.setConf(bc); + br.restore(h); + RepositoryImpl repo = br.getRepo(); + this.backup = BackupManager.create(repo, bc, login, password); + this.repo = this.backup.getRepo(); + this.conf = this.backup.getConf(); + } /** * Backup a repository @@ -215,13 +290,17 @@ *Restore a repository * * @param BackupIOHandler h a reference to the backup to restore + * @throws IOException + * @throws RepositoryException + * @throws IllegalAccessException */ - public void restore(BackupIOHandler h) { + public void restore(BackupIOHandler h) throws RepositoryException, IOException, IllegalAccessException { this.backup.restore(h); } - + private void shutdown() { - this.repo.shutdown(); + //TODO while refactoring and deletion of RestoreFromScratch + this.repo.shutdown(); } - + } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NamespaceBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NamespaceBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NamespaceBackup.java (working copy) @@ -16,8 +16,10 @@ */ package org.apache.jackrabbit.backup; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.HashMap; @@ -28,6 +30,8 @@ import javax.jcr.Session; import javax.jcr.Workspace; +import org.apache.jackrabbit.core.NamespaceRegistryImpl; +import org.apache.jackrabbit.core.NodeId; import org.apache.jackrabbit.core.RepositoryImpl; @@ -41,7 +45,7 @@ * */ public class NamespaceBackup extends Backup implements Serializable { - + /** * */ @@ -46,7 +50,7 @@ * */ private static final long serialVersionUID = 4703796138774238005L; - + /** * This class holds all namespaces in a serializable way. We only put the relevant information. * (Do not change this class or you might lose backward compatibility; instead use another version) @@ -56,30 +60,36 @@ private static final long serialVersionUID = 8384076353482950602L; - HashMap h; - - - public Namespaces() { + private HashMap h; + + + protected Namespaces() { h = new HashMap(); } - public void addNamespace(String prefix, String uri) { - h.put(prefix, uri); + protected void addNamespace(String prefix, String uri) { + h.put(prefix, uri); } - + + protected String[] getAllPrefixes() { + String[] s = new String[1]; + return (String[]) h.keySet().toArray(s); + } + + protected String getUri(String prefix) { + + return (String) h.get(prefix); + } } - - /** + + /** * @param repo * @param conf - * @throws RepositoryException - * @throws LoginException + * @throws RepositoryException + * @throws LoginException */ - public NamespaceBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); - - - + public NamespaceBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); } public NamespaceBackup() { @@ -85,8 +95,8 @@ public NamespaceBackup() { super(); } - - + + /* (non-Javadoc) * TODO where do I find the local ns? * TODO use a ByteArrayOutputStream? @@ -94,25 +104,25 @@ */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { - Session s = this.getSession(); - Workspace wsp = s.getWorkspace(); - NamespaceRegistry ns = wsp.getNamespaceRegistry(); - - Namespaces myNs = new Namespaces(); + Session s = this.getSession(); + Workspace wsp = s.getWorkspace(); + NamespaceRegistry ns = wsp.getNamespaceRegistry(); - String[] allPrefixes = ns.getPrefixes(); - - for (int i = 0; i < allPrefixes.length; i++) { - String prefix = allPrefixes[i]; - myNs.addNamespace(prefix, ns.getURI(prefix)); - } - - String name = this.getClass().toString(); - - ByteArrayOutputStream fos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(myNs); - h.write(name, fos); + Namespaces myNs = new Namespaces(); + + String[] allPrefixes = ns.getPrefixes(); + + for (int i = 0; i < allPrefixes.length; i++) { + String prefix = allPrefixes[i]; + myNs.addNamespace(prefix, ns.getURI(prefix)); + } + + String name = this.getClass().toString(); + + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(myNs); + h.write(name, fos); } /* (non-Javadoc) @@ -118,11 +128,29 @@ /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub + public void restore(BackupIOHandler h) throws RepositoryException, IOException { + String name = this.getClass().toString(); + byte[] ns = h.read(name); - } - - + ByteArrayInputStream bis = new ByteArrayInputStream(ns); + ObjectInputStream ois = new ObjectInputStream(bis); + + try { + Namespaces allNs = (Namespaces) ois.readObject(); + String[] allPrefixes = allNs.getAllPrefixes(); + + Session s = this.getSession(); + Workspace wsp = s.getWorkspace(); + NamespaceRegistryImpl nsr = (NamespaceRegistryImpl) wsp.getNamespaceRegistry(); + + for (int i = 0; i < allPrefixes.length; i++) { + if (!nsr.isRegistered(allPrefixes[i])) { + nsr.registerNamespace(allPrefixes[i], allNs.getUri(allPrefixes[i])); + } + } + } catch (ClassNotFoundException e) { + throw new RepositoryException(); + } + } } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeTypeBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeTypeBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeTypeBackup.java (working copy) @@ -16,8 +16,12 @@ */ package org.apache.jackrabbit.backup; +import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.util.zip.ZipException; import javax.jcr.LoginException; import javax.jcr.NamespaceRegistry; @@ -27,11 +31,15 @@ import javax.jcr.nodetype.NoSuchNodeTypeException; import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; import org.apache.jackrabbit.core.nodetype.NodeTypeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; +import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; import org.apache.jackrabbit.core.nodetype.xml.NodeTypeWriter; +import org.apache.jackrabbit.name.IllegalNameException; import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.UnknownPrefixException; /** * @author ntoper @@ -45,14 +53,13 @@ * @throws RepositoryException * @throws LoginException */ - public NodeTypeBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); - } - + public NodeTypeBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); + } + public NodeTypeBackup() { super(); - } - + } /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) @@ -58,10 +65,9 @@ * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) */ public void backup(BackupIOHandler h) throws IOException, RepositoryException { - //Can we assume the default wsp always exist? Session s = this.getSession(); Workspace wsp = s.getWorkspace(); - + NodeTypeManagerImpl ntm = (NodeTypeManagerImpl) wsp.getNodeTypeManager(); NodeTypeRegistry ntreg = ntm.getNodeTypeRegistry(); NamespaceRegistry ns = wsp.getNamespaceRegistry(); @@ -68,10 +74,9 @@ NodeTypeDef[] ntd = getRegisteredNodesTypesDefs(ntreg); ByteArrayOutputStream out = new ByteArrayOutputStream(); NodeTypeWriter.write(out, ntd, ns); - h.write("NodeType", out); + h.write("NodeType", out); } - - + /** * Returns the nodes types definitions of all registered node types. * @@ -76,18 +81,18 @@ * Returns the nodes types definitions of all registered node types. * * @return the node type definition of all registered node types. - * @throws NoSuchNodeTypeException + * @throws NoSuchNodeTypeException */ private static NodeTypeDef[] getRegisteredNodesTypesDefs(NodeTypeRegistry ntreg) throws NoSuchNodeTypeException { - QName[] qn = ntreg.getRegisteredNodeTypes(); - NodeTypeDef[] ntd = new NodeTypeDef[qn.length]; - - for (int i=0; i < qn.length; i++) { - ntd[i] = ntreg.getNodeTypeDef(qn[i]); - } - return ntd; + QName[] qn = ntreg.getRegisteredNodeTypes(); + NodeTypeDef[] ntd = new NodeTypeDef[qn.length]; + + for (int i=0; i < qn.length; i++) { + ntd[i] = ntreg.getNodeTypeDef(qn[i]); + } + + return ntd; } - /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) @@ -92,9 +97,37 @@ /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub + public void restore(BackupIOHandler h) throws ZipException, IOException, RepositoryException { + + File f = new File(this.getConf().getWorkFolder() + "Node.xml"); + try { + h.read("NodeType", f); + FileInputStream is = new FileInputStream(f); + NodeTypeReader r = new NodeTypeReader(is); + NodeTypeDef[] ntds = r.getNodeTypeDefs(); + Session s = this.getSession(); + Workspace wsp = s.getWorkspace(); + + NodeTypeManagerImpl ntm = (NodeTypeManagerImpl) wsp.getNodeTypeManager(); + NodeTypeRegistry ntreg = ntm.getNodeTypeRegistry(); + + for (int i = 0; i < ntds.length; i++) { + if (!ntreg.isRegistered(ntds[i].getName())) { + ntreg.registerNodeType(ntds[i]); + } + } + NamespaceRegistry ns = wsp.getNamespaceRegistry(); + + } catch (IllegalNameException e) { + new RepositoryException(); + } catch (UnknownPrefixException e) { + new RepositoryException(); + } catch (InvalidNodeTypeDefException e) { + new RepositoryException(); + } + finally { + f.delete(); + } } - } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeVersionHistoriesBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeVersionHistoriesBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeVersionHistoriesBackup.java (working copy) @@ -38,8 +38,8 @@ * @throws RepositoryException * @throws LoginException */ - public NodeVersionHistoriesBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); + public NodeVersionHistoriesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); // TODO Auto-generated constructor stub } @@ -55,7 +55,7 @@ IOException { Session s = this.getSession(); - File temp = new File(this.conf.getWorkFolder() + "history.xml"); + File temp = new File(this.getConf().getWorkFolder() + "history.xml"); try { FileOutputStream out = new FileOutputStream(temp); Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/RepositoryBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/RepositoryBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/RepositoryBackup.java (working copy) @@ -16,11 +16,17 @@ */ package org.apache.jackrabbit.backup; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Properties; +import java.util.zip.ZipException; import javax.jcr.LoginException; import javax.jcr.RepositoryException; @@ -29,6 +35,7 @@ import org.apache.jackrabbit.core.NodeId; import org.apache.jackrabbit.core.NodeImpl; import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.config.RepositoryConfig; /** * @author ntoper @@ -36,17 +43,19 @@ */ public class RepositoryBackup extends Backup { - + private String repoConfFile; + private String home; + /** * @param repo * @param conf - * @throws RepositoryException - * @throws LoginException + * @throws RepositoryException + * @throws LoginException */ - public RepositoryBackup(RepositoryImpl repo, BackupConfig conf) throws LoginException, RepositoryException { - super(repo, conf); + public RepositoryBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); } - + public RepositoryBackup() { super(); } @@ -51,48 +60,81 @@ super(); } + public RepositoryBackup(String repoConfFile, String home) { + super(); + this.repoConfFile = repoConfFile; + this.home = home; + } /** * Backup the repository config file - * + * * TODO Backup properties? Metadata store? Other ressources? - * @throws IOException - * @throws RepositoryException - * - * + * @throws IOException + * @throws RepositoryException + * + * */ public void backup(BackupIOHandler h) throws IOException, RepositoryException { - - File file = this.conf.getRepoConfFile(); + + File file = this.getConf().getRepoConfFile(); //Backup repository.xml h.write("repository_xml", file); - + //Properties Properties p = new Properties(); - String[] keys = repo.getDescriptorKeys(); + String[] keys = this.getRepo().getDescriptorKeys(); for (int i = 0; i < keys.length; i++) { - p.setProperty(keys[i], repo.getDescriptor(keys[i])); + p.setProperty(keys[i], this.getRepo().getDescriptor(keys[i])); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); - p.store(bos,""); + p.store(bos, ""); h.write("repository_properties", bos); - + // Root node ID NodeImpl nod = (NodeImpl) this.getSession().getRootNode(); NodeId n = nod.getNodeId(); - - //We persist the string as a serialized object to avoid compatibility issue - String s = n.toString(); + ByteArrayOutputStream fos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(s); + oos.writeObject(n); h.write("repository_rootNode", fos); } - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub - + public void restore(BackupIOHandler h) throws ZipException, IOException, RepositoryException { + + //Restore repository.xml + File f = new File(this.repoConfFile); + h.read("repository_xml", f); + + // Launch the repository and launch it. + RepositoryConfig repoConf = RepositoryConfig.create(this.repoConfFile, this.home); + this.setRepo(RepositoryImpl.create(repoConf)); + + //Properties + File f2 = new File(this.getConf().getWorkFolder() + "repository_properties"); + h.read("repository_properties", f2); + + Properties p = new Properties(); + p.load(new FileInputStream(f2)); + this.getRepo().setRepProps(p); + + + //Root node + byte[] root = h.read("repository_rootNode"); + + ByteArrayInputStream bis = new ByteArrayInputStream(root); + ObjectInputStream ois = new ObjectInputStream(bis); + try { + NodeId rootNode = (NodeId) ois.readObject(); + this.getRepo().setRootNodeId(rootNode); + } catch (ClassNotFoundException e) { + throw new RepositoryException(); + } + //TODO sanitycheck? But I need to put the method in public... + } -} + +} \ No newline at end of file Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceBackup.java (working copy) @@ -17,15 +17,24 @@ package org.apache.jackrabbit.backup; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.zip.ZipException; -import javax.jcr.Item; +import javax.jcr.InvalidSerializedDataException; +import javax.jcr.ItemExistsException; import javax.jcr.LoginException; +import javax.jcr.NoSuchWorkspaceException; import javax.jcr.Node; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; +import javax.jcr.Session; import javax.jcr.SimpleCredentials; +import javax.jcr.Workspace; +import javax.jcr.lock.LockException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.version.VersionException; import javax.xml.transform.OutputKeys; import javax.xml.transform.TransformerException; import javax.xml.transform.sax.SAXTransformerFactory; @@ -34,7 +43,10 @@ import org.apache.jackrabbit.core.RepositoryImpl; import org.apache.jackrabbit.core.SessionImpl; +import org.apache.jackrabbit.core.WorkspaceImpl; import org.apache.jackrabbit.core.xml.SysViewSAXEventGenerator; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; import org.xml.sax.SAXException; //TODO Wiki doc to update @@ -43,10 +55,9 @@ * */ public class WorkspaceBackup extends Backup { - - private static int called = 0; + private String wspName; - + /** * @param repo * @param conf @@ -53,16 +64,16 @@ * @throws RepositoryException * @throws LoginException */ - public WorkspaceBackup(RepositoryImpl repo, BackupConfig conf, String name) throws LoginException, RepositoryException { - super(repo, conf); + public WorkspaceBackup(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); this.wspName = name; } - public void init(RepositoryImpl repo, BackupConfig conf, String name) throws LoginException, RepositoryException { - super.init(repo, conf); + public void init(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + super.init(repo, conf, login, password); this.wspName = name; } - + /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) */ @@ -67,45 +78,87 @@ * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) */ public void backup(BackupIOHandler h) throws RepositoryException, - IOException { - SessionImpl s = (SessionImpl) repo.login(new SimpleCredentials(this.conf.getLogin(), this.conf.getPassword().toCharArray()), this.wspName); - - SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); - File temp = new File(this.conf.getWorkFolder() + "wsp.xml"); - try { - TransformerHandler th = stf.newTransformerHandler(); - th.setResult(new StreamResult(new FileOutputStream(temp))); - th.getTransformer().setParameter(OutputKeys.METHOD, "xml"); - th.getTransformer().setParameter(OutputKeys.ENCODING, "UTF-8"); - th.getTransformer().setParameter(OutputKeys.INDENT, "no"); - - new SysViewSAXEventGenerator( - s.getRootNode(), false, false, th) { - protected void process(Node node, int level) - throws RepositoryException, SAXException { - if (!"/jcr:system".equals(node.getPath())) { - super.process(node, level); - } - } - }.serialize(); - h.write("export"+ called +".xml", temp); - } catch (TransformerException te) { - throw new RepositoryException(te); - } catch (SAXException se) { - throw new RepositoryException(se); - } finally { - temp.delete(); - called += 1; - } - + IOException { + SessionImpl s = (SessionImpl) this.getRepo().login(this.getCredentials(), this.wspName); + + SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + File temp = new File(this.getConf().getWorkFolder() + "wsp.xml"); + try { + TransformerHandler th = stf.newTransformerHandler(); + th.setResult(new StreamResult(new FileOutputStream(temp))); + th.getTransformer().setParameter(OutputKeys.METHOD, "xml"); + th.getTransformer().setParameter(OutputKeys.ENCODING, "UTF-8"); + th.getTransformer().setParameter(OutputKeys.INDENT, "no"); + + new SysViewSAXEventGenerator( + s.getRootNode(), false, false, th) { + protected void process(Node node, int level) + throws RepositoryException, SAXException { + if (!"/jcr:system".equals(node.getPath())) { + super.process(node, level); + } + } + }.serialize(); + h.write("export_"+ this.wspName +".xml", temp); + } catch (TransformerException te) { + throw new RepositoryException(te); + } catch (SAXException se) { + throw new RepositoryException(se); + } finally { + temp.delete(); + } + } - + /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub - + public void restore(BackupIOHandler h) throws ZipException, IOException, LoginException, NoSuchWorkspaceException, RepositoryException { + //TODO put temp and constant in object's attribute. + //Restore the DocView in a temp file + + File wspXml = new File(this.getConf().getWorkFolder() + "/workspace.xml"); + File temp = new File(this.getConf().getWorkFolder() + "wsp.xml"); + + try { + FileInputStream fis = new FileInputStream(wspXml); + InputSource xml = new InputSource(fis); + + //Launch & register the wsp + //There is at least the default wsp. + Session s = this.getSession(); + Workspace wsp = s.getWorkspace(); + + //Check if the workspace already exist (UC: partial restore) + String[] allWsp = wsp.getAccessibleWorkspaceNames(); + boolean isCreated = false; + + for (int i = 0; i < allWsp.length; i++) { + if (this.wspName.equals(allWsp[i])) { + isCreated = true; + break; + } + } + + if (!isCreated) { + ((WorkspaceImpl) wsp).createWorkspace(this.wspName, xml); + } + + h.read("export_"+ this.wspName +".xml", temp); + + SessionImpl s2 = (SessionImpl) this.getRepo().login(this.getCredentials(), this.wspName); + + FileInputStream iTemp = new FileInputStream(temp); + + //TODO add a parameter in the conf file to manage UUIDBehavior + s2.importXML("/", iTemp, 0); + } + finally { + wspXml.delete(); + temp.delete(); + } + + } - + } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceConfigBackup.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceConfigBackup.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceConfigBackup.java (working copy) @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; +import java.util.zip.ZipException; import javax.jcr.LoginException; import javax.jcr.RepositoryException; @@ -22,12 +23,13 @@ import javax.jcr.LoginException; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.SimpleCredentials; + import org.apache.jackrabbit.core.RepositoryImpl; import org.apache.jackrabbit.core.WorkspaceImpl; +import org.apache.jackrabbit.core.config.ConfigurationException; +import org.apache.jackrabbit.core.config.RepositoryConfig; import org.apache.jackrabbit.core.config.WorkspaceConfig; -import org.apache.jackrabbit.backup.Backup; /** * @author ntoper @@ -35,9 +37,8 @@ */ public class WorkspaceConfigBackup extends Backup { - private static int called = 0; private String wspName; - + /** * @param repo * @param conf @@ -44,13 +45,13 @@ * @throws RepositoryException * @throws LoginException */ - public WorkspaceConfigBackup(RepositoryImpl repo, BackupConfig conf, String name) throws LoginException, RepositoryException { - super(repo, conf); + public WorkspaceConfigBackup(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + super(repo, conf, login, password); this.wspName = name; } - public void init(RepositoryImpl repo, BackupConfig conf, String name) throws LoginException, RepositoryException { - super.init(repo, conf); + public void init(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + super.init(repo, conf, login, password); this.wspName = name; } @@ -63,15 +64,14 @@ */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { - Session s = repo.login(new SimpleCredentials(this.conf.getLogin(), this.conf.getPassword().toCharArray()), this.wspName); - + Session s = this.getRepo().login(this.getCredentials(), this.wspName); + WorkspaceImpl wsp = (WorkspaceImpl) s.getWorkspace(); WorkspaceConfig c = wsp.getConfig(); - + String home = c.getHomeDir(); File wspXml = new File (home + "/workspace.xml"); - h.write("WspConf" + called , wspXml); - called += 1; + h.write("WspConf_" + this.wspName , wspXml); } /* (non-Javadoc) @@ -77,9 +77,10 @@ /* (non-Javadoc) * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) */ - public void restore(BackupIOHandler h) { - // TODO Auto-generated method stub + public void restore(BackupIOHandler h) throws ConfigurationException, ZipException, IOException { + //Replace workspace.xml if needed + File wspXml = new File(this.getConf().getWorkFolder() + "/workspace.xml"); + h.read("WspConf_" + this.wspName, wspXml); } - } Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipBackupIOHandler.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipBackupIOHandler.java (revision 0) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipBackupIOHandler.java (revision 0) @@ -0,0 +1,195 @@ +/* + * 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.backup; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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.util.Enumeration; +import java.util.zip.CRC32; +import java.util.zip.CheckedInputStream; +import java.util.zip.Checksum; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +/** + * Question: ZipFile + * + * @author ntoper + * + */ +public class ZipBackupIOHandler implements BackupIOHandler { + + private static int BUFFER_SIZE = 1024; + + private File zip; + private FileOutputStream fout; + private ZipOutputStream zipOut; + + private FileInputStream fin; + private ZipInputStream zipIn; + + private boolean isBackup = false; + + + public ZipBackupIOHandler(String zipFile, boolean isBackup) throws IOException { + this.zip = new File(zipFile); + this.isBackup = isBackup; + + if (isBackup) { + this.fout = new FileOutputStream(this.zip); + this.zipOut = new ZipOutputStream(this.fout); + } + else { + this.fin = new FileInputStream(this.zip); + this.zipIn = new ZipInputStream(this.fin); + } + } + + public void close() throws IOException { + if (isBackup) { + zipOut.finish(); + zipOut.close(); + } + else { + zipIn.close(); + } + } + + /** + * Create a directory per resources + * Backup the resource and zip it + * @param string + * @param content + */ + public void write(String name, File f) throws IOException { + zipOut.flush(); + ZipEntry e = new ZipEntry(name); + zipOut.putNextEntry(e); + + Checksum crc = new CRC32(); + CheckedInputStream i = new CheckedInputStream(new FileInputStream(f), crc); + + byte[] buffer = new byte[BUFFER_SIZE]; + int len; while ( (len = i.read(buffer, 0, BUFFER_SIZE)) != -1) { + zipOut.write(buffer, 0, len); + } + + //Checksum management + // TODO Is crc up to date? To be checked... + long check = crc.getValue(); + e.setCrc(check); + zipOut.closeEntry(); + } + + /** + * + * TODO: refactor this method with the one upper. + * + * + * Used for small I/O operations (no NIO used there). Take a file and zip it. + * + * Most I/O operations are operated on RAM. + * + */ + public void write(String name, ByteArrayOutputStream fos) throws IOException { + zipOut.flush(); + ZipEntry e = new ZipEntry(name); + zipOut.putNextEntry(e); + + Checksum crc = new CRC32(); + + InputStream io = new ByteArrayInputStream(fos.toByteArray()); + + CheckedInputStream i = new CheckedInputStream(io, crc); + + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ( (len = i.read(buffer, 0, BUFFER_SIZE)) != -1) { + zipOut.write(buffer, 0, len); + } + + //Checksum management + // TODO Is crc up to date? To be checked... + long check = crc.getValue(); + e.setCrc(check); + zipOut.closeEntry(); + } + + public byte[] read(String zipEntry) throws ZipException, IOException { + ZipFile zf = new ZipFile(this.zip); + ZipEntry ze = new ZipEntry(zipEntry); + long crc1 = ze.getCrc(); + + Checksum chkCrc2 = new CRC32(); + InputStream is = zf.getInputStream(ze); + CheckedInputStream cis = new CheckedInputStream(is, chkCrc2); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ( (len = cis.read(buffer, 0, BUFFER_SIZE)) != -1) { + os.write(buffer, 0, len); + } + //TODO check CRC + /* if (crc1 == chkCrc2.getValue()) {*/ + return os.toByteArray(); +/* } + else { + throw new ZipException(); + }*/ + } + + //TODO Refactor: the two upper are the same!! + quite similar to Backup + public void read(String zipEntry, File myFile) throws ZipException, IOException { + ZipFile zf = new ZipFile(this.zip); + ZipEntry ze = new ZipEntry(zipEntry); + //TODO check CRC + + Checksum chkCrc2 = new CRC32(); + InputStream is = zf.getInputStream(ze); + CheckedInputStream cis = new CheckedInputStream(is, chkCrc2); + + OutputStream os = new FileOutputStream(myFile); + + + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ( (len = cis.read(buffer, 0, BUFFER_SIZE)) != -1) { + os.write(buffer, 0, len); + } + + /* if (!(crc1 == chkCrc2.getValue())) { + System.out.println("crc1:" + crc1 + "a crc2:"+ chkCrc2.getValue() ); + throw new ZipException(); + }*/ + } + + public Enumeration getEntries() throws ZipException, IOException { + ZipFile zf = new ZipFile(this.zip); + return zf.entries(); + } +} Index: /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipFileBackupIOHandler.java =================================================================== --- /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipFileBackupIOHandler.java (revision 428521) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipFileBackupIOHandler.java (working copy) @@ -1,161 +0,0 @@ -/* - * 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.backup; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Array; -import java.util.zip.CRC32; -import java.util.zip.CheckedInputStream; -import java.util.zip.Checksum; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * Question: ZipFile - * - * @author ntoper - * - */ -public class ZipFileBackupIOHandler implements BackupIOHandler { - - private static int BUFFER_SIZE = 1024; - - private File zip; - // private FileInputStream fin; - // private ByteBuffer buffer; - private FileOutputStream fout; - private ZipOutputStream zipOut; - - - public ZipFileBackupIOHandler(String zipFile) throws FileNotFoundException { - this.zip = new File(zipFile); - // this.buffer = ByteBuffer.allocateDirect(2048); - } - - public void close() throws IOException { - zipOut.finish(); - zipOut.close(); - } - - /// private void init() { - //Useful? - // this.buffer.clear(); - //} - - public void initBackup() throws IOException { - boolean a = this.zip.createNewFile(); - - if (!a) { - throw new IOException(); - } - - this.fout = new FileOutputStream(this.zip); - this.zipOut = new ZipOutputStream(this.fout); - } - - public void initRestore() throws FileNotFoundException { - // this.fin = new FileInputStream(this.zip); - // this.fcin = this.fin.getChannel(); - //Restore zipFile - } - - /** - * Create a directory per resources - * Backup the resource and zip it - * @param string - * @param content - */ - /*private void writeFile(String string, String content) { - File conf = new File(); - FileWriter fw = new FileWriter(cheminAbstraitSortie); - BufferedWriter tamponEcriture = new BufferedWriter(fluxEcritureTexte); - tamponEcriture.write(xml); - tamponEcriture.flush(); - tamponEcriture.close(); - - } */ - - public void read() { - } - - - public void write(String name, File f) throws IOException { - zipOut.flush(); - ZipEntry e = new ZipEntry(name); - zipOut.putNextEntry(e); - - Checksum crc = new CRC32(); - CheckedInputStream i = new CheckedInputStream(new FileInputStream(f), crc); - - byte[] buffer = new byte[BUFFER_SIZE]; - - int len; - while ( (len = i.read(buffer, 0, BUFFER_SIZE)) != -1) { - zipOut.write(buffer,0, len); - } - - //Checksum management - // TODO Is crc up to date? To be checked... - long check = crc.getValue(); - e.setCrc(check); - zipOut.closeEntry(); - } - - - /** - * - * TODO: refactor this method with the one upper. - * - * - * Used for small I/O operations (no NIO used there). Take a file and zip it. - * - * Most I/O operations are operated on RAM. - * - */ - public void write(String name, ByteArrayOutputStream fos) throws IOException { - zipOut.flush(); - ZipEntry e = new ZipEntry(name); - zipOut.putNextEntry(e); - - Checksum crc = new CRC32(); - - InputStream io = new ByteArrayInputStream(fos.toByteArray()); - - CheckedInputStream i = new CheckedInputStream(io, crc); - - byte[] buffer = new byte[BUFFER_SIZE]; - int len; - while ( (len = i.read(buffer, 0, BUFFER_SIZE)) != -1) { - zipOut.write(buffer,0, len); - } - - //Checksum management - // TODO Is crc up to date? To be checked... - long check = crc.getValue(); - e.setCrc(check); - zipOut.closeEntry(); - } - - -} Index: /home/ntoper/workspace/backup/src/test/backup.xml =================================================================== --- /home/ntoper/workspace/backup/src/test/backup.xml (revision 428521) +++ /home/ntoper/workspace/backup/src/test/backup.xml (working copy) @@ -4,10 +4,10 @@ + - - + Index: /home/ntoper/workspace/backup/src/test/java/org/apache/jackrabbit/backup/BackupTest.java =================================================================== --- /home/ntoper/workspace/backup/src/test/java/org/apache/jackrabbit/backup/BackupTest.java (revision 428521) +++ /home/ntoper/workspace/backup/src/test/java/org/apache/jackrabbit/backup/BackupTest.java (working copy) @@ -18,8 +18,8 @@ package org.apache.jackrabbit.backup; import javax.jcr.*; -import javax.jcr.nodetype.NodeTypeManager; +import org.apache.jackrabbit.core.NamespaceRegistryImpl; import org.apache.jackrabbit.core.TransientRepository; import org.apache.jackrabbit.core.WorkspaceImpl; import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; @@ -26,7 +26,10 @@ import org.apache.jackrabbit.core.nodetype.NodeTypeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.NameFormat; import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.UnknownPrefixException; import java.io.File; import java.io.FileInputStream; @@ -38,7 +41,7 @@ * and outputs the contents of the entire workspace. */ public class BackupTest { - + /** Runs the ThirdHop example. */ public static void main(String[] args) throws Exception { // Set up a Jackrabbit repository with the specified @@ -44,14 +47,14 @@ // Set up a Jackrabbit repository with the specified // configuration file and repository directory Repository repository = new TransientRepository(); - + // Login to the default workspace as a dummy user Session session = repository.login( - new SimpleCredentials("username", "password".toCharArray())); + new SimpleCredentials("username", "password".toCharArray())); try { // Use the root node as a starting point Node root = session.getRootNode(); - + // Import the XML file unless already imported if (!root.hasNode("importxml")) { System.out.print("Importing xml... "); @@ -60,7 +63,7 @@ // Import the file "test.xml" under the created node FileInputStream xml = new FileInputStream("src/test/test.xml"); session.importXML( - "/importxml", xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); + "/importxml", xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); xml.close(); // Save the changes to the repository session.save(); @@ -74,7 +77,7 @@ n.setProperty("anyProperty", "Blah"); session.save(); n.checkin(); - + //add new version Node child = root.getNode("childNode"); child.checkout(); @@ -82,6 +85,11 @@ session.save(); child.checkin(); + //Register a namespace if not already existing + NamespaceRegistryImpl nr = (NamespaceRegistryImpl) session.getWorkspace().getNamespaceRegistry(); + if (!nr.isRegistered("backup_example")) { + nr.registerNamespace("backup_example","http://www.deviant-abstraction.net"); + } //Creating a second workspace Workspace wsp = session.getWorkspace(); String[] allWsp = wsp.getAccessibleWorkspaceNames(); @@ -88,7 +96,7 @@ if (allWsp.length < 2) { ((WorkspaceImpl)wsp).createWorkspace("secondTest"); - session.logout(); + Session session2 = repository.login(new SimpleCredentials("username", "password".toCharArray()), "secondTest"); root = session2.getRootNode(); @@ -99,19 +107,16 @@ // Import the file "test.xml" under the created node FileInputStream xml = new FileInputStream("src/test/test.xml"); session2.importXML( - "/importxml", xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); + "/importxml", xml, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW); xml.close(); // Save the changes to the repository session2.save(); - System.out.println("done."); - + session2.logout(); + System.out.println("done."); } - - //Registering a NodeType - /* System.out.print("Registering a test nodeType...\r\n "); - + System.out.print("Registering a test nodeType...\r\n "); NodeTypeDef ntd = new NodeTypeDef(); ntd.setMixin(true); ntd.setName(new QName("http://www.jcp.org/jcr/nt/1.0", "example")); @@ -116,9 +121,9 @@ ntd.setMixin(true); ntd.setName(new QName("http://www.jcp.org/jcr/nt/1.0", "example")); registerNodeType(ntd, session); - - */ - + session.save(); + session.logout(); + System.out.print("Launching backup...\r\n "); /* Tested params: @@ -132,8 +137,20 @@ String[] argsBackup ="--zip myzip.zip --login username --password password --conf src/test/backup.xml backup repository.xml repository/".split(" "); LaunchBackup.main(argsBackup); System.out.print("Backup done. "); + + //Launching restore in another repository instance + + //Delete all previous resource + File f = new File("repository2.xml"); + f.delete(); + + File f1 = new File("repository2/"); + deleteDir(f1); + f1.delete(); - + String[] argsBackup1 ="--zip myzip.zip --login username --password password restore repository2.xml repository2/".split(" "); + LaunchBackup.main(argsBackup1); + System.out.print("Restore done. "); } finally { session.logout(); } @@ -138,19 +155,39 @@ session.logout(); } } - - private static void registerNodeType(NodeTypeDef nodeTypeDef, Session session) throws RepositoryException, InvalidNodeTypeDefException + + private static void registerNodeType(NodeTypeDef nodeTypeDef, Session session) throws RepositoryException, InvalidNodeTypeDefException, IllegalNameException, UnknownPrefixException { //NodeTypeRegistry object Workspace wsp = session.getWorkspace(); - NodeTypeManager ntMgr = wsp.getNodeTypeManager(); + NodeTypeManagerImpl ntMgr = (NodeTypeManagerImpl) wsp.getNodeTypeManager(); + //non-JSR 170 - jackrabbit specific NodeTypeRegistry ntReg = - ((NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry(); + ((NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry(); - ntReg.registerNodeType(nodeTypeDef); + if (!ntReg.isRegistered(nodeTypeDef.getName())) + ntReg.registerNodeType(nodeTypeDef); } - - + + // Deletes all files and subdirectories under dir. + // Returns true if all deletions were successful. + // If a deletion fails, the method stops attempting to delete and returns false. + public static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i=0; i