@Override public void test() throws Exception { if (!SysProperties.MODIFY_ON_WRITE) { return; } deleteDb("modifyOnWrite"); String dbFile = getBaseDir() + "/modifyOnWrite.h2.db"; assertFalse(FileUtils.exists(dbFile)); Connection conn = getConnection("modifyOnWrite"); Statement stat = conn.createStatement(); stat.execute("create table test(id int)"); conn.close(); byte[] test = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); ResultSet rs; rs = stat.executeQuery("select * from test"); assertFalse(rs.next()); conn.close(); assertTrue(FileUtils.exists(dbFile)); byte[] test2 = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); assertEquals(test, test2); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); stat.execute("insert into test values(1)"); conn.close(); conn = getConnection("modifyOnWrite"); stat = conn.createStatement(); rs = stat.executeQuery("select * from test"); assertTrue(rs.next()); conn.close(); test2 = IOUtils.readBytesAndClose(FileUtils.newInputStream(dbFile), -1); assertFalse(Utils.compareSecure(test, test2)); }
private static String getOriginalDbName(String fileName, String db) throws IOException { InputStream in = null; try { in = FileUtils.newInputStream(fileName); ZipInputStream zipIn = new ZipInputStream(in); String originalDbName = null; boolean multiple = false; while (true) { ZipEntry entry = zipIn.getNextEntry(); if (entry == null) { break; } String entryName = entry.getName(); zipIn.closeEntry(); String name = getDatabaseNameFromFileName(entryName); if (name != null) { if (db.equals(name)) { originalDbName = name; // we found the correct database break; } else if (originalDbName == null) { originalDbName = name; // we found a database, but maybe another one } else { // we have found multiple databases, but not the correct // one multiple = true; } } } zipIn.close(); if (multiple && !db.equals(originalDbName)) { throw new IOException("Multiple databases found, but not " + db); } return originalDbName; } finally { IOUtils.closeSilently(in); } }
/** * Restores database files. * * @param zipFileName the name of the backup file * @param directory the directory name * @param db the database name (null for all databases) * @throws DbException if there is an IOException */ public static void execute(String zipFileName, String directory, String db) { InputStream in = null; try { if (!FileUtils.exists(zipFileName)) { throw new IOException("File not found: " + zipFileName); } String originalDbName = null; int originalDbLen = 0; if (db != null) { originalDbName = getOriginalDbName(zipFileName, db); if (originalDbName == null) { throw new IOException("No database named " + db + " found"); } if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) { originalDbName = originalDbName.substring(1); } originalDbLen = originalDbName.length(); } in = FileUtils.newInputStream(zipFileName); ZipInputStream zipIn = new ZipInputStream(in); while (true) { ZipEntry entry = zipIn.getNextEntry(); if (entry == null) { break; } String fileName = entry.getName(); // restoring windows backups on linux and vice versa fileName = fileName.replace('\\', SysProperties.FILE_SEPARATOR.charAt(0)); fileName = fileName.replace('/', SysProperties.FILE_SEPARATOR.charAt(0)); if (fileName.startsWith(SysProperties.FILE_SEPARATOR)) { fileName = fileName.substring(1); } boolean copy = false; if (db == null) { copy = true; } else if (fileName.startsWith(originalDbName + ".")) { fileName = db + fileName.substring(originalDbLen); copy = true; } if (copy) { OutputStream o = null; try { o = FileUtils.newOutputStream( directory + SysProperties.FILE_SEPARATOR + fileName, false); IOUtils.copy(zipIn, o); o.close(); } finally { IOUtils.closeSilently(o); } } zipIn.closeEntry(); } zipIn.closeEntry(); zipIn.close(); } catch (IOException e) { throw DbException.convertIOException(e, zipFileName); } finally { IOUtils.closeSilently(in); } }