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.File;
009: import java.io.IOException;
010: import java.io.InputStream;
011: import java.io.OutputStream;
012: import java.sql.SQLException;
013: import java.util.zip.ZipEntry;
014: import java.util.zip.ZipInputStream;
015:
016: import org.h2.message.Message;
017: import org.h2.store.FileLister;
018: import org.h2.util.FileUtils;
019: import org.h2.util.IOUtils;
020:
021: /**
022: * Restores a H2 database by extracting the database files from a .zip file.
023: */
024: public class Restore {
025:
026: private void showUsage() {
027: System.out
028: .println("java "
029: + getClass().getName()
030: + " [-file <filename>] [-dir <dir>] [-db <database>] [-quiet]");
031: System.out
032: .println("See also http://h2database.com/javadoc/org/h2/tools/Restore.html");
033: }
034:
035: /**
036: * The command line interface for this tool.
037: * The options must be split into strings like this: "-db", "test",...
038: * Options are case sensitive. The following options are supported:
039: * <ul>
040: * <li>-help or -? (print the list of options)
041: * </li><li>-file filename (the default is backup.zip)
042: * </li><li>-dir database directory (the default is the current directory)
043: * </li><li>-db database name (as stored in the backup if no name is specified)
044: * </li><li>-quiet does not print progress information
045: * </li></ul>
046: *
047: * @param args the command line arguments
048: * @throws SQLException
049: */
050: public static void main(String[] args) throws SQLException {
051: new Restore().run(args);
052: }
053:
054: private void run(String[] args) throws SQLException {
055: String zipFileName = "backup.zip";
056: String dir = ".";
057: String db = null;
058: boolean quiet = false;
059: for (int i = 0; args != null && i < args.length; i++) {
060: if (args[i].equals("-dir")) {
061: dir = args[++i];
062: } else if (args[i].equals("-file")) {
063: zipFileName = args[++i];
064: } else if (args[i].equals("-db")) {
065: db = args[++i];
066: } else if (args[i].equals("-quiet")) {
067: quiet = true;
068: } else {
069: showUsage();
070: return;
071: }
072: }
073: Restore.execute(zipFileName, dir, db, quiet);
074: }
075:
076: private static String getOriginalDbName(String fileName, String db)
077: throws IOException {
078: InputStream in = null;
079: try {
080: in = FileUtils.openFileInputStream(fileName);
081: ZipInputStream zipIn = new ZipInputStream(in);
082: String originalDbName = null;
083: boolean multiple = false;
084: while (true) {
085: ZipEntry entry = zipIn.getNextEntry();
086: if (entry == null) {
087: break;
088: }
089: String entryName = entry.getName();
090: zipIn.closeEntry();
091: String name = FileLister
092: .getDatabaseNameFromFileName(entryName);
093: if (name != null) {
094: if (db.equals(name)) {
095: originalDbName = name;
096: // we found the correct database
097: break;
098: } else if (originalDbName == null) {
099: originalDbName = name;
100: // we found a database, but maybe another one
101: } else {
102: // we have found multiple databases, but not the correct
103: // one
104: multiple = true;
105: }
106: }
107: }
108: zipIn.close();
109: if (multiple && !originalDbName.equals(db)) {
110: throw new IOException(
111: "Multiple databases found, but not " + db);
112: }
113: return originalDbName;
114: } finally {
115: IOUtils.closeSilently(in);
116: }
117: }
118:
119: /**
120: * Restores database files.
121: *
122: * @param zipFileName the name of the backup file
123: * @param directory the directory name
124: * @param db the database name (null for all databases)
125: * @param quiet don't print progress information
126: * @throws SQLException
127: */
128: public static void execute(String zipFileName, String directory,
129: String db, boolean quiet) throws SQLException {
130: InputStream in = null;
131: try {
132: if (!FileUtils.exists(zipFileName)) {
133: throw new IOException("File not found: " + zipFileName);
134: }
135: String originalDbName = null;
136: if (db != null) {
137: originalDbName = getOriginalDbName(zipFileName, db);
138: if (originalDbName == null) {
139: throw new IOException("No database named " + db
140: + " found");
141: }
142: if (originalDbName.startsWith(File.separator)) {
143: originalDbName = originalDbName.substring(1);
144: }
145: }
146: in = FileUtils.openFileInputStream(zipFileName);
147: ZipInputStream zipIn = new ZipInputStream(in);
148: while (true) {
149: ZipEntry entry = zipIn.getNextEntry();
150: if (entry == null) {
151: break;
152: }
153: String fileName = entry.getName();
154: // restoring windows backups on linux and vice versa
155: fileName = fileName.replace('\\', File.separatorChar);
156: fileName = fileName.replace('/', File.separatorChar);
157: if (fileName.startsWith(File.separator)) {
158: fileName = fileName.substring(1);
159: }
160: boolean copy = false;
161: if (db == null) {
162: copy = true;
163: } else if (fileName.startsWith(originalDbName)) {
164: fileName = db
165: + fileName.substring(originalDbName
166: .length());
167: copy = true;
168: }
169: if (copy) {
170: OutputStream out = null;
171: try {
172: out = FileUtils.openFileOutputStream(directory
173: + File.separator + fileName, false);
174: IOUtils.copy(zipIn, out);
175: out.close();
176: } finally {
177: IOUtils.closeSilently(out);
178: }
179: }
180: zipIn.closeEntry();
181: }
182: zipIn.closeEntry();
183: zipIn.close();
184: } catch (IOException e) {
185: throw Message.convertIOException(e, zipFileName);
186: } finally {
187: IOUtils.closeSilently(in);
188: }
189: }
190:
191: }
|