/* * eXist Open Source Native XML Database * Copyright (C) 2001-2011 The eXist Project * http://exist-db.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ */ package org.exist.backup; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URISyntaxException; import java.util.List; import java.util.Properties; import java.util.prefs.Preferences; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.xml.parsers.ParserConfigurationException; import org.apache.avalon.excalibur.cli.CLArgsParser; import org.apache.avalon.excalibur.cli.CLOption; import org.apache.avalon.excalibur.cli.CLOptionDescriptor; import org.apache.avalon.excalibur.cli.CLUtil; import org.exist.storage.DBBroker; import org.exist.util.ConfigurationHelper; import org.exist.xmldb.DatabaseInstanceManager; import org.exist.xmldb.XmldbURI; import org.xml.sax.SAXException; import org.xmldb.api.DatabaseManager; import org.xmldb.api.base.Collection; import org.xmldb.api.base.Database; import org.xmldb.api.base.XMLDBException; /** * Main.java * * @author Wolfgang Meier */ public class Main { private final static int HELP_OPT = 'h'; private final static int USER_OPT = 'u'; private final static int PASS_OPT = 'p'; private final static int DBA_PASS_OPT = 'P'; private final static int BACKUP_OPT = 'b'; private final static int BACKUP_DIR_OPT = 'd'; private final static int RESTORE_OPT = 'r'; private final static int OPTION_OPT = 'o'; private final static int GUI_OPT = 'U'; private final static int QUIET_OPT = 'q'; private final static CLOptionDescriptor OPTIONS[] = new CLOptionDescriptor[] { new CLOptionDescriptor( "help", CLOptionDescriptor.ARGUMENT_DISALLOWED, HELP_OPT, "print help on command line options and exit."), new CLOptionDescriptor( "gui", CLOptionDescriptor.ARGUMENT_DISALLOWED, GUI_OPT, "start in GUI mode"), new CLOptionDescriptor( "user", CLOptionDescriptor.ARGUMENT_REQUIRED, USER_OPT, "set user."), new CLOptionDescriptor( "password", CLOptionDescriptor.ARGUMENT_REQUIRED, PASS_OPT, "set the password for connecting to the database."), new CLOptionDescriptor( "dba-password", CLOptionDescriptor.ARGUMENT_REQUIRED, DBA_PASS_OPT, "if the backup specifies a different password for the admin/dba user, use this option " + "to specify the new password. Otherwise you will get a permission denied"), new CLOptionDescriptor( "backup", CLOptionDescriptor.ARGUMENT_REQUIRED, BACKUP_OPT, "backup the specified collection."), new CLOptionDescriptor( "dir", CLOptionDescriptor.ARGUMENT_REQUIRED, BACKUP_DIR_OPT, "specify the directory to use for backups."), new CLOptionDescriptor( "restore", CLOptionDescriptor.ARGUMENT_REQUIRED, RESTORE_OPT, "read the specified restore file and restore the " + "resources described there."), new CLOptionDescriptor( "option", CLOptionDescriptor.ARGUMENTS_REQUIRED_2 | CLOptionDescriptor.DUPLICATES_ALLOWED, OPTION_OPT, "specify extra options: property=value. For available properties see " + "client.properties."), new CLOptionDescriptor( "quiet", CLOptionDescriptor.ARGUMENT_DISALLOWED, QUIET_OPT, "be quiet. Just print errors.") }; /** * Constructor for Main. */ public static void process(String args[]) { // read properties Properties properties = new Properties(); try { File propFile = ConfigurationHelper.lookup("backup.properties"); InputStream pin; if (propFile.canRead()) pin = new FileInputStream(propFile); else pin = Main.class.getResourceAsStream("backup.properties"); if (pin != null) properties.load(pin); } catch (IOException ioe) { } Preferences preferences = Preferences.userNodeForPackage(Main.class); // parse command-line options final CLArgsParser optParser = new CLArgsParser(args, OPTIONS); if (optParser.getErrorString() != null) { System.err.println("ERROR: " + optParser.getErrorString()); return; } final List opt = optParser.getArguments(); final int size = opt.size(); CLOption option; String optionBackup = null; String optionRestore = null; String optionPass = null; String optionDbaPass = null; boolean doBackup = false; boolean doRestore = false; boolean guiMode = false; boolean quiet = false; for (int i = 0; i < size; i++) { option = (CLOption) opt.get(i); switch (option.getId()) { case HELP_OPT : printUsage(); return; case GUI_OPT : guiMode = true; break; case QUIET_OPT : quiet = true; break; case OPTION_OPT : properties.setProperty(option.getArgument(0), option.getArgument(1)); break; case USER_OPT : properties.setProperty("user", option.getArgument()); break; case PASS_OPT : properties.setProperty("password", option.getArgument()); optionPass = option.getArgument(); //remove after change inside restore break; case DBA_PASS_OPT : optionDbaPass = option.getArgument(); break; case BACKUP_OPT : if (option.getArgumentCount() == 1) optionBackup = option.getArgument(); else optionBackup = null; doBackup = true; break; case RESTORE_OPT : if(option.getArgumentCount() == 1) optionRestore = option.getArgument(); doRestore = true; break; case BACKUP_DIR_OPT : properties.setProperty("backup-dir", option.getArgument()); break; } } // initialize driver Database database; try { Class cl = Class.forName(properties.getProperty("driver", "org.exist.xmldb.DatabaseImpl")); database = (Database) cl.newInstance(); database.setProperty("create-database", "true"); if (properties.containsKey("configuration")) database.setProperty("configuration", properties.getProperty("configuration")); DatabaseManager.registerDatabase(database); } catch (ClassNotFoundException e) { reportError(e); return; } catch (InstantiationException e) { reportError(e); return; } catch (IllegalAccessException e) { reportError(e); return; } catch (XMLDBException e) { reportError(e); return; } // process if (doBackup) { if (optionBackup == null) { if (guiMode) { CreateBackupDialog dialog = new CreateBackupDialog( properties.getProperty("uri", "xmldb:exist://"), properties.getProperty("user", "admin"), properties.getProperty("password",""), new File(preferences.get("directory.backup", System.getProperty("user.dir")))); if (JOptionPane .showOptionDialog( null, dialog, "Create Backup", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.YES_OPTION) { optionBackup = dialog.getCollection(); properties.setProperty("backup-dir", dialog.getBackupTarget()); } } else optionBackup = DBBroker.ROOT_COLLECTION; } if (optionBackup != null) { try { Backup backup = new Backup( properties.getProperty("user", "admin"), properties.getProperty("password",""), properties.getProperty("backup-dir", "backup"), XmldbURI.xmldbUriFor(properties.getProperty("uri", "xmldb:exist://") + optionBackup), properties); backup.backup(guiMode, null); } catch (Exception e) { reportError(e); } } } if (doRestore) { if (optionRestore == null && guiMode) { JFileChooser chooser = new JFileChooser(); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); if (chooser.showDialog(null, "Select backup file for restore") == JFileChooser.APPROVE_OPTION) { File f = chooser.getSelectedFile(); optionRestore = f.getAbsolutePath(); } } if (optionRestore != null) { try { Restore restore = new Restore( properties.getProperty("user", "admin"), optionPass, optionDbaPass, new File(optionRestore), properties.getProperty("uri", "xmldb:exist://")); restore.restore(guiMode, null); } catch (Exception e) { reportError(e); } } } try { Collection root = DatabaseManager.getCollection( properties.getProperty("uri", "xmldb:exist://") + DBBroker.ROOT_COLLECTION, properties.getProperty("user", "admin"), optionDbaPass == null ? optionPass : optionDbaPass); shutdown(root); } catch (Exception e) { reportError(e); } System.exit(0); } private final static void reportError(Throwable e) { e.printStackTrace(); if (e.getCause() != null) { System.err.println("caused by "); e.getCause().printStackTrace(); } System.exit(1); } private final static void printUsage() { System.out.println("Usage: java " + Main.class.getName() + " [options]"); System.out.println(CLUtil.describeOptions(OPTIONS).toString()); } private final static void shutdown(Collection root) { try { DatabaseInstanceManager mgr = (DatabaseInstanceManager) root.getService("DatabaseInstanceManager", "1.0"); if (mgr == null) { System.err.println("service is not available"); } else if (mgr.isLocalInstance()) { System.out.println("shutting down database..."); mgr.shutdown(); } } catch (XMLDBException e) { System.err.println("database shutdown failed: "); e.printStackTrace(); } } public static void main(String[] args) { try { process(args); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } } }