提交 ab1e8d62 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 784e7774
#Fri Oct 19 18:51:44 CEST 2007
javac=javac
#Fri Oct 26 09:46:47 CEST 2007
benchmark.drivers.dir=C\:/data/java
javac=javac
path.servlet.jar=C\:/data/classpath/servlet-api.jar
version.name.maven=1.0.60
jdk=1.4
......@@ -46,7 +46,7 @@
<delete file="src/tools/org/h2/tools/code/CodeSwitch.class"/>
</target>
<target name="codeswitchPrepare">
<target name="codeswitchPrepare" depends="clean">
<javac executable="${javac}" srcdir="src/tools" destdir="bin" debug="true" includes="org/h2/tools/code/CodeSwitch.java"/>
</target>
......
......@@ -17,6 +17,7 @@ import java.util.StringTokenizer;
import org.h2.server.web.DbContextRule;
import org.h2.tools.Csv;
import org.h2.util.Resources;
import org.h2.util.StringCache;
import org.h2.util.StringUtils;
public class Bnf {
......@@ -254,6 +255,8 @@ public class Bnf {
StringTokenizer tokenizer = new StringTokenizer(syntax, SEPARATORS, true);
while (tokenizer.hasMoreTokens()) {
String s = tokenizer.nextToken();
// avoid duplicate strings
s = StringCache.get(s);
if (s.length() == 1) {
if (" \r\n".indexOf(s.charAt(0)) >= 0) {
continue;
......
......@@ -54,7 +54,7 @@ public class BackupCommand extends Prepared {
try {
String name = db.getName();
name = FileUtils.getFileName(name);
OutputStream zip = FileUtils.openFileOutputStream(fileName);
OutputStream zip = FileUtils.openFileOutputStream(fileName, false);
ZipOutputStream out = new ZipOutputStream(zip);
LogSystem log = db.getLog();
try {
......
......@@ -93,11 +93,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
// always use a big buffer, otherwise end-of-block is written a lot
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else {
try {
outStream = FileUtils.openFileOutputStream(fileName);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
outStream = FileUtils.openFileOutputStream(fileName, false);
out = new BufferedOutputStream(outStream, Constants.IO_BUFFER_SIZE);
out = CompressTool.wrapOutputStream(out, compressionAlgorithm, Constants.SCRIPT_SQL);
}
......
......@@ -376,7 +376,7 @@ public class ScriptCommand extends ScriptBase {
}
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT BDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART");
OutputStream out = FileUtils.openFileOutputStream(TEMP_LOB_FILENAME);
OutputStream out = FileUtils.openFileOutputStream(TEMP_LOB_FILENAME, false);
while (rs.next()) {
InputStream in = rs.getBinaryStream(1);
IOUtils.copyAndCloseInput(in, out);
......
......@@ -11,6 +11,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.h2.api.DatabaseEventListener;
import org.h2.command.dml.SetTypes;
import org.h2.constant.ErrorCode;
......@@ -37,6 +38,7 @@ import org.h2.store.FileStore;
import org.h2.store.RecordReader;
import org.h2.store.Storage;
import org.h2.store.WriterThread;
import org.h2.store.fs.FileSystem;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.MetaTable;
......@@ -51,7 +53,6 @@ import org.h2.util.ClassUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.IntHashMap;
import org.h2.util.MemoryFile;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
......@@ -224,14 +225,8 @@ public class Database implements DataHandler {
byte[] magicText = Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
byte[] magicBinary = Constants.MAGIC_FILE_HEADER.getBytes();
try {
byte[] magic;
if (FileUtils.isInMemory(fileName)) {
MemoryFile file = FileUtils.getMemoryFile(fileName);
magic = file.getMagic();
} else {
InputStream fin = FileUtils.openFileInputStream(fileName);
magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
}
byte[] magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
if (ByteUtils.compareNotNull(magic, magicText) == 0) {
return true;
} else if (ByteUtils.compareNotNull(magic, magicBinary) == 0) {
......@@ -422,7 +417,7 @@ public class Database implements DataHandler {
}
dummy = DataPage.create(this, 0);
if (persistent) {
if (readOnly || FileUtils.isInMemory(databaseName)) {
if (readOnly) {
traceSystem = new TraceSystem(null, false);
} else {
traceSystem = new TraceSystem(databaseName + Constants.SUFFIX_TRACE_FILE, true);
......@@ -1069,7 +1064,7 @@ public class Database implements DataHandler {
boolean inTempDir = readOnly;
String name = databaseName;
if (!persistent) {
name = FileUtils.MEMORY_PREFIX + name;
name = FileSystem.MEMORY_PREFIX + name;
}
return FileUtils.createTempFile(name, Constants.SUFFIX_TEMP_FILE, true, inTempDir);
} catch (IOException e) {
......
......@@ -97,6 +97,11 @@ public class LogFile {
}
String s = fileName.substring(fileNamePrefix.length() + 1, fileName.length()
- Constants.SUFFIX_LOG_FILE.length());
for (int i = 0; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
return null;
}
}
int id = Integer.parseInt(s);
return new LogFile(log, id, fileNamePrefix);
}
......
......@@ -4,7 +4,6 @@
*/
package org.h2.message;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigDecimal;
......@@ -189,7 +188,7 @@ public class TraceObject {
e.printStackTrace(p);
p.close();
writer.close();
} catch (IOException e2) {
} catch (Exception e2) {
e2.printStackTrace();
}
}
......
......@@ -149,7 +149,7 @@ public class SecureSocketFactory {
}
}
if (needWrite) {
OutputStream out = FileUtils.openFileOutputStream(fileName);
OutputStream out = FileUtils.openFileOutputStream(fileName, false);
out.write(data);
out.close();
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface FileObject {
boolean exists();
boolean isDirectory();
boolean isFile();
boolean delete();
boolean mkdirs();
long lastModified();
boolean renameTo(FileObject fileNew);
void read(long skip, OutputStream out) throws IOException;
FileObject[] listFiles();
long length();
boolean canRead();
boolean canWrite();
String getName();
void write(InputStream in) throws IOException;
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileObjectDatabase implements FileObject {
static FileObjectDatabase get(FileSystemDatabase db, String name) {
return new FileObjectDatabase(db, name);
}
private FileSystemDatabase db;
private String fullName;
private FileObjectDatabase(FileSystemDatabase db, String fullName) {
this.db = db;
this.fullName = fullName;
}
public boolean canRead() {
return true;
}
public boolean canWrite() {
return true;
}
public boolean delete() {
db.delete(fullName);
return true;
}
public boolean exists() {
return db.exists(fullName);
}
public void read(long skip, OutputStream out) throws IOException {
db.read(fullName, skip, out);
}
public String getName() {
return db.getName(fullName);
}
public void write(InputStream in) throws IOException {
db.write(fullName, in);
}
public boolean isDirectory() {
return db.isDirectory(fullName);
}
public boolean isFile() {
return !db.isDirectory(fullName);
}
public long lastModified() {
return db.lastModified(fullName);
}
public long length() {
return db.length(fullName);
}
public FileObject[] listFiles() {
return db.listFiles(fullName);
}
public boolean mkdirs() {
db.mkdirs(fullName);
return true;
}
public boolean renameTo(FileObject fileNew) {
return db.renameTo(fullName, ((FileObjectDatabase) fileNew).fullName);
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
public class FileObjectNative implements FileObject {
private File file;
static FileObjectNative get(String name) {
name = FileUtils.translateFileName(name);
return new FileObjectNative(new File(name));
}
private FileObjectNative(File f) {
this.file = f;
}
public boolean exists() {
return file.exists();
}
public boolean isDirectory() {
return file.isDirectory();
}
public boolean canRead() {
return file.canRead();
}
public boolean canWrite() {
return file.canWrite();
}
public boolean delete() {
return file.delete();
}
public String getName() {
return file.getName();
}
public boolean isFile() {
return file.isFile();
}
public long lastModified() {
return file.lastModified();
}
public long length() {
return file.length();
}
public FileObject[] listFiles() {
File[] list = file.listFiles();
FileObject[] result = new FileObject[list.length];
for (int i = 0; i < list.length; i++) {
result[i] = get(list[i].getAbsolutePath());
}
return result;
}
public boolean mkdirs() {
return file.mkdirs();
}
public boolean renameTo(FileObject newFile) {
return file.renameTo(((FileObjectNative) newFile).file);
}
public void write(InputStream in) throws IOException {
try {
OutputStream out = FileUtils.openFileOutputStream(file.getAbsolutePath());
IOUtils.copyAndClose(in, out);
} catch (SQLException e) {
throw new IOException(e.getMessage());
}
}
public void read(long skip, OutputStream out) throws IOException {
InputStream in = FileUtils.openFileInputStream(file.getAbsolutePath());
IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out);
}
}
......@@ -11,8 +11,10 @@ import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import org.h2.engine.Constants;
import org.h2.store.fs.FileSystem;
import org.h2.util.StringUtils;
public class FtpControl extends Thread {
......@@ -20,6 +22,7 @@ public class FtpControl extends Thread {
private static final String SERVER_NAME = "Small FTP Server";
private FtpServer server;
private FileSystem fs;
private Socket control;
private FtpData data;
private PrintWriter output;
......@@ -34,6 +37,7 @@ public class FtpControl extends Thread {
public FtpControl(Socket control, FtpServer server, boolean stop) {
this.server = server;
this.fs = server.getFileSystem();
this.control = control;
this.stop = stop;
}
......@@ -70,7 +74,7 @@ public class FtpControl extends Thread {
server.closeConnection();
}
private void process(String command) throws IOException {
private void process(String command) throws SQLException, IOException {
int idx = command.indexOf(' ');
String param = "";
if (idx >= 0) {
......@@ -122,17 +126,17 @@ public class FtpControl extends Thread {
}
}
private void processConnected(String command, String param) throws IOException {
private void processConnected(String command, String param) throws SQLException, IOException {
switch (command.charAt(0)) {
case 'C':
if ("CWD".equals(command)) {
param = getFileName(param);
FileObject file = server.getFile(param);
if (file.exists() && file.isDirectory()) {
if (!param.endsWith("/")) {
param += "/";
String path = getPath(param);
String fileName = getFileName(path);
if (fs.exists(fileName) && fs.isDirectory(fileName)) {
if (!path.endsWith("/")) {
path += "/";
}
currentDir = param;
currentDir = path;
reply(250, "Ok");
} else {
reply(550, "Failed");
......@@ -149,10 +153,10 @@ public class FtpControl extends Thread {
break;
case 'D':
if ("DELE".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (!readonly && file.exists() && file.isFile() && file.delete()) {
if (server.getAllowTask() && param.endsWith(FtpServer.TASK_SUFFIX)) {
server.stopTask(file);
String fileName = getFileName(param);
if (!readonly && fs.exists(fileName) && !fs.isDirectory(fileName) && fs.tryDelete(fileName)) {
if (server.getAllowTask() && fileName.endsWith(FtpServer.TASK_SUFFIX)) {
server.stopTask(fileName);
}
reply(250, "Ok");
} else {
......@@ -167,12 +171,18 @@ public class FtpControl extends Thread {
break;
case 'M':
if ("MKD".equals(command)) {
param = getFileName(param);
FileObject file = server.getFile(param);
if (!readonly && file.mkdirs()) {
reply(257, "\"" + param + "\" directory"); // TODO quote ("
// > "")
} else {
String fileName = getFileName(param);
boolean ok = false;
if (!readonly) {
try {
fs.mkdirs(fileName);
reply(257, "\"" + param + "\" directory"); // TODO quote (" > "")
ok = true;
} catch (SQLException e) {
server.logError(e);
}
}
if (!ok) {
reply(500, "Failed");
}
} else if ("MODE".equals(command)) {
......@@ -182,9 +192,9 @@ public class FtpControl extends Thread {
reply(504, "Invalid");
}
} else if ("MDTM".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (file.exists() && file.isFile()) {
reply(213, server.formatLastModified(file));
String fileName = getFileName(param);
if (fs.exists(fileName) && !fs.isDirectory(fileName)) {
reply(213, server.formatLastModified(fileName));
} else {
reply(550, "Failed");
}
......@@ -199,8 +209,7 @@ public class FtpControl extends Thread {
break;
case 'P':
if ("PWD".equals(command)) {
reply(257, "\"" + currentDir + "\" directory"); // TODO quote ("
// > "")
reply(257, "\"" + currentDir + "\" directory"); // TODO quote (" > "")
} else if ("PASV".equals(command)) {
ServerSocket dataSocket = server.createDataSocket();
data = new FtpData(server, control.getInetAddress(), dataSocket);
......@@ -212,10 +221,9 @@ public class FtpControl extends Thread {
break;
case 'R':
if ("RNFR".equals(command)) {
param = getFileName(param);
FileObject file = server.getFile(param);
if (file.exists()) {
renameFrom = param;
String fileName = getFileName(param);
if (fs.exists(fileName)) {
renameFrom = fileName;
reply(350, "Ok");
} else {
reply(450, "Not found");
......@@ -224,22 +232,31 @@ public class FtpControl extends Thread {
if (renameFrom == null) {
reply(503, "RNFR required");
} else {
FileObject fileOld = server.getFile(renameFrom);
FileObject fileNew = server.getFile(getFileName(param));
if (!readonly && fileOld.renameTo(fileNew)) {
String fileOld = renameFrom;
String fileNew = getFileName(param);
boolean ok = false;
if (!readonly) {
try {
fs.rename(fileOld, fileNew);
reply(250, "Ok");
} else {
ok = true;
} catch (SQLException e) {
server.logError(e);
}
}
if (!ok) {
reply(550, "Failed");
}
}
} else if ("RETR".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (file.exists() && file.isFile()) {
String fileName = getFileName(param);
if (fs.exists(fileName) && !fs.isDirectory(fileName)) {
reply(150, "Starting transfer");
try {
data.send(file, restart);
data.send(fs, fileName, restart);
reply(226, "Ok");
} catch (IOException e) {
server.logError(e);
reply(426, "Failed");
}
restart = 0;
......@@ -249,8 +266,8 @@ public class FtpControl extends Thread {
// reply(426, "Not a file");
}
} else if ("RMD".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (!readonly && file.exists() && file.isDirectory() && file.delete()) {
String fileName = getFileName(param);
if (!readonly && fs.exists(fileName) && fs.isDirectory(fileName) && fs.tryDelete(fileName)) {
reply(250, "Ok");
} else {
reply(500, "Failed");
......@@ -270,23 +287,24 @@ public class FtpControl extends Thread {
} else if ("SITE".equals(command)) {
reply(500, "Not understood");
} else if ("SIZE".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (file.exists() && file.isFile()) {
reply(250, String.valueOf(file.length()));
param = getFileName(param);
if (fs.exists(param) && !fs.isDirectory(param)) {
reply(250, String.valueOf(fs.length(param)));
} else {
reply(500, "Failed");
}
} else if ("STOR".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if (!readonly && !file.exists() || file.isFile()) {
String fileName = getFileName(param);
if (!readonly && !fs.exists(fileName) || !fs.isDirectory(fileName)) {
reply(150, "Starting transfer");
try {
data.receive(file);
data.receive(fs, fileName);
if (server.getAllowTask() && param.endsWith(FtpServer.TASK_SUFFIX)) {
server.startTask(file);
server.startTask(fileName);
}
reply(226, "Ok");
} catch (IOException e) {
} catch (Exception e) {
server.logError(e);
reply(426, "Failed");
}
} else {
......@@ -318,15 +336,19 @@ public class FtpControl extends Thread {
}
private String getFileName(String file) {
return file.startsWith("/") ? file : currentDir + file;
return server.getFileName(file.startsWith("/") ? file : currentDir + file);
}
private String getPath(String path) {
return path.startsWith("/") ? path : currentDir + path;
}
private void processList(String param, boolean directories) throws IOException {
FileObject directory = server.getFile(getFileName(param));
if (!directory.exists()) {
private void processList(String param, boolean directories) throws SQLException, IOException {
String directory = getFileName(param);
if (!fs.exists(directory)) {
reply(450, "Directory does not exist");
return;
} else if (!directory.isDirectory()) {
} else if (!fs.isDirectory(directory)) {
reply(450, "Not a directory");
return;
}
......
......@@ -10,6 +10,10 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils;
public class FtpData extends Thread {
......@@ -58,22 +62,27 @@ public class FtpData extends Thread {
socket = null;
}
public synchronized void receive(FileObject file) throws IOException {
public synchronized void receive(FileSystem fs, String fileName) throws IOException, SQLException {
waitUntilConnected();
try {
InputStream in = socket.getInputStream();
file.write(in);
OutputStream out = fs.openFileOutputStream(fileName, false);
IOUtils.copy(in, out);
out.close();
} finally {
socket.close();
}
server.log("closed");
}
public synchronized void send(FileObject file, long skip) throws IOException {
public synchronized void send(FileSystem fs, String fileName, long skip) throws IOException {
waitUntilConnected();
try {
OutputStream out = socket.getOutputStream();
file.read(skip, out);
InputStream in = fs.openFileInputStream(fileName);
in.skip(skip);
IOUtils.copy(in, out);
in.close();
} finally {
socket.close();
}
......
......@@ -4,16 +4,12 @@
*/
package org.h2.server.ftp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
......@@ -21,9 +17,9 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Properties;
import org.h2.Driver;
import org.h2.engine.Constants;
import org.h2.server.Service;
import org.h2.store.fs.FileSystem;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
......@@ -54,7 +50,7 @@ public class FtpServer implements Service {
private String readUserName = DEFAULT_READ;
private HashMap tasks = new HashMap();
private FileSystemDatabase db;
private FileSystem fs;
private boolean log;
private boolean allowTask;
static final String TASK_SUFFIX = ".task";
......@@ -87,18 +83,18 @@ public class FtpServer implements Service {
return dataSocket;
}
void appendFile(StringBuffer buff, FileObject f) {
buff.append(f.isDirectory() ? 'd' : '-');
buff.append(f.canRead() ? 'r' : '-');
buff.append(f.canWrite() ? 'w' : '-');
void appendFile(StringBuffer buff, String fileName) throws SQLException {
buff.append(fs.isDirectory(fileName) ? 'd' : '-');
buff.append('r');
buff.append(fs.canWrite(fileName) ? 'w' : '-');
buff.append("------- 1 owner group ");
String size = String.valueOf(f.length());
String size = String.valueOf(fs.length(fileName));
for (int i = size.length(); i < 15; i++) {
buff.append(' ');
}
buff.append(size);
buff.append(' ');
Date now = new Date(), mod = new Date(f.lastModified());
Date now = new Date(), mod = new Date(fs.getLastModified(fileName));
String date;
if (mod.after(now) || Math.abs((now.getTime() - mod.getTime()) / 1000 / 60 / 60 / 24) > 180) {
synchronized (dateFormatOld) {
......@@ -111,17 +107,21 @@ public class FtpServer implements Service {
}
buff.append(date);
buff.append(' ');
buff.append(f.getName());
buff.append(FileUtils.getFileName(fileName));
buff.append("\r\n");
}
String formatLastModified(FileObject file) {
String formatLastModified(String fileName) {
synchronized (dateFormat) {
return dateFormat.format(new Date(file.lastModified()));
return dateFormat.format(new Date(fs.getLastModified(fileName)));
}
}
FileObject getFile(String path) {
String getFileName(String path) {
return root + getPath(path);
}
String getPath(String path) {
if (path.indexOf("..") > 0) {
path = "/";
}
......@@ -131,21 +131,17 @@ public class FtpServer implements Service {
while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
log("file: " + root + path);
if (db != null) {
return FileObjectDatabase.get(db, root + path);
} else {
return FileObjectNative.get(root + path);
}
log("path: " + path);
return path;
}
String getDirectoryListing(FileObject directory, boolean listDirectories) {
FileObject[] list = directory.listFiles();
String getDirectoryListing(String directory, boolean listDirectories) throws SQLException {
String[] list = fs.listFiles(directory);
StringBuffer buff = new StringBuffer();
for (int i = 0; list != null && i < list.length; i++) {
FileObject f = list[i];
if (f.isFile() || (f.isDirectory() && listDirectories)) {
appendFile(buff, f);
String fileName = list[i];
if (!fs.isDirectory(fileName) || (fs.isDirectory(fileName) && listDirectories)) {
appendFile(buff, fileName);
}
}
return buff.toString();
......@@ -164,7 +160,7 @@ public class FtpServer implements Service {
if ("-ftpPort".equals(args[i])) {
port = MathUtils.decodeInt(args[++i]);
} else if ("-ftpDir".equals(args[i])) {
root = FileUtils.translateFileName(args[++i]);
root = FileUtils.normalize(args[++i]);
} else if ("-ftpRead".equals(args[i])) {
readUserName = args[++i];
} else if ("-ftpWrite".equals(args[i])) {
......@@ -177,17 +173,8 @@ public class FtpServer implements Service {
allowTask = Boolean.valueOf(args[++i]).booleanValue();
}
}
if (root.startsWith("jdbc:")) {
Connection conn;
if (root.startsWith("jdbc:h2:")) {
// avoid using DriverManager if possible
conn = Driver.load().connect(root, new Properties());
} else {
conn = DriverManager.getConnection(root);
}
db = new FileSystemDatabase(conn, log);
root = "/";
}
fs = FileSystem.getInstance(root);
root = fs.normalize(root);
}
public String getURL() {
......@@ -195,7 +182,7 @@ public class FtpServer implements Service {
}
public void start() throws SQLException {
getFile("").mkdirs();
fs.mkdirs(root);
serverSocket = NetUtils.createServerSocket(port, false);
}
......@@ -245,31 +232,24 @@ public class FtpServer implements Service {
return allowTask;
}
void startTask(FileObject file) throws IOException {
stopTask(file);
String processName = file.getName();
if (file.getName().endsWith(".zip.task")) {
log("expand: " + file.getName());
Process p = Runtime.getRuntime().exec("jar -xf " + file.getName(), null, new File(root));
String processFile = root + "/" + processName;
new StreamRedirect(processFile, p.getInputStream(), null).start();
void startTask(String path) throws IOException {
stopTask(path);
if (path.endsWith(".zip.task")) {
log("expand: " + path);
Process p = Runtime.getRuntime().exec("jar -xf " + path, null, new File(root));
new StreamRedirect(path, p.getInputStream(), null).start();
return;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
file.read(0, out);
byte[] data = out.toByteArray();
Properties prop = new Properties();
prop.load(new ByteArrayInputStream(data));
Properties prop = FileUtils.loadProperties(path);
String command = prop.getProperty("command");
String outFile = processName.substring(0, processName.length() - TASK_SUFFIX.length());
String outFile = path.substring(0, path.length() - TASK_SUFFIX.length());
String errorFile = root + "/" + prop.getProperty("error", outFile + ".err.txt");
String outputFile = root + "/" + prop.getProperty("output", outFile + ".out.txt");
String processFile = root + "/" + processName;
log("start process: " + processName + " / " + command);
log("start process: " + path + " / " + command);
Process p = Runtime.getRuntime().exec(command, null, new File(root));
new StreamRedirect(processFile, p.getErrorStream(), errorFile).start();
new StreamRedirect(processFile, p.getInputStream(), outputFile).start();
tasks.put(processName, p);
new StreamRedirect(path, p.getErrorStream(), errorFile).start();
new StreamRedirect(path, p.getInputStream(), outputFile).start();
tasks.put(path, p);
}
private static class StreamRedirect extends Thread {
......@@ -287,7 +267,7 @@ public class FtpServer implements Service {
private void openOutput() {
if (outFile != null) {
try {
this.out = FileUtils.openFileOutputStream(outFile);
this.out = FileUtils.openFileOutputStream(outFile, false);
} catch (Exception e) {
// ignore
}
......@@ -316,8 +296,7 @@ public class FtpServer implements Service {
}
}
void stopTask(FileObject file) {
String processName = file.getName();
void stopTask(String processName) {
log("kill process: " + processName);
Process p = (Process) tasks.remove(processName);
if (p == null) {
......@@ -326,4 +305,8 @@ public class FtpServer implements Service {
p.destroy();
}
public FileSystem getFileSystem() {
return fs;
}
}
......@@ -143,7 +143,10 @@ public class PgServer implements Service {
PgServerThread c = (PgServerThread) list.get(i);
c.close();
try {
c.getThread().join(100);
Thread t = c.getThread();
if (t != null) {
t.join(100);
}
} catch (Exception e) {
// TODO log exception
e.printStackTrace();
......
......@@ -42,21 +42,19 @@ public class WebServer implements Service {
private static final String DEFAULT_LANGUAGE = "en";
/**
* Hungarian spec chars: &eacute;&#369;&aacute;&#337;&uacute;&ouml;&uuml;&oacute;&iacute;&Eacute;&Aacute;&#368;&#336;&Uacute;&Ouml;&Uuml;&Oacute;&Iacute;
*/
private static final String[][] LANGUAGES = {
{ "en", "English" },
{ "de", "Deutsch" },
{ "fr", "Fran\u00e7ais" },
{ "en", "English" },
{ "es", "Espa\u00f1ol" },
{ "zh_CN", "\u4E2D\u6587"},
{ "ja", "\u65e5\u672c\u8a9e"},
{ "fr", "Fran\u00e7ais" },
{ "hu", "Magyar"},
{ "in", "Indonesia"},
{ "pt_PT", "Portugu\u00eas (Europeu)"},
{ "pl", "Polski"},
{ "it", "Italiano"},
{ "ja", "\u65e5\u672c\u8a9e"},
{ "pl", "Polski"},
{ "pt_PT", "Portugu\u00eas (Europeu)"},
{ "ru", "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"},
{ "zh_CN", "\u4E2D\u6587"},
};
private static final String[] GENERIC = new String[] {
......@@ -76,6 +74,18 @@ public class WebServer implements Service {
"Generic H2|org.h2.Driver|jdbc:h2:~/test|sa",
};
/*
String lang = new java.util.Locale("hu").getDisplayLanguage(new java.util.Locale("hu"));
java.util.Locale.CHINESE.getDisplayLanguage(
java.util.Locale.CHINESE);
for(int i=0; i<lang.length(); i++)
System.out.println(Integer.toHexString(lang.charAt(i))+" ");
*/
/**
* Hungarian spec chars: &eacute;&#369;&aacute;&#337;&uacute;&ouml;&uuml;&oacute;&iacute;&Eacute;&Aacute;&#368;&#336;&Uacute;&Ouml;&Uuml;&Oacute;&Iacute;
* Or use PropertiesToUTF8
*/
// private URLClassLoader urlClassLoader;
private String driverList;
private static int ticker;
......@@ -85,14 +95,6 @@ public class WebServer implements Service {
private boolean ssl;
private HashMap connInfoMap = new HashMap();
/*
String lang = new java.util.Locale("hu").getDisplayLanguage(new java.util.Locale("hu"));
java.util.Locale.CHINESE.getDisplayLanguage(
java.util.Locale.CHINESE);
for(int i=0; i<lang.length(); i++)
System.out.println(Integer.toHexString(lang.charAt(i))+" ");
*/
private static final long SESSION_TIMEOUT = 30 * 60 * 1000; // timeout is 30 min
private long lastTimeoutCheck;
private HashMap sessions = new HashMap();
......@@ -445,7 +447,7 @@ public class WebServer implements Service {
prop.setProperty(String.valueOf(len - i - 1), info.getString());
}
}
OutputStream out = FileUtils.openFileOutputStream(getPropertiesFileName());
OutputStream out = FileUtils.openFileOutputStream(getPropertiesFileName(), false);
prop.store(out, Constants.SERVER_PROPERTIES_TITLE);
out.close();
} catch (Exception e) {
......
......@@ -805,6 +805,7 @@ class WebThread extends Thread implements DatabaseEventListener {
}
private String getStackTrace(int id, Throwable e) {
try {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String s = writer.toString();
......@@ -816,6 +817,10 @@ class WebThread extends Thread implements DatabaseEventListener {
+ "</a><span style=\"display: none;\" id=\"st" + id + "\"><br />" + s + "</span>";
s = formatAsError(s);
return s;
} catch (OutOfMemoryError e2) {
e.printStackTrace();
return e.toString();
}
}
private String formatAsError(String s) {
......
.translator=Vlad Alexahin
a.help=&\#1055;&\#1086;&\#1084;&\#1086;&\#1097;&\#1100;
a.language=&\#1056;&\#1091;&\#1089;&\#1089;&\#1082;&\#1080;&\#1081;
a.lynxNotSupported=&\#1048;&\#1079;&\#1074;&\#1080;&\#1085;&\#1080;&\#1090;&\#1077;, Lynx &\#1087;&\#1086;&\#1082;&\#1072; &\#1095;&\#1090;&\#1086; &\#1085;&\#1077; &\#1087;&\#1086;&\#1076;&\#1076;&\#1077;&\#1088;&\#1078;&\#1080;&\#1074;&\#1072;&\#1077;&\#1090;&\#1089;&\#1103;
a.password=&\#1055;&\#1072;&\#1088;&\#1086;&\#1083;&\#1100;
a.remoteConnectionsDisabled=&\#1048;&\#1079;&\#1074;&\#1080;&\#1085;&\#1080;&\#1090;&\#1077;, &\#1091;&\#1076;&\#1072;&\#1083;&\#1077;&\#1085;&\#1085;&\#1099;&\#1077; &\#1087;&\#1086;&\#1076;&\#1082;&\#1083;&\#1102;&\#1095;&\#1077;&\#1085;&\#1080;&\#1103; ('webAllowOthers') &\#1079;&\#1072;&\#1087;&\#1088;&\#1077;&\#1097;&\#1077;&\#1085;&\#1099; &\#1085;&\#1072; &\#1101;&\#1090;&\#1086;&\#1084; &\#1089;&\#1077;&\#1088;&\#1074;&\#1077;&\#1088;&\#1077;.
a.title=H2 Console
a.user=&\#1055;&\#1086;&\#1083;&\#1100;&\#1079;&\#1086;&\#1074;&\#1072;&\#1090;&\#1077;&\#1083;&\#1100; &\#1048;&\#1084;&\#1103;
admin.executing=&\#1042;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1103;&\#1077;&\#1090;&\#1089;&\#1103;
admin.ip=IP
admin.lastAccess=&\#1055;&\#1086;&\#1089;&\#1083;&\#1077;&\#1076;&\#1085;&\#1080;&\#1081; &\#1042;&\#1093;&\#1086;&\#1076;
admin.lastQuery=&\#1055;&\#1086;&\#1089;&\#1083;&\#1077;&\#1076;&\#1085;&\#1080;&\#1081; &\#1047;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;
admin.url=URL
adminAllow=&\#1056;&\#1072;&\#1079;&\#1088;&\#1077;&\#1096;&\#1077;&\#1085;&\#1085;&\#1099;&\#1077; &\#1082;&\#1083;&\#1080;&\#1077;&\#1085;&\#1090;&\#1099;
adminConnection=&\#1041;&\#1077;&\#1079;&\#1086;&\#1087;&\#1072;&\#1089;&\#1085;&\#1086;&\#1089;&\#1090;&\#1100; &\#1087;&\#1086;&\#1076;&\#1082;&\#1083;&\#1102;&\#1095;&\#1077;&\#1085;&\#1080;&\#1103;
adminHttp=&\#1048;&\#1089;&\#1087;&\#1086;&\#1083;&\#1100;&\#1079;&\#1091;&\#1081;&\#1090;&\#1077; &\#1085;&\#1077;&\#1079;&\#1072;&\#1096;&\#1080;&\#1092;&\#1088;&\#1086;&\#1074;&\#1072;&\#1085;&\#1099;&\#1077; HTTP-&\#1089;&\#1086;&\#1077;&\#1076;&\#1080;&\#1085;&\#1077;&\#1085;&\#1080;&\#1103;
adminHttps=&\#1048;&\#1089;&\#1087;&\#1086;&\#1083;&\#1100;&\#1079;&\#1091;&\#1081;&\#1090;&\#1077; SSL (HTTPS) &\#1089;&\#1086;&\#1077;&\#1076;&\#1080;&\#1085;&\#1077;&\#1085;&\#1080;&\#1103;
adminLocal=&\#1056;&\#1072;&\#1079;&\#1088;&\#1077;&\#1096;&\#1077;&\#1085;&\#1099; &\#1090;&\#1086;&\#1083;&\#1100;&\#1082;&\#1086; &\#1083;&\#1086;&\#1082;&\#1072;&\#1083;&\#1100;&\#1085;&\#1099;&\#1077; &\#1087;&\#1086;&\#1076;&\#1082;&\#1083;&\#1102;&\#1095;&\#1077;&\#1085;&\#1080;&\#1103;
adminLogin=&\#1040;&\#1076;&\#1084;&\#1080;&\#1085;&\#1080;&\#1089;&\#1090;&\#1088;&\#1072;&\#1090;&\#1086;&\#1088; &\#1051;&\#1086;&\#1075;&\#1080;&\#1085;
adminLoginCancel=&\#1054;&\#1090;&\#1084;&\#1077;&\#1085;&\#1080;&\#1090;&\#1100;
adminLoginOk=OK
adminLogout=Logout
adminOthers=&\#1056;&\#1072;&\#1079;&\#1088;&\#1077;&\#1096;&\#1080;&\#1090;&\#1100; &\#1091;&\#1076;&\#1072;&\#1083;&\#1077;&\#1085;&\#1085;&\#1099;&\#1077; &\#1087;&\#1086;&\#1076;&\#1082;&\#1083;&\#1102;&\#1095;&\#1077;&\#1085;&\#1080;&\#1103;
adminPort=&\#1053;&\#1086;&\#1084;&\#1077;&\#1088; &\#1087;&\#1086;&\#1088;&\#1090;&\#1072;
adminPortWeb=&\#1055;&\#1086;&\#1088;&\#1090; web-&\#1089;&\#1077;&\#1088;&\#1074;&\#1077;&\#1088;&\#1072;
adminRestart=&\#1048;&\#1079;&\#1084;&\#1077;&\#1085;&\#1077;&\#1085;&\#1080;&\#1103; &\#1074;&\#1089;&\#1090;&\#1091;&\#1087;&\#1103;&\#1090; &\#1074; &\#1089;&\#1080;&\#1083;&\#1091; &\#1087;&\#1086;&\#1089;&\#1083;&\#1077; &\#1087;&\#1077;&\#1088;&\#1077;&\#1079;&\#1072;&\#1075;&\#1088;&\#1091;&\#1079;&\#1082;&\#1080; &\#1089;&\#1077;&\#1088;&\#1074;&\#1077;&\#1088;&\#1072;.
adminSave=&\#1057;&\#1086;&\#1093;&\#1088;&\#1072;&\#1085;&\#1080;&\#1090;&\#1100;
adminSessions=&\#1040;&\#1082;&\#1090;&\#1080;&\#1074;&\#1085;&\#1099;&\#1077; &\#1089;&\#1077;&\#1089;&\#1089;&\#1080;&\#1080;
adminShutdown=&\#1042;&\#1099;&\#1082;&\#1083;&\#1102;&\#1095;&\#1080;&\#1090;&\#1100;
adminTitle=H2 Console Preferences
helpAction=&\#1044;&\#1077;&\#1081;&\#1089;&\#1090;&\#1074;&\#1080;&\#1077;
helpAddAnotherRow=&\#1044;&\#1086;&\#1073;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1091;
helpAddDrivers=&\#1044;&\#1072;&\#1073;&\#1072;&\#1074;&\#1083;&\#1103;&\#1077;&\#1084; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093;
helpAddDriversOnlyJava=&\#1058;&\#1086;&\#1083;&\#1100;&\#1082;&\#1086; &\#1074;&\#1077;&\#1088;&\#1089;&\#1080;&\#1103; Java &\#1087;&\#1086;&\#1076;&\#1076;&\#1077;&\#1088;&\#1078;&\#1080;&\#1074;&\#1072;&\#1077;&\#1090; &\#1076;&\#1086;&\#1087;&\#1086;&\#1083;&\#1085;&\#1080;&\#1090;&\#1077;&\#1083;&\#1100;&\#1085;&\#1099;&\#1077; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088;&\#1072; (&\#1101;&\#1090;&\#1072; &\#1086;&\#1087;&\#1094;&\#1080;&\#1103; &\#1085;&\#1077; &\#1087;&\#1086;&\#1076;&\#1076;&\#1077;&\#1088;&\#1078;&\#1080;&\#1074;&\#1072;&\#1077;&\#1090;&\#1089;&\#1103; &\#1088;&\#1086;&\#1076;&\#1085;&\#1086;&\#1081; (&\#1090;&\#1077;&\#1082;&\#1091;&\#1097;&\#1077;&\#1081;) &\#1074;&\#1077;&\#1088;&\#1089;&\#1080;&\#1077;&\#1081;).
helpAddDriversText=&\#1044;&\#1086;&\#1087;&\#1086;&\#1083;&\#1085;&\#1080;&\#1090;&\#1077;&\#1083;&\#1100;&\#1085;&\#1099;&\#1077; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088;&\#1099; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093; &\#1084;&\#1086;&\#1075;&\#1091;&\#1090; &\#1073;&\#1099;&\#1090;&\#1100; &\#1079;&\#1072;&\#1088;&\#1077;&\#1075;&\#1077;&\#1089;&\#1090;&\#1088;&\#1080;&\#1088;&\#1086;&\#1074;&\#1072;&\#1085;&\#1099; &\#1076;&\#1086;&\#1073;&\#1072;&\#1074;&\#1083;&\#1077;&\#1085;&\#1080;&\#1077;&\#1084; &\#1089;&\#1086;&\#1086;&\#1090;&\#1074;&\#1077;&\#1090;&\#1089;&\#1090;&\#1074;&\#1091;&\#1102;&\#1097;&\#1080;&\#1093; Jar-&\#1092;&\#1072;&\#1081;&\#1083;&\#1086;&\#1074; &\#1074; &\#1087;&\#1077;&\#1088;&\#1077;&\#1084;&\#1077;&\#1085;&\#1085;&\#1091;&\#1102; &\#1089;&\#1088;&\#1077;&\#1076;&\#1099; H2DRIVERS &\#1080;&\#1083;&\#1080; &\#1074; CLASSPATH. &\#1055;&\#1088;&\#1080;&\#1084;&\#1077;&\#1088; (Windows)\: &\#1063;&\#1090;&\#1086;&\#1073;&\#1099; &\#1076;&\#1086;&\#1073;&\#1072;&\#1080;&\#1090;&\#1100; &\#1073;&\#1080;&\#1073;&\#1083;&\#1080;&\#1086;&\#1090;&\#1077;&\#1082;&\#1091; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088;&\#1072; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093; C\:\\Programs\\hsqldb\\lib\\hsqldb.jar, &\#1091;&\#1089;&\#1090;&\#1072;&\#1085;&\#1086;&\#1074;&\#1080;&\#1090;&\#1077; &\#1074; &\#1087;&\#1077;&\#1088;&\#1077;&\#1084;&\#1077;&\#1085;&\#1085;&\#1091;&\#1102; &\#1089;&\#1088;&\#1077;&\#1076;&\#1099; H2DRIVERS &\#1079;&\#1085;&\#1072;&\#1095;&\#1077;&\#1085;&\#1080;&\#1077; C\:\\Programs\\hsqldb\\lib\\hsqldb.jar.
helpAddRow=&\#1044;&\#1086;&\#1073;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100; &\#1085;&\#1086;&\#1074;&\#1091;&\#1102; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1091;
helpCommandHistory=&\#1055;&\#1086;&\#1082;&\#1072;&\#1079;&\#1099;&\#1074;&\#1072;&\#1077;&\#1090; &\#1080;&\#1089;&\#1090;&\#1086;&\#1088;&\#1080;&\#1102; &\#1074;&\#1099;&\#1087;&\#1086;&\#1083;&\#1077;&\#1085;&\#1085;&\#1099;&\#1093; &\#1082;&\#1086;&\#1084;&\#1072;&\#1085;&\#1076;
helpCreateTable=&\#1057;&\#1086;&\#1079;&\#1076;&\#1072;&\#1090;&\#1100; &\#1085;&\#1086;&\#1074;&\#1091;&\#1102; &\#1090;&\#1072;&\#1073;&\#1083;&\#1080;&\#1094;&\#1091;
helpDeleteRow=&\#1059;&\#1076;&\#1072;&\#1083;&\#1080;&\#1090;&\#1100; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1091;
helpDisconnect=&\#1054;&\#1090;&\#1082;&\#1083;&\#1102;&\#1095;&\#1080;&\#1090;&\#1100;&\#1089;&\#1103; &\#1086;&\#1090; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093;
helpDisplayThis=&\#1055;&\#1086;&\#1082;&\#1072;&\#1079;&\#1099;&\#1074;&\#1072;&\#1077;&\#1090; &\#1101;&\#1090;&\#1086; &\#1086;&\#1082;&\#1085;&\#1086; &\#1087;&\#1086;&\#1084;&\#1086;&\#1097;&\#1080;
helpDropTable=&\#1059;&\#1076;&\#1072;&\#1083;&\#1103;&\#1077;&\#1090; &\#1090;&\#1072;&\#1073;&\#1083;&\#1080;&\#1094;&\#1091;, &\#1077;&\#1089;&\#1083;&\#1080; &\#1086;&\#1085;&\#1072; &\#1091;&\#1078;&\#1077; &\#1089;&\#1091;&\#1097;&\#1077;&\#1089;&\#1090;&\#1074;&\#1091;&\#1077;&\#1090;
helpExecuteCurrent=&\#1042;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1080;&\#1090;&\#1100; &\#1090;&\#1077;&\#1082;&\#1091;&\#1097;&\#1080;&\#1081; SQL-&\#1079;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;
helpIcon=&\#1048;&\#1082;&\#1086;&\#1085;&\#1082;&\#1072;
helpImportantCommands=&\#1042;&\#1072;&\#1078;&\#1085;&\#1099;&\#1077; &\#1082;&\#1086;&\#1084;&\#1072;&\#1085;&\#1076;&\#1099;
helpOperations=&\#1054;&\#1087;&\#1077;&\#1088;&\#1072;&\#1094;&\#1080;&\#1080;
helpQuery=&\#1047;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089; &\#1082; &\#1090;&\#1072;&\#1073;&\#1083;&\#1080;&\#1094;&\#1077;
helpSampleSQL=&\#1055;&\#1088;&\#1080;&\#1084;&\#1077;&\#1088;&\#1099; SQL-&\#1089;&\#1082;&\#1088;&\#1080;&\#1087;&\#1090;&\#1086;&\#1074;
helpStatements=SQL-&\#1079;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;
helpUpdate=&\#1048;&\#1079;&\#1084;&\#1077;&\#1085;&\#1080;&\#1090;&\#1100; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1077; &\#1074; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1077;
helpWithColumnsIdName=&\#1089; &\#1082;&\#1086;&\#1083;&\#1086;&\#1085;&\#1082;&\#1072;&\#1084;&\#1080; ID &\#1080; NAME
login.connect=&\#1057;&\#1086;&\#1077;&\#1076;&\#1080;&\#1085;&\#1080;&\#1090;&\#1100;&\#1089;&\#1103;
login.driverClass=&\#1050;&\#1083;&\#1072;&\#1089;&\#1089; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088;&\#1072;
login.driverNotFound=&\#1044;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093; &\#1085;&\#1077; &\#1085;&\#1072;&\#1081;&\#1076;&\#1077;&\#1085;&lt;br /&gt;&\#1055;&\#1086;&\#1089;&\#1084;&\#1086;&\#1090;&\#1088;&\#1080;&\#1090;&\#1077; &\#1074; &\#1055;&\#1086;&\#1084;&\#1086;&\#1097;&\#1080;, &\#1082;&\#1072;&\#1082; &\#1076;&\#1086;&\#1073;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100; &\#1076;&\#1088;&\#1072;&\#1081;&\#1074;&\#1077;&\#1088; &\#1073;&\#1072;&\#1079;&\#1099; &\#1076;&\#1072;&\#1085;&\#1085;&\#1099;&\#1093;
login.goAdmin=Preferences
login.jdbcUrl=JDBC URL
login.language=&\#1071;&\#1079;&\#1099;&\#1082;
login.login=&\#1051;&\#1086;&\#1075;&\#1080;&\#1085;
login.remove=&\#1059;&\#1076;&\#1072;&\#1083;&\#1080;&\#1090;&\#1100;
login.save=&\#1057;&\#1086;&\#1093;&\#1088;&\#1072;&\#1085;&\#1080;&\#1090;&\#1100;
login.savedSetting=&\#1057;&\#1086;&\#1093;&\#1088;&\#1072;&\#1085;&\#1080;&\#1090;&\#1100; &\#1085;&\#1072;&\#1089;&\#1090;&\#1088;&\#1086;&\#1081;&\#1082;&\#1080;
login.settingName=&\#1048;&\#1084;&\#1103; &\#1085;&\#1072;&\#1089;&\#1090;&\#1088;&\#1086;&\#1081;&\#1082;&\#1080;
login.testConnection=&\#1058;&\#1077;&\#1089;&\#1090;&\#1086;&\#1074;&\#1086;&\#1077; &\#1089;&\#1086;&\#1077;&\#1076;&\#1080;&\#1085;&\#1077;&\#1085;&\#1080;&\#1077;
login.testSuccessful=&\#1058;&\#1077;&\#1089;&\#1090; &\#1087;&\#1088;&\#1086;&\#1096;&\#1077;&\#1083; &\#1091;&\#1089;&\#1087;&\#1077;&\#1096;&\#1085;&\#1086;
login.welcome=H2 Console
result.1row=1 &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1072;
result.autoCommitOff=&\#1040;&\#1074;&\#1090;&\#1086;-&\#1074;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1077;&\#1085;&\#1080;&\#1077; &\#1089;&\#1077;&\#1081;&\#1095;&\#1072;&\#1089; &\#1042;&\#1067;&\#1050;&\#1051;&\#1070;&\#1063;&\#1045;&\#1053;&\#1054;
result.autoCommitOn=&\#1040;&\#1074;&\#1090;&\#1086;-&\#1074;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1077;&\#1085;&\#1080;&\#1077; &\#1089;&\#1077;&\#1081;&\#1095;&\#1072;&\#1089; &\#1042;&\#1050;&\#1051;&\#1070;&\#1063;&\#1045;&\#1053;&\#1054;
result.maxrowsSet=&\#1059;&\#1089;&\#1090;&\#1072;&\#1085;&\#1086;&\#1074;&\#1083;&\#1077;&\#1085;&\#1086; &\#1084;&\#1072;&\#1082;&\#1089;&\#1080;&\#1084;&\#1072;&\#1083;&\#1100;&\#1085;&\#1086;&\#1077; &\#1082;&\#1086;&\#1083;&\#1080;&\#1095;&\#1077;&\#1089;&\#1090;&\#1074;&\#1086; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;
result.noRows=&\#1085;&\#1077;&\#1090; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;
result.noRunningStatement=&\#1057;&\#1077;&\#1081;&\#1095;&\#1072;&\#1089; &\#1085;&\#1077;&\#1090;&\#1091; &\#1074;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1103;&\#1077;&\#1084;&\#1099;&\#1093; &\#1079;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;&\#1086;&\#1074;
result.rows=&\#1089;&\#1090;&\#1088;&\#1086;&\#1082;&\#1080;
result.statementWasCancelled=&\#1047;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089; &\#1073;&\#1099;&\#1083; &\#1086;&\#1090;&\#1084;&\#1077;&\#1085;&\#1077;&\#1085;
result.updateCount=&\#1054;&\#1073;&\#1085;&\#1086;&\#1074;&\#1080;&\#1090;&\#1100; &\#1082;&\#1086;&\#1083;&\#1080;&\#1095;&\#1077;&\#1089;&\#1090;&\#1074;&\#1086;
resultEdit.add=&\#1044;&\#1086;&\#1073;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100;
resultEdit.cancel=&\#1054;&\#1090;&\#1084;&\#1077;&\#1085;&\#1080;&\#1090;&\#1100;
resultEdit.delete=&\#1059;&\#1076;&\#1072;&\#1083;&\#1080;&\#1090;&\#1100;
resultEdit.edit=&\#1055;&\#1088;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100;
resultEdit.editResult=&\#1055;&\#1088;&\#1072;&\#1074;&\#1080;&\#1090;&\#1100;
resultEdit.save=&\#1057;&\#1086;&\#1093;&\#1088;&\#1072;&\#1085;&\#1080;&\#1090;&\#1100;
toolbar.all=&\#1042;&\#1089;&\#1077;
toolbar.autoCommit=&\#1040;&\#1074;&\#1090;&\#1086;-&\#1074;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1077;&\#1085;&\#1080;&\#1077;
toolbar.autoComplete=&\#1040;&\#1074;&\#1090;&\#1086;-&\#1079;&\#1072;&\#1074;&\#1077;&\#1088;&\#1096;&\#1077;&\#1085;&\#1080;&\#1077;
toolbar.autoComplete.full=&\#1042;&\#1089;&\#1077;
toolbar.autoComplete.normal=&\#1053;&\#1086;&\#1088;&\#1084;&\#1072;&\#1083;&\#1100;&\#1085;&\#1099;&\#1077;
toolbar.autoComplete.off=&\#1042;&\#1099;&\#1082;&\#1083;&\#1102;&\#1095;&\#1077;&\#1085;&\#1086;
toolbar.cancelStatement=&\#1054;&\#1090;&\#1084;&\#1077;&\#1085;&\#1080;&\#1090;&\#1100; &\#1090;&\#1077;&\#1082;&\#1091;&\#1097;&\#1080;&\#1081; &\#1079;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;
toolbar.clear=&\#1054;&\#1095;&\#1080;&\#1089;&\#1090;&\#1080;&\#1090;&\#1100;
toolbar.commit=&\#1042;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1080;&\#1090;&\#1100;
toolbar.disconnect=&\#1054;&\#1090;&\#1089;&\#1086;&\#1077;&\#1076;&\#1077;&\#1085;&\#1080;&\#1090;&\#1100;&\#1089;&\#1103;
toolbar.history=&\#1048;&\#1089;&\#1090;&\#1086;&\#1088;&\#1080;&\#1103; &\#1082;&\#1086;&\#1084;&\#1072;&\#1085;&\#1076;
toolbar.maxRows=&\#1052;&\#1072;&\#1082;&\#1089;&\#1080;&\#1084;&\#1072;&\#1083;&\#1100;&\#1085;&\#1086;&\#1077; &\#1082;&\#1086;&\#1083;&\#1080;&\#1095;&\#1077;&\#1089;&\#1090;&\#1074;&\#1086; &\#1089;&\#1090;&\#1088;&\#1086;&\#1082;
toolbar.refresh=&\#1054;&\#1073;&\#1085;&\#1086;&\#1074;&\#1080;&\#1090;&\#1100;
toolbar.rollback=&\#1042;&\#1077;&\#1088;&\#1085;&\#1091;&\#1090;&\#1100; &\#1085;&\#1072;&\#1079;&\#1072;&\#1076;
toolbar.run=&\#1042;&\#1099;&\#1087;&\#1086;&\#1083;&\#1085;&\#1080;&\#1090;&\#1100; (Ctrl+Enter)
toolbar.sqlStatement=SQL-&\#1079;&\#1072;&\#1087;&\#1088;&\#1086;&\#1089;
tree.admin=&\#1040;&\#1076;&\#1084;&\#1080;&\#1085;&\#1080;&\#1089;&\#1090;&\#1088;&\#1072;&\#1090;&\#1086;&\#1088;
tree.current=&\#1058;&\#1077;&\#1082;&\#1091;&\#1097;&\#1077;&\#1077; &\#1079;&\#1085;&\#1072;&\#1095;&\#1077;&\#1085;&\#1080;&\#1077;
tree.hashed=Hashed
tree.increment=&\#1059;&\#1074;&\#1077;&\#1083;&\#1080;&\#1095;&\#1080;&\#1090;&\#1100;
tree.indexes=&\#1048;&\#1085;&\#1076;&\#1077;&\#1082;&\#1089;&\#1099;
tree.nonUnique=&\#1053;&\#1077;&\#1091;&\#1085;&\#1080;&\#1082;&\#1072;&\#1083;&\#1100;&\#1085;&\#1086;&\#1077;
tree.sequences=&\#1055;&\#1086;&\#1089;&\#1083;&\#1077;&\#1076;&\#1086;&\#1074;&\#1072;&\#1090;&\#1077;&\#1083;&\#1100;&\#1085;&\#1086;&\#1089;&\#1090;&\#1100;
tree.unique=&\#1059;&\#1085;&\#1080;&\#1082;&\#1072;&\#1083;&\#1100;&\#1085;&\#1086;&\#1077;
tree.users=&\#1055;&\#1086;&\#1083;&\#1100;&\#1079;&\#1086;&\#1074;&\#1072;&\#1090;&\#1077;&\#1083;&\#1080;
......@@ -4,7 +4,6 @@
*/
package org.h2.store;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
......@@ -35,12 +34,12 @@ public class FileLister {
* @throws SQLException
*/
public static ArrayList getDatabaseFiles(String dir, String db, boolean all) throws SQLException {
dir = FileUtils.translateFileName(dir);
dir = FileUtils.normalize(dir);
ArrayList files = new ArrayList();
if (dir == null || dir.equals("")) {
dir = ".";
}
String start = db == null ? null : FileUtils.normalize(dir + File.separator + db);
String start = db == null ? null : FileUtils.normalize(dir + "/" + db);
String[] list = FileUtils.listFiles(dir);
for (int i = 0; list != null && i < list.length; i++) {
String f = list[i];
......@@ -68,7 +67,7 @@ public class FileLister {
}
}
if (ok) {
if (db == null || FileUtils.fileStartsWith(f, start + ".") || FileUtils.isInMemory(dir)) {
if (db == null || FileUtils.fileStartsWith(f, start + ".")) {
String fileName = f;
files.add(fileName);
}
......
......@@ -21,6 +21,7 @@ import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.RandomUtils;
......@@ -46,6 +47,7 @@ public class FileLock {
private int sleep;
private long lastWrite;
private Properties properties;
private FileSystem fs;
private volatile String fileName;
private volatile ServerSocket socket;
private boolean locked;
......@@ -59,6 +61,7 @@ public class FileLock {
}
public synchronized void lock(String fileName, boolean allowSocket) throws SQLException {
this.fs = FileSystem.getInstance(fileName);
this.fileName = fileName;
if (locked) {
throw Message.getInternalError("already locked");
......@@ -95,7 +98,7 @@ public class FileLock {
try {
if (fileName != null) {
if (load().equals(properties)) {
FileUtils.delete(fileName);
fs.delete(fileName);
}
}
if (socket != null) {
......@@ -111,14 +114,14 @@ public class FileLock {
void save() throws SQLException {
try {
OutputStream out = FileUtils.openFileOutputStream(fileName);
OutputStream out = fs.openFileOutputStream(fileName, false);
try {
properties.setProperty("method", String.valueOf(method));
properties.store(out, MAGIC);
} finally {
out.close();
}
lastWrite = FileUtils.getLastModified(fileName);
lastWrite = fs.getLastModified(fileName);
trace.debug("save " + properties);
} catch (IOException e) {
throw getException(e);
......@@ -137,7 +140,7 @@ public class FileLock {
private void waitUntilOld() throws SQLException {
for (int i = 0; i < 10; i++) {
long last = FileUtils.getLastModified(fileName);
long last = fs.getLastModified(fileName);
long dist = System.currentTimeMillis() - last;
if (dist < -TIME_GRANULARITY) {
throw error("Lock file modified in the future: dist=" + dist);
......@@ -161,7 +164,7 @@ public class FileLock {
byte[] bytes = RandomUtils.getSecureBytes(RANDOM_BYTES);
String random = ByteUtils.convertBytesToString(bytes);
properties.setProperty("id", Long.toHexString(System.currentTimeMillis())+random);
if (!FileUtils.createNewFile(fileName)) {
if (!fs.createNewFile(fileName)) {
waitUntilOld();
String m2 = load().getProperty("method", FILE);
if (!m2.equals(FILE)) {
......@@ -172,8 +175,8 @@ public class FileLock {
if (!load().equals(properties)) {
throw error("Locked by another process");
}
FileUtils.delete(fileName);
if (!FileUtils.createNewFile(fileName)) {
fs.delete(fileName);
if (!fs.createNewFile(fileName)) {
throw error("Another process was faster");
}
}
......@@ -189,7 +192,7 @@ public class FileLock {
while (fileName != null) {
// trace.debug("watchdog check");
try {
if (!FileUtils.exists(fileName) || FileUtils.getLastModified(fileName) != lastWrite) {
if (!fs.exists(fileName) || fs.getLastModified(fileName) != lastWrite) {
save();
}
Thread.sleep(sleep);
......@@ -218,9 +221,9 @@ public class FileLock {
} catch (UnknownHostException e) {
throw getException(e);
}
if (!FileUtils.createNewFile(fileName)) {
if (!fs.createNewFile(fileName)) {
waitUntilOld();
long read = FileUtils.getLastModified(fileName);
long read = fs.getLastModified(fileName);
Properties p2 = load();
String m2 = p2.getProperty("method", SOCKET);
if (m2.equals(FILE)) {
......@@ -254,11 +257,11 @@ public class FileLock {
throw error("IOException");
}
}
if (read != FileUtils.getLastModified(fileName)) {
if (read != fs.getLastModified(fileName)) {
throw error("Concurrent update");
}
FileUtils.delete(fileName);
if (!FileUtils.createNewFile(fileName)) {
fs.delete(fileName);
if (!fs.createNewFile(fileName)) {
throw error("Another process was faster");
}
}
......
......@@ -5,7 +5,6 @@
package org.h2.store;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.Reference;
import java.sql.SQLException;
......@@ -14,8 +13,9 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.Message;
import org.h2.security.SecureFileStore;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.TempFileDeleter;
/**
......@@ -31,7 +31,7 @@ public class FileStore {
protected String name;
protected DataHandler handler;
private byte[] magic;
private RandomAccessFile file;
private FileObject file;
private long filePos;
private long fileLength;
private Reference autoDeleteReference;
......@@ -50,9 +50,7 @@ public class FileStore {
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher,
byte[] key, int keyIterations) throws SQLException {
FileStore store;
if (FileUtils.isInMemory(name)) {
store = new MemoryFileStore(handler, name, magic);
} else if (cipher == null) {
if (cipher == null) {
store = new FileStore(handler, name, mode, magic);
} else {
store = new SecureFileStore(handler, name, mode, magic, cipher, key, keyIterations);
......@@ -61,17 +59,18 @@ public class FileStore {
}
protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
FileSystem fs = FileSystem.getInstance(name);
this.handler = handler;
this.name = name;
this.magic = magic;
this.mode = mode;
try {
FileUtils.createDirs(name);
if (FileUtils.exists(name) && !FileUtils.canWrite(name)) {
fs.createDirs(name);
if (fs.exists(name) && !fs.canWrite(name)) {
mode = "r";
this.mode = mode;
}
file = FileUtils.openRandomAccessFile(name, mode);
file = fs.openFileObject(name, mode);
if (mode.length() > 2) {
synchronousMode = true;
}
......@@ -124,7 +123,7 @@ public class FileStore {
write(magic, 0, len);
checkedWriting = true;
} else {
// write unencrypted
// read unencrypted
seek(0);
byte[] buff = new byte[len];
readFullyDirect(buff, 0, len);
......@@ -262,13 +261,13 @@ public class FileStore {
}
file.seek(pos);
} else {
FileUtils.setLength(file, newLength);
file.setLength(newLength);
}
fileLength = newLength;
} catch (IOException e) {
if (freeUpDiskSpace()) {
try {
FileUtils.setLength(file, newLength);
file.setLength(newLength);
} catch (IOException e2) {
throw Message.convertIOException(e2, name);
}
......@@ -289,7 +288,7 @@ public class FileStore {
}
if (SysProperties.CHECK2 && len % Constants.FILE_BLOCK_SIZE != 0) {
long newLength = len + Constants.FILE_BLOCK_SIZE - (len % Constants.FILE_BLOCK_SIZE);
FileUtils.setLength(file, newLength);
file.setLength(newLength);
fileLength = newLength;
throw Message.getInternalError("unaligned file length " + name + " len " + len);
}
......@@ -314,7 +313,7 @@ public class FileStore {
public void sync() {
try {
file.getFD().sync();
file.sync();
} catch (IOException e) {
// TODO log exception
}
......@@ -340,7 +339,7 @@ public class FileStore {
public void openFile() throws IOException {
if (file == null) {
file = FileUtils.openRandomAccessFile(name, mode);
file = FileSystem.getInstance(name).openFileObject(name, mode);
file.seek(filePos);
}
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.io.IOException;
import java.sql.SQLException;
import org.h2.util.FileUtils;
import org.h2.util.MemoryFile;
/**
* This class is an abstraction of an in-memory file.
* A {@link MemoryFile} contains the actual bytes.
*/
public class MemoryFileStore extends FileStore {
private MemoryFile memFile;
public MemoryFileStore(DataHandler handler, String name, byte[] magic) throws SQLException {
super(handler, magic);
this.name = name;
memFile = FileUtils.getMemoryFile(name);
memFile.setMagic(magic);
}
public void close() {
memFile.close();
}
public long getFilePointer() {
return memFile.getFilePointer();
}
public long length() {
return memFile.length();
}
public void readFully(byte[] b, int off, int len) throws SQLException {
checkPowerOff();
memFile.readFully(b, off, len);
}
public void seek(long pos) {
memFile.seek(pos);
}
public void setLength(long newLength) throws SQLException {
checkPowerOff();
memFile.setLength(newLength);
}
public void write(byte[] b, int off, int len) throws SQLException {
checkPowerOff();
memFile.write(b, off, len);
}
public void closeFile() throws IOException {
memFile.close();
}
public void openFile() throws IOException {
memFile.open();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 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;
public class FileInputStream extends InputStream {
private FileObject file;
private byte[] buffer = new byte[1];
FileInputStream(FileObject file) {
this.file = file;
}
public int read() throws IOException {
if (file.getFilePointer() >= file.length()) {
return -1;
}
file.readFully(buffer, 0, 1);
return buffer[0];
}
private int todoWriteFtpTest;
private int todoReadBlock;
public void close() throws IOException {
file.close();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
/**
* This interface represents a RandomAccessFile.
*/
public interface FileObject {
long length() throws IOException;
void close() throws IOException;
void readFully(byte[] b, int off, int len) throws IOException;
void seek(long pos) throws IOException;
void write(byte[] b, int off, int len) throws IOException;
long getFilePointer() throws IOException;
void sync() throws IOException;
void setLength(long newLength) throws IOException;
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
public class FileObjectDatabase implements FileObject {
private FileSystemDatabase db;
private String fileName;
private byte[] data;
private int pos, length;
private boolean changed;
FileObjectDatabase(FileSystemDatabase db, String fileName, byte[] data, boolean changed) {
this.db = db;
this.fileName = fileName;
this.data = data;
this.length = data.length;
this.changed = changed;
}
public void close() throws IOException {
sync();
}
public long getFilePointer() throws IOException {
return pos;
}
public long length() throws IOException {
return length;
}
public void readFully(byte[] b, int off, int len) throws IOException {
if (pos + len > length) {
throw new IOException("Can not read past EOF");
}
System.arraycopy(data, pos, b, off, len);
pos += len;
}
public void seek(long pos) throws IOException {
this.pos = (int) pos;
}
public void setLength(long newLength) throws IOException {
this.length = (int) newLength;
if (length != data.length) {
byte[] n = new byte[length];
System.arraycopy(data, 0, n, 0, Math.min(data.length, n.length));
data = n;
changed = true;
}
}
public void sync() throws IOException {
if (changed) {
db.write(fileName, data, length);
changed = false;
}
}
public void write(byte[] b, int off, int len) throws IOException {
if (pos + len > data.length) {
int newLen = Math.max(data.length * 2, 1024);
byte[] n = new byte[newLen];
System.arraycopy(data, 0, n, 0, length);
data = n;
}
System.arraycopy(b, off, data, pos, len);
pos += len;
length = Math.max(length, pos);
changed = true;
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 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.RandomAccessFile;
import org.h2.util.FileUtils;
/**
* This class is wraps a RandomAccessFile.
*/
public class FileObjectDisk implements FileObject {
private RandomAccessFile file;
FileObjectDisk(RandomAccessFile file) {
this.file = file;
}
public long length() throws IOException {
return file.length();
}
public void close() throws IOException {
file.close();
}
public void readFully(byte[] b, int off, int len) throws IOException {
file.read(b, off, len);
}
public void seek(long pos) throws IOException {
file.seek(pos);
}
public void write(byte[] b, int off, int len) throws IOException {
file.write(b, off, len);
}
public long getFilePointer() throws IOException {
return file.getFilePointer();
}
public void sync() throws IOException {
file.getFD().sync();
}
public void setLength(long newLength) throws IOException {
FileUtils.setLength(file, newLength);
}
}
......@@ -2,27 +2,27 @@
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.util;
package org.h2.store.fs;
import java.sql.SQLException;
import java.io.EOFException;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.h2.compress.CompressLZF;
import org.h2.constant.ErrorCode;
import org.h2.message.Message;
import org.h2.util.MathUtils;
/**
* This class is an abstraction of an in-memory random access file.
* Data compression using the LZF algorithm is supported as well.
*/
public class MemoryFile {
public class FileObjectMemory implements FileObject {
private static final int CACHE_SIZE = 8;
private static final int BLOCK_SIZE_SHIFT = 16;
private static final int BLOCK_SIZE = 1 << BLOCK_SIZE_SHIFT;
private static final int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
private String name;
private final boolean compress;
private byte[] magic;
private long length;
private long pos;
private byte[][] data;
......@@ -112,7 +112,7 @@ public class MemoryFile {
System.arraycopy(BUFFER, 0, COMPRESSED_BLOCK, 0, len);
}
MemoryFile(String name, boolean compress) {
public FileObjectMemory(String name, boolean compress) {
this.name = name;
this.compress = compress;
data = new byte[0][];
......@@ -170,7 +170,7 @@ public class MemoryFile {
}
private void readWrite(byte[] b, int off, int len, boolean write) throws SQLException {
private void readWrite(byte[] b, int off, int len, boolean write) throws IOException {
long end = pos + len;
if (end > length) {
if (write) {
......@@ -179,7 +179,7 @@ public class MemoryFile {
if (len == 0) {
return;
}
throw Message.getSQLException(ErrorCode.IO_EXCEPTION_1, "EOF");
throw new EOFException("File: " + name);
}
}
while (len > 0) {
......@@ -202,11 +202,11 @@ public class MemoryFile {
}
}
public void write(byte[] b, int off, int len) throws SQLException {
public void write(byte[] b, int off, int len) throws IOException {
readWrite(b, off, len, true);
}
public void readFully(byte[] b, int off, int len) throws SQLException {
public void readFully(byte[] b, int off, int len) throws IOException {
readWrite(b, off, len, false);
}
......@@ -214,18 +214,10 @@ public class MemoryFile {
return pos;
}
public void setMagic(byte[] magic) {
this.magic = magic;
}
public byte[] getMagic() {
return magic;
}
public void close() {
pos = 0;
}
public void open() {
public void sync() throws IOException {
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 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.OutputStream;
public class FileOutputStream extends OutputStream {
private FileObject file;
private byte[] buffer = new byte[1];
FileOutputStream(FileObject file, boolean append) throws IOException {
this.file = file;
if (append) {
file.seek(file.length());
} else {
file.seek(0);
file.setLength(0);
}
}
public void write(int b) throws IOException {
buffer[0] = (byte) b;
file.write(buffer, 0, 1);
}
private int todoWriteBlock;
public void close() throws IOException {
file.close();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 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 java.sql.SQLException;
public abstract class FileSystem {
public static final String MEMORY_PREFIX = "memFS:";
public static final String MEMORY_PREFIX_LZF = "memLZF:";
public static final String DB_PREFIX = "jdbc:";
public static FileSystem getInstance(String fileName) {
if (isInMemory(fileName)) {
return FileSystemMemory.getInstance();
} else if (fileName.startsWith(DB_PREFIX)) {
return FileSystemDatabase.getInstance(fileName);
}
return FileSystemDisk.getInstance();
}
private static boolean isInMemory(String fileName) {
return fileName != null && fileName.startsWith(MEMORY_PREFIX) || fileName.startsWith(MEMORY_PREFIX_LZF);
}
public abstract long length(String fileName);
public abstract void rename(String oldName, String newName) throws SQLException;
public abstract boolean createNewFile(String fileName) throws SQLException;
public abstract boolean exists(String fileName);
public abstract void delete(String fileName) throws SQLException;
public abstract boolean tryDelete(String fileName);
public abstract String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException;
public abstract String[] listFiles(String path) throws SQLException;
public abstract void deleteRecursive(String fileName) throws SQLException;
public abstract boolean isReadOnly(String fileName);
public abstract String normalize(String fileName) throws SQLException;
public abstract String getParent(String fileName);
public abstract boolean isDirectory(String fileName);
public abstract boolean isAbsolute(String fileName);
public abstract String getAbsolutePath(String fileName);
public abstract long getLastModified(String fileName);
public abstract boolean canWrite(String fileName);
public abstract void copy(String original, String copy) throws SQLException;
public void mkdirs(String directoryName) throws SQLException {
createDirs(directoryName + "/x");
}
public abstract void createDirs(String fileName) throws SQLException;
public abstract String getFileName(String name) throws SQLException;
public abstract boolean fileStartsWith(String fileName, String prefix);
public abstract OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException;
public abstract FileObject openFileObject(String fileName, String mode) throws IOException;
public abstract InputStream openFileInputStream(String fileName) throws IOException;
}
......@@ -2,8 +2,10 @@
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
package org.h2.store.fs;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
......@@ -14,28 +16,69 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import org.h2.Driver;
import org.h2.message.Message;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils;
public class FileSystemDatabase {
public class FileSystemDatabase extends FileSystem {
private Connection conn;
private String url;
private static final HashMap INSTANCES = new HashMap();
private HashMap preparedMap = new HashMap();
private boolean log;
FileSystemDatabase(Connection conn, boolean log) throws SQLException {
public static synchronized FileSystem getInstance(String url) {
int idx = url.indexOf('/');
if (idx > 0) {
url = url.substring(0, idx);
}
FileSystemDatabase fs = (FileSystemDatabase) INSTANCES.get(url);
if (fs != null) {
return fs;
}
Connection conn;
try {
if (url.startsWith("jdbc:h2:")) {
// avoid using DriverManager if possible
conn = Driver.load().connect(url, new Properties());
} else {
conn = JdbcUtils.getConnection(null, url, new Properties());
}
boolean log = url.toUpperCase().indexOf("TRACE_") >= 0;
fs = new FileSystemDatabase(url, conn, log);
INSTANCES.put(url, fs);
return fs;
} catch (SQLException e) {
throw Message.getInternalError("Can not connect to " + url, e);
}
}
public void close() {
JdbcUtils.closeSilently(conn);
}
private FileSystemDatabase(String url, Connection conn, boolean log) throws SQLException {
this.url = url;
this.conn = conn;
this.log = log;
Statement stat = conn.createStatement();
conn.setAutoCommit(false);
stat.execute("SET ALLOW_LITERALS NONE");
stat.execute("CREATE TABLE IF NOT EXISTS FILES(" + "ID IDENTITY, PARENTID BIGINT, NAME VARCHAR, "
+ "LASTMODIFIED BIGINT, LENGTH BIGINT, " + "UNIQUE(PARENTID, NAME))");
stat.execute("CREATE TABLE IF NOT EXISTS FILEDATA(" + "ID BIGINT PRIMARY KEY, DATA BLOB)");
stat.execute("CREATE TABLE IF NOT EXISTS FILES("
+ "ID IDENTITY, PARENTID BIGINT, NAME VARCHAR, "
+ "LASTMODIFIED BIGINT, LENGTH BIGINT, "
+ "UNIQUE(PARENTID, NAME))");
stat.execute("CREATE TABLE IF NOT EXISTS FILEDATA("
+ "ID BIGINT PRIMARY KEY, DATA BLOB)");
PreparedStatement prep = conn.prepareStatement("SET MAX_LENGTH_INPLACE_LOB ?");
prep.setLong(1, 4096);
prep.execute();
stat.execute("MERGE INTO FILES VALUES(ZERO(), NULL, SPACE(ZERO()), ZERO(), NULL)");
commit();
if (log) {
ResultSet rs = stat.executeQuery("SELECT * FROM FILES ORDER BY PARENTID, NAME");
......@@ -45,77 +88,163 @@ public class FileSystemDatabase {
String name = rs.getString("NAME");
long lastModified = rs.getLong("LASTMODIFIED");
long length = rs.getLong("LENGTH");
System.out.println(id + " " + name + " parent:" + parentId + " length:" + length + " lastMod:"
log(id + " " + name + " parent:" + parentId + " length:" + length + " lastMod:"
+ lastModified);
}
}
}
synchronized void delete(String fullName) {
private void commit() {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?");
prep.setLong(1, id);
prep.execute();
prep = prepare("DELETE FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
prep.execute();
commit();
conn.commit();
} catch (SQLException e) {
rollback();
throw convert(e);
if (log) {
e.printStackTrace();
}
}
}
synchronized boolean exists(String fullName) {
long id = getId(fullName, false);
return id >= 0;
private void rollback() {
try {
conn.rollback();
} catch (SQLException e) {
if (log) {
e.printStackTrace();
}
}
}
private void log(String s) {
if (log) {
System.out.println(s);
}
}
synchronized void read(String fullName, long skip, OutputStream out) throws IOException {
private long getId(String fileName, boolean parent) {
fileName = translateFileName(fileName);
log(fileName);
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT DATA FROM FILEDATA WHERE ID=?");
String[] path = StringUtils.arraySplit(fileName, '/', false);
long id = 0;
int len = parent ? path.length - 1 : path.length;
if (fileName.endsWith("/")) {
len--;
}
for (int i = 1; i < len; i++) {
PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?");
prep.setLong(1, id);
prep.setString(2, path[i]);
ResultSet rs = prep.executeQuery();
if (rs.next()) {
InputStream in = rs.getBinaryStream(1);
IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out);
if (!rs.next()) {
return -1;
}
id = rs.getLong(1);
}
return id;
} catch (SQLException e) {
throw convert(e);
}
}
synchronized void write(String fullName, InputStream in) throws IOException {
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 = (PreparedStatement) preparedMap.get(sql);
if (prep == null) {
prep = conn.prepareStatement(sql);
preparedMap.put(sql, prep);
}
return prep;
}
private RuntimeException convert(SQLException e) {
if (log) {
e.printStackTrace();
}
return new RuntimeException(e.toString());
}
public boolean canWrite(String fileName) {
return true;
}
public void copy(String original, String copy) throws SQLException {
throw Message.getUnsupportedException();
}
public void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
try {
long id = getId(fullName, false);
if (id >= 0) {
PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?");
prep.setLong(1, id);
prep.execute();
prep = prepare("DELETE FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
prep.execute();
String[] path = StringUtils.arraySplit(fileName, '/', false);
long parentId = 0;
int len = path.length;
if (fileName.endsWith("/")) {
len--;
}
long parentId = getId(fullName, true);
PreparedStatement prep = prepare("INSERT INTO FILES(PARENTID, NAME, LASTMODIFIED) VALUES(?, ?, ?)");
len--;
for (int i = 1; i < len; i++) {
PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?");
prep.setLong(1, parentId);
prep.setString(2, getName(fullName));
prep.setString(2, path[i]);
ResultSet rs = prep.executeQuery();
if (!rs.next()) {
prep = prepare("INSERT INTO FILES(NAME, PARENTID, LASTMODIFIED) VALUES(?, ?, ?)");
prep.setString(1, path[i]);
prep.setLong(2, parentId);
prep.setLong(3, System.currentTimeMillis());
prep.execute();
ResultSet rs = JdbcUtils.getGeneratedKeys(prep);
rs = JdbcUtils.getGeneratedKeys(prep);
rs.next();
id = rs.getLong(1);
prep = prepare("INSERT INTO FILEDATA(ID, DATA) VALUES(?, ?)");
parentId = rs.getLong(1);
} else {
parentId = rs.getLong(1);
}
}
commit();
} catch (SQLException e) {
rollback();
throw convert(e);
}
}
public boolean createNewFile(String fileName) throws SQLException {
try {
if (exists(fileName)) {
return false;
}
openFileObject(fileName, "rw").close();
return true;
} catch (IOException e) {
throw Message.convert(e);
}
}
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
name = translateFileName(name);
name += ".";
for (int i = 0;; i++) {
String n = name + i + suffix;
if (!exists(n)) {
// creates the file (not thread safe)
openFileObject(n, "rw").close();
return n;
}
}
}
public synchronized void delete(String fileName) throws SQLException {
try {
long id = getId(fileName, false);
PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?");
prep.setLong(1, id);
prep.setBinaryStream(2, in, -1);
in.close();
prep.execute();
prep = prepare("UPDATE FILES SET LENGTH=(SELECT LENGTH(DATA) FROM FILEDATA WHERE ID=?) WHERE ID=?");
prep = prepare("DELETE FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
prep.setLong(2, id);
prep.execute();
commit();
} catch (SQLException e) {
......@@ -124,36 +253,73 @@ public class FileSystemDatabase {
}
}
synchronized boolean isDirectory(String fullName) {
public void deleteRecursive(String fileName) throws SQLException {
throw Message.getUnsupportedException();
}
public boolean exists(String fileName) {
long id = getId(fileName, false);
return id >= 0;
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
return fileName.startsWith(prefix);
}
public String getAbsolutePath(String fileName) {
return fileName;
}
public String getFileName(String fileName) throws SQLException {
fileName = translateFileName(fileName);
String[] path = StringUtils.arraySplit(fileName, '/', false);
return path[path.length - 1];
}
public synchronized long getLastModified(String fileName) {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?");
long id = getId(fileName, false);
PreparedStatement prep = prepare("SELECT LASTMODIFIED FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
rs.next();
rs.getLong(1);
return rs.wasNull();
return rs.getLong(1);
} catch (SQLException e) {
throw convert(e);
}
}
synchronized long lastModified(String fullName) {
public String getParent(String fileName) {
int idx = Math.max(fileName.indexOf(':'), fileName.lastIndexOf('/'));
return fileName.substring(0, idx);
}
public boolean isAbsolute(String fileName) {
return true;
}
public synchronized boolean isDirectory(String fileName) {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT LASTMODIFIED FROM FILES WHERE ID=?");
long id = getId(fileName, false);
PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
rs.next();
return rs.getLong(1);
rs.getLong(1);
return rs.wasNull();
} catch (SQLException e) {
throw convert(e);
}
}
synchronized long length(String fullName) {
public boolean isReadOnly(String fileName) {
return false;
}
public synchronized long length(String fileName) {
try {
long id = getId(fullName, false);
long id = getId(fileName, false);
PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
......@@ -164,22 +330,21 @@ public class FileSystemDatabase {
}
}
synchronized FileObject[] listFiles(String fullName) {
public synchronized String[] listFiles(String path) throws SQLException {
try {
String name = fullName;
String name = path;
if (!name.endsWith("/")) {
name += "/";
}
long id = getId(fullName, false);
long id = getId(path, false);
PreparedStatement prep = prepare("SELECT NAME FROM FILES WHERE PARENTID=? ORDER BY NAME");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
ArrayList list = new ArrayList();
while (rs.next()) {
FileObject f = FileObjectDatabase.get(this, name + rs.getString(1));
list.add(f);
list.add(name + rs.getString(1));
}
FileObject[] result = new FileObject[list.size()];
String[] result = new String[list.size()];
list.toArray(result);
return result;
} catch (SQLException e) {
......@@ -187,122 +352,104 @@ public class FileSystemDatabase {
}
}
String getName(String fullName) {
String[] path = StringUtils.arraySplit(fullName, '/', false);
return path[path.length - 1];
public String normalize(String fileName) throws SQLException {
return fileName;
}
private long getId(String fullName, boolean parent) {
try {
String[] path = StringUtils.arraySplit(fullName, '/', false);
long id = 0;
int len = parent ? path.length - 1 : path.length;
if (fullName.endsWith("/")) {
len--;
public InputStream openFileInputStream(String fileName) throws IOException {
return new FileInputStream(openFileObject(fileName, "r"));
}
for (int i = 0; i < len; i++) {
PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?");
public FileObject openFileObject(String fileName, String mode) throws IOException {
try {
long id = getId(fileName, false);
PreparedStatement prep = prepare("SELECT DATA FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
prep.setString(2, path[i]);
ResultSet rs = prep.executeQuery();
if (!rs.next()) {
return -1;
}
id = rs.getLong(1);
if (rs.next()) {
InputStream in = rs.getBinaryStream(1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.copyAndClose(in, out);
byte[] data = out.toByteArray();
return new FileObjectDatabase(this, fileName, data, false);
} else {
return new FileObjectDatabase(this, fileName, new byte[0], true);
}
return id;
} catch (SQLException e) {
throw convert(e);
}
}
synchronized void mkdirs(String fullName) {
public OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
try {
String[] path = StringUtils.arraySplit(fullName, '/', false);
long parentId = 0;
int len = path.length;
if (fullName.endsWith("/")) {
len--;
}
for (int i = 0; i < len; i++) {
PreparedStatement prep = prepare("SELECT ID FROM FILES WHERE PARENTID=? AND NAME=?");
prep.setLong(1, parentId);
prep.setString(2, path[i]);
ResultSet rs = prep.executeQuery();
if (!rs.next()) {
prep = prepare("INSERT INTO FILES(NAME, PARENTID, LASTMODIFIED) VALUES(?, ?, ?)");
prep.setString(1, path[i]);
prep.setLong(2, parentId);
prep.setLong(3, System.currentTimeMillis());
prep.execute();
rs = JdbcUtils.getGeneratedKeys(prep);
rs.next();
parentId = rs.getLong(1);
} else {
parentId = rs.getLong(1);
}
}
commit();
} catch (SQLException e) {
rollback();
throw convert(e);
return new FileOutputStream(openFileObject(fileName, "rw"), append);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
}
synchronized boolean renameTo(String oldFullName, String newFullName) {
public synchronized void rename(String oldName, String newName) throws SQLException {
try {
long parentOld = getId(oldFullName, true);
long parentNew = getId(newFullName, true);
long parentOld = getId(oldName, true);
long parentNew = getId(newName, true);
if (parentOld != parentNew) {
return false;
throw Message.getUnsupportedException();
}
String newName = getName(newFullName);
long id = getId(oldFullName, false);
newName = getFileName(newName);
long id = getId(oldName, false);
PreparedStatement prep = prepare("UPDATE FILES SET NAME=? WHERE ID=?");
prep.setString(1, newName);
prep.setLong(2, id);
prep.execute();
commit();
return true;
} catch (SQLException e) {
rollback();
throw convert(e);
}
}
private RuntimeException convert(SQLException e) {
if (log) {
e.printStackTrace();
}
return new RuntimeException(e.toString());
}
private PreparedStatement prepare(String sql) throws SQLException {
PreparedStatement prep = (PreparedStatement) preparedMap.get(sql);
if (prep == null) {
prep = conn.prepareStatement(sql);
preparedMap.put(sql, prep);
}
return prep;
}
private void commit() {
public boolean tryDelete(String fileName) {
try {
conn.commit();
delete(fileName);
} catch (SQLException e) {
if (log) {
e.printStackTrace();
}
return false;
}
return true;
}
private void rollback() {
synchronized void write(String fileName, byte[] b, int len) throws IOException {
try {
conn.rollback();
} catch (SQLException e) {
if (log) {
e.printStackTrace();
long id = getId(fileName, false);
if (id >= 0) {
PreparedStatement prep = prepare("DELETE FROM FILES WHERE ID=?");
prep.setLong(1, id);
prep.execute();
prep = prepare("DELETE FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
prep.execute();
}
long parentId = getId(fileName, true);
PreparedStatement prep = prepare("INSERT INTO FILES(PARENTID, NAME, LASTMODIFIED) VALUES(?, ?, ?)");
prep.setLong(1, parentId);
prep.setString(2, getFileName(fileName));
prep.setLong(3, System.currentTimeMillis());
prep.execute();
ResultSet rs = JdbcUtils.getGeneratedKeys(prep);
rs.next();
id = rs.getLong(1);
prep = prepare("INSERT INTO FILEDATA(ID, DATA) VALUES(?, ?)");
prep.setLong(1, id);
ByteArrayInputStream in = new ByteArrayInputStream(b, 0, len);
prep.setBinaryStream(2, in, -1);
prep.execute();
prep = prepare("UPDATE FILES SET LENGTH=(SELECT LENGTH(DATA) FROM FILEDATA WHERE ID=?) WHERE ID=?");
prep.setLong(1, id);
prep.setLong(2, id);
prep.execute();
commit();
} catch (SQLException e) {
rollback();
throw convert(e);
}
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.sql.SQLException;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.Message;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.StringUtils;
public class FileSystemDisk extends FileSystem {
private static final FileSystemDisk INSTANCE = new FileSystemDisk();
// TODO detection of 'case in sensitive filesystem' could maybe implemented using some other means
private static final boolean IS_FILE_SYSTEM_CASE_INSENSITIVE = (File.separatorChar == '\\');
public static FileSystemDisk getInstance() {
return INSTANCE;
}
private FileSystemDisk() {
}
public long length(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).length();
}
private String translateFileName(String fileName) {
if (fileName != null && fileName.startsWith("~")) {
String userDir = System.getProperty("user.home");
fileName = userDir + fileName.substring(1);
}
return fileName;
}
public void rename(String oldName, String newName) throws SQLException {
File oldFile = new File(oldName);
File newFile = new File(newName);
if (oldFile.getName().equals(newFile.getName())) {
throw Message.getInternalError("rename file old=new");
}
if (!oldFile.exists()) {
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2, new String[] { oldName + " (not found)",
newName });
}
if (newFile.exists()) {
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2,
new String[] { oldName, newName + " (exists)" });
}
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("rename", oldName + " >" + newName, null);
boolean ok = oldFile.renameTo(newFile);
if (ok) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2, new String[]{oldName, newName});
}
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();
}
try {
// sleep at most 256 ms
long sleep = Math.min(256, i * i);
Thread.sleep(sleep);
} catch (InterruptedException e) {
// ignore
}
}
public boolean createNewFile(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File file = new File(fileName);
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
try {
return file.createNewFile();
} catch (IOException e) {
// 'access denied' is really a concurrent access problem
wait(i);
}
}
return false;
}
public boolean exists(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).exists();
}
public void delete(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File file = new File(fileName);
if (file.exists()) {
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("delete", fileName, null);
boolean ok = file.delete();
if (ok) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_DELETE_FAILED_1, fileName);
}
}
public boolean tryDelete(String fileName) {
fileName = translateFileName(fileName);
trace("tryDelete", fileName, null);
return new File(fileName).delete();
}
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException {
name = translateFileName(name);
name += ".";
String prefix = new File(name).getName();
File dir;
if (inTempDir) {
dir = null;
} else {
dir = new File(name).getAbsoluteFile().getParentFile();
dir.mkdirs();
}
File f = File.createTempFile(prefix, suffix, dir);
if (deleteOnExit) {
f.deleteOnExit();
}
return f.getCanonicalPath();
}
public String[] listFiles(String path) throws SQLException {
path = translateFileName(path);
File f = new File(path);
try {
String[] list = f.list();
if (list == null) {
return new String[0];
}
String base = f.getCanonicalPath();
if (!base.endsWith(File.separator)) {
base += File.separator;
}
for (int i = 0; i < list.length; i++) {
list[i] = base + list[i];
}
return list;
} catch (IOException e) {
throw Message.convertIOException(e, path);
}
}
public void deleteRecursive(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if (FileUtils.isDirectory(fileName)) {
String[] list = listFiles(fileName);
for (int i = 0; list != null && i < list.length; i++) {
deleteRecursive(list[i]);
}
}
delete(fileName);
}
public boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
File f = new File(fileName);
return f.exists() && !f.canWrite();
}
public String normalize(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File f = new File(fileName);
try {
return f.getCanonicalPath();
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
}
public String getParent(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).getParent();
}
public boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).isDirectory();
}
public boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
File file = new File(fileName);
return file.isAbsolute();
}
public String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
File parent = new File(fileName).getAbsoluteFile();
return parent.getAbsolutePath();
}
public long getLastModified(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).lastModified();
}
public boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).canWrite();
}
public void copy(String original, String copy) throws SQLException {
original = translateFileName(original);
copy = translateFileName(copy);
OutputStream out = null;
InputStream in = null;
try {
out = FileUtils.openFileOutputStream(copy, false);
in = FileUtils.openFileInputStream(original);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while (true) {
int len = in.read(buffer);
if (len < 0) {
break;
}
out.write(buffer, 0, len);
}
} catch (IOException e) {
throw Message.convertIOException(e, "original: " + original + " copy: " + copy);
} finally {
IOUtils.closeSilently(in);
IOUtils.closeSilently(out);
}
}
public void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File f = new File(fileName);
if (!f.exists()) {
String parent = f.getParent();
if (parent == null) {
return;
}
File dir = new File(parent);
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
if (dir.exists() || dir.mkdirs()) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_CREATION_FAILED_1, parent);
}
}
public String getFileName(String name) throws SQLException {
name = translateFileName(name);
String separator = System.getProperty("file.separator");
String path = getParent(name);
if (!path.endsWith(separator)) {
path += separator;
}
String fullFileName = normalize(name);
if (!fullFileName.startsWith(path)) {
throw Message.getInternalError("file utils error: " + fullFileName+" does not start with "+path);
}
String fileName = fullFileName.substring(path.length());
return fileName;
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
if (IS_FILE_SYSTEM_CASE_INSENSITIVE) {
fileName = StringUtils.toUpperEnglish(fileName);
prefix = StringUtils.toUpperEnglish(prefix);
}
return fileName.startsWith(prefix);
}
public OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
fileName = translateFileName(fileName);
try {
File file = new File(fileName);
createDirs(file.getAbsolutePath());
FileOutputStream out = new FileOutputStream(fileName, append);
trace("openFileOutputStream", fileName, out);
return out;
} catch (IOException e) {
freeMemoryAndFinalize();
try {
return new FileOutputStream(fileName);
} catch (IOException e2) {
throw Message.convertIOException(e, fileName);
}
}
}
public InputStream openFileInputStream(String fileName) throws IOException {
int todoMaybeUseAnotherFileSystem;
if (fileName.indexOf(':') > 1) {
// if the : is in position 1, a windows file access is assumed: C:.. or D:
// otherwise a URL is assumed
URL url = new URL(fileName);
InputStream in = url.openStream();
return in;
}
fileName = translateFileName(fileName);
FileInputStream in = new FileInputStream(fileName);
trace("openFileInputStream", fileName, in);
return in;
}
private void freeMemoryAndFinalize() {
trace("freeMemoryAndFinalize", null, null);
Runtime rt = Runtime.getRuntime();
long mem = rt.freeMemory();
for (int i = 0; i < 16; i++) {
rt.gc();
long now = rt.freeMemory();
rt.runFinalization();
if (now == mem) {
break;
}
mem = now;
}
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
RandomAccessFile f;
try {
f = new RandomAccessFile(fileName, mode);
trace("openRandomAccessFile", fileName, f);
} catch (IOException e) {
freeMemoryAndFinalize();
f = new RandomAccessFile(fileName, mode);
}
return new FileObjectDisk(f);
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 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 java.sql.SQLException;
import java.util.HashMap;
import org.h2.message.Message;
public class FileSystemMemory extends FileSystem {
private static final FileSystemMemory INSTANCE = new FileSystemMemory();
private static final HashMap MEMORY_FILES = new HashMap();
public static FileSystemMemory getInstance() {
return INSTANCE;
}
private FileSystemMemory() {
}
public long length(String fileName) {
return getMemoryFile(fileName).length();
}
public void rename(String oldName, String newName) throws SQLException {
FileObjectMemory f = getMemoryFile(oldName);
f.setName(newName);
synchronized (MEMORY_FILES) {
MEMORY_FILES.put(newName, f);
}
}
public boolean createNewFile(String fileName) throws SQLException {
if (exists(fileName)) {
return false;
}
// creates the file (not thread safe)
getMemoryFile(fileName);
return true;
}
public boolean exists(String fileName) {
synchronized (MEMORY_FILES) {
return MEMORY_FILES.get(fileName) != null;
}
}
public void delete(String fileName) throws SQLException {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
}
public boolean tryDelete(String fileName) {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
return true;
}
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
name += ".";
for (int i = 0;; i++) {
String n = name + i + suffix;
if (!exists(n)) {
// creates the file (not thread safe)
getMemoryFile(n);
return n;
}
}
}
public String[] listFiles(String path) throws SQLException {
synchronized (MEMORY_FILES) {
String[] list = new String[MEMORY_FILES.size()];
FileObjectMemory[] l = new FileObjectMemory[MEMORY_FILES.size()];
MEMORY_FILES.values().toArray(l);
for (int i = 0; i < list.length; i++) {
list[i] = l[i].getName();
}
return list;
}
}
public void deleteRecursive(String fileName) throws SQLException {
throw Message.getUnsupportedException();
}
public boolean isReadOnly(String fileName) {
return false;
}
public String normalize(String fileName) throws SQLException {
return fileName;
}
public String getParent(String fileName) {
int idx = Math.max(fileName.indexOf(':'), fileName.lastIndexOf('/'));
return fileName.substring(0, idx);
}
public boolean isDirectory(String fileName) {
// TODO in memory file system currently doesn't support directories
return false;
}
public boolean isAbsolute(String fileName) {
// TODO relative files are not supported
return true;
}
public String getAbsolutePath(String fileName) {
// TODO relative files are not supported
return fileName;
}
public long getLastModified(String fileName) {
// TODO last modified is not supported
return 0;
}
public boolean canWrite(String fileName) {
return true;
}
public void copy(String original, String copy) throws SQLException {
// TODO support copying
throw Message.getUnsupportedException();
}
public void createDirs(String fileName) throws SQLException {
}
public String getFileName(String name) throws SQLException {
// TODO directories are not supported
return name;
}
public boolean fileStartsWith(String fileName, String prefix) {
return fileName.startsWith(prefix);
}
public OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
try {
return new FileOutputStream(getMemoryFile(fileName), append);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
}
public InputStream openFileInputStream(String fileName) throws IOException {
return new FileInputStream(getMemoryFile(fileName));
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
return getMemoryFile(fileName);
}
private FileObjectMemory getMemoryFile(String fileName) {
synchronized (MEMORY_FILES) {
FileObjectMemory m = (FileObjectMemory) MEMORY_FILES.get(fileName);
if (m == null) {
boolean compress = fileName.startsWith(FileSystem.MEMORY_PREFIX_LZF);
m = new FileObjectMemory(fileName, compress);
MEMORY_FILES.put(fileName, m);
}
// TODO the memory file only supports one pointer
m.seek(0);
return m;
}
}
}
......@@ -88,13 +88,13 @@ public class Backup {
}
return;
}
zipFileName = FileUtils.translateFileName(zipFileName);
zipFileName = FileUtils.normalize(zipFileName);
if (FileUtils.exists(zipFileName)) {
FileUtils.delete(zipFileName);
}
OutputStream out = null;
try {
out = FileUtils.openFileOutputStream(zipFileName);
out = FileUtils.openFileOutputStream(zipFileName, false);
ZipOutputStream zipOut = new ZipOutputStream(out);
String base = "";
for (int i = 0; i < list.size(); i++) {
......
......@@ -71,7 +71,7 @@ public class ConvertTraceFile {
* @param javaClassName
* @throws IOException
*/
private void convertFile(String traceFileName, String javaClassName, String script) throws IOException {
private void convertFile(String traceFileName, String javaClassName, String script) throws IOException, SQLException {
LineNumberReader reader = new LineNumberReader(FileUtils.openFileReader(traceFileName));
PrintWriter javaWriter = new PrintWriter(FileUtils.openFileWriter(javaClassName + ".java", false));
PrintWriter scriptWriter = new PrintWriter(FileUtils.openFileWriter(script, false));
......
......@@ -26,6 +26,7 @@ import java.util.ArrayList;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringCache;
import org.h2.util.StringUtils;
/**
......@@ -337,6 +338,7 @@ public class Csv implements SimpleRowSource {
private String readValue() throws IOException {
endOfLine = false;
String value = null;
outer:
while (true) {
int ch = readChar();
if (ch < 0 || ch == '\r' || ch == '\n') {
......@@ -362,7 +364,8 @@ public class Csv implements SimpleRowSource {
while (true) {
ch = readChar();
if (ch < 0) {
return buff.toString();
value = buff.toString();
break outer;
} else if (ch == fieldDelimiter) {
ch = readChar();
if (ch == fieldDelimiter) {
......@@ -425,7 +428,8 @@ public class Csv implements SimpleRowSource {
break;
}
}
return value;
// save memory
return StringCache.get(value);
}
private String unEscape(String s) {
......
......@@ -271,7 +271,7 @@ public class Recover implements DataHandler {
}
}
private static PrintWriter getWriter(String fileName, String suffix) throws IOException {
private static PrintWriter getWriter(String fileName, String suffix) throws IOException, SQLException {
fileName = fileName.substring(0, fileName.length() - 3);
String outputFile = fileName + suffix;
System.out.println("Created file: " + outputFile);
......@@ -310,7 +310,7 @@ public class Recover implements DataHandler {
String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
InputStream in = null;
try {
out = FileUtils.openFileOutputStream(n);
out = FileUtils.openFileOutputStream(n, false);
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
......
......@@ -159,7 +159,7 @@ public class Restore {
if (copy) {
OutputStream out = null;
try {
out = FileUtils.openFileOutputStream(directory + File.separator + fileName);
out = FileUtils.openFileOutputStream(directory + File.separator + fileName, false);
IOUtils.copy(zipIn, out);
} finally {
IOUtils.closeSilently(out);
......
......@@ -5,7 +5,6 @@
package org.h2.tools;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.sql.Connection;
......@@ -14,7 +13,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.message.Message;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
......@@ -143,8 +141,6 @@ public class Script {
writer.println(s + ";");
}
writer.close();
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
} finally {
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
......
......@@ -5,49 +5,26 @@
package org.h2.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.net.URL;
import java.io.Writer;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Properties;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.Message;
import org.h2.message.TraceSystem;
import org.h2.store.fs.FileSystem;
/**
* @author Thomas
* This utility class supports basic operations on files
*/
public class FileUtils {
public static final String MEMORY_PREFIX = "memFS:", MEMORY_PREFIX_LZF = "memLZF:";
private static final HashMap MEMORY_FILES = new HashMap();
// TODO detection of 'case in sensitive filesystem' could maybe implemented using some other means
private static final boolean IS_FILE_SYSTEM_CASE_INSENSITIVE = (File.separatorChar == '\\');
public static RandomAccessFile openRandomAccessFile(String fileName, String mode) throws IOException {
fileName = translateFileName(fileName);
try {
RandomAccessFile file = new RandomAccessFile(fileName, mode);
trace("openRandomAccessFile", fileName, file);
return file;
} catch (IOException e) {
freeMemoryAndFinalize();
return new RandomAccessFile(fileName, mode);
}
}
public static void setLength(RandomAccessFile file, long newLength) throws IOException {
try {
trace("setLength", null, file);
......@@ -73,109 +50,10 @@ public class FileUtils {
}
}
public static FileWriter openFileWriter(String fileName, boolean append) throws IOException {
fileName = translateFileName(fileName);
try {
return new FileWriter(fileName, append);
} catch (IOException e) {
freeMemoryAndFinalize();
return new FileWriter(fileName, append);
}
}
public static boolean fileStartsWith(String fileName, String prefix) {
fileName = translateFileName(fileName);
if (IS_FILE_SYSTEM_CASE_INSENSITIVE) {
fileName = StringUtils.toUpperEnglish(fileName);
prefix = StringUtils.toUpperEnglish(prefix);
}
return fileName.startsWith(prefix);
}
public static InputStream openFileInputStream(String fileName) throws IOException {
if (fileName.indexOf(':') > 1) {
// if the : is in position 1, a windows file access is assumed: C:.. or D:
// otherwise a URL is assumed
URL url = new URL(fileName);
InputStream in = url.openStream();
return in;
}
fileName = translateFileName(fileName);
FileInputStream in = new FileInputStream(fileName);
trace("openFileInputStream", fileName, in);
return in;
}
public static FileOutputStream openFileOutputStream(String fileName) throws IOException, SQLException {
fileName = translateFileName(fileName);
try {
File file = new File(fileName);
FileUtils.createDirs(file.getAbsolutePath());
FileOutputStream out = new FileOutputStream(fileName);
trace("openFileOutputStream", fileName, out);
return out;
} catch (IOException e) {
freeMemoryAndFinalize();
return new FileOutputStream(fileName);
}
}
private static void freeMemoryAndFinalize() {
trace("freeMemoryAndFinalize", null, null);
Runtime rt = Runtime.getRuntime();
long mem = rt.freeMemory();
for (int i = 0; i < 16; i++) {
rt.gc();
long now = rt.freeMemory();
rt.runFinalization();
if (now == mem) {
break;
}
mem = now;
}
}
public static void rename(String oldName, String newName) throws SQLException {
oldName = translateFileName(oldName);
newName = translateFileName(newName);
if (isInMemory(oldName)) {
MemoryFile f = getMemoryFile(oldName);
f.setName(newName);
synchronized (MEMORY_FILES) {
MEMORY_FILES.put(newName, f);
}
return;
}
File oldFile = new File(oldName);
File newFile = new File(newName);
if (oldFile.getName().equals(newFile.getName())) {
throw Message.getInternalError("rename file old=new");
}
if (!oldFile.exists()) {
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2, new String[] { oldName + " (not found)",
newName });
}
if (newFile.exists()) {
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2,
new String[] { oldName, newName + " (exists)" });
}
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("rename", oldName + " >" + newName, null);
boolean ok = oldFile.renameTo(newFile);
if (ok) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_RENAME_FAILED_2, new String[]{oldName, newName});
}
public static synchronized Properties loadProperties(String fileName) throws IOException {
fileName = translateFileName(fileName);
Properties prop = new SortedProperties();
File file = new File(fileName);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
if (exists(fileName)) {
InputStream in = openFileInputStream(fileName);
try {
prop.load(in);
} finally {
......@@ -205,98 +83,6 @@ public class FileUtils {
}
}
public static void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
File f = new File(fileName);
if (!f.exists()) {
String parent = f.getParent();
if (parent == null) {
return;
}
File dir = new File(parent);
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
if (dir.exists() || dir.mkdirs()) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_CREATION_FAILED_1, parent);
}
}
public static boolean createNewFile(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
if (exists(fileName)) {
return false;
}
// creates the file (not thread safe)
getMemoryFile(fileName);
return true;
}
File file = new File(fileName);
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
try {
return file.createNewFile();
} catch (IOException e) {
// TODO file lock: check if 'access denied' exceptions are
// really a concurrent access problem
wait(i);
}
}
return false;
}
public static void delete(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
return;
}
File file = new File(fileName);
if (file.exists()) {
for (int i = 0; i < SysProperties.MAX_FILE_RETRY; i++) {
trace("delete", fileName, null);
boolean ok = file.delete();
if (ok) {
return;
}
wait(i);
}
throw Message.getSQLException(ErrorCode.FILE_DELETE_FAILED_1, fileName);
}
}
private static void wait(int i) {
if (i > 8) {
System.gc();
}
try {
// sleep at most 256 ms
long sleep = Math.min(256, i * i);
Thread.sleep(sleep);
} catch (InterruptedException e) {
// ignore
}
}
public static String getFileName(String name) throws SQLException {
name = translateFileName(name);
String separator = System.getProperty("file.separator");
String path = getParent(name);
if (!path.endsWith(separator)) {
path += separator;
}
String fullFileName = normalize(name);
if (!fullFileName.startsWith(path)) {
throw Message.getInternalError("file utils error: " + fullFileName+" does not start with "+path);
}
String fileName = fullFileName.substring(path.length());
return fileName;
}
public static String getFileInUserHome(String fileName) {
String userDir = System.getProperty("user.home");
if (userDir == null) {
......@@ -306,227 +92,91 @@ public class FileUtils {
return file.getAbsolutePath();
}
public static String normalize(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
return fileName;
public static void trace(String method, String fileName, Object o) {
if (SysProperties.TRACE_IO) {
System.out.println("FileUtils." + method + " " + fileName + " " + o);
}
File f = new File(fileName);
try {
return f.getCanonicalPath();
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
public static Reader openFileReader(String fileName) throws IOException {
return new InputStreamReader(openFileInputStream(fileName));
}
public static void tryDelete(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
public static String getFileName(String name) throws SQLException {
return FileSystem.getInstance(name).getFileName(name);
}
return;
public static String normalize(String fileName) throws SQLException {
return FileSystem.getInstance(fileName).normalize(fileName);
}
trace("tryDelete", fileName, null);
new File(fileName).delete();
public static void tryDelete(String fileName) {
FileSystem.getInstance(fileName).tryDelete(fileName);
}
public static boolean isReadOnly(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
return false;
}
File f = new File(fileName);
return f.exists() && !f.canWrite();
return FileSystem.getInstance(fileName).isReadOnly(fileName);
}
public static boolean exists(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
synchronized (MEMORY_FILES) {
return MEMORY_FILES.get(fileName) != null;
}
}
return new File(fileName).exists();
}
public static MemoryFile getMemoryFile(String fileName) {
synchronized (MEMORY_FILES) {
MemoryFile m = (MemoryFile) MEMORY_FILES.get(fileName);
if (m == null) {
boolean compress = fileName.startsWith(MEMORY_PREFIX_LZF);
m = new MemoryFile(fileName, compress);
MEMORY_FILES.put(fileName, m);
}
return m;
}
return FileSystem.getInstance(fileName).exists(fileName);
}
public static long length(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
return getMemoryFile(fileName).length();
}
return new File(fileName).length();
}
public static boolean isInMemory(String fileName) {
return fileName.startsWith(MEMORY_PREFIX) || fileName.startsWith(MEMORY_PREFIX_LZF);
return FileSystem.getInstance(fileName).length(fileName);
}
public static String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir)
public static String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir)
throws IOException, SQLException {
name = translateFileName(name);
name += ".";
if (isInMemory(name)) {
for (int i = 0;; i++) {
String n = name + i + suffix;
if (!exists(n)) {
// creates the file (not thread safe)
getMemoryFile(n);
return n;
}
}
}
String prefix = new File(name).getName();
File dir;
if (inTempDir) {
dir = null;
} else {
dir = new File(name).getAbsoluteFile().getParentFile();
dir.mkdirs();
}
File f = File.createTempFile(prefix, suffix, dir);
if (deleteOnExit) {
f.deleteOnExit();
}
// return f.getPath();
return f.getCanonicalPath();
return FileSystem.getInstance(prefix).createTempFile(prefix, suffix, deleteOnExit, inTempDir);
}
public static String getParent(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
return MEMORY_PREFIX;
}
return new File(fileName).getParent();
return FileSystem.getInstance(fileName).getParent(fileName);
}
public static String[] listFiles(String path) throws SQLException {
path = translateFileName(path);
if (isInMemory(path)) {
synchronized (MEMORY_FILES) {
String[] list = new String[MEMORY_FILES.size()];
MemoryFile[] l = new MemoryFile[MEMORY_FILES.size()];
MEMORY_FILES.values().toArray(l);
for (int i = 0; i < list.length; i++) {
list[i] = l[i].getName();
}
return list;
}
}
File f = new File(path);
try {
String[] list = f.list();
if (list == null) {
return new String[0];
}
String base = f.getCanonicalPath();
if (!base.endsWith(File.separator)) {
base += File.separator;
}
for (int i = 0; i < list.length; i++) {
list[i] = base + list[i];
}
return list;
} catch (IOException e) {
throw Message.convertIOException(e, path);
}
return FileSystem.getInstance(path).listFiles(path);
}
public static boolean isDirectory(String fileName) {
fileName = translateFileName(fileName);
if (isInMemory(fileName)) {
// TODO in memory file system currently doesn't support directories
return false;
}
return new File(fileName).isDirectory();
return FileSystem.getInstance(fileName).isDirectory(fileName);
}
public static void copy(String original, String copy) throws SQLException {
original = translateFileName(original);
copy = translateFileName(copy);
FileOutputStream out = null;
InputStream in = null;
try {
out = openFileOutputStream(copy);
in = openFileInputStream(original);
byte[] buffer = new byte[Constants.IO_BUFFER_SIZE];
while (true) {
int len = in.read(buffer);
if (len < 0) {
break;
}
out.write(buffer, 0, len);
}
} catch (IOException e) {
throw Message.convertIOException(e, "original: " + original + " copy: " + copy);
} finally {
IOUtils.closeSilently(in);
IOUtils.closeSilently(out);
}
public static boolean isAbsolute(String fileName) {
return FileSystem.getInstance(fileName).isAbsolute(fileName);
}
public static void deleteRecursive(String fileName) throws SQLException {
fileName = translateFileName(fileName);
if (FileUtils.isDirectory(fileName)) {
String[] list = FileUtils.listFiles(fileName);
for (int i = 0; list != null && i < list.length; i++) {
deleteRecursive(list[i]);
}
}
FileUtils.delete(fileName);
public static String getAbsolutePath(String fileName) {
return FileSystem.getInstance(fileName).getAbsolutePath(fileName);
}
public static String translateFileName(String fileName) {
if (fileName != null && fileName.startsWith("~")) {
String userDir = System.getProperty("user.home");
fileName = userDir + fileName.substring(1);
}
return fileName;
public static Writer openFileWriter(String fileName, boolean append) throws SQLException {
return new OutputStreamWriter(FileSystem.getInstance(fileName).openFileOutputStream(fileName, append));
}
public static boolean isAbsolute(String fileName) {
fileName = translateFileName(fileName);
File file = new File(fileName);
return file.isAbsolute();
public static boolean fileStartsWith(String fileName, String prefix) {
return FileSystem.getInstance(fileName).fileStartsWith(fileName, prefix);
}
public static String getAbsolutePath(String fileName) {
fileName = translateFileName(fileName);
File parent = new File(fileName).getAbsoluteFile();
return parent.getAbsolutePath();
public static InputStream openFileInputStream(String fileName) throws IOException {
return FileSystem.getInstance(fileName).openFileInputStream(fileName);
}
public static long getLastModified(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).lastModified();
public static OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
return FileSystem.getInstance(fileName).openFileOutputStream(fileName, append);
}
public static Reader openFileReader(String fileName) throws IOException {
fileName = translateFileName(fileName);
return new FileReader(fileName);
public static void rename(String oldName, String newName) throws SQLException {
FileSystem.getInstance(oldName).rename(oldName, newName);
}
public static boolean canWrite(String fileName) {
fileName = translateFileName(fileName);
return new File(fileName).canWrite();
public static void createDirs(String fileName) throws SQLException {
FileSystem.getInstance(fileName).createDirs(fileName);
}
static void trace(String method, String fileName, Object o) {
if (SysProperties.TRACE_IO) {
System.out.println("FileUtils." + method + " " + fileName + " " + o);
}
public static void delete(String fileName) throws SQLException {
FileSystem.getInstance(fileName).delete(fileName);
}
}
......@@ -4,13 +4,13 @@
*/
package org.h2.util;
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import org.h2.constant.SysProperties;
public class StringCache {
private static final boolean ENABLED = true;
private static WeakReference weakCache = new WeakReference(null);
private static SoftReference softCache = new SoftReference(null);
// testing: cacheHit / miss are public!
// public static int cacheHit = 0, cacheMiss = 0;
......@@ -54,11 +54,11 @@ public class StringCache {
} else if (s.length() == 0) {
return "";
}
String[] cache = (String[]) weakCache.get();
String[] cache = (String[]) softCache.get();
int hash = s.hashCode();
if (cache == null) {
cache = new String[SysProperties.OBJECT_CACHE_SIZE];
weakCache = new WeakReference(cache);
softCache = new SoftReference(cache);
}
int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1);
String cached = cache[index];
......@@ -81,11 +81,11 @@ public class StringCache {
} else if (s.length() == 0) {
return "";
}
String[] cache = (String[]) weakCache.get();
String[] cache = (String[]) softCache.get();
int hash = s.hashCode();
if (cache == null) {
cache = new String[SysProperties.OBJECT_CACHE_SIZE];
weakCache = new WeakReference(cache);
softCache = new SoftReference(cache);
}
int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1);
String cached = cache[index];
......@@ -102,7 +102,7 @@ public class StringCache {
}
public static void clearCache() {
weakCache = new WeakReference(null);
softCache = new SoftReference(null);
}
}
......@@ -153,6 +153,18 @@ public class StringUtils {
case 'f':
buff.append('\f');
break;
case '#':
// for properties files
buff.append('#');
break;
case '=':
// for properties files
buff.append('=');
break;
case ':':
// for properties files
buff.append(':');
break;
case '"':
buff.append('"');
break;
......
......@@ -20,6 +20,7 @@ import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream;
import org.h2.store.FileStoreOutputStream;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
......@@ -621,7 +622,7 @@ public class ValueLob extends Value {
private void copyFile(DataHandler handler, String fileName, String live) throws SQLException {
synchronized (handler.getLobSyncObject()) {
FileUtils.copy(fileName, live);
FileSystem.getInstance(fileName).copy(fileName, live);
}
}
......
......@@ -8,6 +8,7 @@ import java.sql.SQLException;
import java.util.Properties;
import org.h2.server.TcpServer;
import org.h2.store.fs.FileSystemDisk;
import org.h2.test.db.TestAutoRecompile;
import org.h2.test.db.TestBackup;
import org.h2.test.db.TestBatchUpdates;
......@@ -77,6 +78,7 @@ import org.h2.test.unit.TestDataPage;
import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock;
import org.h2.test.unit.TestFileSystem;
import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMultiThreadedKernel;
......@@ -93,7 +95,6 @@ import org.h2.test.unit.TestTools;
import org.h2.test.unit.TestValueHashMap;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server;
import org.h2.util.FileUtils;
import org.h2.util.StringUtils;
/**
......@@ -141,6 +142,19 @@ java org.h2.test.TestAll timer
/*
replicating file system
test DbStarter
TestFileSystem
create table test(id int, name varchar);
insert into test select x, '' from system_range(1, 10000);
-- fast
update test set name = 'y' where cast(id as varchar) like '1%';
-- slow
update test set name = 'x' where id in (select x from system_range(1, 10000) where cast(x as varchar) like '1%');
drop table test;
----
A file is sent although the Japanese translation has not been completed yet.
......@@ -484,6 +498,7 @@ write tests using the PostgreSQL JDBC driver
new TestExit().runTest(this);
new TestFile().runTest(this);
new TestFileLock().runTest(this);
new TestFileSystem().runTest(this);
new TestIntArray().runTest(this);
new TestIntIntHashMap().runTest(this);
new TestMultiThreadedKernel().runTest(this);
......@@ -575,7 +590,7 @@ write tests using the PostgreSQL JDBC driver
}
public void beforeTest() throws SQLException {
FileUtils.deleteRecursive("trace.db");
FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked) {
TcpServer.logInternalErrors = true;
String[] args = ssl ? new String[] { "-tcpSSL", "true" } : new String[0];
......@@ -590,7 +605,7 @@ write tests using the PostgreSQL JDBC driver
}
public void afterTest() throws SQLException {
FileUtils.deleteRecursive("trace.db");
FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked && server != null) {
server.stop();
}
......
......@@ -212,6 +212,10 @@ public class TestPowerOff extends TestBase {
if (config.networked) {
return;
}
if (config.cipher != null) {
// this would take too long (setLength uses individual writes, many thousand operations)
return;
}
deleteDb(dir, dbName);
// ((JdbcConnection)conn).setPowerOffCount(Integer.MAX_VALUE);
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Random;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemMemory;
import org.h2.test.TestBase;
public class TestFileSystem extends TestBase {
public void test() throws Exception {
testFileSystem(FileSystem.getInstance(FileSystemMemory.MEMORY_PREFIX));
testFileSystem(FileSystem.getInstance(baseDir + "/fs"));
testFileSystem(FileSystem.getInstance(FileSystemMemory.MEMORY_PREFIX_LZF));
}
private void testFileSystem(FileSystem fs) throws Exception {
testTempFile(fs);
testRandomAccess(fs);
}
private void testRandomAccess(FileSystem fs) throws Exception {
String s = fs.createTempFile("temp", "tmp", false, false);
File file = new File(baseDir + "temp");
file.delete();
RandomAccessFile ra = new RandomAccessFile(file, "rw");
fs.delete(s);
FileObject f = fs.openFileObject(s, "rw");
Random random = new Random(1);
for (int i = 0; i < 200; i++) {
int pos = random.nextInt(10000);
switch(random.nextInt(7)) {
case 0: {
pos = (int) Math.min(pos, ra.length());
trace("seek " + pos);
f.seek(pos);
ra.seek(pos);
break;
}
case 1: {
byte[] buffer = new byte[random.nextInt(1000)];
random.nextBytes(buffer);
trace("write " + buffer.length);
f.write(buffer, 0, buffer.length);
ra.write(buffer, 0, buffer.length);
break;
}
case 2: {
f.setLength(pos);
ra.setLength(pos);
if (ra.getFilePointer() > pos) {
f.seek(0);
ra.seek(0);
}
trace("setLength " + pos);
break;
}
case 3: {
int len = random.nextInt(1000);
len = (int) Math.min(len, ra.length() - ra.getFilePointer());
byte[] b1 = new byte[len];
byte[] b2 = new byte[len];
f.readFully(b1, 0, len);
ra.readFully(b2, 0, len);
trace("readFully " + len);
check(b1, b2);
break;
}
case 4: {
trace("getFilePointer");
check(f.getFilePointer(), ra.getFilePointer());
break;
}
case 5: {
trace("length " + ra.length());
check(f.length(), ra.length());
break;
}
case 6: {
trace("reopen");
f.close();
ra.close();
ra = new RandomAccessFile(file, "rw");
f = fs.openFileObject(s, "rw");
check(f.length(), ra.length());
break;
}
}
}
f.close();
ra.close();
}
private void testTempFile(FileSystem fs) throws Exception {
String s = fs.createTempFile("temp", "tmp", false, false);
OutputStream out = fs.openFileOutputStream(s, false);
byte[] buffer = new byte[10000];
out.write(buffer);
out.close();
out = fs.openFileOutputStream(s, true);
out.write(1);
out.close();
InputStream in = fs.openFileInputStream(s);
for (int i = 0; i < 10000; i++) {
check(in.read(), 0);
}
check(in.read(), 1);
check(in.read(), -1);
}
}
......@@ -11,28 +11,55 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
public class DbStarter implements ServletContextListener {
private Connection conn;
private Server server;
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
org.h2.Driver.load();
// You can also get the setting from a context-param in web.xml:
// This will get the setting from a context-param in web.xml if defined:
ServletContext servletContext = servletContextEvent.getServletContext();
// String url = servletContext.getInitParameter("db.url");
conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
String url = getParameter(servletContext, "db.url", "jdbc:h2:~/test");
String user = getParameter(servletContext, "db.user", "sa");
String password = getParameter(servletContext, "db.password", "sa");
conn = DriverManager.getConnection(url, user, password);
servletContext.setAttribute("connection", conn);
// Start the server if configured to do so
String serverParams = getParameter(servletContext, "db.tcpServer", null);
if (serverParams != null) {
String[] params = StringUtils.arraySplit(serverParams, ' ', true);
server = Server.createTcpServer(params);
}
// To access the database using the server, use the URL:
// jdbc:h2:tcp://localhost/~/test
} catch (Exception e) {
e.printStackTrace();
}
}
private String getParameter(ServletContext servletContext, String key, String defaultValue) {
String value = servletContext.getInitParameter(key);
return value == null ? defaultValue : value;
}
public Connection getConnection() {
return conn;
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (server != null) {
server.stop();
server = null;
}
try {
conn.close();
} catch (Exception e) {
......
......@@ -511,5 +511,5 @@ lumber thus taking repositories ago delegated mention leaks pgsql seeded felt ef
spfile svr pkey synced semicolon terminating
framework constructing architectural jmatter workgroup upgraded naked stopper skipping assumed
opensource atlassian hhh establish pawel nice italiano ucchino paolo italian pier shorter although
uklinux credential crypt kerberos redferni routine
uklinux credential crypt kerberos redferni routine reopen tmp configured replicating wraps
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论