001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.tools;
007:
008: import java.io.FileNotFoundException;
009: import java.io.IOException;
010: import java.io.InputStream;
011: import java.io.OutputStream;
012: import java.sql.SQLException;
013: import java.util.ArrayList;
014: import java.util.zip.ZipEntry;
015: import java.util.zip.ZipOutputStream;
016:
017: import org.h2.command.dml.BackupCommand;
018: import org.h2.engine.Constants;
019: import org.h2.message.Message;
020: import org.h2.store.FileLister;
021: import org.h2.util.FileUtils;
022: import org.h2.util.IOUtils;
023:
024: /**
025: * Backs up a H2 database by creating a .zip file from the database files.
026: */
027: public class Backup {
028:
029: private void showUsage() {
030: System.out
031: .println("java "
032: + getClass().getName()
033: + " [-file <filename>] [-dir <dir>] [-db <database>] [-quiet]");
034: System.out
035: .println("See also http://h2database.com/javadoc/org/h2/tools/Backup.html");
036: }
037:
038: /**
039: * The command line interface for this tool.
040: * The options must be split into strings like this: "-db", "test",...
041: * Options are case sensitive. The following options are supported:
042: * <ul>
043: * <li>-help or -? (print the list of options)
044: * </li><li>-file filename (the default is backup.zip)
045: * </li><li>-dir database directory (the default is the current directory)
046: * </li><li>-db database name (not required if there is only one database)
047: * </li><li>-quiet does not print progress information
048: * </li></ul>
049: *
050: * @param args the command line arguments
051: * @throws SQLException
052: */
053: public static void main(String[] args) throws SQLException {
054: new Backup().run(args);
055: }
056:
057: private void run(String[] args) throws SQLException {
058: String zipFileName = "backup.zip";
059: String dir = ".";
060: String db = null;
061: boolean quiet = false;
062: for (int i = 0; args != null && i < args.length; i++) {
063: if (args[i].equals("-dir")) {
064: dir = args[++i];
065: } else if (args[i].equals("-db")) {
066: db = args[++i];
067: } else if (args[i].equals("-quiet")) {
068: quiet = true;
069: } else if (args[i].equals("-file")) {
070: zipFileName = args[++i];
071: } else {
072: showUsage();
073: return;
074: }
075: }
076: Backup.execute(zipFileName, dir, db, quiet);
077: }
078:
079: /**
080: * Backs up database files.
081: *
082: * @param zipFileName the name of the backup file
083: * @param directory the directory name
084: * @param db the database name (null if there is only one database)
085: * @param quiet don't print progress information
086: * @throws SQLException
087: */
088: public static void execute(String zipFileName, String directory,
089: String db, boolean quiet) throws SQLException {
090: ArrayList list = FileLister.getDatabaseFiles(directory, db,
091: true);
092: if (list.size() == 0) {
093: if (!quiet) {
094: System.out.println("No database files found");
095: }
096: return;
097: }
098: zipFileName = FileUtils.normalize(zipFileName);
099: if (FileUtils.exists(zipFileName)) {
100: FileUtils.delete(zipFileName);
101: }
102: OutputStream out = null;
103: try {
104: out = FileUtils.openFileOutputStream(zipFileName, false);
105: ZipOutputStream zipOut = new ZipOutputStream(out);
106: String base = "";
107: for (int i = 0; i < list.size(); i++) {
108: String fileName = (String) list.get(i);
109: if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) {
110: base = FileUtils.getParent(fileName);
111: }
112: }
113: for (int i = 0; i < list.size(); i++) {
114: String fileName = (String) list.get(i);
115: String f = FileUtils.getAbsolutePath(fileName);
116: if (!f.startsWith(base)) {
117: throw Message.getInternalError(f
118: + " does not start with " + base);
119: }
120: f = f.substring(base.length());
121: f = BackupCommand.correctFileName(f);
122: ZipEntry entry = new ZipEntry(f);
123: zipOut.putNextEntry(entry);
124: InputStream in = null;
125: try {
126: in = FileUtils.openFileInputStream(fileName);
127: IOUtils.copyAndCloseInput(in, zipOut);
128: } catch (FileNotFoundException e) {
129: // the file could have been deleted in the meantime
130: // ignore this (in this case an empty file is created)
131: } finally {
132: IOUtils.closeSilently(in);
133: }
134: zipOut.closeEntry();
135: if (!quiet) {
136: System.out.println("processed: " + fileName);
137: }
138: }
139: zipOut.closeEntry();
140: zipOut.close();
141: } catch (IOException e) {
142: throw Message.convertIOException(e, zipFileName);
143: } finally {
144: IOUtils.closeSilently(out);
145: }
146: }
147:
148: }
|