提交 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
<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>
<td>
The database name. This can include connections settings.<br />
By default, the database is stored in the current working directory <br />
where the Server is started except when the -baseDir setting is used. <br />
The database name. This can include connections settings.
By default, the database is stored in the current working directory
where the Server is started except when the -baseDir setting is used.
The name must be at least 3 characters.
</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
<h1>Change Log</h1>
<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),
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
......
......@@ -6,7 +6,6 @@
*/
package org.h2.engine;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
......@@ -137,31 +136,24 @@ public class ConnectionInfo implements Cloneable {
*/
public void setBaseDir(String dir) {
if (persistent) {
String fileSystemPrefix = "";
int colonIndex = name.lastIndexOf(':');
if (colonIndex > 1) {
// cut FileSystem prefixes, but not
// C: and D: (Microsoft Windows drive letters)
fileSystemPrefix = name.substring(0, colonIndex+1);
name = name.substring(colonIndex+1);
}
String testFileName;
if (name.startsWith("~")) {
testFileName = System.getProperty("user.home") + SysProperties.FILE_SEPARATOR + name.substring(1);
String absDir = IOUtils.unwrap(IOUtils.getAbsolutePath(dir));
boolean absolute = IOUtils.isAbsolute(name);
String n;
String prefix = null;
if (absolute) {
n = name;
} 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;
}
File testFile = new File(testFileName);
File baseDir = new File(dir);
if (!IOUtils.isInDir(testFile, baseDir)) {
throw DbException.get(ErrorCode.IO_EXCEPTION_1, testFile.getAbsolutePath() + " outside " +
baseDir.getAbsolutePath());
String absName = IOUtils.unwrap(IOUtils.getAbsolutePath(n));
if (absName.equals(absDir) || !absName.startsWith(absDir)) {
throw DbException.get(ErrorCode.IO_EXCEPTION_1, absName + " outside " +
absDir);
}
if (name.startsWith("~")) {
name = fileSystemPrefix + name;
} else {
name = fileSystemPrefix + dir + SysProperties.FILE_SEPARATOR + name;
if (!absolute) {
name = prefix + dir + SysProperties.FILE_SEPARATOR + IOUtils.unwrap(name);
}
}
}
......
......@@ -32,8 +32,8 @@ import org.h2.command.Parser;
import org.h2.engine.Session;
import org.h2.expression.ExpressionColumn;
import org.h2.jdbc.JdbcConnection;
import org.h2.store.fs.FileSystem;
import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
......@@ -348,7 +348,7 @@ public class FullTextLucene extends FullText {
if (access != null) {
removeIndexAccess(access, path);
}
FileSystem.getInstance(path).deleteRecursive(path, false);
IOUtils.deleteRecursive(path, false);
}
/**
......
......@@ -120,9 +120,11 @@ public class FileObjectDiskMapped implements FileObject {
}
public void close() throws IOException {
unMap();
file.close();
file = null;
if (file != null) {
unMap();
file.close();
file = null;
}
}
public long getFilePointer() {
......
......@@ -225,10 +225,10 @@ public abstract class FileSystem {
/**
* 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
* @param source the name of the original file
* @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.
......@@ -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 {
new String[] { oldName, newName + " (exists)" });
}
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);
if (ok) {
return;
......@@ -104,19 +104,6 @@ public class FileSystemDisk extends FileSystem {
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) {
if (i > 8) {
System.gc();
......@@ -154,7 +141,7 @@ public class FileSystemDisk extends FileSystem {
File file = new File(fileName);
if (file.exists()) {
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("delete", fileName, null);
IOUtils.trace("delete", fileName, null);
boolean ok = file.delete();
if (ok) {
return;
......@@ -167,7 +154,7 @@ public class FileSystemDisk extends FileSystem {
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
trace("tryDelete", fileName, null);
IOUtils.trace("tryDelete", fileName, null);
return new File(fileName).delete();
}
......@@ -214,8 +201,8 @@ public class FileSystemDisk extends FileSystem {
return new String[0];
}
String base = f.getCanonicalPath();
if (!base.endsWith(File.separator)) {
base += File.separator;
if (!base.endsWith(SysProperties.FILE_SEPARATOR)) {
base += SysProperties.FILE_SEPARATOR;
}
for (int i = 0, len = list.length; i < len; i++) {
list[i] = base + list[i];
......@@ -327,14 +314,14 @@ public class FileSystemDisk extends FileSystem {
}
}
public void copy(String original, String copy) {
original = translateFileName(original);
copy = translateFileName(copy);
public void copy(String source, String target) {
source = translateFileName(source);
target = translateFileName(target);
OutputStream out = null;
InputStream in = null;
try {
out = IOUtils.openFileOutputStream(copy, false);
in = IOUtils.openFileInputStream(original);
out = IOUtils.openFileOutputStream(target, false);
in = IOUtils.openFileInputStream(source);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while (true) {
int len = in.read(buffer);
......@@ -345,7 +332,7 @@ public class FileSystemDisk extends FileSystem {
}
out.close();
} catch (IOException e) {
throw DbException.convertIOException(e, "original: " + original + " copy: " + copy);
throw DbException.convertIOException(e, "original: " + source + " copy: " + target);
} finally {
IOUtils.closeSilently(in);
IOUtils.closeSilently(out);
......@@ -392,7 +379,7 @@ public class FileSystemDisk extends FileSystem {
File file = new File(fileName);
createDirs(file.getAbsolutePath());
FileOutputStream out = new FileOutputStream(fileName, append);
trace("openFileOutputStream", fileName, out);
IOUtils.trace("openFileOutputStream", fileName, out);
return out;
} catch (IOException e) {
freeMemoryAndFinalize();
......@@ -414,7 +401,7 @@ public class FileSystemDisk extends FileSystem {
}
fileName = translateFileName(fileName);
FileInputStream in = new FileInputStream(fileName);
trace("openFileInputStream", fileName, in);
IOUtils.trace("openFileInputStream", fileName, in);
return in;
}
......@@ -422,8 +409,8 @@ public class FileSystemDisk extends FileSystem {
* Call the garbage collection and run finalization. This close all files that
* were not closed, and are no longer referenced.
*/
protected void freeMemoryAndFinalize() {
trace("freeMemoryAndFinalize", null, null);
static void freeMemoryAndFinalize() {
IOUtils.trace("freeMemoryAndFinalize", null, null);
Runtime rt = Runtime.getRuntime();
long mem = rt.freeMemory();
for (int i = 0; i < 16; i++) {
......@@ -442,7 +429,7 @@ public class FileSystemDisk extends FileSystem {
FileObjectDisk f;
try {
f = new FileObjectDisk(fileName, mode);
trace("openRandomAccessFile", fileName, f);
IOUtils.trace("openFileObject", fileName, f);
} catch (IOException e) {
freeMemoryAndFinalize();
try {
......@@ -458,4 +445,8 @@ public class FileSystemDisk extends FileSystem {
return true;
}
public String unwrap(String fileName) {
return fileName;
}
}
......@@ -7,13 +7,13 @@
package org.h2.store.fs;
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 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.
......@@ -24,51 +24,14 @@ public class FileSystemDiskNio extends FileSystemDisk {
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 {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
FileObject f;
try {
f = open(fileName, mode);
trace("openRandomAccessFile", fileName, f);
IOUtils.trace("openFileObject", fileName, f);
} catch (IOException e) {
freeMemoryAndFinalize();
FileSystemDisk.freeMemoryAndFinalize();
try {
f = open(fileName, mode);
} catch (IOException e2) {
......@@ -99,8 +62,4 @@ public class FileSystemDiskNio extends FileSystemDisk {
return new FileObjectDiskChannel(fileName, mode);
}
protected boolean accepts(String fileName) {
return fileName.startsWith(getPrefix());
}
}
......@@ -168,13 +168,13 @@ public class FileSystemMemory extends FileSystem {
return true;
}
public void copy(String original, String copy) {
public void copy(String source, String target) {
try {
OutputStream out = openFileOutputStream(copy, false);
InputStream in = openFileInputStream(original);
OutputStream out = openFileOutputStream(target, false);
InputStream in = openFileInputStream(source);
IOUtils.copyAndClose(in, out);
} 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 {
return fileName.startsWith(PREFIX) || fileName.startsWith(PREFIX_LZF);
}
public String unwrap(String fileName) {
return fileName;
}
}
......@@ -20,7 +20,7 @@ import org.h2.util.New;
* A file system that may split files into multiple smaller files.
* (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.
......@@ -35,13 +35,8 @@ public class FileSystemSplit extends FileSystem {
FileSystem.register(new FileSystemSplit());
}
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return getFileSystem(fileName).canWrite(fileName);
}
public boolean setReadOnly(String fileName) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
boolean result = false;
for (int i = 0;; i++) {
String f = getFileName(fileName, i);
......@@ -54,14 +49,14 @@ public class FileSystemSplit extends FileSystem {
return result;
}
public void copy(String original, String copy) {
original = translateFileName(original);
copy = translateFileName(copy);
getFileSystem(original).copy(original, copy);
public void copy(String source, String target) {
source = unwrap(source);
target = unwrap(target);
getFileSystem(source).copy(source, target);
for (int i = 1;; i++) {
String o = getFileName(original, i);
String o = getFileName(source, i);
if (getFileSystem(o).exists(o)) {
String c = getFileName(copy, i);
String c = getFileName(target, i);
getFileSystem(o).copy(o, c);
} else {
break;
......@@ -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) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
for (int i = 0;; i++) {
String f = getFileName(fileName, i);
if (getFileSystem(fileName).exists(f)) {
......@@ -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) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
long lastModified = 0;
for (int i = 0;; i++) {
String f = getFileName(fileName, i);
......@@ -138,28 +91,8 @@ public class FileSystemSplit extends FileSystem {
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) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
long length = 0;
for (int i = 0;; i++) {
String f = getFileName(fileName, i);
......@@ -173,15 +106,13 @@ public class FileSystemSplit extends FileSystem {
}
public String[] listFiles(String directory) {
directory = translateFileName(directory);
String[] array = getFileSystem(directory).listFiles(directory);
String[] array = super.listFiles(directory);
ArrayList<String> list = New.arrayList();
for (int i = 0; i < array.length; i++) {
String f = array[i];
if (f.endsWith(PART_SUFFIX)) {
continue;
}
array[i] = f = PREFIX + f;
list.add(f);
}
if (list.size() != array.length) {
......@@ -191,13 +122,8 @@ public class FileSystemSplit extends FileSystem {
return array;
}
public String normalize(String fileName) {
fileName = translateFileName(fileName);
return PREFIX + getFileSystem(fileName).normalize(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
InputStream input = getFileSystem(fileName).openFileInputStream(fileName);
for (int i = 1;; i++) {
String f = getFileName(fileName, i);
......@@ -212,7 +138,7 @@ public class FileSystemSplit extends FileSystem {
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
ArrayList<FileObject> list = New.arrayList();
FileObject o = getFileSystem(fileName).openFileObject(fileName, mode);
list.add(o);
......@@ -265,14 +191,16 @@ public class FileSystemSplit extends FileSystem {
}
public OutputStream openFileOutputStream(String fileName, boolean append) {
fileName = translateFileName(fileName);
// TODO the output stream is not split
return getFileSystem(fileName).openFileOutputStream(fileName, append);
try {
return new FileObjectOutputStream(openFileObject(fileName, "rw"), append);
} catch (IOException e) {
throw DbException.convertIOException(e, fileName);
}
}
public void rename(String oldName, String newName) {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
oldName = unwrap(oldName);
newName = unwrap(newName);
for (int i = 0;; i++) {
String o = getFileName(oldName, i);
if (getFileSystem(o).exists(o)) {
......@@ -285,7 +213,7 @@ public class FileSystemSplit extends FileSystem {
}
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
for (int i = 0;; i++) {
String f = getFileName(fileName, i);
if (getFileSystem(fileName).exists(f)) {
......@@ -300,7 +228,7 @@ public class FileSystemSplit extends FileSystem {
return true;
}
private String translateFileName(String fileName) {
public String unwrap(String fileName) {
if (!fileName.startsWith(PREFIX)) {
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
}
......@@ -336,8 +264,8 @@ public class FileSystemSplit extends FileSystem {
return FileSystem.getInstance(fileName);
}
protected boolean accepts(String fileName) {
return fileName.startsWith(PREFIX);
protected String getPrefix() {
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 {
return fileName.startsWith(PREFIX);
}
public String unwrap(String fileName) {
return fileName;
}
}
......@@ -19,7 +19,6 @@ import org.h2.command.dml.BackupCommand;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.store.FileLister;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils;
import org.h2.util.Tool;
......@@ -110,7 +109,7 @@ public class Backup extends Tool {
List<String> list;
boolean allFiles = db != null && db.length() == 0;
if (allFiles) {
list = Arrays.asList(FileSystem.getInstance(directory).listFiles(directory));
list = Arrays.asList(IOUtils.listFiles(directory));
} else {
list = FileLister.getDatabaseFiles(directory, db, true);
}
......
......@@ -6,7 +6,6 @@
*/
package org.h2.tools;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
......@@ -14,6 +13,7 @@ import java.sql.SQLException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.h2.constant.SysProperties;
import org.h2.message.DbException;
import org.h2.store.FileLister;
import org.h2.util.IOUtils;
......@@ -146,7 +146,7 @@ public class Restore extends Tool {
if (originalDbName == null) {
throw new IOException("No database named " + db + " found");
}
if (originalDbName.startsWith(File.separator)) {
if (originalDbName.startsWith(SysProperties.FILE_SEPARATOR)) {
originalDbName = originalDbName.substring(1);
}
originalDbLen = originalDbName.length();
......@@ -160,9 +160,9 @@ public class Restore extends Tool {
}
String fileName = entry.getName();
// restoring windows backups on linux and vice versa
fileName = fileName.replace('\\', File.separatorChar);
fileName = fileName.replace('/', File.separatorChar);
if (fileName.startsWith(File.separator)) {
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;
......@@ -175,7 +175,7 @@ public class Restore extends Tool {
if (copy) {
OutputStream o = null;
try {
o = IOUtils.openFileOutputStream(directory + File.separator + fileName, false);
o = IOUtils.openFileOutputStream(directory + SysProperties.FILE_SEPARATOR + fileName, false);
IOUtils.copy(zipIn, o);
o.close();
} finally {
......
......@@ -7,7 +7,6 @@
package org.h2.tools;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
......@@ -17,6 +16,7 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.util.Utils;
......@@ -201,7 +201,7 @@ public class RunScript extends Tool {
sql = trim;
sql = sql.substring("@INCLUDE".length()).trim();
if (!IOUtils.isAbsolute(sql)) {
sql = path + File.separator + sql;
sql = path + SysProperties.FILE_SEPARATOR + sql;
}
process(conn, sql, continueOnError, charsetName);
} else {
......
......@@ -16,7 +16,6 @@ import java.util.UUID;
import org.h2.engine.ConnectionInfo;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils;
import org.h2.util.StringUtils;
import org.h2.util.Utils;
......@@ -155,7 +154,7 @@ public class DbUpgrade {
if (deleteOldDb) {
IOUtils.delete(backupData);
IOUtils.delete(backupIndex);
FileSystem.getInstance(name).deleteRecursive(backupLobs, false);
IOUtils.deleteRecursive(backupLobs, false);
}
} catch (Exception e) {
if (IOUtils.exists(backupData)) {
......
......@@ -25,6 +25,7 @@ import java.io.Writer;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
/**
......@@ -522,7 +523,58 @@ public class IOUtils {
* @return just the file 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 {
* @return the normalized file name
*/
public static String normalize(String fileName) {
return FileSystem.getInstance(fileName).normalize(fileName);
return getFileSystem(fileName).normalize(fileName);
}
/**
......@@ -542,7 +594,7 @@ public class IOUtils {
* @return true if it worked
*/
public static boolean tryDelete(String fileName) {
return FileSystem.getInstance(fileName).tryDelete(fileName);
return getFileSystem(fileName).tryDelete(fileName);
}
/**
......@@ -552,7 +604,7 @@ public class IOUtils {
* @return if it is read only
*/
public static boolean isReadOnly(String fileName) {
return FileSystem.getInstance(fileName).isReadOnly(fileName);
return getFileSystem(fileName).isReadOnly(fileName);
}
/**
......@@ -562,7 +614,7 @@ public class IOUtils {
* @return true if it exists
*/
public static boolean exists(String fileName) {
return FileSystem.getInstance(fileName).exists(fileName);
return getFileSystem(fileName).exists(fileName);
}
/**
......@@ -572,7 +624,7 @@ public class IOUtils {
* @return the length in bytes
*/
public static long length(String fileName) {
return FileSystem.getInstance(fileName).length(fileName);
return getFileSystem(fileName).length(fileName);
}
/**
......@@ -588,7 +640,7 @@ public class IOUtils {
*/
public static String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
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 {
* @return the parent directory name
*/
public static String getParent(String fileName) {
return FileSystem.getInstance(fileName).getParent(fileName);
return getFileSystem(fileName).getParent(fileName);
}
/**
......@@ -608,7 +660,7 @@ public class IOUtils {
* @return the list of fully qualified file names
*/
public static String[] listFiles(String path) {
return FileSystem.getInstance(path).listFiles(path);
return getFileSystem(path).listFiles(path);
}
/**
......@@ -618,7 +670,7 @@ public class IOUtils {
* @return true if it is a directory
*/
public static boolean isDirectory(String fileName) {
return FileSystem.getInstance(fileName).isDirectory(fileName);
return getFileSystem(fileName).isDirectory(fileName);
}
/**
......@@ -628,7 +680,7 @@ public class IOUtils {
* @return if the file name is absolute
*/
public static boolean isAbsolute(String fileName) {
return FileSystem.getInstance(fileName).isAbsolute(fileName);
return getFileSystem(fileName).isAbsolute(fileName);
}
/**
......@@ -638,7 +690,7 @@ public class IOUtils {
* @return the absolute file name
*/
public static String getAbsolutePath(String fileName) {
return FileSystem.getInstance(fileName).getAbsolutePath(fileName);
return getFileSystem(fileName).getAbsolutePath(fileName);
}
/**
......@@ -649,7 +701,7 @@ public class IOUtils {
* @return true if it starts with the 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 {
* @return the input stream
*/
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 {
* @return the output stream
*/
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 {
* @param newName the new fully qualified file name
*/
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 {
* @param fileName the file name (not directory name)
*/
public static void createDirs(String fileName) {
FileSystem.getInstance(fileName).createDirs(fileName);
getFileSystem(fileName).createDirs(fileName);
}
/**
......@@ -699,7 +751,17 @@ public class IOUtils {
* @param fileName the file name
*/
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 {
* @return the last modified date
*/
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 o the object to append to the message
* @return the unwrapped
*/
static void trace(String method, String fileName, Object o) {
if (SysProperties.TRACE_IO) {
System.out.println("IOUtils." + method + " " + fileName + " " + o);
}
public static String unwrap(String fileName) {
return getFileSystem(fileName).unwrap(fileName);
}
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 dir the directory the file must be in
* @return true if the file is within the directory
* @param method the method from where this method was called
* @param fileName the file name
* @param o the object to append to the message
*/
public static boolean isInDir(File file, File dir) {
try {
String canonicalFileName = file.getCanonicalPath();
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;
public static void trace(String method, String fileName, Object o) {
if (SysProperties.TRACE_IO) {
System.out.println("IOUtils." + method + " " + fileName + " " + o);
}
}
......
......@@ -225,14 +225,14 @@ public class ValueLob extends Value {
String name;
int f = objectId % SysProperties.LOB_FILES_PER_DIRECTORY;
if (f > 0) {
name = File.separator + objectId;
name = SysProperties.FILE_SEPARATOR + objectId;
} else {
name = "";
}
objectId /= SysProperties.LOB_FILES_PER_DIRECTORY;
while (objectId > 0) {
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;
}
name = IOUtils.normalize(path + Constants.SUFFIX_LOBS_DIRECTORY + name);
......
......@@ -9,9 +9,9 @@ package org.h2.samples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.h2.store.fs.FileSystem;
import org.h2.tools.Backup;
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
......@@ -30,7 +30,7 @@ public class ReadOnlyDatabaseInZip {
public static void main(String... args) throws Exception {
// delete all files in this directory
FileSystem.getInstance("~/temp").deleteRecursive("~/temp", false);
IOUtils.deleteRecursive("~/temp", false);
Connection conn;
Class.forName("org.h2.Driver");
......
......@@ -25,10 +25,10 @@ import java.util.LinkedList;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.TraceSystem;
import org.h2.store.FileLock;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemSplit;
import org.h2.test.utils.RecordingFileSystem;
import org.h2.tools.DeleteDbFiles;
import org.h2.util.IOUtils;
/**
* The base class for all tests.
......@@ -144,8 +144,8 @@ public abstract class TestBase {
}
} finally {
try {
FileSystem.getInstance("memFS:").deleteRecursive("memFS:", false);
FileSystem.getInstance("memLZF:").deleteRecursive("memLZF:", false);
IOUtils.deleteRecursive("memFS:", false);
IOUtils.deleteRecursive("memLZF:", false);
} catch (RuntimeException e) {
e.printStackTrace();
}
......
......@@ -18,8 +18,6 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Properties;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
......@@ -77,7 +75,7 @@ public class TestPerformance {
if ("-db".equals(arg)) {
dbId = Integer.parseInt(args[++i]);
} else if ("-init".equals(arg)) {
FileSystem.getInstance("data").deleteRecursive("data", true);
IOUtils.deleteRecursive("data", true);
} else if ("-out".equals(arg)) {
out = args[++i];
} else if ("-trace".equals(arg)) {
......
......@@ -17,6 +17,7 @@ import java.util.StringTokenizer;
import org.h2.fulltext.FullText;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.Task;
/**
......@@ -113,7 +114,7 @@ public class TestFullText extends TestBase {
}
String prefix = lucene ? "FTL" : "FT";
deleteDb("fullTextTransaction");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullTextTransaction", false);
IOUtils.deleteRecursive(getBaseDir() + "/fullTextTransaction", false);
Connection conn = getConnection("fullTextTransaction");
Statement stat = conn.createStatement();
String className = lucene ? "FullTextLucene" : "FullText";
......@@ -246,7 +247,7 @@ public class TestFullText extends TestBase {
private void testCreateDrop() throws SQLException {
deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false);
IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
Connection conn = getConnection("fullText");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS IF NOT EXISTS FT_INIT FOR \"org.h2.fulltext.FullText.init\"");
......@@ -257,13 +258,13 @@ public class TestFullText extends TestBase {
}
conn.close();
deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false);
IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
}
private void testReopen(boolean lucene) throws SQLException {
String prefix = lucene ? "FTL" : "FT";
deleteDb("fullTextReopen");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullTextReopen", false);
IOUtils.deleteRecursive(getBaseDir() + "/fullTextReopen", false);
Connection conn = getConnection("fullTextReopen");
Statement stat = conn.createStatement();
String className = lucene ? "FullTextLucene" : "FullText";
......@@ -294,7 +295,7 @@ public class TestFullText extends TestBase {
private void testPerformance(boolean lucene) throws SQLException {
deleteDb("fullText");
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/fullText", false);
IOUtils.deleteRecursive(getBaseDir() + "/fullText", false);
Connection conn = getConnection("fullText");
String prefix = lucene ? "FTL" : "FT";
Statement stat = conn.createStatement();
......
......@@ -24,7 +24,6 @@ import java.util.Properties;
import java.util.UUID;
import org.h2.api.AggregateFunction;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils;
......@@ -63,7 +62,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
testFunctions();
testFileRead();
deleteDb("functions");
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true);
IOUtils.deleteRecursive(TEMP_DIR, true);
}
private void testFunctionInSchema() throws SQLException {
......
......@@ -26,7 +26,6 @@ import java.util.Random;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.store.FileLister;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
import org.h2.util.Utils;
......@@ -86,7 +85,7 @@ public class TestLob extends TestBase {
testLob(true);
testJavaObject();
deleteDb("lob");
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true);
IOUtils.deleteRecursive(TEMP_DIR, true);
}
private void testUniqueIndex() throws Exception {
......@@ -212,7 +211,7 @@ public class TestLob extends TestBase {
private void testTempFilesDeleted() throws Exception {
String[] list;
FileSystem.getInstance(TEMP_DIR).deleteRecursive(TEMP_DIR, true);
IOUtils.deleteRecursive(TEMP_DIR, true);
IOUtils.mkdirs(new File(TEMP_DIR));
list = IOUtils.listFiles(TEMP_DIR);
if (list.length > 0) {
......
......@@ -12,7 +12,6 @@ import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.upgrade.DbUpgrade;
import org.h2.util.IOUtils;
......@@ -198,7 +197,7 @@ public class TestUpgrade extends TestBase {
}
IOUtils.delete(getBaseDir() + "/" + dbName + ".data.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;
import org.h2.constant.SysProperties;
import org.h2.test.TestBase;
import org.h2.tools.Server;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils;
import org.h2.util.StringUtils;
import org.h2.util.Task;
......@@ -127,7 +126,7 @@ public class TestWeb extends TestBase {
new File("transfer/testUpload.txt").delete();
} finally {
server.shutdown();
FileSystem.getInstance("transfer").deleteRecursive("transfer", true);
IOUtils.deleteRecursive("transfer", true);
}
}
......
......@@ -16,8 +16,8 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.New;
import org.h2.util.ScriptReader;
......@@ -159,7 +159,7 @@ public class TestNestedJoins extends TestBase {
} catch (Exception e) {
// ignore
}
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/derby", false);
IOUtils.deleteRecursive(getBaseDir() + "/derby", false);
} catch (Exception e) {
e.printStackTrace();
// database not installed - ok
......
......@@ -16,8 +16,8 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import org.h2.store.fs.FileSystem;
import org.h2.test.TestBase;
import org.h2.util.IOUtils;
import org.h2.util.New;
import org.h2.util.ScriptReader;
......@@ -150,7 +150,7 @@ public class TestOuterJoins extends TestBase {
} catch (Exception e) {
// ignore
}
FileSystem.getInstance(getBaseDir()).deleteRecursive(getBaseDir() + "/derby", false);
IOUtils.deleteRecursive(getBaseDir() + "/derby", false);
} catch (Exception e) {
e.printStackTrace();
// 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 {
}
private long getId(String fileName, boolean parent) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
log(fileName);
try {
String[] path = StringUtils.arraySplit(fileName, '/', false);
......@@ -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 {
PreparedStatement prep = preparedMap.get(sql);
if (prep == null) {
......@@ -182,19 +175,19 @@ public class FileSystemDatabase extends FileSystem {
return true;
}
public void copy(String original, String copy) {
public void copy(String source, String target) {
try {
OutputStream out = openFileOutputStream(copy, false);
InputStream in = openFileInputStream(original);
OutputStream out = openFileOutputStream(target, false);
InputStream in = openFileInputStream(source);
IOUtils.copyAndClose(in, out);
} catch (IOException e) {
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) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
try {
String[] path = StringUtils.arraySplit(fileName, '/', false);
long parentId = 0;
......@@ -266,7 +259,7 @@ public class FileSystemDatabase extends FileSystem {
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
return fileName.startsWith(prefix);
}
......@@ -275,7 +268,7 @@ public class FileSystemDatabase extends FileSystem {
}
public String getFileName(String fileName) {
fileName = translateFileName(fileName);
fileName = unwrap(fileName);
String[] path = StringUtils.arraySplit(fileName, '/', false);
return path[path.length - 1];
}
......@@ -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 {
private void testSplitDatabaseInZip() throws SQLException {
String dir = getBaseDir() + "/fs";
FileSystem.getInstance(dir).deleteRecursive(dir, false);
IOUtils.deleteRecursive(dir, false);
Connection conn;
Statement stat;
conn = DriverManager.getConnection("jdbc:h2:split:18:"+dir+"/test");
......@@ -93,7 +93,7 @@ public class TestFileSystem extends TestBase {
"jdbc:h2:split:zip:"+dir+"/test.zip!/test");
conn.createStatement().execute("select * from test where id=1");
conn.close();
FileSystem.getInstance(dir).deleteRecursive(dir, false);
IOUtils.deleteRecursive(dir, false);
}
private void testDatabaseInMemFileSys() throws SQLException {
......
......@@ -190,7 +190,7 @@ public class TestRecovery extends TestBase {
deleteDb("recovery2");
IOUtils.delete(getBaseDir() + "/recovery.h2.sql");
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 {
return;
}
org.h2.Driver.load();
testInMemoryBaseDir();
testConsole();
testJdbcDriverUtils();
testWrongServer();
......@@ -629,7 +630,7 @@ public class TestTools extends TestBase {
deleteDb("toolsRecover");
IOUtils.delete(getBaseDir() + "/toolsRecover.h2.sql");
String dir = getBaseDir() + "/toolsRecover.lobs.db";
FileSystem.getInstance(dir).deleteRecursive(dir, false);
IOUtils.deleteRecursive(dir, false);
}
private void testManagementDb() throws SQLException {
......@@ -851,4 +852,23 @@ public class TestTools extends TestBase {
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;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemWrapper;
/**
* 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.
......@@ -60,184 +60,146 @@ public class DebugFileSystem extends FileSystem {
}
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "canWrite");
return FileSystem.getInstance(fileName).canWrite(fileName);
return super.canWrite(fileName);
}
public void copy(String original, String copy) {
original = translateFileName(original);
copy = translateFileName(copy);
trace(original, "copy", copy);
FileSystem.getInstance(original).copy(original, copy);
public void copy(String source, String target) {
trace(source, "copy", unwrap(target));
super.copy(source, target);
}
public void createDirs(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "createDirs");
FileSystem.getInstance(fileName).createDirs(fileName);
super.createDirs(fileName);
}
public boolean createNewFile(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "createNewFile");
return FileSystem.getInstance(fileName).createNewFile(fileName);
return super.createNewFile(fileName);
}
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
prefix = translateFileName(prefix);
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) {
fileName = translateFileName(fileName);
trace(fileName, "fileName");
FileSystem.getInstance(fileName).delete(fileName);
super.delete(fileName);
}
public void deleteRecursive(String directory, boolean tryOnly) {
directory = translateFileName(directory);
trace(directory, "deleteRecursive");
FileSystem.getInstance(directory).deleteRecursive(directory, tryOnly);
trace(directory, "deleteRecursive", tryOnly);
super.deleteRecursive(directory, tryOnly);
}
public boolean exists(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "exists");
return FileSystem.getInstance(fileName).exists(fileName);
return super.exists(fileName);
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
prefix = translateFileName(prefix);
trace(fileName, "fileStartsWith", prefix);
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix);
trace(fileName, "fileStartsWith", unwrap(prefix));
return super.fileStartsWith(fileName, prefix);
}
public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getAbsolutePath");
return PREFIX + FileSystem.getInstance(fileName).getAbsolutePath(fileName);
return super.getAbsolutePath(fileName);
}
public String getFileName(String name) {
name = translateFileName(name);
trace(name, "getFileName");
return FileSystem.getInstance(name).getFileName(name);
return super.getFileName(name);
}
public long getLastModified(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getLastModified");
return FileSystem.getInstance(fileName).getLastModified(fileName);
return super.getLastModified(fileName);
}
public String getParent(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "getParent");
return PREFIX + FileSystem.getInstance(fileName).getParent(fileName);
return super.getParent(fileName);
}
public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isAbsolute");
return FileSystem.getInstance(fileName).isAbsolute(fileName);
return super.isAbsolute(fileName);
}
public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isDirectory");
return FileSystem.getInstance(fileName).isDirectory(fileName);
return super.isDirectory(fileName);
}
public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "isReadOnly");
return FileSystem.getInstance(fileName).isReadOnly(fileName);
return super.isReadOnly(fileName);
}
public boolean setReadOnly(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "setReadOnly");
return FileSystem.getInstance(fileName).setReadOnly(fileName);
return super.setReadOnly(fileName);
}
public long length(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "length");
return FileSystem.getInstance(fileName).length(fileName);
return super.length(fileName);
}
public String[] listFiles(String directory) {
directory = translateFileName(directory);
trace(directory, "listFiles");
String[] list = FileSystem.getInstance(directory).listFiles(directory);
for (int i = 0; i < list.length; i++) {
list[i] = PREFIX + list[i];
}
return list;
return super.listFiles(directory);
}
public String normalize(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "normalize");
return PREFIX + FileSystem.getInstance(fileName).normalize(fileName);
return super.normalize(fileName);
}
public InputStream openFileInputStream(String fileName) throws IOException {
fileName = translateFileName(fileName);
trace(fileName, "openFileInputStream");
return FileSystem.getInstance(fileName).openFileInputStream(fileName);
return super.openFileInputStream(fileName);
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
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) {
fileName = translateFileName(fileName);
trace(fileName, "openFileOutputStream", append);
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append);
return super.openFileOutputStream(fileName, append);
}
public void rename(String oldName, String newName) {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
trace(oldName, "rename", newName);
FileSystem.getInstance(oldName).rename(oldName, newName);
trace(oldName, "rename", unwrap(newName));
super.rename(oldName, newName);
}
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
trace(fileName, "tryDelete");
return FileSystem.getInstance(fileName).tryDelete(fileName);
return super.tryDelete(fileName);
}
protected boolean accepts(String fileName) {
return fileName.startsWith(PREFIX);
}
private String translateFileName(String fileName) {
if (!fileName.startsWith(PREFIX)) {
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
}
return fileName.substring(PREFIX.length());
public String getPrefix() {
return PREFIX;
}
/**
* Print a debug message.
* @param fileName the file name
*
* @param fileName the (wrapped) file name
* @param method the method name
* @param params parameters if any
*/
void trace(String fileName, String method, Object... params) {
if (trace) {
StringBuilder buff = new StringBuilder(" ");
buff.append(fileName).append(' ').append(method);
buff.append(unwrap(fileName)).append(' ').append(method);
for (Object s : params) {
buff.append(' ').append(s);
}
......
......@@ -7,16 +7,15 @@
package org.h2.test.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.h2.message.DbException;
import org.h2.store.fs.FileObject;
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.
*/
public class RecordingFileSystem extends FileSystem {
public class RecordingFileSystem extends FileSystemWrapper {
/**
* The prefix used for a debugging file system.
......@@ -45,157 +44,58 @@ public class RecordingFileSystem extends FileSystem {
RecordingFileSystem.recorder = recorder;
}
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return FileSystem.getInstance(fileName).canWrite(fileName);
}
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 copy(String source, String target) {
log(Recorder.COPY, unwrap(source) + ":" + unwrap(target));
super.copy(source, target);
}
public void createDirs(String fileName) {
fileName = translateFileName(fileName);
log(Recorder.CREATE_DIRS, fileName);
FileSystem.getInstance(fileName).createDirs(fileName);
log(Recorder.CREATE_DIRS, unwrap(fileName));
super.createDirs(fileName);
}
public boolean createNewFile(String fileName) {
fileName = translateFileName(fileName);
log(Recorder.CREATE_NEW_FILE, fileName);
return FileSystem.getInstance(fileName).createNewFile(fileName);
log(Recorder.CREATE_NEW_FILE, unwrap(fileName));
return super.createNewFile(fileName);
}
public String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
prefix = translateFileName(prefix);
log(Recorder.CREATE_TEMP_FILE, prefix + ":" + suffix + ":" + deleteOnExit + ":" + inTempDir);
return PREFIX + FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
log(Recorder.CREATE_TEMP_FILE, unwrap(prefix) + ":" + suffix + ":" + deleteOnExit + ":" + inTempDir);
return super.createTempFile(prefix, suffix, deleteOnExit, inTempDir);
}
public void delete(String fileName) {
fileName = translateFileName(fileName);
log(Recorder.DELETE, fileName);
FileSystem.getInstance(fileName).delete(fileName);
log(Recorder.DELETE, unwrap(fileName));
super.delete(fileName);
}
public void deleteRecursive(String directory, boolean tryOnly) {
directory = translateFileName(directory);
log(Recorder.DELETE_RECURSIVE, directory);
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);
log(Recorder.DELETE_RECURSIVE, unwrap(directory));
super.deleteRecursive(directory, tryOnly);
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
return new RecordingFileObject(this, FileSystem.getInstance(fileName).openFileObject(fileName, mode));
return new RecordingFileObject(this, super.openFileObject(fileName, mode));
}
public OutputStream openFileOutputStream(String fileName, boolean append) {
fileName = translateFileName(fileName);
log(Recorder.OPEN_OUTPUT_STREAM, fileName);
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append);
log(Recorder.OPEN_OUTPUT_STREAM, unwrap(fileName));
return super.openFileOutputStream(fileName, append);
}
public void rename(String oldName, String newName) {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
log(Recorder.RENAME, oldName + ":" + newName);
FileSystem.getInstance(oldName).rename(oldName, newName);
log(Recorder.RENAME, unwrap(oldName) + ":" + unwrap(newName));
super.rename(oldName, newName);
}
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
log(Recorder.TRY_DELETE, fileName);
return FileSystem.getInstance(fileName).tryDelete(fileName);
}
protected boolean accepts(String fileName) {
return fileName.startsWith(PREFIX);
log(Recorder.TRY_DELETE, unwrap(fileName));
return super.tryDelete(fileName);
}
private String translateFileName(String fileName) {
if (!fileName.startsWith(PREFIX)) {
DbException.throwInternalError(fileName + " doesn't start with " + PREFIX);
}
return fileName.substring(PREFIX.length());
public String getPrefix() {
return PREFIX;
}
public boolean isTrace() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论