EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.tools]

COVERAGE SUMMARY FOR SOURCE FILE [Restore.java]

nameclass, %method, %block, %line, %
Restore.java100% (1/1)100% (6/6)73%  (266/364)83%  (78.4/94)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Restore100% (1/1)100% (6/6)73%  (266/364)83%  (78.4/94)
getDatabaseNameFromFileName (String): String 100% (1/1)61%  (17/28)60%  (3/5)
getOriginalDbName (String, String): String 100% (1/1)70%  (53/76)88%  (21/24)
execute (String, String, String): void 100% (1/1)72%  (127/176)85%  (37.4/44)
runTool (String []): void 100% (1/1)80%  (60/75)78%  (14/18)
Restore (): void 100% (1/1)100% (3/3)100% (1/1)
main (String []): void 100% (1/1)100% (6/6)100% (2/2)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.tools;
7 
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.OutputStream;
11import java.sql.SQLException;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipInputStream;
14 
15import org.h2.engine.Constants;
16import org.h2.engine.SysProperties;
17import org.h2.message.DbException;
18import org.h2.store.fs.FileUtils;
19import org.h2.util.IOUtils;
20import org.h2.util.Tool;
21 
22/**
23 * Restores a H2 database by extracting the database files from a .zip file.
24 * @h2.resource
25 */
26public class Restore extends Tool {
27 
28    /**
29     * Options are case sensitive. Supported options are:
30     * <table>
31     * <tr><td>[-help] or [-?]</td>
32     * <td>Print the list of options</td></tr>
33     * <tr><td>[-file &lt;filename&gt;]</td>
34     * <td>The source file name (default: backup.zip)</td></tr>
35     * <tr><td>[-dir &lt;dir&gt;]</td>
36     * <td>The target directory (default: .)</td></tr>
37     * <tr><td>[-db &lt;database&gt;]</td>
38     * <td>The target database name (as stored if not set)</td></tr>
39     * <tr><td>[-quiet]</td>
40     * <td>Do not print progress information</td></tr>
41     * </table>
42     * @h2.resource
43     *
44     * @param args the command line arguments
45     */
46    public static void main(String... args) throws SQLException {
47        new Restore().runTool(args);
48    }
49 
50    @Override
51    public void runTool(String... args) throws SQLException {
52        String zipFileName = "backup.zip";
53        String dir = ".";
54        String db = null;
55        for (int i = 0; args != null && i < args.length; i++) {
56            String arg = args[i];
57            if (arg.equals("-dir")) {
58                dir = args[++i];
59            } else if (arg.equals("-file")) {
60                zipFileName = args[++i];
61            } else if (arg.equals("-db")) {
62                db = args[++i];
63            } else if (arg.equals("-quiet")) {
64                // ignore
65            } else if (arg.equals("-help") || arg.equals("-?")) {
66                showUsage();
67                return;
68            } else {
69                showUsageAndThrowUnsupportedOption(arg);
70            }
71        }
72        execute(zipFileName, dir, db);
73    }
74 
75    private static String getOriginalDbName(String fileName, String db)
76            throws IOException {
77        InputStream in = null;
78        try {
79            in = FileUtils.newInputStream(fileName);
80            ZipInputStream zipIn = new ZipInputStream(in);
81            String originalDbName = null;
82            boolean multiple = false;
83            while (true) {
84                ZipEntry entry = zipIn.getNextEntry();
85                if (entry == null) {
86                    break;
87                }
88                String entryName = entry.getName();
89                zipIn.closeEntry();
90                String name = getDatabaseNameFromFileName(entryName);
91                if (name != null) {
92                    if (db.equals(name)) {
93                        originalDbName = name;
94                        // we found the correct database
95                        break;
96                    } else if (originalDbName == null) {
97                        originalDbName = name;
98                        // we found a database, but maybe another one
99                    } else {
100                        // we have found multiple databases, but not the correct
101                        // one
102                        multiple = true;
103                    }
104                }
105            }
106            zipIn.close();
107            if (multiple && !db.equals(originalDbName)) {
108                throw new IOException("Multiple databases found, but not " + db);
109            }
110            return originalDbName;
111        } finally {
112            IOUtils.closeSilently(in);
113        }
114    }
115 
116    /**
117     * Extract the name of the database from a given file name.
118     * Only files ending with .h2.db are considered, all others return null.
119     *
120     * @param fileName the file name (without directory)
121     * @return the database name or null
122     */
123    private static String getDatabaseNameFromFileName(String fileName) {
124        if (fileName.endsWith(Constants.SUFFIX_PAGE_FILE)) {
125            return fileName.substring(0,
126                    fileName.length() - Constants.SUFFIX_PAGE_FILE.length());
127        }
128        if (fileName.endsWith(Constants.SUFFIX_MV_FILE)) {
129            return fileName.substring(0,
130                    fileName.length() - Constants.SUFFIX_MV_FILE.length());
131        }
132        return null;
133    }
134 
135    /**
136     * Restores database files.
137     *
138     * @param zipFileName the name of the backup file
139     * @param directory the directory name
140     * @param db the database name (null for all databases)
141     * @throws DbException if there is an IOException
142     */
143    public static void execute(String zipFileName, String directory, String db) {
144        InputStream in = null;
145        try {
146            if (!FileUtils.exists(zipFileName)) {
147                throw new IOException("File not found: " + zipFileName);
148            }
149            String originalDbName = null;
150            int originalDbLen = 0;
151            if (db != null) {
152                originalDbName = getOriginalDbName(zipFileName, db);
153                if (originalDbName == null) {
154                    throw new IOException("No database named " + db + " found");
155                }
156                if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) {
157                    originalDbName = originalDbName.substring(1);
158                }
159                originalDbLen = originalDbName.length();
160            }
161            in = FileUtils.newInputStream(zipFileName);
162            ZipInputStream zipIn = new ZipInputStream(in);
163            while (true) {
164                ZipEntry entry = zipIn.getNextEntry();
165                if (entry == null) {
166                    break;
167                }
168                String fileName = entry.getName();
169                // restoring windows backups on linux and vice versa
170                fileName = fileName.replace('\\', SysProperties.FILE_SEPARATOR.charAt(0));
171                fileName = fileName.replace('/', SysProperties.FILE_SEPARATOR.charAt(0));
172                if (fileName.startsWith(SysProperties.FILE_SEPARATOR)) {
173                    fileName = fileName.substring(1);
174                }
175                boolean copy = false;
176                if (db == null) {
177                    copy = true;
178                } else if (fileName.startsWith(originalDbName + ".")) {
179                    fileName = db + fileName.substring(originalDbLen);
180                    copy = true;
181                }
182                if (copy) {
183                    OutputStream o = null;
184                    try {
185                        o = FileUtils.newOutputStream(
186                                directory + SysProperties.FILE_SEPARATOR + fileName, false);
187                        IOUtils.copy(zipIn, o);
188                        o.close();
189                    } finally {
190                        IOUtils.closeSilently(o);
191                    }
192                }
193                zipIn.closeEntry();
194            }
195            zipIn.closeEntry();
196            zipIn.close();
197        } catch (IOException e) {
198            throw DbException.convertIOException(e, zipFileName);
199        } finally {
200            IOUtils.closeSilently(in);
201        }
202    }
203 
204}

[all classes][org.h2.tools]
EMMA 2.0.5312 (C) Vladimir Roubtsov