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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/AllWorkspacesBackup.java (working copy) @@ -29,7 +29,7 @@ import org.apache.jackrabbit.core.RepositoryImpl; /** - * This class allows the backup and restore of all the worskspaces. + * This class allows to backup and restore of all worskspaces. * */ public class AllWorkspacesBackup extends Backup { @@ -35,15 +35,17 @@ public class AllWorkspacesBackup extends Backup { /** - * @param repo the repository - * @param conf the BackupConfig object holding all informations about the backup/restore operations - * @param login - * @param password - * @throws RepositoryException - * @throws LoginException + * Constructor. + * + * @param login login to access the repositorye + * @param password password to access the repository + * @param repo The repository to backup + * @param conf The specific BackupConfig object (usually a subset of backup.xml) + * @throws RepositoryException in case of all other error. + * @throws LoginException if the login/pass is incorrect. */ - public AllWorkspacesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) - throws LoginException, RepositoryException { + public AllWorkspacesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); } @@ -48,35 +50,36 @@ } /** - * Constructor used by BackupManager. - * + * Constructed used by BackupManager */ protected AllWorkspacesBackup() { - super(); + super(); } - - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ - public void backup(BackupIOHandler h) throws RepositoryException, - IOException { - Session s = this.getSession(); - Workspace wsp = s.getWorkspace(); - String[] allWsp = wsp.getAccessibleWorkspaceNames(); - String login = this.getCredentials().getUserID(); - String password = this.getCredentials().getPassword().toString(); + public void backup(BackupIOHandler h) throws RepositoryException, IOException { + 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.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); - } + for (int i = 0; i < allWsp.length; 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); + } } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws ZipException, IOException, LoginException, RepositoryException { //Get All workspaces name in the zip @@ -93,7 +96,8 @@ //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); + WorkspaceConfigBackup wspConfb = new WorkspaceConfigBackup(this.getRepo(), + this.getConf(), name, login, password); wspConfb.restore(h); //Restore the content @@ -102,5 +106,4 @@ } } } - } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/Backup.java (working copy) @@ -34,20 +34,38 @@ */ public abstract class Backup { + /** + * We need to access the current repository. If we restore the backup conf or the + * repository this attribute can be null. + */ private RepositoryImpl repo; + + /** + * conf contains all the parameters needed to access + * the backup. + */ private BackupConfig conf; - private Session session;; + + /** + * The current session we use + * to access the repository. + */ + private Session session; + + /** + * The current credentials + */ private SimpleCredentials credentials; /** - * @param login - * @param password + * @param login the current login + * @param password the current password * @param repo The repository to backup * @param conf The specific BackupConfig object (usually a subset of backup.xml) - * @throws RepositoryException - * @throws LoginException + * @throws RepositoryException in case of any error + * @throws LoginException if the login or password is incorrect */ - public Backup(RepositoryImpl repo, BackupConfig conf, String login, String password) + public Backup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { this.repo = repo; this.conf = conf; @@ -60,12 +78,12 @@ */ protected Backup() { } - + /** * This constructor is used explicitly for restore operations - * - * @param login - * @param password + * + * @param login login to use + * @param password password to use */ protected Backup(String login, String password) { this.credentials = new SimpleCredentials(login, password.toCharArray()); @@ -73,15 +91,16 @@ /** * Used by BackupManager with the empty constructor. * - * @param repo - * @param conf - * @param login - * @param password - * @throws LoginException - * @throws RepositoryException + * @param login the current login + * @param password the current password + * @param repo The repository to backup + * @param conf The specific BackupConfig object (usually a subset of backup.xml) + * @throws RepositoryException in case of any error + * @throws LoginException if the login or password is incorrect */ - protected void init(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + protected void init(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { this.repo = repo; this.conf = conf; this.credentials = new SimpleCredentials(login, password.toCharArray()); @@ -88,12 +107,21 @@ this.session = this.repo.login(this.credentials); } + /** + * getter. + * @return RepositoryImpl current repository + */ public RepositoryImpl getRepo() { return this.repo; } + /** + * setter. Used only when restoring the repository. + * @param repo RepositoryImpl + */ protected void setRepo(RepositoryImpl repo) { this.repo = repo; + //TODO move this method in only the few classes using it. } /* @@ -110,11 +138,9 @@ */ /** * Backup the resource designated by this class to h from the current repository - * @param h - * @throws FileNotFoundException - * @throws RepositoryException - * @throws IOException - * + * @param h the current BackupIOHandler + * @throws RepositoryException in case of any error. + * @throws IOException if any issue with the BackupIOHandler */ public abstract void backup(BackupIOHandler h) throws RepositoryException, IOException; @@ -120,11 +146,11 @@ /** * Restore the resource designated by this class from h to the current repository - * @param h - * @throws FileNotFoundException - * @throws RepositoryException - * @throws IOException - */ + * @param h the current BackupIOHandler + * @throws RepositoryException in case of any error. + * @throws IOException if any issue with the BackupIOHandler + * @throws FileNotFoundException if the file is not found... + */ public abstract void restore(BackupIOHandler h) throws FileNotFoundException, RepositoryException, IOException; protected Session getSession() { @@ -147,6 +173,9 @@ this.credentials = cred; } + /** + * This method ensure we log out of the session in all cases. + */ public void finalize() { this.session.logout(); } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfig.java (working copy) @@ -19,13 +19,10 @@ import java.io.File; import java.io.IOException; import java.net.URI; -import java.util.Collection; +import java.util.List; import java.util.Properties; - 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; @@ -39,14 +36,28 @@ */ public class BackupConfig { - //used to backup a workspace first in a backupFile + /** + * Working directory + */ private final File workFolder; - //Not final since BackupManager adds some resources - private Collection allResources; + + /** + * List of all backupping classes + * + * Not final since BackupManager adds some resources + */ + private List allResources; + + /** + * Backup config file + */ private final File backupFile; + + /** + * Repository config file + */ private final File repoConfFile; - /** * Parses the given repository configuration document and returns the * parsed and initialized repository configuration. The given repository @@ -62,13 +73,13 @@ * @param repoConfFile repository file configuration * @return repository configuration * @throws ConfigurationException on configuration errors - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws IOException + * @throws IllegalAccessException if illegalAccess + * @throws InstantiationException if the backupResources are incorrectly instantiated + * @throws ClassNotFoundException if the backupResources are not found. + * @throws IOException error with backupIOHandler in calling the files */ public static BackupConfig create(String myFile, String repoConfFile) - throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { + throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { URI uri = new File(myFile).toURI(); InputSource is = new InputSource(uri.toString()); BackupConfigurationParser parser = new BackupConfigurationParser(new Properties()); @@ -75,9 +86,16 @@ BackupConfig config = parser.parseBackupConfig(is, myFile, repoConfFile); return config; } - - public BackupConfig(File path, Collection allResources, String myFile, String repoConfFile) throws IOException { - + /** + * Constructor + * + * @param path Path of the working directory + * @param allResources List of classes of backupResource class + * @param myFile Path to the backup config file + * @param repoConfFile Path to the repository config file + * @throws IOException in case of error when accessing the file + */ + public BackupConfig(File path, List allResources, String myFile, String repoConfFile) throws IOException { //Logic application: not in the parser: this code has to be here if (!(path.isDirectory() && path.canWrite())) { //if path not set in the conf file then create one as the current dir @@ -90,7 +108,7 @@ this.repoConfFile = new File(repoConfFile); } - public Collection getAllResources() { + public List getAllResources() { return allResources; } @@ -102,7 +120,6 @@ return workFolder; } - public File getFile() { return this.backupFile; } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationBackup.java (working copy) @@ -34,19 +34,24 @@ public class BackupConfigurationBackup extends Backup { /** - * @param repo - * @param conf - * @param login - * @param password - * @throws RepositoryException - * @throws LoginException + * Constructor + * + * @param repo RepositoryImpl + * @param conf BackupConfig + * @param login login String + * @param password String + * @throws RepositoryException if there is an issue with the repository + * @throws LoginException if there is an issue with login/pass */ - public BackupConfigurationBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) - throws LoginException, RepositoryException { + public BackupConfigurationBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); - } + /** + * Empty constructor + * + */ protected BackupConfigurationBackup() { super(); } @@ -51,11 +56,11 @@ super(); } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, - IOException { + IOException { File file = this.getConf().getFile(); h.write("backup.xml", file); } @@ -60,11 +65,8 @@ h.write("backup.xml", file); } - /* (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) + /** + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws ZipException, IOException { File conf = new File("backup.xml"); 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupConfigurationParser.java (working copy) @@ -18,8 +18,8 @@ import java.io.File; import java.io.IOException; -import java.util.Collection; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.Vector; @@ -44,11 +44,11 @@ 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. - //TODO Add UUID choice + //TODO Add UUIDBehavior choice /** - * @param variables + * @param variables Properties. Usually null */ public BackupConfigurationParser(Properties variables) { super(variables); @@ -61,13 +61,13 @@ * * @param xml repository configuration document * @param myFile path and name of the XML configuration file (TODO delete XML argument and build it with myFile) - * @param repoConfFile: path and name of the repository configuration file + * @param repoConfFile path and name of the repository configuration file * @return repository configuration * @throws ConfigurationException if the configuration is broken - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws IOException + * @throws IllegalAccessException if the login/password is incorrect + * @throws InstantiationException if we cannot instantiate the classes in the backup conf file + * @throws ClassNotFoundException if we cannot find the classes in the backup conf file + * @throws IOException in case of IO issues... * @see #parseBeanConfig(Element, String) * @see #parseVersioningConfig(Element) */ @@ -82,7 +82,7 @@ //Management of resources tag Element resources = this.getElement(root, RESOURCES); - Collection allResources = this.parseResourcesConfig(resources); + List allResources = this.parseResourcesConfig(resources); return new BackupConfig(path, allResources, myFile, repoConfFile); } @@ -106,7 +106,7 @@ selected.addElement((Element) child); } } - if (selected.size() == 0){ + if (selected.size() == 0) { return null; } else { @@ -120,15 +120,15 @@ * Be careful the objects aren't properly initialized yet. You need to call init (in BackupManager). * * Pre-condition: there are resource tags in the conf file (otherwise there is a problem in the backup) - * @root root Element of the XML - * @throws ConfigurationException - * @throws ClassNotFoundException - * @throws InstantiationException - * @throws IllegalAccessException + * @param root Element of the XML + * @throws ConfigurationException if configuration issue + * @throws ClassNotFoundException if the class defined in the config file is not found + * @throws InstantiationException if the class cannot be instantiated + * @throws IllegalAccessException if issue with login/password * @return Collection of all resources to backup found in the file */ - private Collection parseResourcesConfig(Element root) - throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException { + private List parseResourcesConfig(Element root) + throws ConfigurationException, ClassNotFoundException, InstantiationException, IllegalAccessException { /* * For each resource @@ -134,7 +134,7 @@ * For each resource * get class and instantiate */ - Vector objects = new Vector(); + LinkedList objects = new LinkedList(); Vector resources = (Vector) this.getElements(root, RESOURCE); Iterator it = resources.iterator(); @@ -145,8 +145,8 @@ String savingClass = resource.getAttribute(SAVING_CLASS); //Check we are not backupping/restoring a resource already backuped by BackupManager - if (savingClass.equals("org.apache.jackrabbit.backup.RepositoryBackup") || - savingClass.equals("org.apache.jackrabbit.backup.BackupConfigBackup")) { + if (savingClass.equals("org.apache.jackrabbit.backup.RepositoryBackup") + || savingClass.equals("org.apache.jackrabbit.backup.BackupConfigBackup")) { throw new IllegalAccessException(); } @@ -151,7 +151,7 @@ } Class c = Class.forName(savingClass); - objects.addElement( (Backup) c.newInstance()); + objects.add( (Backup) c.newInstance()); } return objects; } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupIOHandler.java (working copy) @@ -28,10 +28,58 @@ * */ public interface BackupIOHandler { + /** + * Close the Handler + * + * @throws IOException if IO error + */ void close() throws IOException; + + /** + * Write to a zipEntry called name from the File f + * + * @param name the name of the zipEntry (will be created) + * @param f the file to copy + * @throws IOException if IO error + */ void write(String name, File f) throws IOException; + + /** + * Write to a zipEntry called name from the ByteArray. + * Stream fos + * @param name the name of the zipEntry (will be created) + * @param fos the ByteArrayOutputStream + * @throws IOException if IO error + */ void write(String name, ByteArrayOutputStream fos) throws IOException; + + /** + * Read a zipEntry and return its content into a byte array.Z + * Useful for small files to store. + * + * @param zipEntry the zipEntry to read + * @return byte[] + * @throws ZipException if Zip error + * @throws IOException if IO error + */ byte[] read(String zipEntry) throws ZipException, IOException; - public void read(String zipEntry, File myFile) throws ZipException, IOException; + + /** + * Read a zipEntry and store its content into a file. + * + * @param zipEntry the zipEntry to read + * @param myFile the file where to store the content + * @throws ZipException if zip error + * @throws IOException if IO error + */ + void read(String zipEntry, File myFile) throws ZipException, IOException; + + /** + * + * Get the entries of the zip file. Used for restore only + * @throws ZipException if zip error + * @throws IOException if IO Exception + * @return Enumeration of all entries in zip + */ 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/BackupManager.java (working copy) @@ -20,6 +20,8 @@ import java.io.IOException; import java.util.Collection; import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; import javax.jcr.LoginException; import javax.jcr.RepositoryException; @@ -27,8 +29,8 @@ import org.apache.jackrabbit.core.RepositoryImpl; /** - * This class manages the backup/restore process. It is responsible to send to/fetch from the BackupIOHandler and to add the repository to the - * BackupConfig. + * This class manages the backup/restore process. It is responsible to send to/fetch + * from the BackupIOHandler and to add the repository to the BackupConfig. * * It extends Backup since it is based on the same semantics. However it is not the same type as a ResourceBackup * (the different semantics are indicated by different names) @@ -40,11 +42,19 @@ */ public class BackupManager extends Backup { - - public BackupManager(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + /** + * Constructor + * + * @param repo RepositoryImpl + * @param conf BackupConfig + * @param login String + * @param password String + * @throws LoginException if issue with login/pass + * @throws RepositoryException in case of any error + */ + 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.getConf().getAllResources().iterator(); while ( it.hasNext() ) { @@ -53,6 +63,10 @@ } } + /** + * Empty constructor + * + */ public BackupManager() { super(); } @@ -57,19 +71,24 @@ super(); } + /** + * Create the backupManager object. + * + * @param impl RepositoryImpl + * @param conf2 BackupConfig + * @param login String + * @param password String + * @return BackupManager + * @throws LoginException if error when login + * @throws RepositoryException if any other error + */ + public static BackupManager create(RepositoryImpl impl, BackupConfig conf2, String login, String password) + throws LoginException, RepositoryException { + return new BackupManager(impl, conf2, login, password); + } - 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. - * This class stores the backup config file also. (simplify its fetching and logical since it's not a configurable resource) - * - * - * @param The BackupIOHandler where the backup will be saved - * @throws RepositoryException - * @throws IOException - * + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { /* This method calls alternatively each backup method of each Backup. @@ -95,11 +114,13 @@ h.close(); } } + /** - * TODO commment - * @param backup - * @throws RepositoryException - * @throws LoginException + * Class to add a resource to the backup/restore + * + * @param backup The backup class to add + * @throws RepositoryException in case of any error + * @throws LoginException in case of login error */ private void addResource(Backup backup) throws LoginException, RepositoryException { String login = this.getCredentials().getUserID(); @@ -109,12 +130,7 @@ } /** - * Same method as backup but for restore. - * TODO Comment - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws RepositoryException, IOException { @@ -130,16 +146,17 @@ * */ try { - Collection resources = this.getConf().getAllResources(); - Iterator it = resources.iterator(); + List resources = this.getConf().getAllResources(); + + ListIterator it = resources.listIterator(); - while (it.hasNext()) { - Backup b = (Backup) it.next(); - b.restore(h); - } - } - finally { - h.close(); - } - } + 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/LaunchBackup.java (working copy) @@ -36,12 +36,7 @@ * Date: 23-jun-06 */ public class LaunchBackup { - /** - * TODO where can I find the generic repository.xml? - * Path to the generic repository.xml - */ - private static final String REPOSITORY_XML = "/home/ntoper/workspace/backup/"; /** * The backupIOHandler used to handle IO @@ -57,7 +52,7 @@ * The backupconfig object. */ private BackupConfig conf; - + /** * The repositoryConfig object. */ @@ -73,9 +68,8 @@ * The command line tool. * * 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) @@ -89,16 +83,16 @@ * * * --help for help option - * - * @throws RepositoryException - * @throws IOException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws AccessDeniedException - * @throws IOException + * @param args List of arguments + * @throws RepositoryException if any error + * @throws IOException if error in reading/writing an input/output file + * @throws IllegalAccessException if issue with login/password + * @throws InstantiationException if issue with classes contained in the XML config file + * @throws ClassNotFoundException if issue with classes contained in the XML config file + * @throws AccessDeniedException if issue with login/password */ - public static void main(String[] args) throws RepositoryException, AccessDeniedException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { + 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. String zipFile = null; String confFile = null; @@ -197,17 +191,21 @@ } /** - * Constructor of LaunchBackup. Initiate the repository. + * Constructor * - * @param String repoConfFile: name of the configuration file - * @throws RepositoryException - * @throws IllegalAccessException - * @throws InstantiationException - * @throws ClassNotFoundException - * @throws IOException - * + * @param repoConfFile Path to the repository configuration file + * @param home Path to the repository home + * @param backupConfFile Path to the backup file (to be created or to read) + * @param login login used with access to all workspaces + * @param password password associated with login + * @throws RepositoryException if any error + * @throws IOException if error in reading/writing an input/output file + * @throws IllegalAccessException if issue with login/password + * @throws InstantiationException if issue with classes contained in the XML config file + * @throws ClassNotFoundException if issue with classes contained in the XML config file */ - public LaunchBackup(String repoConfFile, String home, String backupConfFile, String login, String password) throws RepositoryException, ClassNotFoundException, InstantiationException, IllegalAccessException, 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); @@ -224,19 +222,18 @@ * 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 - * + * @param repoConfFile Path to the repository configuration file + * @param home Path to the repository home + * @param login login used with access to all workspaces + * @param password password associated with login + * @throws RepositoryException if any error + * @throws IOException if error in reading/writing an input/output file + * @throws IllegalAccessException if issue with login/password + * @throws InstantiationException if issue with classes contained in the XML config file + * @throws ClassNotFoundException if issue with classes contained in the XML config file */ - public LaunchBackup(String repoConfFile, String home, String login, String password) throws RepositoryException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException { + 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. @@ -280,7 +277,10 @@ /** * Backup a repository * - * @param BackupIOHandler h a reference where to backup + * @param h BackupIOHandler a reference where to backup + * @throws AccessDeniedException if issue with login/password + * @throws RepositoryException if any other issue + * @throws IOException if any issue with h. */ public void backup(BackupIOHandler h) throws AccessDeniedException, RepositoryException, IOException { this.backup.backup(h); @@ -287,13 +287,13 @@ } /** - *Restore a repository - * - * @param BackupIOHandler h a reference to the backup to restore - * @throws IOException - * @throws RepositoryException - * @throws IllegalAccessException - */ + * Restore a repository + * + * @param h BackupIOHandler a reference where to backup + * @throws IllegalAccessException if issue with login/password + * @throws RepositoryException if any other issue + * @throws IOException if any issue with h. + */ public void restore(BackupIOHandler h) throws RepositoryException, IOException, IllegalAccessException { this.backup.restore(h); } @@ -298,6 +298,10 @@ this.backup.restore(h); } + /** + * We have to shut down the repository at the end of + * the restore/backup. + */ private void shutdown() { 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NamespaceBackup.java (working copy) @@ -25,7 +25,6 @@ import java.util.HashMap; import javax.jcr.LoginException; -import javax.jcr.NamespaceException; import javax.jcr.NamespaceRegistry; import javax.jcr.RepositoryException; import javax.jcr.Session; @@ -38,9 +37,9 @@ /** * This class handles backup of the namespaces of the repository. - * + * * This class needs to be serializable so the internal class can be serialized (does anybody know why?) - * + * * @author ntoper * */ @@ -45,16 +44,16 @@ * */ public class NamespaceBackup extends Backup implements Serializable { - + /** - * + * */ 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) - * + * */ private class Namespaces implements Serializable { @@ -79,42 +78,46 @@ } } + /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * Constructor + * + * @param repo RepositoryImpl + * @param conf BackupConfig + * @param login String + * @param password String + * @throws LoginException if issue with login/pass + * @throws RepositoryException in case of any error */ - public NamespaceBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + public NamespaceBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); } - public NamespaceBackup() { + /** + * Constructor for reflection. + */ + public NamespaceBackup() { super(); } - /* (non-Javadoc) - * TODO where do I find the local ns? - * TODO use a ByteArrayOutputStream? - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { - + Session s = this.getSession(); Workspace wsp = s.getWorkspace(); NamespaceRegistry ns = wsp.getNamespaceRegistry(); - Namespaces myNs = new Namespaces(); - String[] allPrefixes = ns.getPrefixes(); - + for (int i = 0; i < allPrefixes.length; i++) { String prefix = allPrefixes[i]; - myNs.addNamespace(ns.getURI(prefix),prefix); + myNs.addNamespace(ns.getURI(prefix), prefix); } - + String name = this.getClass().toString(); - ByteArrayOutputStream fos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(myNs); @@ -120,9 +123,9 @@ oos.writeObject(myNs); h.write(name, fos); } - - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) + + /** + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws RepositoryException, IOException { String name = this.getClass().toString(); @@ -129,15 +132,15 @@ byte[] ns = h.read(name); ByteArrayInputStream bis = new ByteArrayInputStream(ns); ObjectInputStream ois = new ObjectInputStream(bis); - + try { Namespaces allNs = (Namespaces) ois.readObject(); String[] allUri = allNs.getAllUri(); - + Session s = this.getSession(); Workspace wsp = s.getWorkspace(); NamespaceRegistryImpl nsr = (NamespaceRegistryImpl) wsp.getNamespaceRegistry(); - + for (int i = 0; i < allUri.length; i++) { nsr.safeRegisterNamespace(allNs.getPrefix(allUri[i]), allUri[i]); } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeTypeBackup.java (working copy) @@ -16,7 +16,6 @@ */ package org.apache.jackrabbit.backup; -import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -42,7 +41,7 @@ import org.apache.jackrabbit.name.UnknownPrefixException; /** - * @author ntoper + * Backup and restore the NodeType * */ public class NodeTypeBackup extends Backup { @@ -48,15 +47,20 @@ public class NodeTypeBackup extends Backup { /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * @param repo The current RepositoryImpl + * @param conf the current BackupConf + * @param login the login + * @param password the password + * @throws RepositoryException if any issue + * @throws LoginException if the login/pass is incorrect */ - public NodeTypeBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + public NodeTypeBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); } - + /** + * Empty constructor to use with reflexion + */ public NodeTypeBackup() { super(); } @@ -61,8 +65,8 @@ super(); } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws IOException, RepositoryException { Session s = this.getSession(); @@ -79,9 +83,9 @@ /** * Returns the nodes types definitions of all registered node types. - * + * @param ntreg the NodeTypeRegistry * @return the node type definition of all registered node types. - * @throws NoSuchNodeTypeException + * @throws NoSuchNodeTypeException if one of the node doesn't exist */ private static NodeTypeDef[] getRegisteredNodesTypesDefs(NodeTypeRegistry ntreg) throws NoSuchNodeTypeException { QName[] qn = ntreg.getRegisteredNodeTypes(); @@ -87,7 +91,7 @@ QName[] qn = ntreg.getRegisteredNodeTypes(); NodeTypeDef[] ntd = new NodeTypeDef[qn.length]; - for (int i=0; i < qn.length; i++) { + for (int i = 0; i < qn.length; i++) { ntd[i] = ntreg.getNodeTypeDef(qn[i]); } @@ -94,8 +98,9 @@ return ntd; } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) + + /** + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws ZipException, IOException, RepositoryException { @@ -117,8 +122,6 @@ ntreg.registerNodeType(ntds[i]); } } - NamespaceRegistry ns = wsp.getNamespaceRegistry(); - } catch (IllegalNameException e) { new RepositoryException(); } catch (UnknownPrefixException e) { 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/NodeVersionHistoriesBackup.java (working copy) @@ -20,67 +20,50 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipException; -import javax.jcr.AccessDeniedException; -import javax.jcr.InvalidSerializedDataException; -import javax.jcr.ItemExistsException; import javax.jcr.LoginException; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.lock.LockException; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.NodeDefinition; -import javax.jcr.version.VersionException; -import org.apache.jackrabbit.core.ItemImpl; -import org.apache.jackrabbit.core.ItemManager; -import org.apache.jackrabbit.core.NodeImpl; +import org.apache.jackrabbit.core.NamespaceRegistryImpl; import org.apache.jackrabbit.core.RepositoryImpl; import org.apache.jackrabbit.core.SessionImpl; -import org.apache.jackrabbit.core.nodetype.NodeDef; -import org.apache.jackrabbit.core.nodetype.NodeDefImpl; -import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl; -import org.apache.jackrabbit.core.nodetype.NodeTypeDef; +import org.apache.jackrabbit.core.WorkspaceImpl; import org.apache.jackrabbit.core.version.VersionManager; import org.apache.jackrabbit.core.version.VersionManagerImpl; -import org.apache.jackrabbit.core.xml.ImportHandler; -import org.apache.jackrabbit.core.xml.SessionImporter; -import org.apache.jackrabbit.name.MalformedPathException; -import org.apache.jackrabbit.name.Path; -import org.apache.jackrabbit.name.PathFormat; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.XMLReaderFactory; /** - * @author ntoper + * Backup and restore the NodeVersionHistory. The restore operation is a wrapper to + * the core which take care of the import. * + * The backup exports the versioning in systemView. */ public class NodeVersionHistoriesBackup extends Backup { - + /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * Constructor + * + * @param repo RepositoryImpl + * @param conf BackupConfig + * @param login login String + * @param password String + * @throws RepositoryException if there is an issue with the repository + * @throws LoginException if there is an issue with login/pass */ - public NodeVersionHistoriesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + public NodeVersionHistoriesBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); - // TODO Auto-generated constructor stub } - + + /** + * Empty constructor to use with reflexion. + */ public NodeVersionHistoriesBackup() { super(); - // TODO Auto-generated constructor stub } - - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { @@ -85,9 +68,8 @@ public void backup(BackupIOHandler h) throws RepositoryException, IOException { Session s = this.getSession(); - File temp = new File(this.getConf().getWorkFolder() + "history.xml"); - + try { FileOutputStream out = new FileOutputStream(temp); s.exportSystemView("/jcr:system/jcr:versionStorage", out, false, false); @@ -97,186 +79,16 @@ temp.delete(); } } - - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) - */ - /* public void restore(BackupIOHandler h) throws ZipException, IOException, RepositoryException { - SessionImpl s = (SessionImpl) this.getSession(); - VersionManagerImpl versionMgr = (VersionManager) s.getVersionManager(); - File temp = new File(this.getConf().getWorkFolder() + "history.xml"); - try { - h.read("history.xml", temp); - FileInputStream in = new FileInputStream(temp); - - // this.getRepo().importXML("/jcr:system/jcr:versionStorage", in, 0 ); - } - finally { - temp.delete(); - } - - - public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws RepositoryException, IOException { - - Path p = VersionManagerImpl.getVersionStoragePath(); - SessionImpl s = (SessionImpl) this.getSystemSession("default"); - - //this.getItem() - ItemImpl item = s.getItemManager().getItem(p); - NodeImpl parent = (NodeImpl) item; - SessionImporter importer = new SessionImporter(parent, s, 3); - ImportHandler handler = new ImportHandler(importer, s.getNamespaceResolver(), this.getNamespaceRegistry()); - - try { - XMLReader parser = - XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); - parser.setContentHandler(handler); - parser.setErrorHandler(handler); - // being paranoid... - parser.setFeature("http://xml.org/sax/features/namespaces", true); - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", - false); - - parser.parse(new InputSource(in)); - } catch (SAXException se) { - // check for wrapped repository exception - Exception e = se.getException(); - if (e != null && e instanceof RepositoryException) { - throw (RepositoryException) e; - } else { - String msg = "failed to parse XML stream"; - throw new InvalidSerializedDataException(msg, se); - } - } - - } - } - - SessionImpl s = (SessionImpl) this.getSession(); - Path p; - try { - p = PathFormat.parse("/jcr:system/jcr:versionStorage", s.getNamespaceResolver()).getNormalizedPath(); - } catch (MalformedPathException e) { - //Shouldn't happen or bug in the source code - throw new RepositoryException(); - } - ItemImpl item = s.getItemManager().getItem(p); - NodeImpl parent = (NodeImpl) item; - - //TODO Add a parameter to specify the UUIDBehavior? - SessionImporter importer = new SessionImporter(parent, s, 3); - ImportHandler handler = new ImportHandler(importer, s.getNamespaceResolver(), this.getRepo().getNamespaceRegistry()); - File temp = new File(this.getConf().getWorkFolder() + "history.xml"); - h.read("history.xml", temp); - FileInputStream in = new FileInputStream(temp); - - try { - XMLReader parser = - XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); - parser.setContentHandler(handler); - parser.setErrorHandler(handler); - // being paranoid... - parser.setFeature("http://xml.org/sax/features/namespaces", true); - parser.setFeature("http://xml.org/sax/features/namespace-prefixes", - false); - - parser.parse(new InputSource(in)); - } catch (SAXException se) { - // check for wrapped repository exception - Exception e = se.getException(); - if (e != null && e instanceof RepositoryException) { - throw (RepositoryException) e; - } else { - String msg = "failed to parse XML stream"; - throw new InvalidSerializedDataException(msg, se); - } - } finally { - temp.delete(); - } - - //TODO find a way to put /jcr:system/jcr:versionStorage probably by instanciating as a repo/wsp the versioning pm - File temp = new File(this.getConf().getWorkFolder() + "history.xml"); - SessionImpl s = (SessionImpl) this.getSession(); - - - Path p = null; - try { - p = PathFormat.parse("/jcr:system/jcr:versionStorage", s.getNamespaceResolver()).getNormalizedPath(); - } catch (MalformedPathException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - //Unprotect the tree... - - ItemImpl item = s.getItemManager().getItem(p); - - NodeImpl parent = (NodeImpl) item; - unprotect(parent); - - - - - try { - - h.read("history.xml", temp); - FileInputStream iTemp = new FileInputStream(temp); - s.importXML("/", iTemp, 0); - } catch (PathNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ItemExistsException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ConstraintViolationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (VersionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvalidSerializedDataException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (LockException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - - } - finally { - temp.delete(); - } - - - - - }*/ + /** + * {@inheritDoc} + */ public void restore(BackupIOHandler h) throws RepositoryException, IOException { File temp = new File(this.getConf().getWorkFolder() + "history.xml"); - SessionImpl s = (SessionImpl) this.getSession(); - - Path p = null; try { - p = PathFormat.parse("/jcr:system/jcr:versionStorage", s.getNamespaceResolver()).getNormalizedPath(); - } catch (MalformedPathException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - //Unprotect the tree... - - ItemImpl item = s.getItemManager().getItem(p); - - NodeImpl parent = (NodeImpl) item; - unprotect(parent); - - try { h.read("history.xml", temp); FileInputStream iTemp = new FileInputStream(temp); - s.importXML("/", iTemp, 0); - - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - + this.importXML(iTemp); } finally { temp.delete(); @@ -282,22 +94,21 @@ temp.delete(); } } - - - private static void unprotect(NodeImpl parent) throws RepositoryException { - NodeDefinitionImpl def = (NodeDefinitionImpl) parent.getDefinition(); - NodeDefImpl nd = (NodeDefImpl) def.unwrap(); - //TODO After restore should we W protect the node? - nd.setProtected(false); - if (!def.isProtected()) - System.out.println(def.getName()); - - NodeIterator it = parent.getNodes(); - - while (it.hasNext()) { - unprotect((NodeImpl) it.nextNode()); - } - + /** + * Import versioning XML in systemView. + * + * @param in FileInputStream + * @throws RepositoryException in case of any error + * @throws IOException in case of issue with the file + */ + private void importXML(FileInputStream in) throws RepositoryException, IOException { + SessionImpl s2 = (SessionImpl) this.getSession(); + //TODO Refactor this method with the one in WorkspaceBackup (only the importer changes (using Reflection?)) + VersionManager vMgr = ((RepositoryImpl) s2.getRepository()).getVersionManager(); + VersionManagerImpl vMgrI = (VersionManagerImpl) vMgr; + vMgrI.importVersions(in, ((WorkspaceImpl) s2.getWorkspace()).getHierarchyManager(), + ((SessionImpl) this.getSession()).getNamespaceResolver(), + (NamespaceRegistryImpl) this.getSession().getWorkspace().getNamespaceRegistry()); } } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/RepositoryBackup.java (working copy) @@ -16,55 +16,49 @@ */ 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.HashMap; -import java.util.Properties; import java.util.zip.ZipException; import javax.jcr.LoginException; -import javax.jcr.NamespaceRegistry; import javax.jcr.RepositoryException; - -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; -import org.apache.jackrabbit.core.fs.BasedFileSystem; -import org.apache.jackrabbit.core.fs.FileSystem; -import org.apache.jackrabbit.core.fs.FileSystemException; -import org.apache.jackrabbit.core.fs.FileSystemResource; -import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; -import org.apache.jackrabbit.core.nodetype.NodeTypeDefStore; -import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; /** - * @author ntoper - * + * Backup and restore a repository parameters + * (not the content since it is in the workspaces) */ public class RepositoryBackup extends Backup { + /** + * Repository Config file + */ + private String repoConfFile; - private String repoConfFile; + /** + * Home of the repository + */ private String home; /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * Constructor + * + * @param repo RepositoryImpl + * @param conf BackupConfig + * @param login login String + * @param password String + * @throws RepositoryException if there is an issue with the repository + * @throws LoginException if there is an issue with login/pass */ - public RepositoryBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) throws LoginException, RepositoryException { + public RepositoryBackup(RepositoryImpl repo, BackupConfig conf, String login, String password) + throws LoginException, RepositoryException { super(repo, conf, login, password); } + /** + * Empty constructor. You need to initialize afterward. + */ public RepositoryBackup() { super(); } @@ -69,6 +63,13 @@ super(); } + /** + * Constructor initializing the bare minimum + * (we need it to be able to restore the repository) + * + * @param repoConfFile String + * @param home String + */ public RepositoryBackup(String repoConfFile, String home) { super(); this.repoConfFile = repoConfFile; @@ -76,18 +77,10 @@ } /** - * Backup the repository config file - * - * TODO Backup properties? Metadata store? Other ressources? - * @throws IOException - * @throws RepositoryException - * - * + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws IOException, RepositoryException { - File file = this.getConf().getRepoConfFile(); - //Backup repository.xml h.write("repository_xml", file); } @@ -92,25 +85,19 @@ h.write("repository_xml", file); } + /** + * {@inheritDoc} + */ public void restore(BackupIOHandler h) throws ZipException, IOException, RepositoryException { - //Restore repository.xml - File f = new File(this.repoConfFile); - h.read("repository_xml", f); + //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)); - - -// this.getRepo().setNodeTypeRegistry(createNodeTypeRegistry(nsReg, new BasedFileSystem(this.getRepo().getStore()), "/nodetypes")); - /* - * 1. Create a NodeTypeRegistry specific for the restore (redefines only the load built in types path) - * 2. Update the NodeTypeRegistry in repo - */ - - + // Launch the repository and launch it. + RepositoryConfig repoConf = RepositoryConfig.create(this.repoConfFile, this.home); + this.setRepo(RepositoryImpl.create(repoConf)); + } - -} \ 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceBackup.java (working copy) @@ -22,19 +22,13 @@ import java.io.IOException; import java.util.zip.ZipException; +import javax.jcr.ImportUUIDBehavior; 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; @@ -41,41 +35,70 @@ import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; +import org.apache.jackrabbit.core.NamespaceRegistryImpl; import org.apache.jackrabbit.core.RepositoryImpl; +import org.apache.jackrabbit.core.RestoreBatchedItemOperations; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.WorkspaceImpl; +import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl; +import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; +import org.apache.jackrabbit.core.xml.ImportHandler; +import org.apache.jackrabbit.core.xml.Importer; +import org.apache.jackrabbit.core.xml.SysViewImporter; import org.apache.jackrabbit.core.xml.SysViewSAXEventGenerator; -import org.xml.sax.ContentHandler; +import org.apache.jackrabbit.name.MalformedPathException; +import org.apache.jackrabbit.name.Path; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; -//TODO Wiki doc to update /** - * @author ntoper - * + * Backup and restore a workspace. */ public class WorkspaceBackup extends Backup { - + + /** + * The workspace name to backup + */ private String wspName; - + /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * Constructor of the class + * + * @param repo current RepositoryImpl + * @param conf BackupConf object + * @param name String Name of the workspace to backup + * @param login String + * @param password String + * @throws RepositoryException in case of any error + * @throws LoginException if the login/pass are incorrect */ - public WorkspaceBackup(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + 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, String login, String password) throws LoginException, RepositoryException { + + /** + * Initialize all variable (to use with the empty constructor) + * + * @param repo current RepositoryImpl + * @param conf BackupConf object + * @param name String Name of the workspace to backup + * @param login String + * @param password String + * @throws RepositoryException in case of any error + * @throws LoginException if the login/pass are incorrect + */ + 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.jackrabbijcr:root/t.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { @@ -80,7 +103,7 @@ public void backup(BackupIOHandler h) throws RepositoryException, 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 { @@ -89,7 +112,7 @@ 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) @@ -98,8 +121,8 @@ super.process(node, level); } } - }.serialize(); - h.write("export_"+ this.wspName +".xml", temp); + } .serialize(); + h.write("export_" + this.wspName + ".xml", temp); } catch (TransformerException te) { throw new RepositoryException(te); } catch (SAXException se) { @@ -107,15 +130,16 @@ } finally { temp.delete(); } - + } - - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) + + /** + * {@inheritDoc} */ - public void restore(BackupIOHandler h) throws ZipException, IOException, LoginException, NoSuchWorkspaceException, RepositoryException { + public void restore(BackupIOHandler h) + throws ZipException, IOException, LoginException, NoSuchWorkspaceException, RepositoryException { //TODO put temp and constant in object's attribute. - + //Restore the SysView in a temp file File wspXml = new File(this.getConf().getWorkFolder() + "/workspace.xml"); File temp = new File(this.getConf().getWorkFolder() + "wsp.xml"); @@ -123,16 +147,16 @@ try { FileInputStream fis = new FileInputStream(wspXml); InputSource xml = new InputSource(fis); - + //Launch & register the wsp //There is at least the default wsp. SessionImpl s1 = (SessionImpl) this.getSession(); - Workspace wsp_def = s1.getWorkspace(); - + Workspace wspDef = s1.getWorkspace(); + //Check if the workspace already exist (UC: partial restore) - String[] allWsp = wsp_def.getAccessibleWorkspaceNames(); + String[] allWsp = wspDef.getAccessibleWorkspaceNames(); boolean isCreated = false; - + for (int i = 0; i < allWsp.length; i++) { if (this.wspName.equals(allWsp[i])) { isCreated = true; @@ -141,16 +165,12 @@ } if (!isCreated) { - ((WorkspaceImpl) wsp_def).createWorkspace(this.wspName, xml); + ((WorkspaceImpl) wspDef).createWorkspace(this.wspName, xml); } - h.read("export_"+ this.wspName +".xml", temp); - - SessionImpl s2 = (SessionImpl) this.getRepo().login(this.getCredentials(), this.wspName); - + h.read("export_" + this.wspName + ".xml", temp); FileInputStream iTemp = new FileInputStream(temp); - //TODO add a parameter in the conf file to manage UUIDBehavior - s2.importXML(s2.getRootNode().getPath(), iTemp, 3); + this.importXML(iTemp); } finally { wspXml.delete(); @@ -157,5 +177,66 @@ temp.delete(); } } - + + /** + * Import the in file in the workspace + * @param in FileInputStream SystemView XML + * @throws RepositoryException in case of any error + * @throws IOException if error reading the in file + */ + private void importXML(FileInputStream in) throws RepositoryException, IOException { + + SessionImpl s2 = (SessionImpl) this.getRepo().login(this.getCredentials(), this.wspName); + + try { + NodeTypeRegistry ntReg = ( (NodeTypeManagerImpl) s2.getWorkspace().getNodeTypeManager()).getNodeTypeRegistry(); + + Path.PathBuilder builder = new Path.PathBuilder(); + builder.addRoot(); + Path root = builder.getPath(); + + //We are passing several times the same information in the two methods below but there is no other way... + RestoreBatchedItemOperations itemOps = + new RestoreBatchedItemOperations(((WorkspaceImpl) s2.getWorkspace()).getItemStateManager(), + ntReg, s2.getHierarchyManager(), + s2.getNamespaceResolver()); + + WorkspaceImpl wsp = (WorkspaceImpl) s2.getWorkspace(); + wsp.sanityCheck(); + Importer importer = new SysViewImporter(root, wsp.getHierarchyManager(), + ntReg, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING, itemOps); + wsp.sanityCheck(); + + //TODO perform a sanityCheck before and after + //Everything is already there... We just need to access it. + ImportHandler handler = new ImportHandler(importer, ((SessionImpl) this.getSession()).getNamespaceResolver(), + (NamespaceRegistryImpl) this.getSession().getWorkspace().getNamespaceRegistry()); + + XMLReader parser = + XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); + parser.setContentHandler(handler); + parser.setErrorHandler(handler); + // being paranoid... + parser.setFeature("http://xml.org/sax/features/namespaces", true); + parser.setFeature("http://xml.org/sax/features/namespace-prefixes", + false); + + parser.parse(new InputSource(in)); + } catch (SAXException se) { + // check for wrapped repository exception + Exception e = se.getException(); + if (e != null && e instanceof RepositoryException) { + throw (RepositoryException) e; + } else { + String msg = "failed to parse XML stream"; + throw new InvalidSerializedDataException(msg, se); + } + } catch (MalformedPathException e) { + throw new RepositoryException(); + } finally { + s2.logout(); + } + + } + } 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/WorkspaceConfigBackup.java (working copy) @@ -28,11 +28,10 @@ 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; /** - * @author ntoper + * Backup and restore all workspace configuration parameters. * */ public class WorkspaceConfigBackup extends Backup { @@ -37,20 +36,42 @@ */ public class WorkspaceConfigBackup extends Backup { + /** + * The name of the workspace to backup/restore + */ private String wspName; + /** - * @param repo - * @param conf - * @throws RepositoryException - * @throws LoginException + * Constructor of the class + * + * @param repo current RepositoryImpl + * @param conf BackupConf object + * @param name String Name of the workspace to backup + * @param login String + * @param password String + * @throws RepositoryException in case of any error + * @throws LoginException if the login/pass are incorrect */ - public WorkspaceConfigBackup(RepositoryImpl repo, BackupConfig conf, String name, String login, String password) throws LoginException, RepositoryException { + 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, String login, String password) throws LoginException, RepositoryException { + + /** + * Constructor of the class + * + * @param repo current RepositoryImpl + * @param conf BackupConf object + * @param name String Name of the workspace to backup + * @param login String + * @param password String + * @throws RepositoryException in case of any error + * @throws LoginException if the login/pass are incorrect + */ + 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; } @@ -55,6 +76,9 @@ this.wspName = name; } + /** + * Empty constructor + */ public WorkspaceConfigBackup() { super(); } @@ -59,8 +83,8 @@ super(); } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#backup(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void backup(BackupIOHandler h) throws RepositoryException, IOException { @@ -74,8 +98,8 @@ h.write("WspConf_" + this.wspName , wspXml); } - /* (non-Javadoc) - * @see org.apache.jackrabbit.backup.Backup#restore(org.apache.jackrabbit.backup.BackupIOHandler) + /** + * {@inheritDoc} */ public void restore(BackupIOHandler h) throws ConfigurationException, ZipException, IOException { 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 432609) +++ /home/ntoper/workspace/backup/src/main/java/org/apache/jackrabbit/backup/ZipBackupIOHandler.java (working copy) @@ -35,25 +35,53 @@ import java.util.zip.ZipOutputStream; /** - * Question: ZipFile - * - * @author ntoper - * + * A BackupIOHandler to manage zip file: it backups file to + * a zip file and restore them from a zip file. */ public class ZipBackupIOHandler implements BackupIOHandler { - + + /** + * Buffer size of read/write + */ private static int BUFFER_SIZE = 1024; - + + /** + * The file to read/write from/to + */ private File zip; + + /** + * When backuping. + */ private FileOutputStream fout; + + /** + * When backuping. + */ private ZipOutputStream zipOut; + /** + * When restoring + */ private FileInputStream fin; + + /** + * When restoring + */ private ZipInputStream zipIn; + /** + * A flag to indicate whether this IOHandler is used to backup or not. + */ private boolean isBackup = false; - + /** + * Constructor + * + * @param zipFile path to zip file to use/create + * @param isBackup if we are or not in a backup + * @throws IOException if we cannot access the file + */ public ZipBackupIOHandler(String zipFile, boolean isBackup) throws IOException { this.zip = new File(zipFile); this.isBackup = isBackup; @@ -68,6 +96,9 @@ } } + /** + * {@inheritDoc} + */ public void close() throws IOException { if (isBackup) { zipOut.finish(); @@ -79,10 +110,7 @@ } /** - * Create a directory per resources - * Backup the resource and zip it - * @param string - * @param content + * {@inheritDoc} */ public void write(String name, File f) throws IOException { zipOut.flush(); @@ -88,7 +116,6 @@ zipOut.flush(); ZipEntry e = new ZipEntry(name); zipOut.putNextEntry(e); - Checksum crc = new CRC32(); CheckedInputStream i = new CheckedInputStream(new FileInputStream(f), crc); @@ -103,16 +130,8 @@ 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. - * + * {@inheritDoc} */ public void write(String name, ByteArrayOutputStream fos) throws IOException { zipOut.flush(); @@ -118,13 +137,11 @@ zipOut.flush(); ZipEntry e = new ZipEntry(name); zipOut.putNextEntry(e); - + //TODO refactor it with the one upper. + 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) { @@ -130,9 +147,8 @@ 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(); @@ -137,18 +153,18 @@ e.setCrc(check); zipOut.closeEntry(); } - + + /** + * {@inheritDoc} + */ 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) { @@ -154,16 +170,13 @@ 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 a CRC + return os.toByteArray(); } - - //TODO Refactor: the two upper are the same!! + quite similar to Backup + + /** + * {@inheritDoc} + */ public void read(String zipEntry, File myFile) throws ZipException, IOException { ZipFile zf = new ZipFile(this.zip); ZipEntry ze = new ZipEntry(zipEntry); @@ -168,6 +181,7 @@ ZipFile zf = new ZipFile(this.zip); ZipEntry ze = new ZipEntry(zipEntry); //TODO check CRC + //long crc1 = ze.getCrc(); Checksum chkCrc2 = new CRC32(); InputStream is = zf.getInputStream(ze); @@ -172,10 +186,8 @@ 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) { @@ -181,13 +193,20 @@ 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(); - }*/ + + /* if (!(crc1 == chkCrc2.getValue())) { + System.out.println("crc1:" + crc1 + "a crc2:"+ chkCrc2.getValue() ); + throw new ZipException(); + }*/ } + /** + * Return all zip entries in the file. (works in backup and restore mode) + * + * @return Enumeration of all zip entries in the file + * @throws ZipException if the zip is invalid (or not finished) + * @throws IOException if we cannot access the file or IO error + */ public Enumeration getEntries() throws ZipException, IOException { ZipFile zf = new ZipFile(this.zip); return zf.entries();