提交 63ff6643 authored 作者: Thomas Mueller's avatar Thomas Mueller

TCP Server: a base directory with a prefix with a database name with prefix…

TCP Server: a base directory with a prefix with a database name with prefix didn't work as expected (this only applies to non-disk and wrapped file systems).
上级 0068afd0
...@@ -554,9 +554,9 @@ The property column represents the property key in the <code>odbc.ini</code> fil ...@@ -554,9 +554,9 @@ The property column represents the property key in the <code>odbc.ini</code> fil
<tr><td>Data Source</td><td>H2 Test</td><td>The name of the ODBC Data Source</td></tr> <tr><td>Data Source</td><td>H2 Test</td><td>The name of the ODBC Data Source</td></tr>
<tr><td>Database</td><td>~/test;ifexists=true</td> <tr><td>Database</td><td>~/test;ifexists=true</td>
<td> <td>
The database name. This can include connections settings.<br /> The database name. This can include connections settings.
By default, the database is stored in the current working directory <br /> By default, the database is stored in the current working directory
where the Server is started except when the -baseDir setting is used. <br /> where the Server is started except when the -baseDir setting is used.
The name must be at least 3 characters. The name must be at least 3 characters.
</td></tr> </td></tr>
<tr><td>Servername</td><td>localhost</td><td>The server name or IP address.<br />By default, only remote connections are allowed</td></tr> <tr><td>Servername</td><td>localhost</td><td>The server name or IP address.<br />By default, only remote connections are allowed</td></tr>
......
...@@ -18,7 +18,9 @@ Change Log ...@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Version 1.3: when re-running the same query so that the previous result was re-used, <ul><li>TCP Server: a base directory with a prefix with a database name with prefix didn't work as expected
(this only applies to non-disk and wrapped file systems).
</li><li>Version 1.3: when re-running the same query so that the previous result was re-used,
and if the result set was large so that it was stored externally (in a temp file or in a temp table), and if the result set was large so that it was stored externally (in a temp file or in a temp table),
then reading rows from both result sets resulted in an exception or wrong behavior. then reading rows from both result sets resulted in an exception or wrong behavior.
</li><li>A new sample application that shows how to create </li><li>A new sample application that shows how to create
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
package org.h2.engine; package org.h2.engine;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
...@@ -137,31 +136,24 @@ public class ConnectionInfo implements Cloneable { ...@@ -137,31 +136,24 @@ public class ConnectionInfo implements Cloneable {
*/ */
public void setBaseDir(String dir) { public void setBaseDir(String dir) {
if (persistent) { if (persistent) {
String fileSystemPrefix = ""; String absDir = IOUtils.unwrap(IOUtils.getAbsolutePath(dir));
int colonIndex = name.lastIndexOf(':'); boolean absolute = IOUtils.isAbsolute(name);
if (colonIndex > 1) { String n;
// cut FileSystem prefixes, but not String prefix = null;
// C: and D: (Microsoft Windows drive letters) if (absolute) {
fileSystemPrefix = name.substring(0, colonIndex+1); n = name;
name = name.substring(colonIndex+1);
}
String testFileName;
if (name.startsWith("~")) {
testFileName = System.getProperty("user.home") + SysProperties.FILE_SEPARATOR + name.substring(1);
} else { } else {
testFileName = dir + SysProperties.FILE_SEPARATOR + name; n = IOUtils.unwrap(name);
prefix = name.substring(0, name.length() - n.length());
n = dir + SysProperties.FILE_SEPARATOR + n;
} }
String absName = IOUtils.unwrap(IOUtils.getAbsolutePath(n));
File testFile = new File(testFileName); if (absName.equals(absDir) || !absName.startsWith(absDir)) {
File baseDir = new File(dir); throw DbException.get(ErrorCode.IO_EXCEPTION_1, absName + " outside " +
if (!IOUtils.isInDir(testFile, baseDir)) { absDir);
throw DbException.get(ErrorCode.IO_EXCEPTION_1, testFile.getAbsolutePath() + " outside " +
baseDir.getAbsolutePath());
} }
if (name.startsWith("~")) { if (!absolute) {
name = fileSystemPrefix + name; name = prefix + dir + SysProperties.FILE_SEPARATOR + IOUtils.unwrap(name);
} else {
name = fileSystemPrefix + dir + SysProperties.FILE_SEPARATOR + name;
} }
} }
} }
......
...@@ -32,8 +32,8 @@ import org.h2.command.Parser; ...@@ -32,8 +32,8 @@ import org.h2.command.Parser;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.ExpressionColumn; import org.h2.expression.ExpressionColumn;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.store.fs.FileSystem;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
...@@ -348,7 +348,7 @@ public class FullTextLucene extends FullText { ...@@ -348,7 +348,7 @@ public class FullTextLucene extends FullText {
if (access != null) { if (access != null) {
removeIndexAccess(access, path); removeIndexAccess(access, path);
} }
FileSystem.getInstance(path).deleteRecursive(path, false); IOUtils.deleteRecursive(path, false);
} }
/** /**
......
...@@ -120,10 +120,12 @@ public class FileObjectDiskMapped implements FileObject { ...@@ -120,10 +120,12 @@ public class FileObjectDiskMapped implements FileObject {
} }
public void close() throws IOException { public void close() throws IOException {
if (file != null) {
unMap(); unMap();
file.close(); file.close();
file = null; file = null;
} }
}
public long getFilePointer() { public long getFilePointer() {
return pos; return pos;
......
...@@ -225,10 +225,10 @@ public abstract class FileSystem { ...@@ -225,10 +225,10 @@ public abstract class FileSystem {
/** /**
* Copy a file from one directory to another, or to another file. * Copy a file from one directory to another, or to another file.
* *
* @param original the original file name * @param source the name of the original file
* @param copy the file name of the copy * @param target the file name of the copy
*/ */
public abstract void copy(String original, String copy); public abstract void copy(String source, String target);
/** /**
* Create all required directories. * Create all required directories.
...@@ -337,4 +337,13 @@ public abstract class FileSystem { ...@@ -337,4 +337,13 @@ public abstract class FileSystem {
} }
} }
/**
* Get the unwrapped file name (without wrapper prefixes if wrapping /
* delegating file systems are used).
*
* @param fileName the file name
* @return the unwrapped
*/
public abstract String unwrap(String fileName);
} }
...@@ -94,7 +94,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -94,7 +94,7 @@ public class FileSystemDisk extends FileSystem {
new String[] { oldName, newName + " (exists)" }); new String[] { oldName, newName + " (exists)" });
} }
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) { for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("rename", oldName + " >" + newName, null); IOUtils.trace("rename", oldName + " >" + newName, null);
boolean ok = oldFile.renameTo(newFile); boolean ok = oldFile.renameTo(newFile);
if (ok) { if (ok) {
return; return;
...@@ -104,19 +104,6 @@ public class FileSystemDisk extends FileSystem { ...@@ -104,19 +104,6 @@ public class FileSystemDisk extends FileSystem {
throw DbException.get(ErrorCode.FILE_RENAME_FAILED_2, new String[]{oldName, newName}); throw DbException.get(ErrorCode.FILE_RENAME_FAILED_2, new String[]{oldName, newName});
} }
/**
* Print a trace message if tracing is enabled.
*
* @param method the method
* @param fileName the file name
* @param o the object
*/
protected void trace(String method, String fileName, Object o) {
if (SysProperties.TRACE_IO) {
System.out.println("FileSystem." + method + " " + fileName + " " + o);
}
}
private static void wait(int i) { private static void wait(int i) {
if (i > 8) { if (i > 8) {
System.gc(); System.gc();
...@@ -154,7 +141,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -154,7 +141,7 @@ public class FileSystemDisk extends FileSystem {
File file = new File(fileName); File file = new File(fileName);
if (file.exists()) { if (file.exists()) {
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) { for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("delete", fileName, null); IOUtils.trace("delete", fileName, null);
boolean ok = file.delete(); boolean ok = file.delete();
if (ok) { if (ok) {
return; return;
...@@ -167,7 +154,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -167,7 +154,7 @@ public class FileSystemDisk extends FileSystem {
public boolean tryDelete(String fileName) { public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName); fileName = translateFileName(fileName);
trace("tryDelete", fileName, null); IOUtils.trace("tryDelete", fileName, null);
return new File(fileName).delete(); return new File(fileName).delete();
} }
...@@ -214,8 +201,8 @@ public class FileSystemDisk extends FileSystem { ...@@ -214,8 +201,8 @@ public class FileSystemDisk extends FileSystem {
return new String[0]; return new String[0];
} }
String base = f.getCanonicalPath(); String base = f.getCanonicalPath();
if (!base.endsWith(File.separator)) { if (!base.endsWith(SysProperties.FILE_SEPARATOR)) {
base += File.separator; base += SysProperties.FILE_SEPARATOR;
} }
for (int i = 0, len = list.length; i < len; i++) { for (int i = 0, len = list.length; i < len; i++) {
list[i] = base + list[i]; list[i] = base + list[i];
...@@ -327,14 +314,14 @@ public class FileSystemDisk extends FileSystem { ...@@ -327,14 +314,14 @@ public class FileSystemDisk extends FileSystem {
} }
} }
public void copy(String original, String copy) { public void copy(String source, String target) {
original = translateFileName(original); source = translateFileName(source);
copy = translateFileName(copy); target = translateFileName(target);
OutputStream out = null; OutputStream out = null;
InputStream in = null; InputStream in = null;
try { try {
out = IOUtils.openFileOutputStream(copy, false); out = IOUtils.openFileOutputStream(target, false);
in = IOUtils.openFileInputStream(original); in = IOUtils.openFileInputStream(source);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE]; byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while (true) { while (true) {
int len = in.read(buffer); int len = in.read(buffer);
...@@ -345,7 +332,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -345,7 +332,7 @@ public class FileSystemDisk extends FileSystem {
} }
out.close(); out.close();
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, "original: " + original + " copy: " + copy); throw DbException.convertIOException(e, "original: " + source + " copy: " + target);
} finally { } finally {
IOUtils.closeSilently(in); IOUtils.closeSilently(in);
IOUtils.closeSilently(out); IOUtils.closeSilently(out);
...@@ -392,7 +379,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -392,7 +379,7 @@ public class FileSystemDisk extends FileSystem {
File file = new File(fileName); File file = new File(fileName);
createDirs(file.getAbsolutePath()); createDirs(file.getAbsolutePath());
FileOutputStream out = new FileOutputStream(fileName, append); FileOutputStream out = new FileOutputStream(fileName, append);
trace("openFileOutputStream", fileName, out); IOUtils.trace("openFileOutputStream", fileName, out);
return out; return out;
} catch (IOException e) { } catch (IOException e) {
freeMemoryAndFinalize(); freeMemoryAndFinalize();
...@@ -414,7 +401,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -414,7 +401,7 @@ public class FileSystemDisk extends FileSystem {
} }
fileName = translateFileName(fileName); fileName = translateFileName(fileName);
FileInputStream in = new FileInputStream(fileName); FileInputStream in = new FileInputStream(fileName);
trace("openFileInputStream", fileName, in); IOUtils.trace("openFileInputStream", fileName, in);
return in; return in;
} }
...@@ -422,8 +409,8 @@ public class FileSystemDisk extends FileSystem { ...@@ -422,8 +409,8 @@ public class FileSystemDisk extends FileSystem {
* Call the garbage collection and run finalization. This close all files that * Call the garbage collection and run finalization. This close all files that
* were not closed, and are no longer referenced. * were not closed, and are no longer referenced.
*/ */
protected void freeMemoryAndFinalize() { static void freeMemoryAndFinalize() {
trace("freeMemoryAndFinalize", null, null); IOUtils.trace("freeMemoryAndFinalize", null, null);
Runtime rt = Runtime.getRuntime(); Runtime rt = Runtime.getRuntime();
long mem = rt.freeMemory(); long mem = rt.freeMemory();
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
...@@ -442,7 +429,7 @@ public class FileSystemDisk extends FileSystem { ...@@ -442,7 +429,7 @@ public class FileSystemDisk extends FileSystem {
FileObjectDisk f; FileObjectDisk f;
try { try {
f = new FileObjectDisk(fileName, mode); f = new FileObjectDisk(fileName, mode);
trace("openRandomAccessFile", fileName, f); IOUtils.trace("openFileObject", fileName, f);
} catch (IOException e) { } catch (IOException e) {
freeMemoryAndFinalize(); freeMemoryAndFinalize();
try { try {
...@@ -458,4 +445,8 @@ public class FileSystemDisk extends FileSystem { ...@@ -458,4 +445,8 @@ public class FileSystemDisk extends FileSystem {
return true; return true;
} }
public String unwrap(String fileName) {
return fileName;
}
} }
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
package org.h2.store.fs; package org.h2.store.fs;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import org.h2.util.IOUtils;
/** /**
* This file system stores files on disk and uses java.nio to access the files. * This file system stores files on disk and uses java.nio to access the files.
* This class uses FileChannel. * This class uses FileChannel.
*/ */
public class FileSystemDiskNio extends FileSystemDisk { public class FileSystemDiskNio extends FileSystemWrapper {
/** /**
* The prefix for the file system that uses java.nio.channels.FileChannel. * The prefix for the file system that uses java.nio.channels.FileChannel.
...@@ -24,51 +24,14 @@ public class FileSystemDiskNio extends FileSystemDisk { ...@@ -24,51 +24,14 @@ public class FileSystemDiskNio extends FileSystemDisk {
FileSystem.register(new FileSystemDiskNio()); FileSystem.register(new FileSystemDiskNio());
} }
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
String file = super.createTempFile(name, suffix, deleteOnExit, inTempDir);
return getPrefix() + file;
}
protected String translateFileName(String fileName) {
if (fileName.startsWith(getPrefix())) {
fileName = fileName.substring(getPrefix().length());
}
return super.translateFileName(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException {
return super.openFileInputStream(translateFileName(fileName));
}
public String normalize(String fileName) {
return getPrefix() + super.normalize(fileName);
}
public String[] listFiles(String path) {
String[] list = super.listFiles(path);
for (int i = 0; list != null && i < list.length; i++) {
list[i] = getPrefix() + list[i];
}
return list;
}
public String getParent(String fileName) {
return getPrefix() + super.getParent(fileName);
}
public String getAbsolutePath(String fileName) {
return getPrefix() + super.getAbsolutePath(fileName);
}
public FileObject openFileObject(String fileName, String mode) throws IOException { public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
FileObject f; FileObject f;
try { try {
f = open(fileName, mode); f = open(fileName, mode);
trace("openRandomAccessFile", fileName, f); IOUtils.trace("openFileObject", fileName, f);
} catch (IOException e) { } catch (IOException e) {
freeMemoryAndFinalize(); FileSystemDisk.freeMemoryAndFinalize();
try { try {
f = open(fileName, mode); f = open(fileName, mode);
} catch (IOException e2) { } catch (IOException e2) {
...@@ -99,8 +62,4 @@ public class FileSystemDiskNio extends FileSystemDisk { ...@@ -99,8 +62,4 @@ public class FileSystemDiskNio extends FileSystemDisk {
return new FileObjectDiskChannel(fileName, mode); return new FileObjectDiskChannel(fileName, mode);
} }
protected boolean accepts(String fileName) {
return fileName.startsWith(getPrefix());
}
} }
...@@ -168,13 +168,13 @@ public class FileSystemMemory extends FileSystem { ...@@ -168,13 +168,13 @@ public class FileSystemMemory extends FileSystem {
return true; return true;
} }
public void copy(String original, String copy) { public void copy(String source, String target) {
try { try {
OutputStream out = openFileOutputStream(copy, false); OutputStream out = openFileOutputStream(target, false);
InputStream in = openFileInputStream(original); InputStream in = openFileInputStream(source);
IOUtils.copyAndClose(in, out); IOUtils.copyAndClose(in, out);
} catch (IOException e) { } catch (IOException e) {
throw DbException.convertIOException(e, "Can not copy " + original + " to " + copy); throw DbException.convertIOException(e, "Can not copy " + source + " to " + target);
} }
} }
...@@ -231,4 +231,8 @@ public class FileSystemMemory extends FileSystem { ...@@ -231,4 +231,8 @@ public class FileSystemMemory extends FileSystem {
return fileName.startsWith(PREFIX) || fileName.startsWith(PREFIX_LZF); return fileName.startsWith(PREFIX) || fileName.startsWith(PREFIX_LZF);
} }
public String unwrap(String fileName) {
return fileName;
}
} }
...@@ -20,7 +20,7 @@ import org.h2.util.New; ...@@ -20,7 +20,7 @@ import org.h2.util.New;
* A file system that may split files into multiple smaller files. * A file system that may split files into multiple smaller files.
* (required for a FAT32 because it only support files up to 2 GB). * (required for a FAT32 because it only support files up to 2 GB).
*/ */
public class FileSystemSplit extends FileSystem { public class FileSystemSplit extends FileSystemWrapper {
/** /**
* The prefix to use for this file system. * The prefix to use for this file system.
...@@ -35,13 +35,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -35,13 +35,8 @@ public class FileSystemSplit extends FileSystem {
FileSystem.register(new FileSystemSplit()); FileSystem.register(new FileSystemSplit());
} }
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).canWrite(fileName);
}
public boolean setReadOnly(String fileName) { public boolean setReadOnly(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
boolean result = false; boolean result = false;
for (int i = 0;; i++) { for (int i = 0;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
...@@ -54,14 +49,14 @@ public class FileSystemSplit extends FileSystem { ...@@ -54,14 +49,14 @@ public class FileSystemSplit extends FileSystem {
return result; return result;
} }
public void copy(String original, String copy) { public void copy(String source, String target) {
original = translateFileName(original); source = unwrap(source);
copy = translateFileName(copy); target = unwrap(target);
getFileSystem(original).copy(original, copy); getFileSystem(source).copy(source, target);
for (int i = 1;; i++) { for (int i = 1;; i++) {
String o = getFileName(original, i); String o = getFileName(source, i);
if (getFileSystem(o).exists(o)) { if (getFileSystem(o).exists(o)) {
String c = getFileName(copy, i); String c = getFileName(target, i);
getFileSystem(o).copy(o, c); getFileSystem(o).copy(o, c);
} else { } else {
break; break;
...@@ -69,24 +64,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -69,24 +64,8 @@ public class FileSystemSplit extends FileSystem {
} }
} }
public void createDirs(String fileName) {
fileName = translateFileName(fileName);
getFileSystem(fileName).createDirs(fileName);
}
public boolean createNewFile(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).createNewFile(fileName);
}
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
prefix = translateFileName(prefix);
return PREFIX + getFileSystem(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
}
public void delete(String fileName) { public void delete(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
for (int i = 0;; i++) { for (int i = 0;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
if (getFileSystem(fileName).exists(f)) { if (getFileSystem(fileName).exists(f)) {
...@@ -97,34 +76,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -97,34 +76,8 @@ public class FileSystemSplit extends FileSystem {
} }
} }
public void deleteRecursive(String directory, boolean tryOnly) {
directory = translateFileName(directory);
getFileSystem(directory).deleteRecursive(directory, tryOnly);
}
public boolean exists(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).exists(fileName);
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
prefix = translateFileName(prefix);
return getFileSystem(fileName).fileStartsWith(fileName, prefix);
}
public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + getFileSystem(fileName).getAbsolutePath(fileName);
}
public String getFileName(String name) {
name = translateFileName(name);
return getFileSystem(name).getFileName(name);
}
public long getLastModified(String fileName) { public long getLastModified(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
long lastModified = 0; long lastModified = 0;
for (int i = 0;; i++) { for (int i = 0;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
...@@ -138,28 +91,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -138,28 +91,8 @@ public class FileSystemSplit extends FileSystem {
return lastModified; return lastModified;
} }
public String getParent(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + getFileSystem(fileName).getParent(fileName);
}
public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).isAbsolute(fileName);
}
public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).isDirectory(fileName);
}
public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).isReadOnly(fileName);
}
public long length(String fileName) { public long length(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
long length = 0; long length = 0;
for (int i = 0;; i++) { for (int i = 0;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
...@@ -173,15 +106,13 @@ public class FileSystemSplit extends FileSystem { ...@@ -173,15 +106,13 @@ public class FileSystemSplit extends FileSystem {
} }
public String[] listFiles(String directory) { public String[] listFiles(String directory) {
directory = translateFileName(directory); String[] array = super.listFiles(directory);
String[] array = getFileSystem(directory).listFiles(directory);
ArrayList<String> list = New.arrayList(); ArrayList<String> list = New.arrayList();
for (int i = 0; i < array.length; i++) { for (int i = 0; i < array.length; i++) {
String f = array[i]; String f = array[i];
if (f.endsWith(PART_SUFFIX)) { if (f.endsWith(PART_SUFFIX)) {
continue; continue;
} }
array[i] = f = PREFIX + f;
list.add(f); list.add(f);
} }
if (list.size() != array.length) { if (list.size() != array.length) {
...@@ -191,13 +122,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -191,13 +122,8 @@ public class FileSystemSplit extends FileSystem {
return array; return array;
} }
public String normalize(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + getFileSystem(fileName).normalize(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException { public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
InputStream input = getFileSystem(fileName).openFileInputStream(fileName); InputStream input = getFileSystem(fileName).openFileInputStream(fileName);
for (int i = 1;; i++) { for (int i = 1;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
...@@ -212,7 +138,7 @@ public class FileSystemSplit extends FileSystem { ...@@ -212,7 +138,7 @@ public class FileSystemSplit extends FileSystem {
} }
public FileObject openFileObject(String fileName, String mode) throws IOException { public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
ArrayList<FileObject> list = New.arrayList(); ArrayList<FileObject> list = New.arrayList();
FileObject o = getFileSystem(fileName).openFileObject(fileName, mode); FileObject o = getFileSystem(fileName).openFileObject(fileName, mode);
list.add(o); list.add(o);
...@@ -265,14 +191,16 @@ public class FileSystemSplit extends FileSystem { ...@@ -265,14 +191,16 @@ public class FileSystemSplit extends FileSystem {
} }
public OutputStream openFileOutputStream(String fileName, boolean append) { public OutputStream openFileOutputStream(String fileName, boolean append) {
fileName = translateFileName(fileName); try {
// TODO the output stream is not split return new FileObjectOutputStream(openFileObject(fileName, "rw"), append);
return getFileSystem(fileName).openFileOutputStream(fileName, append); } catch (IOException e) {
throw DbException.convertIOException(e, fileName);
}
} }
public void rename(String oldName, String newName) { public void rename(String oldName, String newName) {
oldName = translateFileName(oldName); oldName = unwrap(oldName);
newName = translateFileName(newName); newName = unwrap(newName);
for (int i = 0;; i++) { for (int i = 0;; i++) {
String o = getFileName(oldName, i); String o = getFileName(oldName, i);
if (getFileSystem(o).exists(o)) { if (getFileSystem(o).exists(o)) {
...@@ -285,7 +213,7 @@ public class FileSystemSplit extends FileSystem { ...@@ -285,7 +213,7 @@ public class FileSystemSplit extends FileSystem {
} }
public boolean tryDelete(String fileName) { public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
for (int i = 0;; i++) { for (int i = 0;; i++) {
String f = getFileName(fileName, i); String f = getFileName(fileName, i);
if (getFileSystem(fileName).exists(f)) { if (getFileSystem(fileName).exists(f)) {
...@@ -300,7 +228,7 @@ public class FileSystemSplit extends FileSystem { ...@@ -300,7 +228,7 @@ public class FileSystemSplit extends FileSystem {
return true; return true;
} }
private String translateFileName(String fileName) { public String unwrap(String fileName) {
if (!fileName.startsWith(PREFIX)) { if (!fileName.startsWith(PREFIX)) {
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX); DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
} }
...@@ -336,8 +264,8 @@ public class FileSystemSplit extends FileSystem { ...@@ -336,8 +264,8 @@ public class FileSystemSplit extends FileSystem {
return FileSystem.getInstance(fileName); return FileSystem.getInstance(fileName);
} }
protected boolean accepts(String fileName) { protected String getPrefix() {
return fileName.startsWith(PREFIX); return PREFIX;
} }
} }
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.h2.message.DbException;
import org.h2.util.IOUtils;
/**
* The base class for wrapping / delegating file systems such as
* FileSystemSplit
*/
public abstract class FileSystemWrapper extends FileSystem {
/**
* Get the prefix for this file system.
*
* @return the prefix
*/
protected abstract String getPrefix();
/**
* Wrap the file object if required.
*
* @param o the file object
* @return the wrapped object
*/
protected FileObject wrap(FileObject o) {
return null;
}
public boolean canWrite(String fileName) {
return IOUtils.canWrite(unwrap(fileName));
}
public boolean setReadOnly(String fileName) {
return IOUtils.setReadOnly(unwrap(fileName));
}
public void copy(String source, String target) {
IOUtils.copy(unwrap(source), unwrap(target));
}
public void createDirs(String fileName) {
IOUtils.createDirs(unwrap(fileName));
}
public boolean createNewFile(String fileName) {
return IOUtils.createNewFile(unwrap(fileName));
}
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
return wrap(IOUtils.createTempFile(unwrap(prefix), suffix, deleteOnExit, inTempDir));
}
public void delete(String fileName) {
IOUtils.delete(unwrap(fileName));
}
public void deleteRecursive(String directory, boolean tryOnly) {
IOUtils.deleteRecursive(unwrap(directory), tryOnly);
}
public boolean exists(String fileName) {
return IOUtils.exists(unwrap(fileName));
}
public boolean fileStartsWith(String fileName, String prefix) {
return IOUtils.fileStartsWith(unwrap(fileName), unwrap(prefix));
}
public String getAbsolutePath(String fileName) {
return wrap(IOUtils.getAbsolutePath(unwrap(fileName)));
}
public String getFileName(String name) {
return IOUtils.getFileName(unwrap(name));
}
public long getLastModified(String fileName) {
return IOUtils.getLastModified(unwrap(fileName));
}
public String getParent(String fileName) {
return wrap(IOUtils.getParent(unwrap(fileName)));
}
public boolean isAbsolute(String fileName) {
return IOUtils.isAbsolute(unwrap(fileName));
}
public boolean isDirectory(String fileName) {
return IOUtils.isDirectory(unwrap(fileName));
}
public boolean isReadOnly(String fileName) {
return IOUtils.isReadOnly(unwrap(fileName));
}
public long length(String fileName) {
return IOUtils.length(unwrap(fileName));
}
public String[] listFiles(String directory) {
String[] array = IOUtils.listFiles(unwrap(directory));
for (int i = 0; i < array.length; i++) {
array[i] = wrap(array[i]);
}
return array;
}
public String normalize(String fileName) {
return wrap(IOUtils.normalize(unwrap(fileName)));
}
public InputStream openFileInputStream(String fileName) throws IOException {
return IOUtils.openFileInputStream(unwrap(fileName));
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
return IOUtils.openFileObject(unwrap(fileName), mode);
}
public OutputStream openFileOutputStream(String fileName, boolean append) {
return IOUtils.openFileOutputStream(unwrap(fileName), append);
}
public void rename(String oldName, String newName) {
IOUtils.rename(unwrap(oldName), unwrap(newName));
}
public boolean tryDelete(String fileName) {
return IOUtils.tryDelete(unwrap(fileName));
}
protected boolean accepts(String fileName) {
return fileName.startsWith(getPrefix());
}
private String wrap(String fileName) {
return getPrefix() + fileName;
}
public String unwrap(String fileName) {
String prefix = getPrefix();
if (!fileName.startsWith(prefix)) {
DbException.throwInternalError(fileName + " doesn't start with " + prefix);
}
return fileName.substring(prefix.length());
}
}
...@@ -253,4 +253,8 @@ public class FileSystemZip extends FileSystem { ...@@ -253,4 +253,8 @@ public class FileSystemZip extends FileSystem {
return fileName.startsWith(PREFIX); return fileName.startsWith(PREFIX);
} }
public String unwrap(String fileName) {
return fileName;
}
} }
...@@ -19,7 +19,6 @@ import org.h2.command.dml.BackupCommand; ...@@ -19,7 +19,6 @@ import org.h2.command.dml.BackupCommand;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.Tool; import org.h2.util.Tool;
...@@ -110,7 +109,7 @@ public class Backup extends Tool { ...@@ -110,7 +109,7 @@ public class Backup extends Tool {
List<String> list; List<String> list;
boolean allFiles = db != null && db.length() == 0; boolean allFiles = db != null && db.length() == 0;
if (allFiles) { if (allFiles) {
list = Arrays.asList(FileSystem.getInstance(directory).listFiles(directory)); list = Arrays.asList(IOUtils.listFiles(directory));
} else { } else {
list = FileLister.getDatabaseFiles(directory, db, true); list = FileLister.getDatabaseFiles(directory, db, true);
} }
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
package org.h2.tools; package org.h2.tools;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
...@@ -14,6 +13,7 @@ import java.sql.SQLException; ...@@ -14,6 +13,7 @@ import java.sql.SQLException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.h2.constant.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -146,7 +146,7 @@ public class Restore extends Tool { ...@@ -146,7 +146,7 @@ public class Restore extends Tool {
if (originalDbName == null) { if (originalDbName == null) {
throw new IOException("No database named " + db + " found"); throw new IOException("No database named " + db + " found");
} }
if (originalDbName.startsWith(File.separator)) { if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) {
originalDbName = originalDbName.substring(1); originalDbName = originalDbName.substring(1);
} }
originalDbLen = originalDbName.length(); originalDbLen = originalDbName.length();
...@@ -160,9 +160,9 @@ public class Restore extends Tool { ...@@ -160,9 +160,9 @@ public class Restore extends Tool {
} }
String fileName = entry.getName(); String fileName = entry.getName();
// restoring windows backups on linux and vice versa // restoring windows backups on linux and vice versa
fileName = fileName.replace('\\', File.separatorChar); fileName = fileName.replace('\\', SysProperties.FILE_SEPARATOR.charAt(0));
fileName = fileName.replace('/', File.separatorChar); fileName = fileName.replace('/', SysProperties.FILE_SEPARATOR.charAt(0));
if (fileName.startsWith(File.separator)) { if (fileName.startsWith(SysProperties.FILE_SEPARATOR)) {
fileName = fileName.substring(1); fileName = fileName.substring(1);
} }
boolean copy = false; boolean copy = false;
...@@ -175,7 +175,7 @@ public class Restore extends Tool { ...@@ -175,7 +175,7 @@ public class Restore extends Tool {
if (copy) { if (copy) {
OutputStream o = null; OutputStream o = null;
try { try {
o = IOUtils.openFileOutputStream(directory + File.separator + fileName, false); o = IOUtils.openFileOutputStream(directory + SysProperties.FILE_SEPARATOR + fileName, false);
IOUtils.copy(zipIn, o); IOUtils.copy(zipIn, o);
o.close(); o.close();
} finally { } finally {
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
package org.h2.tools; package org.h2.tools;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
...@@ -17,6 +16,7 @@ import java.sql.DriverManager; ...@@ -17,6 +16,7 @@ import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -201,7 +201,7 @@ public class RunScript extends Tool { ...@@ -201,7 +201,7 @@ public class RunScript extends Tool {
sql = trim; sql = trim;
sql = sql.substring("@INCLUDE".length()).trim(); sql = sql.substring("@INCLUDE".length()).trim();
if (!IOUtils.isAbsolute(sql)) { if (!IOUtils.isAbsolute(sql)) {
sql = path + File.separator + sql; sql = path + SysProperties.FILE_SEPARATOR + sql;
} }
process(conn, sql, continueOnError, charsetName); process(conn, sql, continueOnError, charsetName);
} else { } else {
......
...@@ -16,7 +16,6 @@ import java.util.UUID; ...@@ -16,7 +16,6 @@ import java.util.UUID;
import org.h2.engine.ConnectionInfo; import org.h2.engine.ConnectionInfo;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -155,7 +154,7 @@ public class DbUpgrade { ...@@ -155,7 +154,7 @@ public class DbUpgrade {
if (deleteOldDb) { if (deleteOldDb) {
IOUtils.delete(backupData); IOUtils.delete(backupData);
IOUtils.delete(backupIndex); IOUtils.delete(backupIndex);
FileSystem.getInstance(name).deleteRecursive(backupLobs, false); IOUtils.deleteRecursive(backupLobs, false);
} }
} catch (Exception e) { } catch (Exception e) {
if (IOUtils.exists(backupData)) { if (IOUtils.exists(backupData)) {
......
...@@ -25,6 +25,7 @@ import java.io.Writer; ...@@ -25,6 +25,7 @@ import java.io.Writer;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
/** /**
...@@ -522,7 +523,58 @@ public class IOUtils { ...@@ -522,7 +523,58 @@ public class IOUtils {
* @return just the file name * @return just the file name
*/ */
public static String getFileName(String name) { public static String getFileName(String name) {
return FileSystem.getInstance(name).getFileName(name); return getFileSystem(name).getFileName(name);
}
/**
* Check if the file is writable.
*
* @param fileName the file name
* @return if the file is writable
*/
public static boolean canWrite(String fileName) {
return getFileSystem(fileName).canWrite(fileName);
}
/**
* Disable the ability to write.
*
* @param fileName the file name
* @return true if the call was successful
*/
public static boolean setReadOnly(String fileName) {
return getFileSystem(fileName).setReadOnly(fileName);
}
/**
* Copy a file from one directory to another, or to another file.
*
* @param original the original file name
* @param copy the file name of the copy
*/
public static void copy(String original, String copy) {
getFileSystem(original).copy(original, copy);
}
/**
* Create a new file.
*
* @param fileName the file name
* @return true if creating was successful
*/
public static boolean createNewFile(String fileName) {
return getFileSystem(fileName).createNewFile(fileName);
}
/**
* Open a random access file object.
*
* @param fileName the file name
* @param mode the access mode. Supported are r, rw, rws, rwd
* @return the file object
*/
public static FileObject openFileObject(String fileName, String mode) throws IOException {
return getFileSystem(fileName).openFileObject(fileName, mode);
} }
/** /**
...@@ -532,7 +584,7 @@ public class IOUtils { ...@@ -532,7 +584,7 @@ public class IOUtils {
* @return the normalized file name * @return the normalized file name
*/ */
public static String normalize(String fileName) { public static String normalize(String fileName) {
return FileSystem.getInstance(fileName).normalize(fileName); return getFileSystem(fileName).normalize(fileName);
} }
/** /**
...@@ -542,7 +594,7 @@ public class IOUtils { ...@@ -542,7 +594,7 @@ public class IOUtils {
* @return true if it worked * @return true if it worked
*/ */
public static boolean tryDelete(String fileName) { public static boolean tryDelete(String fileName) {
return FileSystem.getInstance(fileName).tryDelete(fileName); return getFileSystem(fileName).tryDelete(fileName);
} }
/** /**
...@@ -552,7 +604,7 @@ public class IOUtils { ...@@ -552,7 +604,7 @@ public class IOUtils {
* @return if it is read only * @return if it is read only
*/ */
public static boolean isReadOnly(String fileName) { public static boolean isReadOnly(String fileName) {
return FileSystem.getInstance(fileName).isReadOnly(fileName); return getFileSystem(fileName).isReadOnly(fileName);
} }
/** /**
...@@ -562,7 +614,7 @@ public class IOUtils { ...@@ -562,7 +614,7 @@ public class IOUtils {
* @return true if it exists * @return true if it exists
*/ */
public static boolean exists(String fileName) { public static boolean exists(String fileName) {
return FileSystem.getInstance(fileName).exists(fileName); return getFileSystem(fileName).exists(fileName);
} }
/** /**
...@@ -572,7 +624,7 @@ public class IOUtils { ...@@ -572,7 +624,7 @@ public class IOUtils {
* @return the length in bytes * @return the length in bytes
*/ */
public static long length(String fileName) { public static long length(String fileName) {
return FileSystem.getInstance(fileName).length(fileName); return getFileSystem(fileName).length(fileName);
} }
/** /**
...@@ -588,7 +640,7 @@ public class IOUtils { ...@@ -588,7 +640,7 @@ public class IOUtils {
*/ */
public static String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) public static String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException { throws IOException {
return FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir); return getFileSystem(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
} }
/** /**
...@@ -598,7 +650,7 @@ public class IOUtils { ...@@ -598,7 +650,7 @@ public class IOUtils {
* @return the parent directory name * @return the parent directory name
*/ */
public static String getParent(String fileName) { public static String getParent(String fileName) {
return FileSystem.getInstance(fileName).getParent(fileName); return getFileSystem(fileName).getParent(fileName);
} }
/** /**
...@@ -608,7 +660,7 @@ public class IOUtils { ...@@ -608,7 +660,7 @@ public class IOUtils {
* @return the list of fully qualified file names * @return the list of fully qualified file names
*/ */
public static String[] listFiles(String path) { public static String[] listFiles(String path) {
return FileSystem.getInstance(path).listFiles(path); return getFileSystem(path).listFiles(path);
} }
/** /**
...@@ -618,7 +670,7 @@ public class IOUtils { ...@@ -618,7 +670,7 @@ public class IOUtils {
* @return true if it is a directory * @return true if it is a directory
*/ */
public static boolean isDirectory(String fileName) { public static boolean isDirectory(String fileName) {
return FileSystem.getInstance(fileName).isDirectory(fileName); return getFileSystem(fileName).isDirectory(fileName);
} }
/** /**
...@@ -628,7 +680,7 @@ public class IOUtils { ...@@ -628,7 +680,7 @@ public class IOUtils {
* @return if the file name is absolute * @return if the file name is absolute
*/ */
public static boolean isAbsolute(String fileName) { public static boolean isAbsolute(String fileName) {
return FileSystem.getInstance(fileName).isAbsolute(fileName); return getFileSystem(fileName).isAbsolute(fileName);
} }
/** /**
...@@ -638,7 +690,7 @@ public class IOUtils { ...@@ -638,7 +690,7 @@ public class IOUtils {
* @return the absolute file name * @return the absolute file name
*/ */
public static String getAbsolutePath(String fileName) { public static String getAbsolutePath(String fileName) {
return FileSystem.getInstance(fileName).getAbsolutePath(fileName); return getFileSystem(fileName).getAbsolutePath(fileName);
} }
/** /**
...@@ -649,7 +701,7 @@ public class IOUtils { ...@@ -649,7 +701,7 @@ public class IOUtils {
* @return true if it starts with the prefix * @return true if it starts with the prefix
*/ */
public static boolean fileStartsWith(String fileName, String prefix) { public static boolean fileStartsWith(String fileName, String prefix) {
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix); return getFileSystem(fileName).fileStartsWith(fileName, prefix);
} }
/** /**
...@@ -659,7 +711,7 @@ public class IOUtils { ...@@ -659,7 +711,7 @@ public class IOUtils {
* @return the input stream * @return the input stream
*/ */
public static InputStream openFileInputStream(String fileName) throws IOException { public static InputStream openFileInputStream(String fileName) throws IOException {
return FileSystem.getInstance(fileName).openFileInputStream(fileName); return getFileSystem(fileName).openFileInputStream(fileName);
} }
/** /**
...@@ -671,7 +723,7 @@ public class IOUtils { ...@@ -671,7 +723,7 @@ public class IOUtils {
* @return the output stream * @return the output stream
*/ */
public static OutputStream openFileOutputStream(String fileName, boolean append) { public static OutputStream openFileOutputStream(String fileName, boolean append) {
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append); return getFileSystem(fileName).openFileOutputStream(fileName, append);
} }
/** /**
...@@ -681,7 +733,7 @@ public class IOUtils { ...@@ -681,7 +733,7 @@ public class IOUtils {
* @param newName the new fully qualified file name * @param newName the new fully qualified file name
*/ */
public static void rename(String oldName, String newName) { public static void rename(String oldName, String newName) {
FileSystem.getInstance(oldName).rename(oldName, newName); getFileSystem(oldName).rename(oldName, newName);
} }
/** /**
...@@ -690,7 +742,7 @@ public class IOUtils { ...@@ -690,7 +742,7 @@ public class IOUtils {
* @param fileName the file name (not directory name) * @param fileName the file name (not directory name)
*/ */
public static void createDirs(String fileName) { public static void createDirs(String fileName) {
FileSystem.getInstance(fileName).createDirs(fileName); getFileSystem(fileName).createDirs(fileName);
} }
/** /**
...@@ -699,7 +751,17 @@ public class IOUtils { ...@@ -699,7 +751,17 @@ public class IOUtils {
* @param fileName the file name * @param fileName the file name
*/ */
public static void delete(String fileName) { public static void delete(String fileName) {
FileSystem.getInstance(fileName).delete(fileName); getFileSystem(fileName).delete(fileName);
}
/**
* Delete a directory or file and all subdirectories and files.
*
* @param directory the directory
* @param tryOnly whether errors should be ignored
*/
public static void deleteRecursive(String directory, boolean tryOnly) {
getFileSystem(directory).deleteRecursive(directory, tryOnly);
} }
/** /**
...@@ -709,40 +771,34 @@ public class IOUtils { ...@@ -709,40 +771,34 @@ public class IOUtils {
* @return the last modified date * @return the last modified date
*/ */
public static long getLastModified(String fileName) { public static long getLastModified(String fileName) {
return FileSystem.getInstance(fileName).getLastModified(fileName); return getFileSystem(fileName).getLastModified(fileName);
} }
/** /**
* Trace input or output operations if enabled. * Get the unwrapped file name (without wrapper prefixes if wrapping /
* delegating file systems are used).
* *
* @param method the method from where this method was called
* @param fileName the file name * @param fileName the file name
* @param o the object to append to the message * @return the unwrapped
*/ */
static void trace(String method, String fileName, Object o) { public static String unwrap(String fileName) {
if (SysProperties.TRACE_IO) { return getFileSystem(fileName).unwrap(fileName);
System.out.println("IOUtils." + method + " " + fileName + " " + o);
} }
private static FileSystem getFileSystem(String fileName) {
return FileSystem.getInstance(fileName);
} }
/** /**
* Checks if a file is below a given directory * Trace input or output operations if enabled.
* *
* @param file the file to check * @param method the method from where this method was called
* @param dir the directory the file must be in * @param fileName the file name
* @return true if the file is within the directory * @param o the object to append to the message
*/ */
public static boolean isInDir(File file, File dir) { public static void trace(String method, String fileName, Object o) {
try { if (SysProperties.TRACE_IO) {
String canonicalFileName = file.getCanonicalPath(); System.out.println("IOUtils." + method + " " + fileName + " " + o);
String canonicalDirName = dir.getCanonicalPath();
if (canonicalFileName.equals(canonicalDirName)) {
// the file is the directory: not allowed (file "../test" in dir "test")
return false;
}
return canonicalFileName.startsWith(canonicalDirName);
} catch (Exception e) {
return false;
} }
} }
......
...@@ -225,14 +225,14 @@ public class ValueLob extends Value { ...@@ -225,14 +225,14 @@ public class ValueLob extends Value {
String name; String name;
int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY;
if (f > 0) { if (f > 0) {
name = File.separator + objectId; name = SysProperties.FILE_SEPARATOR + objectId;
} else { } else {
name = ""; name = "";
} }
objectId /= SysProperties.LOB_FILES_PER_DIRECTORY; objectId /= SysProperties.LOB_FILES_PER_DIRECTORY;
while (objectId > 0) { while (objectId > 0) {
f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY; f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY;
name = File.separator + f + Constants.SUFFIX_LOBS_DIRECTORY + name; name = SysProperties.FILE_SEPARATOR + f + Constants.SUFFIX_LOBS_DIRECTORY + name;
objectId /= SysProperties.LOB_FILES_PER_DIRECTORY; objectId /= SysProperties.LOB_FILES_PER_DIRECTORY;
} }
name = IOUtils.normalize(path + Constants.SUFFIX_LOBS_DIRECTORY + name); name = IOUtils.normalize(path + Constants.SUFFIX_LOBS_DIRECTORY + name);
......
...@@ -9,9 +9,9 @@ package org.h2.samples; ...@@ -9,9 +9,9 @@ package org.h2.samples;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.Statement; import java.sql.Statement;
import org.h2.store.fs.FileSystem;
import org.h2.tools.Backup; import org.h2.tools.Backup;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.util.IOUtils;
/** /**
* This sample application shows how to create and use a read-only database in a * This sample application shows how to create and use a read-only database in a
...@@ -30,7 +30,7 @@ public class ReadOnlyDatabaseInZip { ...@@ -30,7 +30,7 @@ public class ReadOnlyDatabaseInZip {
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
// delete all files in this directory // delete all files in this directory
FileSystem.getInstance("~/temp").deleteRecursive("~/temp", false); IOUtils.deleteRecursive("~/temp", false);
Connection conn; Connection conn;
Class.forName("org.h2.Driver"); Class.forName("org.h2.Driver");
......
...@@ -25,10 +25,10 @@ import java.util.LinkedList; ...@@ -25,10 +25,10 @@ import java.util.LinkedList;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.store.FileLock; import org.h2.store.FileLock;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemSplit; import org.h2.store.fs.FileSystemSplit;
import org.h2.test.utils.RecordingFileSystem; import org.h2.test.utils.RecordingFileSystem;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.util.IOUtils;
/** /**
* The base class for all tests. * The base class for all tests.
...@@ -144,8 +144,8 @@ public abstract class TestBase { ...@@ -144,8 +144,8 @@ public abstract class TestBase {
} }
} finally { } finally {
try { try {
FileSystem.getInstance("memFS:").deleteRecursive("memFS:", false); IOUtils.deleteRecursive("memFS:", false);
FileSystem.getInstance("memLZF:").deleteRecursive("memLZF:", false); IOUtils.deleteRecursive("memLZF:", false);
} catch (RuntimeException e) { } catch (RuntimeException e) {
e.printStackTrace(); e.printStackTrace();
} }
......
...@@ -18,8 +18,6 @@ import java.sql.SQLException; ...@@ -18,8 +18,6 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Properties; import java.util.Properties;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
...@@ -77,7 +75,7 @@ public class TestPerformance { ...@@ -77,7 +75,7 @@ public class TestPerformance {
if ("-db".equals(arg)) { if ("-db".equals(arg)) {
dbId = Integer.parseInt(args[++i]); dbId = Integer.parseInt(args[++i]);
} else if ("-init".equals(arg)) { } else if ("-init".equals(arg)) {
FileSystem.getInstance("data").deleteRecursive("data", true); IOUtils.deleteRecursive("data", true);
} else if ("-out".equals(arg)) { } else if ("-out".equals(arg)) {
out = args[++i]; out = args[++i];
} else if ("-trace".equals(arg)) { } else if ("-trace".equals(arg)) {
......
...@@ -17,6 +17,7 @@ import java.util.StringTokenizer; ...@@ -17,6 +17,7 @@ import java.util.StringTokenizer;
import org.h2.fulltext.FullText; import org.h2.fulltext.FullText;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.Task; import org.h2.util.Task;
/** /**
...@@ -113,7 +114,7 @@ public class TestFullText extends TestBase { ...@@ -113,7 +114,7 @@ public class TestFullText extends TestBase {
} }
String prefix = lucene ? "FTL" : "FT"; String prefix = lucene ? "FTL" : "FT";
deleteDb("fullTextTransaction"); deleteDb("fullTextTransaction");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullTextTransaction", false); IOUtils.deleteRecursive(getBaseDir() + "/fullTextTransaction", false);
Connection conn = getConnection("fullTextTransaction"); Connection conn = getConnection("fullTextTransaction");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
String className = lucene ? "FullTextLucene" : "FullText"; String className = lucene ? "FullTextLucene" : "FullText";
...@@ -246,7 +247,7 @@ public class TestFullText extends TestBase { ...@@ -246,7 +247,7 @@ public class TestFullText extends TestBase {
private void testCreateDrop() throws SQLException { private void testCreateDrop() throws SQLException {
deleteDb("fullText"); deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false); IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
Connection conn = getConnection("fullText"); Connection conn = getConnection("fullText");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS IF NOT EXISTS FT_INIT FOR \"org.h2.fulltext.FullText.init\""); stat.execute("CREATE ALIAS IF NOT EXISTS FT_INIT FOR \"org.h2.fulltext.FullText.init\"");
...@@ -257,13 +258,13 @@ public class TestFullText extends TestBase { ...@@ -257,13 +258,13 @@ public class TestFullText extends TestBase {
} }
conn.close(); conn.close();
deleteDb("fullText"); deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false); IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
} }
private void testReopen(boolean lucene) throws SQLException { private void testReopen(boolean lucene) throws SQLException {
String prefix = lucene ? "FTL" : "FT"; String prefix = lucene ? "FTL" : "FT";
deleteDb("fullTextReopen"); deleteDb("fullTextReopen");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullTextReopen", false); IOUtils.deleteRecursive(getBaseDir() + "/fullTextReopen", false);
Connection conn = getConnection("fullTextReopen"); Connection conn = getConnection("fullTextReopen");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
String className = lucene ? "FullTextLucene" : "FullText"; String className = lucene ? "FullTextLucene" : "FullText";
...@@ -294,7 +295,7 @@ public class TestFullText extends TestBase { ...@@ -294,7 +295,7 @@ public class TestFullText extends TestBase {
private void testPerformance(boolean lucene) throws SQLException { private void testPerformance(boolean lucene) throws SQLException {
deleteDb("fullText"); deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false); IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
Connection conn = getConnection("fullText"); Connection conn = getConnection("fullText");
String prefix = lucene ? "FTL" : "FT"; String prefix = lucene ? "FTL" : "FT";
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -24,7 +24,6 @@ import java.util.Properties; ...@@ -24,7 +24,6 @@ import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import org.h2.api.AggregateFunction; import org.h2.api.AggregateFunction;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -63,7 +62,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -63,7 +62,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
testFunctions(); testFunctions();
testFileRead(); testFileRead();
deleteDb("functions"); deleteDb("functions");
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true); IOUtils.deleteRecursive(TEMP_DIR, true);
} }
private void testFunctionInSchema() throws SQLException { private void testFunctionInSchema() throws SQLException {
......
...@@ -26,7 +26,6 @@ import java.util.Random; ...@@ -26,7 +26,6 @@ import java.util.Random;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -86,7 +85,7 @@ public class TestLob extends TestBase { ...@@ -86,7 +85,7 @@ public class TestLob extends TestBase {
testLob(true); testLob(true);
testJavaObject(); testJavaObject();
deleteDb("lob"); deleteDb("lob");
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true); IOUtils.deleteRecursive(TEMP_DIR, true);
} }
private void testUniqueIndex() throws Exception { private void testUniqueIndex() throws Exception {
...@@ -212,7 +211,7 @@ public class TestLob extends TestBase { ...@@ -212,7 +211,7 @@ public class TestLob extends TestBase {
private void testTempFilesDeleted() throws Exception { private void testTempFilesDeleted() throws Exception {
String[] list; String[] list;
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true); IOUtils.deleteRecursive(TEMP_DIR, true);
IOUtils.mkdirs(new File(TEMP_DIR)); IOUtils.mkdirs(new File(TEMP_DIR));
list = IOUtils.listFiles(TEMP_DIR); list = IOUtils.listFiles(TEMP_DIR);
if (list.length > 0) { if (list.length > 0) {
......
...@@ -12,7 +12,6 @@ import java.sql.DriverManager; ...@@ -12,7 +12,6 @@ import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.upgrade.DbUpgrade; import org.h2.upgrade.DbUpgrade;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -198,7 +197,7 @@ public class TestUpgrade extends TestBase { ...@@ -198,7 +197,7 @@ public class TestUpgrade extends TestBase {
} }
IOUtils.delete(getBaseDir() + "/" + dbName + ".data.db.backup"); IOUtils.delete(getBaseDir() + "/" + dbName + ".data.db.backup");
IOUtils.delete(getBaseDir() + "/" + dbName + ".index.db.backup"); IOUtils.delete(getBaseDir() + "/" + dbName + ".index.db.backup");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/" + dbName + ".lobs.db.backup", false); IOUtils.deleteRecursive(getBaseDir() + "/" + dbName + ".lobs.db.backup", false);
} }
} }
\ No newline at end of file
...@@ -17,7 +17,6 @@ import java.sql.Connection; ...@@ -17,7 +17,6 @@ import java.sql.Connection;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Task; import org.h2.util.Task;
...@@ -127,7 +126,7 @@ public class TestWeb extends TestBase { ...@@ -127,7 +126,7 @@ public class TestWeb extends TestBase {
new File("transfer/testUpload.txt").delete(); new File("transfer/testUpload.txt").delete();
} finally { } finally {
server.shutdown(); server.shutdown();
FileSystem.getInstance("transfer").deleteRecursive("transfer", true); IOUtils.deleteRecursive("transfer", true);
} }
} }
......
...@@ -16,8 +16,8 @@ import java.sql.Statement; ...@@ -16,8 +16,8 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.Random;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ScriptReader; import org.h2.util.ScriptReader;
...@@ -159,7 +159,7 @@ public class TestNestedJoins extends TestBase { ...@@ -159,7 +159,7 @@ public class TestNestedJoins extends TestBase {
} catch (Exception e) { } catch (Exception e) {
// ignore // ignore
} }
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/derby", false); IOUtils.deleteRecursive(getBaseDir() + "/derby", false);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// database not installed - ok // database not installed - ok
......
...@@ -16,8 +16,8 @@ import java.sql.Statement; ...@@ -16,8 +16,8 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.Random;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ScriptReader; import org.h2.util.ScriptReader;
...@@ -150,7 +150,7 @@ public class TestOuterJoins extends TestBase { ...@@ -150,7 +150,7 @@ public class TestOuterJoins extends TestBase {
} catch (Exception e) { } catch (Exception e) {
// ignore // ignore
} }
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/derby", false); IOUtils.deleteRecursive(getBaseDir() + "/derby", false);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// database not installed - ok // database not installed - ok
......
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.io.IOException;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemWrapper;
/**
* This file system encrypts the data.
*/
public class FileSystemCrypt extends FileSystemWrapper {
private static final String PREFIX = "aes:";
private static final int HEADER_LENGTH = 4096;
static {
FileSystem.register(new FileSystemCrypt());
}
protected String getPrefix() {
return PREFIX;
}
public long length(String fileName) {
return super.length(fileName) - HEADER_LENGTH;
}
public FileObject openFileObject(String fileName, String mode) {
return null;
}
/**
* An encrypted file.
*/
static class FileObjectCrypt implements FileObject {
// private FileObject
public void close() throws IOException {
// TODO Auto-generated method stub
}
public long getFilePointer() throws IOException {
// TODO Auto-generated method stub
return 0;
}
public String getName() {
// TODO Auto-generated method stub
return null;
}
public long length() throws IOException {
// TODO Auto-generated method stub
return 0;
}
public void readFully(byte[] b, int off, int len) throws IOException {
// TODO Auto-generated method stub
}
public void releaseLock() {
// TODO Auto-generated method stub
}
public void seek(long pos) throws IOException {
// TODO Auto-generated method stub
}
public void setFileLength(long newLength) throws IOException {
// TODO Auto-generated method stub
}
public void sync() throws IOException {
// TODO Auto-generated method stub
}
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
}
public void write(byte[] b, int off, int len) throws IOException {
// TODO Auto-generated method stub
}
}
}
...@@ -130,7 +130,7 @@ public class FileSystemDatabase extends FileSystem { ...@@ -130,7 +130,7 @@ public class FileSystemDatabase extends FileSystem {
} }
private long getId(String fileName, boolean parent) { private long getId(String fileName, boolean parent) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
log(fileName); log(fileName);
try { try {
String[] path = StringUtils.arraySplit(fileName, '/', false); String[] path = StringUtils.arraySplit(fileName, '/', false);
...@@ -155,13 +155,6 @@ public class FileSystemDatabase extends FileSystem { ...@@ -155,13 +155,6 @@ public class FileSystemDatabase extends FileSystem {
} }
} }
private String translateFileName(String fileName) {
if (fileName.startsWith(url)) {
fileName = fileName.substring(url.length());
}
return fileName;
}
private PreparedStatement prepare(String sql) throws SQLException { private PreparedStatement prepare(String sql) throws SQLException {
PreparedStatement prep = preparedMap.get(sql); PreparedStatement prep = preparedMap.get(sql);
if (prep == null) { if (prep == null) {
...@@ -182,19 +175,19 @@ public class FileSystemDatabase extends FileSystem { ...@@ -182,19 +175,19 @@ public class FileSystemDatabase extends FileSystem {
return true; return true;
} }
public void copy(String original, String copy) { public void copy(String source, String target) {
try { try {
OutputStream out = openFileOutputStream(copy, false); OutputStream out = openFileOutputStream(target, false);
InputStream in = openFileInputStream(original); InputStream in = openFileInputStream(source);
IOUtils.copyAndClose(in, out); IOUtils.copyAndClose(in, out);
} catch (IOException e) { } catch (IOException e) {
rollback(); rollback();
throw DbException.convertIOException(e, "Can not copy " + original + " to " + copy); throw DbException.convertIOException(e, "Can not copy " + source + " to " + target);
} }
} }
public void createDirs(String fileName) { public void createDirs(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
try { try {
String[] path = StringUtils.arraySplit(fileName, '/', false); String[] path = StringUtils.arraySplit(fileName, '/', false);
long parentId = 0; long parentId = 0;
...@@ -266,7 +259,7 @@ public class FileSystemDatabase extends FileSystem { ...@@ -266,7 +259,7 @@ public class FileSystemDatabase extends FileSystem {
} }
public boolean fileStartsWith(String fileName, String prefix) { public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
return fileName.startsWith(prefix); return fileName.startsWith(prefix);
} }
...@@ -275,7 +268,7 @@ public class FileSystemDatabase extends FileSystem { ...@@ -275,7 +268,7 @@ public class FileSystemDatabase extends FileSystem {
} }
public String getFileName(String fileName) { public String getFileName(String fileName) {
fileName = translateFileName(fileName); fileName = unwrap(fileName);
String[] path = StringUtils.arraySplit(fileName, '/', false); String[] path = StringUtils.arraySplit(fileName, '/', false);
return path[path.length - 1]; return path[path.length - 1];
} }
...@@ -462,4 +455,11 @@ public class FileSystemDatabase extends FileSystem { ...@@ -462,4 +455,11 @@ public class FileSystemDatabase extends FileSystem {
} }
} }
public String unwrap(String fileName) {
if (fileName.startsWith(url)) {
fileName = fileName.substring(url.length());
}
return fileName;
}
} }
...@@ -77,7 +77,7 @@ public class TestFileSystem extends TestBase { ...@@ -77,7 +77,7 @@ public class TestFileSystem extends TestBase {
private void testSplitDatabaseInZip() throws SQLException { private void testSplitDatabaseInZip() throws SQLException {
String dir = getBaseDir() + "/fs"; String dir = getBaseDir() + "/fs";
FileSystem.getInstance(dir).deleteRecursive(dir, false); IOUtils.deleteRecursive(dir, false);
Connection conn; Connection conn;
Statement stat; Statement stat;
conn = DriverManager.getConnection("jdbc:h2:split:18:"+dir+"/test"); conn = DriverManager.getConnection("jdbc:h2:split:18:"+dir+"/test");
...@@ -93,7 +93,7 @@ public class TestFileSystem extends TestBase { ...@@ -93,7 +93,7 @@ public class TestFileSystem extends TestBase {
"jdbc:h2:split:zip:"+dir+"/test.zip!/test"); "jdbc:h2:split:zip:"+dir+"/test.zip!/test");
conn.createStatement().execute("select * from test where id=1"); conn.createStatement().execute("select * from test where id=1");
conn.close(); conn.close();
FileSystem.getInstance(dir).deleteRecursive(dir, false); IOUtils.deleteRecursive(dir, false);
} }
private void testDatabaseInMemFileSys() throws SQLException { private void testDatabaseInMemFileSys() throws SQLException {
......
...@@ -190,7 +190,7 @@ public class TestRecovery extends TestBase { ...@@ -190,7 +190,7 @@ public class TestRecovery extends TestBase {
deleteDb("recovery2"); deleteDb("recovery2");
IOUtils.delete(getBaseDir() + "/recovery.h2.sql"); IOUtils.delete(getBaseDir() + "/recovery.h2.sql");
String dir = getBaseDir() + "/recovery.lobs.db"; String dir = getBaseDir() + "/recovery.lobs.db";
FileSystem.getInstance(dir).deleteRecursive(dir, false); IOUtils.deleteRecursive(dir, false);
} }
} }
...@@ -73,6 +73,7 @@ public class TestTools extends TestBase { ...@@ -73,6 +73,7 @@ public class TestTools extends TestBase {
return; return;
} }
org.h2.Driver.load(); org.h2.Driver.load();
testInMemoryBaseDir();
testConsole(); testConsole();
testJdbcDriverUtils(); testJdbcDriverUtils();
testWrongServer(); testWrongServer();
...@@ -629,7 +630,7 @@ public class TestTools extends TestBase { ...@@ -629,7 +630,7 @@ public class TestTools extends TestBase {
deleteDb("toolsRecover"); deleteDb("toolsRecover");
IOUtils.delete(getBaseDir() + "/toolsRecover.h2.sql"); IOUtils.delete(getBaseDir() + "/toolsRecover.h2.sql");
String dir = getBaseDir() + "/toolsRecover.lobs.db"; String dir = getBaseDir() + "/toolsRecover.lobs.db";
FileSystem.getInstance(dir).deleteRecursive(dir, false); IOUtils.deleteRecursive(dir, false);
} }
private void testManagementDb() throws SQLException { private void testManagementDb() throws SQLException {
...@@ -851,4 +852,23 @@ public class TestTools extends TestBase { ...@@ -851,4 +852,23 @@ public class TestTools extends TestBase {
deleteDb("testSplit"); deleteDb("testSplit");
} }
private void testInMemoryBaseDir() throws SQLException {
Connection conn;
Server tcpServer = Server.createTcpServer(
"-baseDir", "memFS:/testDir",
"-tcpPort", "9192",
"-tcpAllowOthers").start();
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9192/test", "sa", "");
conn.close();
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost:9192/split:test", "sa", "");
conn.close();
try {
DriverManager.getConnection("jdbc:h2:tcp://localhost:9192/split:../test", "sa", "");
fail("Should throw an exception!");
} catch (Throwable e) {
// Expected
}
tcpServer.stop();
}
} }
...@@ -9,14 +9,14 @@ package org.h2.test.utils; ...@@ -9,14 +9,14 @@ package org.h2.test.utils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject; import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemWrapper;
/** /**
* A debugging file system that logs all operations. * A debugging file system that logs all operations.
*/ */
public class DebugFileSystem extends FileSystem { public class DebugFileSystem extends FileSystemWrapper {
/** /**
* The prefix used for a debugging file system. * The prefix used for a debugging file system.
...@@ -60,184 +60,146 @@ public class DebugFileSystem extends FileSystem { ...@@ -60,184 +60,146 @@ public class DebugFileSystem extends FileSystem {
} }
public boolean canWrite(String fileName) { public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "canWrite"); trace(fileName, "canWrite");
return FileSystem.getInstance(fileName).canWrite(fileName); return super.canWrite(fileName);
} }
public void copy(String original, String copy) { public void copy(String source, String target) {
original = translateFileName(original); trace(source, "copy", unwrap(target));
copy = translateFileName(copy); super.copy(source, target);
trace(original, "copy", copy);
FileSystem.getInstance(original).copy(original, copy);
} }
public void createDirs(String fileName) { public void createDirs(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "createDirs"); trace(fileName, "createDirs");
FileSystem.getInstance(fileName).createDirs(fileName); super.createDirs(fileName);
} }
public boolean createNewFile(String fileName) { public boolean createNewFile(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "createNewFile"); trace(fileName, "createNewFile");
return FileSystem.getInstance(fileName).createNewFile(fileName); return super.createNewFile(fileName);
} }
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException { throws IOException {
prefix = translateFileName(prefix);
trace(prefix, "createTempFile", suffix, deleteOnExit, inTempDir); trace(prefix, "createTempFile", suffix, deleteOnExit, inTempDir);
return PREFIX + FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir); return super.createTempFile(prefix, suffix, deleteOnExit, inTempDir);
} }
public void delete(String fileName) { public void delete(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "fileName"); trace(fileName, "fileName");
FileSystem.getInstance(fileName).delete(fileName); super.delete(fileName);
} }
public void deleteRecursive(String directory, boolean tryOnly) { public void deleteRecursive(String directory, boolean tryOnly) {
directory = translateFileName(directory); trace(directory, "deleteRecursive", tryOnly);
trace(directory, "deleteRecursive"); super.deleteRecursive(directory, tryOnly);
FileSystem.getInstance(directory).deleteRecursive(directory, tryOnly);
} }
public boolean exists(String fileName) { public boolean exists(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "exists"); trace(fileName, "exists");
return FileSystem.getInstance(fileName).exists(fileName); return super.exists(fileName);
} }
public boolean fileStartsWith(String fileName, String prefix) { public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName); trace(fileName, "fileStartsWith", unwrap(prefix));
prefix = translateFileName(prefix); return super.fileStartsWith(fileName, prefix);
trace(fileName, "fileStartsWith", prefix);
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix);
} }
public String getAbsolutePath(String fileName) { public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getAbsolutePath"); trace(fileName, "getAbsolutePath");
return PREFIX + FileSystem.getInstance(fileName).getAbsolutePath(fileName); return super.getAbsolutePath(fileName);
} }
public String getFileName(String name) { public String getFileName(String name) {
name = translateFileName(name);
trace(name, "getFileName"); trace(name, "getFileName");
return FileSystem.getInstance(name).getFileName(name); return super.getFileName(name);
} }
public long getLastModified(String fileName) { public long getLastModified(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getLastModified"); trace(fileName, "getLastModified");
return FileSystem.getInstance(fileName).getLastModified(fileName); return super.getLastModified(fileName);
} }
public String getParent(String fileName) { public String getParent(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getParent"); trace(fileName, "getParent");
return PREFIX + FileSystem.getInstance(fileName).getParent(fileName); return super.getParent(fileName);
} }
public boolean isAbsolute(String fileName) { public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isAbsolute"); trace(fileName, "isAbsolute");
return FileSystem.getInstance(fileName).isAbsolute(fileName); return super.isAbsolute(fileName);
} }
public boolean isDirectory(String fileName) { public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isDirectory"); trace(fileName, "isDirectory");
return FileSystem.getInstance(fileName).isDirectory(fileName); return super.isDirectory(fileName);
} }
public boolean isReadOnly(String fileName) { public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isReadOnly"); trace(fileName, "isReadOnly");
return FileSystem.getInstance(fileName).isReadOnly(fileName); return super.isReadOnly(fileName);
} }
public boolean setReadOnly(String fileName) { public boolean setReadOnly(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "setReadOnly"); trace(fileName, "setReadOnly");
return FileSystem.getInstance(fileName).setReadOnly(fileName); return super.setReadOnly(fileName);
} }
public long length(String fileName) { public long length(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "length"); trace(fileName, "length");
return FileSystem.getInstance(fileName).length(fileName); return super.length(fileName);
} }
public String[] listFiles(String directory) { public String[] listFiles(String directory) {
directory = translateFileName(directory);
trace(directory, "listFiles"); trace(directory, "listFiles");
String[] list = FileSystem.getInstance(directory).listFiles(directory); return super.listFiles(directory);
for (int i = 0; i < list.length; i++) {
list[i] = PREFIX + list[i];
}
return list;
} }
public String normalize(String fileName) { public String normalize(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "normalize"); trace(fileName, "normalize");
return PREFIX + FileSystem.getInstance(fileName).normalize(fileName); return super.normalize(fileName);
} }
public InputStream openFileInputStream(String fileName) throws IOException { public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
trace(fileName, "openFileInputStream"); trace(fileName, "openFileInputStream");
return FileSystem.getInstance(fileName).openFileInputStream(fileName); return super.openFileInputStream(fileName);
} }
public FileObject openFileObject(String fileName, String mode) throws IOException { public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
trace(fileName, "openFileObject", mode); trace(fileName, "openFileObject", mode);
return new DebugFileObject(this, FileSystem.getInstance(fileName).openFileObject(fileName, mode)); return new DebugFileObject(this, super.openFileObject(fileName, mode));
} }
public OutputStream openFileOutputStream(String fileName, boolean append) { public OutputStream openFileOutputStream(String fileName, boolean append) {
fileName = translateFileName(fileName);
trace(fileName, "openFileOutputStream", append); trace(fileName, "openFileOutputStream", append);
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append); return super.openFileOutputStream(fileName, append);
} }
public void rename(String oldName, String newName) { public void rename(String oldName, String newName) {
oldName = translateFileName(oldName); trace(oldName, "rename", unwrap(newName));
newName = translateFileName(newName); super.rename(oldName, newName);
trace(oldName, "rename", newName);
FileSystem.getInstance(oldName).rename(oldName, newName);
} }
public boolean tryDelete(String fileName) { public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "tryDelete"); trace(fileName, "tryDelete");
return FileSystem.getInstance(fileName).tryDelete(fileName); return super.tryDelete(fileName);
} }
protected boolean accepts(String fileName) { public String getPrefix() {
return fileName.startsWith(PREFIX); return PREFIX;
}
private String translateFileName(String fileName) {
if (!fileName.startsWith(PREFIX)) {
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
}
return fileName.substring(PREFIX.length());
} }
/** /**
* Print a debug message. * Print a debug message.
* @param fileName the file name *
* @param fileName the (wrapped) file name
* @param method the method name * @param method the method name
* @param params parameters if any * @param params parameters if any
*/ */
void trace(String fileName, String method, Object... params) { void trace(String fileName, String method, Object... params) {
if (trace) { if (trace) {
StringBuilder buff = new StringBuilder(" "); StringBuilder buff = new StringBuilder(" ");
buff.append(fileName).append(' ').append(method); buff.append(unwrap(fileName)).append(' ').append(method);
for (Object s : params) { for (Object s : params) {
buff.append(' ').append(s); buff.append(' ').append(s);
} }
......
...@@ -7,16 +7,15 @@ ...@@ -7,16 +7,15 @@
package org.h2.test.utils; package org.h2.test.utils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject; import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemWrapper;
/** /**
* A file system that records all write operations and can re-play them. * A file system that records all write operations and can re-play them.
*/ */
public class RecordingFileSystem extends FileSystem { public class RecordingFileSystem extends FileSystemWrapper {
/** /**
* The prefix used for a debugging file system. * The prefix used for a debugging file system.
...@@ -45,157 +44,58 @@ public class RecordingFileSystem extends FileSystem { ...@@ -45,157 +44,58 @@ public class RecordingFileSystem extends FileSystem {
RecordingFileSystem.recorder = recorder; RecordingFileSystem.recorder = recorder;
} }
public boolean canWrite(String fileName) { public void copy(String source, String target) {
fileName = translateFileName(fileName); log(Recorder.COPY, unwrap(source) + ":" + unwrap(target));
return FileSystem.getInstance(fileName).canWrite(fileName); super.copy(source, target);
}
public void copy(String original, String copy) {
original = translateFileName(original);
copy = translateFileName(copy);
log(Recorder.COPY, original + ":" + copy);
FileSystem.getInstance(original).copy(original, copy);
} }
public void createDirs(String fileName) { public void createDirs(String fileName) {
fileName = translateFileName(fileName); log(Recorder.CREATE_DIRS, unwrap(fileName));
log(Recorder.CREATE_DIRS, fileName); super.createDirs(fileName);
FileSystem.getInstance(fileName).createDirs(fileName);
} }
public boolean createNewFile(String fileName) { public boolean createNewFile(String fileName) {
fileName = translateFileName(fileName); log(Recorder.CREATE_NEW_FILE, unwrap(fileName));
log(Recorder.CREATE_NEW_FILE, fileName); return super.createNewFile(fileName);
return FileSystem.getInstance(fileName).createNewFile(fileName);
} }
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException { throws IOException {
prefix = translateFileName(prefix); log(Recorder.CREATE_TEMP_FILE, unwrap(prefix) + ":" + suffix + ":" + deleteOnExit + ":" + inTempDir);
log(Recorder.CREATE_TEMP_FILE, prefix + ":" + suffix + ":" + deleteOnExit + ":" + inTempDir); return super.createTempFile(prefix, suffix, deleteOnExit, inTempDir);
return PREFIX + FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
} }
public void delete(String fileName) { public void delete(String fileName) {
fileName = translateFileName(fileName); log(Recorder.DELETE, unwrap(fileName));
log(Recorder.DELETE, fileName); super.delete(fileName);
FileSystem.getInstance(fileName).delete(fileName);
} }
public void deleteRecursive(String directory, boolean tryOnly) { public void deleteRecursive(String directory, boolean tryOnly) {
directory = translateFileName(directory); log(Recorder.DELETE_RECURSIVE, unwrap(directory));
log(Recorder.DELETE_RECURSIVE, directory); super.deleteRecursive(directory, tryOnly);
FileSystem.getInstance(directory).deleteRecursive(directory, tryOnly);
}
public boolean exists(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).exists(fileName);
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
prefix = translateFileName(prefix);
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix);
}
public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + FileSystem.getInstance(fileName).getAbsolutePath(fileName);
}
public String getFileName(String name) {
name = translateFileName(name);
return FileSystem.getInstance(name).getFileName(name);
}
public long getLastModified(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).getLastModified(fileName);
}
public String getParent(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + FileSystem.getInstance(fileName).getParent(fileName);
}
public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).isAbsolute(fileName);
}
public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).isDirectory(fileName);
}
public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).isReadOnly(fileName);
}
public boolean setReadOnly(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).setReadOnly(fileName);
}
public long length(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).length(fileName);
}
public String[] listFiles(String directory) {
directory = translateFileName(directory);
String[] list = FileSystem.getInstance(directory).listFiles(directory);
for (int i = 0; i < list.length; i++) {
list[i] = PREFIX + list[i];
}
return list;
}
public String normalize(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + FileSystem.getInstance(fileName).normalize(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).openFileInputStream(fileName);
} }
public FileObject openFileObject(String fileName, String mode) throws IOException { public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName); return new RecordingFileObject(this, super.openFileObject(fileName, mode));
return new RecordingFileObject(this, FileSystem.getInstance(fileName).openFileObject(fileName, mode));
} }
public OutputStream openFileOutputStream(String fileName, boolean append) { public OutputStream openFileOutputStream(String fileName, boolean append) {
fileName = translateFileName(fileName); log(Recorder.OPEN_OUTPUT_STREAM, unwrap(fileName));
log(Recorder.OPEN_OUTPUT_STREAM, fileName); return super.openFileOutputStream(fileName, append);
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append);
} }
public void rename(String oldName, String newName) { public void rename(String oldName, String newName) {
oldName = translateFileName(oldName); log(Recorder.RENAME, unwrap(oldName) + ":" + unwrap(newName));
newName = translateFileName(newName); super.rename(oldName, newName);
log(Recorder.RENAME, oldName + ":" + newName);
FileSystem.getInstance(oldName).rename(oldName, newName);
} }
public boolean tryDelete(String fileName) { public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName); log(Recorder.TRY_DELETE, unwrap(fileName));
log(Recorder.TRY_DELETE, fileName); return super.tryDelete(fileName);
return FileSystem.getInstance(fileName).tryDelete(fileName);
}
protected boolean accepts(String fileName) {
return fileName.startsWith(PREFIX);
} }
private String translateFileName(String fileName) { public String getPrefix() {
if (!fileName.startsWith(PREFIX)) { return PREFIX;
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
}
return fileName.substring(PREFIX.length());
} }
public boolean isTrace() { public boolean isTrace() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论