📄 filesystemdatabase.java
字号:
/*
* Copyright 2004-2008 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.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
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;
/**
* This file system stores everything in a database.
*/
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;
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.convertToInternal(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)");
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");
while (rs.next()) {
long id = rs.getLong("ID");
long parentId = rs.getLong("PARENTID");
String name = rs.getString("NAME");
long lastModified = rs.getLong("LASTMODIFIED");
long length = rs.getLong("LENGTH");
log(id + " " + name + " parent:" + parentId + " length:" + length + " lastMod:"
+ lastModified);
}
}
}
private void commit() {
try {
conn.commit();
} catch (SQLException e) {
if (log) {
e.printStackTrace();
}
}
}
private void rollback() {
try {
conn.rollback();
} catch (SQLException e) {
if (log) {
e.printStackTrace();
}
}
}
private void log(String s) {
if (log) {
System.out.println(s);
}
}
private long getId(String fileName, boolean parent) {
fileName = translateFileName(fileName);
log(fileName);
try {
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()) {
return -1;
}
id = rs.getLong(1);
}
return id;
} catch (SQLException e) {
throw convert(e);
}
}
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 {
try {
OutputStream out = openFileOutputStream(copy, false);
InputStream in = openFileInputStream(original);
IOUtils.copyAndClose(in, out);
} catch (IOException e) {
rollback();
throw Message.convertIOException(e, "Can not copy " + original + " to " + copy);
}
}
public void createDirs(String fileName) throws SQLException {
fileName = translateFileName(fileName);
try {
String[] path = StringUtils.arraySplit(fileName, '/', false);
long parentId = 0;
int len = path.length;
if (fileName.endsWith("/")) {
len--;
}
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, 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);
}
}
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -