提交 858f95f3 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 5a86eaff
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import org.h2.util.MathUtils;
import org.h2.util.NetUtils;
/**
* @author Thomas
*/
public class OdbcServer implements Service {
public static final int DEFAULT_PORT = 9083; // also in the docs
private int port = OdbcServer.DEFAULT_PORT;
private boolean stop;
private boolean log;
private ServerSocket serverSocket;
private HashSet running = new HashSet();
private String baseDir;
private String url;
private boolean allowOthers;
private boolean ifExists;
boolean getLog() {
return log;
}
void log(String s) {
if (log) {
System.out.println(s);
}
}
synchronized void remove(OdbcServerThread t) {
running.remove(t);
}
void logError(Exception e) {
if (log) {
e.printStackTrace();
}
}
public void init(String[] args) throws Exception {
port = DEFAULT_PORT;
for (int i = 0; i < args.length; i++) {
String a = args[i];
if (a.equals("-log")) {
log = Boolean.valueOf(args[++i]).booleanValue();
} else if (a.equals("-odbcPort")) {
port = MathUtils.decodeInt(args[++i]);
} else if (a.equals("-baseDir")) {
baseDir = args[++i];
} else if (a.equals("-odbcAllowOthers")) {
allowOthers = Boolean.valueOf(args[++i]).booleanValue();
} else if (a.equals("-ifExists")) {
ifExists = Boolean.valueOf(args[++i]).booleanValue();
}
}
org.h2.Driver.load();
url = "tcp://localhost:" + port;
}
public String getURL() {
return url;
}
boolean allow(Socket socket) {
if(allowOthers) {
return true;
}
return socket.getInetAddress().isLoopbackAddress();
}
public void start() throws SQLException {
serverSocket = NetUtils.createServerSocket(port, false);
}
public void listen() {
String threadName = Thread.currentThread().getName();
try {
while (!stop) {
Socket s = serverSocket.accept();
if(!allow(s)) {
log("Connection not allowed");
s.close();
} else {
OdbcServerThread c = new OdbcServerThread(s, this);
running.add(c);
Thread thread = new Thread(c);
thread.setName(threadName+" thread");
c.setThread(thread);
thread.start();
}
}
} catch (Exception e) {
if(!stop) {
e.printStackTrace();
}
}
}
public void stop() {
// TODO server: share code between web and tcp servers
if(!stop) {
stop = true;
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
// TODO log exception
e.printStackTrace();
}
serverSocket = null;
}
}
// TODO server: using a boolean 'now' argument? a timeout?
ArrayList list = new ArrayList(running);
for(int i=0; i<list.size(); i++) {
OdbcServerThread c = (OdbcServerThread) list.get(i);
c.close();
try {
c.getThread().join(100);
} catch(Exception e) {
// TODO log exception
e.printStackTrace();
}
}
}
public boolean isRunning() {
if(serverSocket == null) {
return false;
}
try {
Socket s = NetUtils.createSocket(InetAddress.getLocalHost(), serverSocket.getLocalPort(), false);
s.close();
return true;
} catch(Exception e) {
return false;
}
}
public String getBaseDir() {
return baseDir;
}
public boolean getAllowOthers() {
return allowOthers;
}
public String getType() {
return "ODBC";
}
public boolean getIfExists() {
return ifExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.HashMap;
import org.h2.engine.ConnectionInfo;
import org.h2.message.Message;
import org.h2.util.StringUtils;
/**
* @author Thomas
*/
public class OdbcServerThread implements Runnable {
private OdbcServer server;
private Socket socket;
private Connection conn;
private DatabaseMetaData meta;
private boolean stop;
private int cacheId;
private Object cache;
private OdbcTransfer transfer;
private Thread thread;
private BufferedOutputStream outBuff;
private HashMap object = new HashMap();
private int nextId;
OdbcServerThread(Socket socket, OdbcServer server) {
this.server = server;
this.socket = socket;
}
private int addObject(Object o) {
int id = nextId++;
server.log("addObj "+id+" "+o);
object.put(new Integer(id), o);
cacheId = id;
cache = o;
return id;
}
private void freeObject(int id) {
if (cacheId == id) {
cacheId = -1;
cache = null;
}
object.remove(new Integer(id));
}
private Object getObject(int id) {
if (id == cacheId) {
server.log("getObj "+id+" "+cache);
return cache;
}
server.log("getObj "+id+" "+object.get(new Integer(id)));
return object.get(new Integer(id));
}
public void run() {
try {
server.log("Connect");
InputStream ins = socket.getInputStream();
OutputStream outs = socket.getOutputStream();
DataInputStream in;
in = new DataInputStream(new BufferedInputStream(ins,
OdbcTransfer.BUFFER_SIZE));
outBuff = new BufferedOutputStream(outs, OdbcTransfer.BUFFER_SIZE);
DataOutputStream out = new DataOutputStream(outBuff);
transfer = new OdbcTransfer(in, out);
outBuff.flush();
while (!stop) {
process();
outBuff.flush();
}
server.log("Disconnect");
} catch (Exception e) {
server.logError(e);
}
}
public void close() {
try {
stop = true;
conn.close();
socket.close();
server.log("Close");
} catch(Exception e) {
server.logError(e);
}
conn = null;
socket = null;
server.remove(this);
}
private void sendError(Throwable e) throws IOException {
SQLException s = Message.convert(e);
server.log("Exception "+s);
s.printStackTrace();
transfer.writeByte((byte)'E');
}
private void processResultSet(ResultSet rs) throws IOException, SQLException {
int id = addObject(rs);
transfer.writeInt(id);
ResultSetMetaData m = rs.getMetaData();
int columnCount = m.getColumnCount();
transfer.writeInt(columnCount);
for(int i=0; i<columnCount; i++) {
transfer.writeInt(mapType(m.getColumnType(i+1)));
transfer.writeString(m.getTableName(i+1));
transfer.writeString(m.getColumnLabel(i+1));
transfer.writeInt(m.getPrecision(i+1));
transfer.writeInt(m.getScale(i+1));
transfer.writeInt(m.getColumnDisplaySize(i+1));
}
}
private void setParameter(PreparedStatement prep, int index, int type) throws SQLException, IOException {
switch(type) {
case Types.NULL: {
// fake: use Integer data type for now
prep.setNull(index, Types.INTEGER);
break;
}
case Types.INTEGER: {
int value = transfer.readInt();
server.log(" index="+index+" int="+value);
prep.setInt(index, value);
break;
}
case Types.VARCHAR: {
String value = transfer.readString();
server.log(" index="+index+" string="+value);
prep.setString(index, value);
break;
}
default:
throw Message.getInternalError("unexpected data type "+type);
}
}
private void setParameters(PreparedStatement prep) throws SQLException, IOException {
while(true) {
int x = transfer.readByte();
if(x == '0') {
break;
} else if(x=='1') {
int index = transfer.readInt();
int type = transfer.readInt();
setParameter(prep, index+1, type);
} else {
throw Message.getInternalError("unexpected "+x);
}
}
}
private void processMeta() throws IOException {
int operation = transfer.readByte();
server.log("meta op="+(char)operation);
switch(operation) {
case 'B': {
String catalog = transfer.readString();
String schema = transfer.readString();
String table = transfer.readString();
if(table ==null || table.length()==0) {
table = "%";
}
int scope = transfer.readInt();
boolean nullable = transfer.readBoolean();
try {
ResultSet rs = meta.getBestRowIdentifier(catalog, schema, table, scope, nullable);
processResultSet(rs);
} catch(Throwable e) {
sendError(e);
}
break;
}
case 'C': {
// String catalog = transfer.readString();
String schemaPattern = transfer.readString();
String tableNamePattern = transfer.readString();
String columnNamePattern = transfer.readString();
if(tableNamePattern ==null || tableNamePattern.length()==0) {
tableNamePattern = "%";
}
if(columnNamePattern ==null || columnNamePattern.length()==0) {
columnNamePattern = "%";
}
try {
PreparedStatement prep = conn.prepareStatement("SELECT "
+ "TABLE_CATALOG TABLE_CAT, "
+ "TABLE_SCHEMA TABLE_SCHEM, "
+ "TABLE_NAME, "
+ "COLUMN_NAME, "
+ "DATA_TYPE, "
+ "TYPE_NAME, "
+ "CHARACTER_MAXIMUM_LENGTH COLUMN_SIZE, "
+ "CHARACTER_MAXIMUM_LENGTH BUFFER_LENGTH, "
+ "CAST(NUMERIC_SCALE AS SMALLINT) DECIMAL_DIGITS, " // different in JDBC
+ "CAST(10 AS SMALLINT) NUM_PREC_RADIX, " // different in JDBC
+ "CAST(NULLABLE AS SMALLINT) NULLABLE, " // different in JDBC
+ "'' REMARKS, "
+ "COLUMN_DEFAULT COLUMN_DEF, "
+ "CAST(DATA_TYPE AS SMALLINT) SQL_DATA_TYPE, " // different in JDBC
+ "CAST(0 AS SMALLINT) SQL_DATETIME_SUB, " // different in JDBC
+ "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH, "
+ "ORDINAL_POSITION ORDINAL_POSITION, "
+ "NULLABLE IS_NULLABLE "
+ "FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE TABLE_SCHEMA LIKE ? "
+ "AND TABLE_NAME LIKE ? "
+ "AND COLUMN_NAME LIKE ? "
+ "ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION");
prep.setString(1, schemaPattern == null ? "%" : schemaPattern);
prep.setString(2, tableNamePattern == null ? "%" : tableNamePattern);
prep.setString(3, columnNamePattern == null ? "%" : columnNamePattern);
// ResultSet rs = meta.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
ResultSet rs = prep.executeQuery();
processResultSet(rs);
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'D': {
String where;
if(transfer.readByte()=='A') {
where= "";
} else {
int type = transfer.readInt();
where = " WHERE TYPE="+type+" ";
}
try {
ResultSet rs = conn.createStatement().executeQuery("SELECT "
+ "TYPE_NAME, "
+ "DATA_TYPE, "
+ "PRECISION COLUMN_SIZE, "
+ "PREFIX LITERAL_PREFIX, "
+ "PREFIX LITERAL_SUFFIX, "
+ "PARAMS CREATE_PARAMS, "
+ "CAST(" +DatabaseMetaData.typeNullable + " AS SMALLINT) NULLABLE, "
+ "CAST(1 AS SMALLINT) CASE_SENSITIVE, " // TODO metadata: check if this is ok
+ "CAST(1 AS SMALLINT) SEARCHABLE, " // TODO metadata: check if this is ok
+ "CAST(0 AS SMALLINT) UNSIGNED_ATTRIBUTE, " // TODO metadata: check if this is ok
+ "CAST(0 AS SMALLINT) FIXED_PREC_SCALE, " // TODO metadata: check if this is ok
+ "CAST(0 AS SMALLINT) AUTO_UNIQUE_VALUE, " // TODO metadata: check if this is ok
+ "TYPE_NAME LOCAL_TYPE_NAME, "
+ "MINIMUM_SCALE, "
+ "MAXIMUM_SCALE, "
+ "DATA_TYPE SQL_DATA_TYPE, "
+ "CAST(1 AS SMALLINT) SQL_DATETIME_SUB, " // TODO metadata: check if this is ok
+ "RADIX NUM_PREC_RADIX, "
+ "CAST(0 AS SMALLINT) INTERVAL_PRECISION "
+ "FROM INFORMATION_SCHEMA.TYPE_INFO "
+ where
+ "ORDER BY DATA_TYPE, POS");
processResultSet(rs);
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'I': {
// String catalog = transfer.readString();
String schemaPattern = transfer.readString();
String tableNamePattern = transfer.readString();
if(tableNamePattern==null || tableNamePattern.length()==0) {
tableNamePattern = "%";
}
// boolean unique = transfer.readBoolean();
// boolean approximate = transfer.readBoolean();
try {
//ResultSet rs = meta.getIndexInfo(catalog, schemaPattern, tableNamePattern, unique, approximate);
PreparedStatement prep = conn.prepareStatement("SELECT "
+ "TABLE_CATALOG TABLE_CAT, "
+ "TABLE_SCHEMA TABLE_SCHEM, "
+ "TABLE_NAME, "
+ "CAST(NON_UNIQUE AS SMALLINT) NON_UNIQUE, "
+ "TABLE_CATALOG INDEX_QUALIFIER, "
+ "INDEX_NAME, "
+ "CAST("+DatabaseMetaData.tableIndexOther + " AS SMALLINT) TYPE, "
+ "ORDINAL_POSITION, "
+ "COLUMN_NAME, "
+ "'A' ASC_OR_DESC, "
+ "CARDINALITY, "
+ "0 PAGES, "
+ "'' FILTER_CONDITION "
+ "FROM INFORMATION_SCHEMA.INDEXES "
+ "WHERE CATALOG_NAME LIKE ? "
+ "AND TABLE_NAME LIKE ? "
+ "ORDER BY NON_UNIQUE, TYPE, TABLE_SCHEM, INDEX_NAME, ORDINAL_POSITION");
prep.setString(1, schemaPattern);
prep.setString(2, tableNamePattern);
ResultSet rs = prep.executeQuery();
processResultSet(rs);
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'N': {
String sql = transfer.readString();
try {
sql = conn.nativeSQL(sql);
} catch(SQLException e) {
sendError(e);
}
transfer.writeString(sql);
break;
}
case 'T': {
String catalog = transfer.readString();
String schema = transfer.readString();
String table = transfer.readString();
String tableTypes = transfer.readString();
server.log(" catalog="+catalog+" schema="+schema+" table="+table+" tableTypes="+tableTypes);
ResultSet rs;
String[] types = null;
try {
if(catalog.equals("%") && schema.length()==0 && table.length()==0) {
server.log(" allCatalogs");
PreparedStatement prep = conn.prepareStatement("SELECT "
+ "CATALOG_NAME TABLE_CAT, "
+ "NULL TABLE_SCHEM, "
+ "NULL TABLE_NAME, "
+ "NULL TABLE_TYPE, "
+ "'' REMARKS "
+ "FROM INFORMATION_SCHEMA.CATALOGS");
rs = prep.executeQuery();
} else if(catalog.length()==0 && schema.equals("%") && table.length()==0) {
server.log(" allSchemas");
PreparedStatement prep = conn.prepareStatement("SELECT "
+ "CATALOG_NAME TABLE_CAT, "
+ "SCHEMA_NAME TABLE_SCHEM, "
+ "NULL TABLE_NAME, "
+ "NULL TABLE_TYPE, "
+ "'' REMARKS "
+ "FROM INFORMATION_SCHEMA.SCHEMATA");
rs = prep.executeQuery();
} else if(catalog.length()==0 && schema.length()==0 && table.length()==0 && tableTypes.equals("%")) {
server.log(" allTableTypes");
PreparedStatement prep = conn.prepareStatement("SELECT "
+ "NULL TABLE_CAT, "
+ "NULL TABLE_SCHEM, "
+ "NULL TABLE_NAME, "
+ "TYPE TABLE_TYPE, "
+ "'' REMARKS "
+ "FROM INFORMATION_SCHEMA.TABLE_TYPES");
rs = prep.executeQuery();
} else {
server.log(" getTables");
if(tableTypes.equals("%") || tableTypes.length()==0) {
types = null;
} else {
types = StringUtils.arraySplit(tableTypes, ',', false);
for(int i=0; i<types.length; i++) {
String t = StringUtils.toUpperEnglish(types[i]);
if(t.startsWith("\'")) {
t = t.substring(1, t.length()-2);
}
types[i] = t;
}
}
server.log("getTables "+catalog+" "+schema+" "+table);
if(table.length() == 0) {
table = null;
}
rs = meta.getTables(catalog, schema, table, types);
}
processResultSet(rs);
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'V': {
String catalog = transfer.readString();
String schema = transfer.readString();
String table = transfer.readString();
if(table ==null || table.length()==0) {
table = "%";
}
try {
ResultSet rs = meta.getVersionColumns(catalog, schema, table);
// PreparedStatement prep = conn.prepareStatement("SELECT "
// + "CAST(NULL AS INT) SCOPE, "
// + "NULL COLUMN_NAME, "
// + "CAST(NULL AS INT) DATA_TYPE, "
// + "NULL TYPE_NAME, "
// + "CAST(NULL AS INT) COLUMN_SIZE, "
// + "CAST(NULL AS INT) BUFFER_LENGTH, "
// + "CAST(NULL AS INT) DECIMAL_DIGITS, "
// + "CAST(NULL AS INT) PSEUDO_COLUMN "
// + "FROM SYSTEM_TABLES "
// + "WHERE 1=0");
// ResultSet rs = prep.executeQuery();
processResultSet(rs);
} catch(SQLException e) {
sendError(e);
}
break;
}
default:
server.log("meta operation? " + (char)operation);
}
}
private void process() throws IOException {
int operation = transfer.readByte();
if(operation == -1) {
stop = true;
return;
}
server.log("op="+(char)operation);
switch(operation) {
case 'A': {
try {
int op = transfer.readByte();
switch(op) {
case '0':
server.log("autoCommit false");
conn.setAutoCommit(false);
break;
case '1':
server.log("autoCommit true");
conn.setAutoCommit(true);
break;
case 'C':
server.log("commit");
conn.commit();
break;
case 'R':
server.log("rollback");
conn.rollback();
break;
default:
server.log("operation? " + (char)operation);
}
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'C':
server.log("connect");
String db = transfer.readString();
server.log(" db="+db);
String user = transfer.readString();
server.log(" user="+user);
String password = transfer.readString();
server.log(" password="+password);
String baseDir = server.getBaseDir();
ConnectionInfo ci = new ConnectionInfo(db);
if(baseDir != null) {
ci.setBaseDir(baseDir);
}
if(server.getIfExists()) {
ci.setProperty("IFEXISTS", "TRUE");
}
String dbName = ci.getDatabaseName();
try {
conn = DriverManager.getConnection("jdbc:h2:" + dbName, user, password);
meta = conn.getMetaData();
transfer.writeByte((byte)'O');
} catch(SQLException e) {
sendError(e);
}
break;
case 'E': {
String sql = transfer.readString();
server.log("<"+sql+">");
try {
int params = getParametersCount(sql);
if(params > 0) {
// it is a prepared statement
PreparedStatement prep = conn.prepareStatement(sql);
int id = addObject(prep);
transfer.writeByte((byte)'O');
transfer.writeInt(id);
transfer.writeInt(params);
} else {
Statement stat = conn.createStatement();
boolean isResultSet = stat.execute(sql);
if(isResultSet) {
transfer.writeByte((byte)'R');
ResultSet rs = stat.getResultSet();
processResultSet(rs);
} else {
transfer.writeByte((byte)'U');
transfer.writeInt(stat.getUpdateCount());
}
}
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'F': {
int id = transfer.readInt();
server.log("free "+id);
freeObject(id);
break;
}
case 'G': {
int objectId = transfer.readInt();
ResultSet rs = (ResultSet)getObject(objectId);
try {
boolean hasNext = rs.next();
if(hasNext) {
transfer.writeByte((byte)'1');
ResultSetMetaData m = rs.getMetaData();
int columnCount = m.getColumnCount();
for(int i=0; i<columnCount; i++) {
write(m, rs, i);
}
} else {
transfer.writeByte((byte)'0');
}
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'M':
processMeta();
break;
case 'P': {
String sql = transfer.readString();
server.log("<"+sql+">");
try {
PreparedStatement prep = conn.prepareStatement(sql);
int id = addObject(prep);
transfer.writeByte((byte)'O');
transfer.writeInt(id);
int params = getParametersCount(sql);
transfer.writeInt(params);
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'Q': {
// executePrepared
int id = transfer.readInt();
PreparedStatement prep = (PreparedStatement)getObject(id);
try {
setParameters(prep);
boolean isResultSet = prep.execute();
if(isResultSet) {
transfer.writeByte((byte)'R');
ResultSet rs = prep.getResultSet();
processResultSet(rs);
} else {
transfer.writeByte((byte)'U');
transfer.writeInt(prep.getUpdateCount());
}
} catch(SQLException e) {
sendError(e);
}
break;
}
case 'X':
stop = true;
break;
default:
server.log("operation? " + (char)operation);
}
}
private void write(ResultSetMetaData m, ResultSet rs, int i) throws IOException {
try {
int type = mapType(m.getColumnType(i+1));
switch(type) {
case Types.SMALLINT:
case Types.INTEGER: {
int value = rs.getInt(i+1);
if(rs.wasNull()) {
transfer.writeBoolean(true);
} else {
transfer.writeBoolean(false);
transfer.writeInt(value);
}
break;
}
case Types.NULL:
break;
case Types.VARCHAR:
transfer.writeString(rs.getString(i+1));
break;
default:
throw Message.getInternalError("unsupported data type "+type);
}
} catch(SQLException e) {
sendError(e);
}
}
int mapType(int sqlType) {
switch(sqlType) {
case Types.SMALLINT:
case Types.INTEGER:
case Types.NULL:
case Types.VARCHAR:
return sqlType;
case Types.TINYINT:
case Types.BIT:
case Types.BOOLEAN:
return Types.INTEGER;
case Types.BIGINT:
case Types.BINARY:
case Types.BLOB:
case Types.CHAR:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.DECIMAL:
case Types.DOUBLE:
case Types.FLOAT:
case Types.JAVA_OBJECT:
case Types.LONGVARBINARY:
case Types.LONGVARCHAR:
case Types.NUMERIC:
case Types.OTHER:
case Types.REAL:
case Types.VARBINARY:
return Types.VARCHAR;
default:
throw Message.getInternalError("sqlType "+sqlType);
}
}
int getParametersCount(String sql) throws SQLException {
if (sql == null || sql.indexOf('?') < 0) {
return 0;
}
int len = sql.length();
int param = 0;
for (int i = 0; i < len; i++) {
try {
char c = sql.charAt(i);
switch (c) {
case '\'': {
int j = sql.indexOf('\'', i + 1);
if (j < 0) {
throw Message.getSyntaxError(sql, i);
}
i = j;
break;
}
case '"': {
int j = sql.indexOf('"', i + 1);
if (j < 0) {
throw Message.getSyntaxError(sql, i);
}
i = j;
break;
}
case '/': {
if (sql.charAt(i + 1) == '*') {
// block comment
int j = sql.indexOf("*/", i + 2);
if (j < 0) {
throw Message.getSyntaxError(sql, i);
}
i = j + 1;
} else if (sql.charAt(i + 1) == '/') {
// single line comment
i += 2;
while (i < len && (c = sql.charAt(i)) != '\r'
&& c != '\n') {
i++;
}
}
break;
}
case '-':
if (sql.charAt(i + 1) == '-') {
// single line comment
i += 2;
while (i < len && (c = sql.charAt(i)) != '\r'
&& c != '\n') {
i++;
}
}
break;
case '?':
param++;
break;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw Message.getSyntaxError(sql, i);
}
}
return param;
}
public void setThread(Thread thread) {
this.thread = thread;
}
public Thread getThread() {
return thread;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* @author Thomas
*/
public class OdbcTransfer {
static final int BUFFER_SIZE = 1024;
private DataInputStream in;
private DataOutputStream out;
OdbcTransfer(DataInputStream in, DataOutputStream out) {
this.in = in;
this.out = out;
}
OdbcTransfer writeBoolean(boolean x) throws IOException {
writeInt(x ? 1 : 0);
return this;
}
OdbcTransfer writeOk() throws IOException {
writeBoolean(true);
return this;
}
boolean readBoolean() throws IOException {
return readInt() == 1;
}
OdbcTransfer writeByte(byte x) throws IOException {
out.write(x);
return this;
}
int readByte() throws IOException {
return in.read();
}
OdbcTransfer writeShort(short x) throws IOException {
return writeInt(x);
}
short readShort() throws IOException {
return (short) readInt();
}
OdbcTransfer writeInt(int i) throws IOException {
out.writeInt(i);
return this;
}
int readInt() throws IOException {
return in.readInt();
}
OdbcTransfer writeLong(long i) throws IOException {
out.writeLong(i);
return this;
}
long readLong() throws IOException {
return in.readLong();
}
OdbcTransfer writeFloat(float i) throws IOException {
out.writeFloat(i);
return this;
}
float readFloat() throws IOException {
return in.readFloat();
}
OdbcTransfer writeDouble(double i) throws IOException {
out.writeDouble(i);
return this;
}
double readDouble() throws IOException {
return in.readDouble();
}
OdbcTransfer writeString(String s) throws IOException {
if (s == null) {
out.writeInt(-1);
} else {
out.writeInt(s.length());
for(int i=0; i<s.length(); i++) {
out.write(s.charAt(i));
}
}
return this;
}
String readString() throws IOException {
int len = in.readInt();
if (len == -1) {
return null;
}
char[] chars = new char[len];
for(int i=0; i<len; i++) {
chars[i] = (char)in.readByte();
}
return new String(chars);
}
OdbcTransfer writeDate(java.sql.Date x) throws IOException {
if (x == null) {
writeString(null);
} else {
writeString(x.toString());
}
return this;
}
OdbcTransfer writeTime(java.sql.Time x) throws IOException {
if (x == null) {
writeString(null);
} else {
writeString(x.toString());
}
return this;
}
OdbcTransfer writeTimestamp(java.sql.Timestamp x) throws IOException {
if (x == null) {
writeString(null);
} else {
writeString(x.toString());
}
return this;
}
java.sql.Date readDate() throws IOException {
String s = readString();
if (s == null) {
return null;
}
return java.sql.Date.valueOf(s);
}
java.sql.Time readTime() throws IOException {
String s = readString();
if (s == null) {
return null;
}
return java.sql.Time.valueOf(s);
}
java.sql.Timestamp readTimestamp() throws IOException {
String s = readString();
if (s == null) {
return null;
}
return java.sql.Timestamp.valueOf(s);
}
OdbcTransfer writeByteArray(byte[] data) throws IOException {
if (data == null) {
writeInt(-1);
} else {
writeInt(data.length);
}
out.write(data);
return this;
}
byte[] readByteArray() throws IOException {
int len = readInt();
if (len == -1) {
return null;
}
byte[] b = new byte[len];
in.readFully(b);
return b;
}
OdbcTransfer writeIntArray(int[] s) throws IOException {
if (s == null) {
writeInt(-1);
} else {
writeInt(s.length);
for (int i = 0; i < s.length; i++) {
writeInt(s[i]);
}
}
return this;
}
int[] readIntArray() throws IOException {
int len = readInt();
if (len == -1) {
return null;
}
int[] s = new int[len];
for (int i = 0; i < len; i++) {
s[i] = readInt();
}
return s;
}
OdbcTransfer writeStringArray(String[] s) throws IOException {
if (s == null) {
writeInt(-1);
} else {
writeInt(s.length);
for (int i = 0; i < s.length; i++) {
writeString(s[i]);
}
}
return this;
}
String[] readStringArray() throws IOException {
int len = readInt();
if (len == -1) {
return null;
}
String[] s = new String[len];
for (int i = 0; i < len; i++) {
s[i] = readString();
}
return s;
}
// buffer - cannot be null
OdbcTransfer writeBuffer(byte[] buffer) throws IOException {
out.write(buffer);
return this;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.sql.SQLException;
public interface Service {
void init(String[] args) throws Exception;
String getURL();
void start() throws SQLException;
void listen();
void stop();
boolean isRunning();
boolean getAllowOthers();
String getType();
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.engine.Constants;
import org.h2.message.TraceSystem;
import org.h2.util.MathUtils;
import org.h2.util.NetUtils;
public class TcpServer implements Service {
// TODO new feature: implement automatic client / server mode if 'socket' file locking is used
// TODO make the kernel multi-threaded
// TODO better exception message if the port is already in use, maybe automatically use the next free port?
public static final int DEFAULT_PORT = 9092;
public static final int SHUTDOWN_NORMAL = 0;
public static final int SHUTDOWN_FORCE = 1;
public static boolean LOG_INTERNAL_ERRORS;
private int port;
private boolean log;
private boolean ssl;
private boolean stop;
private ServerSocket serverSocket;
private HashSet running = new HashSet();
private String baseDir;
private String url;
private boolean allowOthers;
private boolean ifExists;
private Connection managementDb;
private String managementPassword = "";
private static HashMap servers = new HashMap();
public static String getManagementDbName(int port) {
return "mem:" + Constants.MANAGEMENT_DB_PREFIX + port;
}
private void initManagementDb() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:h2:" + getManagementDbName(port), "sa", managementPassword);
managementDb = conn;
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS IF NOT EXISTS STOP_SERVER FOR \"" + TcpServer.class.getName() +".stopServer\"");
servers.put(""+port, this);
}
private void stopManagementDb() {
if(managementDb != null) {
try {
managementDb.close();
} catch (SQLException e) {
TraceSystem.traceThrowable(e);
}
managementDb = null;
}
}
public static void stopServer(int port, String password, int shutdownMode) {
TcpServer server = (TcpServer) servers.get("" + port);
if(server == null) {
return;
}
if(!server.managementPassword.equals(password)) {
return;
}
if(shutdownMode == TcpServer.SHUTDOWN_NORMAL) {
server.stop = true;
try {
Socket s = new Socket("localhost", port);
s.close();
} catch (Exception e) {
// try to connect - so that accept returns
}
} else if(shutdownMode == TcpServer.SHUTDOWN_FORCE) {
server.stop();
}
}
public void init(String[] args) throws Exception {
port = DEFAULT_PORT;
for (int i = 0; i < args.length; i++) {
String a = args[i];
if (a.equals("-log")) {
log = Boolean.valueOf(args[++i]).booleanValue();
} else if (a.equals("-tcpSSL")) {
ssl = Boolean.valueOf(args[++i]).booleanValue();
} else if (a.equals("-tcpPort")) {
port = MathUtils.decodeInt(args[++i]);
} else if (a.equals("-tcpPassword")) {
managementPassword= args[++i];
} else if (a.equals("-baseDir")) {
baseDir = args[++i];
} else if (a.equals("-tcpAllowOthers")) {
allowOthers = Boolean.valueOf(args[++i]).booleanValue();
} else if (a.equals("-ifExists")) {
ifExists = Boolean.valueOf(args[++i]).booleanValue();
}
}
org.h2.Driver.load();
url = (ssl ? "ssl" : "tcp") + "://localhost:" + port;
}
public String getURL() {
return url;
}
boolean allow(Socket socket) {
if(allowOthers) {
return true;
}
return socket.getInetAddress().isLoopbackAddress();
}
public void start() throws SQLException {
initManagementDb();
serverSocket = NetUtils.createServerSocket(port, ssl);
}
public void listen() {
String threadName = Thread.currentThread().getName();
try {
while (!stop) {
Socket s = serverSocket.accept();
TcpServerThread c = new TcpServerThread(s, this);
running.add(c);
Thread thread = new Thread(c);
thread.setName(threadName+" thread");
c.setThread(thread);
thread.start();
}
} catch (Exception e) {
if(!stop) {
TraceSystem.traceThrowable(e);
}
}
stopManagementDb();
}
public boolean isRunning() {
if(serverSocket == null) {
return false;
}
try {
Socket s = NetUtils.createLoopbackSocket(port, ssl);
s.close();
return true;
} catch(Exception e) {
return false;
}
}
public synchronized void stop() {
// TODO server: share code between web and tcp servers
if(!stop) {
stop = true;
if(serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
TraceSystem.traceThrowable(e);
}
serverSocket = null;
}
}
// TODO server: using a boolean 'now' argument? a timeout?
ArrayList list = new ArrayList(running);
for(int i=0; i<list.size(); i++) {
TcpServerThread c = (TcpServerThread) list.get(i);
c.close();
try {
c.getThread().join(100);
} catch(Exception e) {
TraceSystem.traceThrowable(e);
}
}
servers.remove(""+port);
}
synchronized void remove(TcpServerThread t) {
running.remove(t);
}
boolean getLog() {
return log;
}
String getBaseDir() {
return baseDir;
}
void log(String s) {
// TODO log: need concept for server log
if (log) {
System.out.println(s);
}
}
void logError(Exception e) {
if (log) {
e.printStackTrace();
}
}
public boolean getAllowOthers() {
return allowOthers;
}
public String getType() {
return "TCP";
}
public void logInternalError(String string) {
if(TcpServer.LOG_INTERNAL_ERRORS) {
System.out.println(string);
new Error(string).printStackTrace();
}
}
public boolean getIfExists() {
return ifExists;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;
import java.sql.SQLException;
import org.h2.command.Command;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Constants;
import org.h2.engine.Engine;
import org.h2.engine.Session;
import org.h2.engine.SessionRemote;
import org.h2.expression.Parameter;
import org.h2.message.Message;
import org.h2.result.LocalResult;
import org.h2.result.ResultColumn;
import org.h2.util.ObjectArray;
import org.h2.util.SmallMap;
import org.h2.value.Transfer;
import org.h2.value.Value;
public class TcpServerThread implements Runnable {
private TcpServer server;
private Session session;
private boolean stop;
private Thread thread;
private Transfer transfer;
private Command commit;
private SmallMap cache = new SmallMap(Constants.SERVER_CACHED_OBJECTS);
public TcpServerThread(Socket socket, TcpServer server) {
this.server = server;
transfer = new Transfer(null);
transfer.setSocket(socket);
}
public void run() {
try {
transfer.init();
server.log("Connect");
// TODO server: should support a list of allowed databases and a list of allowed clients
try {
int version = transfer.readInt();
if(!server.allow(transfer.getSocket())) {
throw Message.getSQLException(Message.REMOTE_CONNECTION_NOT_ALLOWED);
}
if(version != Constants.TCP_DRIVER_VERSION) {
throw Message.getSQLException(Message.DRIVER_VERSION_ERROR_2,
new String[] { "" + version, "" + Constants.TCP_DRIVER_VERSION }, null);
}
String db = transfer.readString();
String originalURL = transfer.readString();
String baseDir = server.getBaseDir();
ConnectionInfo ci = new ConnectionInfo(db);
if(baseDir != null) {
ci.setBaseDir(baseDir);
}
if(server.getIfExists()) {
ci.setProperty("IFEXISTS", "TRUE");
}
ci.setOriginalURL(originalURL);
ci.setUserName(transfer.readString());
ci.setUserPasswordHash(transfer.readBytes());
ci.setFilePasswordHash(transfer.readBytes());
int len = transfer.readInt();
for(int i=0; i<len; i++) {
ci.setProperty(transfer.readString(), transfer.readString());
}
Engine engine = Engine.getInstance();
session = engine.getSession(ci);
transfer.setSession(session);
transfer.writeInt(SessionRemote.STATUS_OK).flush();
server.log("Connected");
} catch(Throwable e) {
sendError(e);
stop = true;
}
while (!stop) {
try {
process();
} catch(Throwable e) {
sendError(e);
}
}
server.log("Disconnect");
} catch(Exception e) {
server.logError(e);
} finally {
close();
}
}
private void closeSession() {
if(session != null) {
try {
Command rollback = session.prepareLocal("ROLLBACK");
rollback.executeUpdate();
session.close();
} catch(Exception e) {
server.logError(e);
} finally {
session = null;
}
}
}
public void close() {
try {
stop = true;
closeSession();
transfer.close();
server.log("Close");
} catch(Exception e) {
server.logError(e);
}
server.remove(this);
}
private void sendError(Throwable e) {
try {
SQLException s = Message.convert(e);
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String trace = writer.toString();
transfer.writeInt(SessionRemote.STATUS_ERROR).
writeString(s.getSQLState()).
writeString(e.getMessage()).
writeInt(s.getErrorCode()).
writeString(trace).
flush();
} catch(IOException e2) {
server.logError(e2);
// if writing the error does not work, close the connection
stop = true;
}
}
private void setParameters(Command command) throws IOException, SQLException {
int len = transfer.readInt();
ObjectArray params = command.getParameters();
for(int i=0; i<len; i++) {
Parameter p = (Parameter) params.get(i);
p.setValue(transfer.readValue());
}
}
private void process() throws IOException, SQLException {
int operation = transfer.readInt();
switch(operation) {
case SessionRemote.SESSION_PREPARE: {
int id = transfer.readInt();
String sql = transfer.readString();
Command command = session.prepareLocal(sql);
cache.addObject(id, command);
boolean isQuery = command.isQuery();
int paramCount = command.getParameters().size();
transfer.writeInt(SessionRemote.STATUS_OK).writeBoolean(isQuery).writeInt(paramCount).flush();
break;
}
case SessionRemote.SESSION_CLOSE: {
closeSession();
transfer.writeInt(SessionRemote.STATUS_OK).flush();
close();
break;
}
case SessionRemote.COMMAND_COMMIT: {
if (commit == null) {
commit = session.prepareLocal("COMMIT");
}
commit.executeUpdate();
transfer.writeInt(SessionRemote.STATUS_OK).flush();
break;
}
case SessionRemote.COMMAND_EXECUTE_QUERY: {
int id = transfer.readInt();
int objectId = transfer.readInt();
int maxRows = transfer.readInt();
int readRows = transfer.readInt();
Command command = (Command)cache.getObject(id, false);
setParameters(command);
LocalResult result = command.executeQueryLocal(maxRows);
cache.addObject(objectId, result);
int columnCount = result.getVisibleColumnCount();
transfer.writeInt(SessionRemote.STATUS_OK).writeInt(columnCount);
int rowCount = result.getRowCount();
transfer.writeInt(rowCount);
for(int i=0; i<columnCount; i++) {
ResultColumn.writeColumn(transfer, result, i);
}
if(rowCount<readRows) {
for(int i=0; i<=rowCount; i++) {
sendRow(result);
}
}
transfer.flush();
break;
}
case SessionRemote.COMMAND_EXECUTE_UPDATE: {
int id = transfer.readInt();
Command command = (Command)cache.getObject(id, false);
setParameters(command);
int updateCount = command.executeUpdate();
int status = SessionRemote.STATUS_OK;
if(session.isClosed()) {
status = SessionRemote.STATUS_CLOSED;
}
transfer.writeInt(status).writeInt(updateCount).writeBoolean(session.getAutoCommit());
transfer.flush();
break;
}
case SessionRemote.COMMAND_CLOSE: {
int id = transfer.readInt();
Command command = (Command)cache.getObject(id, true);
if(command != null) {
command.close();
cache.freeObject(id);
}
break;
}
case SessionRemote.RESULT_FETCH_ROW: {
int id = transfer.readInt();
LocalResult result = (LocalResult)cache.getObject(id, false);
transfer.writeInt(SessionRemote.STATUS_OK);
sendRow(result);
transfer.flush();
break;
}
case SessionRemote.RESULT_RESET: {
int id = transfer.readInt();
LocalResult result = (LocalResult)cache.getObject(id, false);
result.reset();
break;
}
case SessionRemote.RESULT_CLOSE: {
int id = transfer.readInt();
LocalResult result = (LocalResult)cache.getObject(id, true);
if(result != null) {
result.close();
cache.freeObject(id);
}
break;
}
case SessionRemote.CHANGE_ID: {
int oldId = transfer.readInt();
int newId = transfer.readInt();
Object obj = cache.getObject(oldId, false);
cache.freeObject(oldId);
cache.addObject(newId, obj);
break;
}
default:
server.logInternalError("Unknown operation: " + operation);
server.log("Unknown operation: " + operation);
closeSession();
close();
}
}
private void sendRow(LocalResult result) throws IOException, SQLException {
boolean n = result.next();
transfer.writeBoolean(n);
if(n) {
Value[] v = result.currentRow();
for(int i=0; i<result.getVisibleColumnCount(); i++) {
transfer.writeValue(v[i]);
}
}
}
public void setThread(Thread thread) {
this.thread = thread;
}
public Thread getThread() {
return thread;
}
}
/*
* Copyright 2004-2006 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-2006 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-2006 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.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.h2.util.IOUtils;
public class FileObjectNative implements FileObject {
private File file;
static FileObjectNative get(String 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(get(newFile.getName()).file);
}
public void write(InputStream in) throws IOException {
FileOutputStream out = new FileOutputStream(file);
IOUtils.copyAndClose(in, out);
}
public void read(long skip, OutputStream out) throws IOException {
InputStream in = new FileInputStream(file);
IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out);
}
}
/*
* Copyright 2004-2006 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;
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 org.h2.util.IOUtils;
import org.h2.util.StringUtils;
public class FileSystemDatabase {
private Connection conn;
private HashMap preparedMap = new HashMap();
private boolean log;
FileSystemDatabase(Connection conn, boolean log) throws SQLException {
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();
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");
System.out.println(id + " " + name + " parent:"+parentId+" length:" + length + " lastMod:" + lastModified);
}
}
}
synchronized void delete(String fullName) {
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();
} catch(SQLException e) {
rollback();
throw convert(e);
}
}
synchronized boolean exists(String fullName) {
long id = getId(fullName, false);
return id >= 0;
}
synchronized void read(String fullName, long skip, OutputStream out) throws IOException {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT DATA FROM FILEDATA WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
if(rs.next()) {
InputStream in = rs.getBinaryStream(1);
IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out);
}
} catch(SQLException e) {
throw convert(e);
}
}
synchronized void write(String fullName, InputStream in) throws IOException {
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();
}
long parentId = getId(fullName, true);
PreparedStatement prep = prepare("INSERT INTO FILES(PARENTID, NAME, LASTMODIFIED) VALUES(?, ?, ?)");
prep.setLong(1, parentId);
prep.setString(2, getName(fullName));
prep.setLong(3, System.currentTimeMillis());
prep.execute();
ResultSet rs = prep.getGeneratedKeys();
rs.next();
id = rs.getLong(1);
prep = prepare("INSERT INTO FILEDATA(ID, DATA) VALUES(?, ?)");
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.setLong(1, id);
prep.setLong(2, id);
prep.execute();
commit();
} catch(SQLException e) {
rollback();
throw convert(e);
}
}
synchronized boolean isDirectory(String fullName) {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
rs.next();
rs.getLong(1);
return rs.wasNull();
} catch(SQLException e) {
throw convert(e);
}
}
synchronized long lastModified(String fullName) {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT LASTMODIFIED FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
rs.next();
return rs.getLong(1);
} catch(SQLException e) {
throw convert(e);
}
}
synchronized long length(String fullName) {
try {
long id = getId(fullName, false);
PreparedStatement prep = prepare("SELECT LENGTH FROM FILES WHERE ID=?");
prep.setLong(1, id);
ResultSet rs = prep.executeQuery();
rs.next();
return rs.getLong(1);
} catch(SQLException e) {
throw convert(e);
}
}
synchronized FileObject[] listFiles(String fullName) {
try {
String name = fullName;
if(!name.endsWith("/")) {
name += "/";
}
long id = getId(fullName, 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);
}
FileObject[] result = new FileObject[list.size()];
list.toArray(result);
return result;
} catch(SQLException e) {
throw convert(e);
}
}
String getName(String fullName) {
String[] path = StringUtils.arraySplit(fullName, '/', false);
return path[path.length-1];
}
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--;
}
for(int i=0; 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);
}
}
synchronized void mkdirs(String fullName) {
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 = prep.getGeneratedKeys();
rs.next();
parentId = rs.getLong(1);
} else {
parentId = rs.getLong(1);
}
}
commit();
} catch(SQLException e) {
rollback();
throw convert(e);
}
}
synchronized boolean renameTo(String oldFullName, String newFullName) {
try {
long parentOld = getId(oldFullName, true);
long parentNew = getId(newFullName, true);
if(parentOld != parentNew) {
return false;
}
String newName = getName(newFullName);
long id = getId(oldFullName, 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() {
try {
conn.commit();
} catch(SQLException e) {
if(log) {
e.printStackTrace();
}
}
}
private void rollback() {
try {
conn.rollback();
} catch(SQLException e) {
if(log) {
e.printStackTrace();
}
}
}
}
/*
* Copyright 2004-2006 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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import org.h2.engine.Constants;
import org.h2.util.StringUtils;
public class FtpControl extends Thread {
private static final String SERVER_NAME = "Small FTP Server";
private FtpServer server;
private Socket control;
private FtpData data;
private PrintWriter output;
private String userName;
private boolean connected, readonly;
private String currentDir = "/";
private String serverIpAddress;
private boolean stop;
private String renameFrom;
private boolean replied;
private long restart;
public FtpControl(Socket control, FtpServer server, boolean stop) {
this.server = server;
this.control = control;
this.stop = stop;
}
public void run() {
try {
output = new PrintWriter(new OutputStreamWriter(control.getOutputStream(), Constants.UTF8));
if(stop) {
reply(421, "Too many users");
} else {
reply(220, SERVER_NAME);
// TODO need option to configure the serverIpAddress
serverIpAddress = control.getLocalAddress().getHostAddress().replace('.', ',');
BufferedReader input = new BufferedReader(new InputStreamReader(control.getInputStream()));
while(!stop) {
String command = null;
try {
command = input.readLine();
} catch(IOException e) {
// ignore
}
if(command == null) {
break;
}
process(command);
}
if(data != null) {
data.close();
}
}
} catch(Throwable t) {
server.logError(t);
}
server.closeConnection();
}
private void process(String command) throws IOException {
int idx = command.indexOf(' ');
String param = "";
if(idx >= 0) {
param = command.substring(idx).trim();
command = command.substring(0, idx);
}
command = StringUtils.toUpperEnglish(command);
if(command.length() == 0) {
reply(506, "No command");
return;
}
server.log(">" + command);
replied = false;
if(connected) {
processConnected(command, param);
}
if(!replied) {
if("USER".equals(command)) {
userName = param;
reply(331, "Need password");
} else if("QUIT".equals(command)) {
reply(221, "Bye");
stop = true;
} else if("PASS".equals(command)) {
if(userName == null) {
reply(332, "Need username");
} else if(server.checkUserPassword(userName, param)) {
reply(230, "Ok");
readonly = false;
connected = true;
} else if(server.checkUserPasswordReadOnly(userName, param)) {
reply(230, "Ok, readonly");
readonly = true;
connected = true;
} else {
reply(431, "Wrong user/password");
}
} else if("REIN".equals(command)) {
userName = null;
connected = false;
currentDir = "/";
reply(200, "Ok");
} else if("HELP".equals(command)) {
reply(214, SERVER_NAME);
}
}
if(!replied) {
reply(506, "Invalid command");
}
}
private void processConnected(String command, String param) throws 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 += "/";
}
currentDir = param;
reply(250, "Ok");
} else {
reply(550, "Failed");
}
} else if("CDUP".equals(command)) {
if(currentDir.length()>1) {
int idx = currentDir.lastIndexOf("/", currentDir.length()-2);
currentDir = currentDir.substring(0, idx+1);
reply(250, "Ok");
} else {
reply(550, "Failed");
}
}
break;
case 'D':
if("DELE".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if(!readonly && file.exists() && file.isFile() && file.delete()) {
reply(250, "Ok");
} else {
reply(500, "Delete failed");
}
}
break;
case 'L':
if("LIST".equals(command)) {
processList(param, true);
}
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 {
reply(500, "Failed");
}
} else if("MODE".equals(command)) {
if("S".equals(StringUtils.toUpperEnglish(param))) {
reply(200, "Ok");
} else {
reply(504, "Invalid");
}
} else if("MDTM".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if(file.exists() && file.isFile()) {
reply(213, server.formatLastModified(file));
} else {
reply(550, "Failed");
}
}
break;
case 'N':
if("NLST".equals(command)) {
processList(param, false);
} else if("NOOP".equals(command)) {
reply(200, "Ok");
}
break;
case 'P':
if("PWD".equals(command)) {
reply(257, "\"" + currentDir + "\" directory"); // TODO quote (" > "")
} else if("PASV".equals(command)) {
ServerSocket dataSocket = server.createDataSocket();
data = new FtpData(server, control.getInetAddress(), dataSocket);
data.start();
int port = dataSocket.getLocalPort();
reply(227, "Passive Mode (" + serverIpAddress + "," + (port >> 8) + "," + (port & 255) + ")");
// reply(501, ne.getMessage());
}
break;
case 'R':
if("RNFR".equals(command)) {
param = getFileName(param);
FileObject file = server.getFile(param);
if(file.exists()) {
renameFrom = param;
reply(350, "Ok");
} else {
reply(450, "Not found");
}
} else if("RNTO".equals(command)) {
if (renameFrom == null) {
reply(503, "RNFR required");
} else {
FileObject fileOld = server.getFile(renameFrom);
FileObject fileNew = server.getFile(getFileName(param));
if(!readonly && fileOld.renameTo(fileNew)) {
reply(250, "Ok");
} else {
reply(550, "Failed");
}
}
} else if("RETR".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if(file.exists() && file.isFile()) {
reply(150, "Starting transfer");
try {
data.send(file, restart);
reply(226, "Ok");
} catch(IOException e) {
reply(426, "Failed");
}
restart = 0;
} else {
processList(param, true); // Firefox compatibility (still not good)
// reply(426, "Not a file");
}
} else if("RMD".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if(!readonly && file.exists() && file.isDirectory() && file.delete()) {
reply(250, "Ok");
} else {
reply(500, "Failed");
}
} else if("REST".equals(command)) {
try {
restart = Integer.parseInt(param);
reply(350, "Ok");
} catch(NumberFormatException e) {
reply(500, "Invalid");
}
}
break;
case 'S':
if("SYST".equals(command)) {
reply(215, "UNIX Type: L8");
} 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()));
} else {
reply(500, "Failed");
}
} else if("STOR".equals(command)) {
FileObject file = server.getFile(getFileName(param));
if(!readonly && !file.exists() || file.isFile()) {
reply(150, "Starting transfer");
try {
data.receive(file);
reply(226, "Ok");
} catch(IOException e) {
reply(426, "Failed");
}
} else {
reply(550, "Failed");
}
} else if("STRU".equals(command)) {
if("F".equals(StringUtils.toUpperEnglish(param))) {
reply(200, "Ok");
} else {
reply(504, "Invalid");
}
}
break;
case 'T':
if("TYPE".equals(command)) {
param = StringUtils.toUpperEnglish(param);
if("A".equals(param) || "A N".equals(param)) {
reply(200, "Ok");
} else if("I".equals(param) || "L 8".equals(param)) {
reply(200, "Ok");
} else {
reply(500, "Invalid");
}
}
break;
}
}
private String getFileName(String file) {
return file.startsWith("/") ? file : currentDir + file;
}
private void processList(String param, boolean directories) throws IOException {
FileObject directory = server.getFile(getFileName(param));
if(!directory.exists()) {
reply(450, "Directory does not exist");
return;
} else if(!directory.isDirectory()) {
reply(450, "Not a directory");
return;
}
String list = server.getDirectoryListing(directory, directories);
reply(150, "Starting transfer");
server.log(list);
data.send(list.getBytes("UTF-8"));
reply(226, "Done");
}
private void reply(int code, String message) throws IOException {
server.log(code + " " + message);
output.print(code + " " + message + "\r\n");
output.flush();
replied = true;
}
}
/*
* Copyright 2004-2006 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;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class FtpData extends Thread {
private FtpServer server;
private InetAddress address;
private ServerSocket serverSocket;
private volatile Socket socket;
public FtpData(FtpServer server, InetAddress address, ServerSocket serverSocket) throws IOException {
this.server = server;
this.address = address;
this.serverSocket = serverSocket;
}
public void run() {
try {
synchronized(this) {
Socket s = serverSocket.accept();
if(s.getInetAddress().equals(address)) {
server.log("Data connected:" + s.getInetAddress() + " expected:" + address);
socket = s;
notifyAll();
} else {
server.log("Data REJECTED:" + s.getInetAddress() + " expected:" + address);
close();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
private void waitUntilConnected() {
while(serverSocket != null && socket == null) {
try {
wait();
} catch(InterruptedException e) {
// ignore
}
}
server.log("connected");
}
public void close() {
serverSocket = null;
socket = null;
}
public synchronized void receive(FileObject file) throws IOException {
waitUntilConnected();
try {
InputStream in = socket.getInputStream();
file.write(in);
} finally {
socket.close();
}
server.log("closed");
}
public synchronized void send(FileObject file, long skip) throws IOException {
waitUntilConnected();
try {
OutputStream out = socket.getOutputStream();
file.read(skip, out);
} finally {
socket.close();
}
server.log("closed");
}
public synchronized void send(byte[] data) throws IOException {
waitUntilConnected();
try {
OutputStream out = socket.getOutputStream();
out.write(data);
} finally {
socket.close();
}
server.log("closed");
}
}
/*
* Copyright 2004-2006 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.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;
import java.util.Locale;
import org.h2.engine.Constants;
import org.h2.server.Service;
import org.h2.util.MathUtils;
import org.h2.util.NetUtils;
/**
* Small FTP Server. Intended for ad-hoc networks in a secure environment.
* See also http://cr.yp.to/ftp.html http://www.ftpguide.com/
*/
public class FtpServer implements Service {
public static final String DEFAULT_ROOT = "ftp";
public static final String DEFAULT_READ = "guest";
public static final String DEFAULT_WRITE = "sa";
public static final String DEFAULT_WRITE_PASSWORD = "sa";
private ServerSocket serverSocket;
private int port = Constants.DEFAULT_FTP_PORT;
private int openConnectionCount;
private int maxConnectionCount = 100;
private SimpleDateFormat dateFormatNew = new SimpleDateFormat("MMM dd HH:mm", Locale.ENGLISH);
private SimpleDateFormat dateFormatOld = new SimpleDateFormat("MMM dd yyyy", Locale.ENGLISH);
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
private String root = DEFAULT_ROOT;
private String writeUserName = DEFAULT_WRITE, writePassword = DEFAULT_WRITE_PASSWORD;
private String readUserName = DEFAULT_READ;
private FileSystemDatabase db;
private boolean log;
public void listen() {
try {
while (serverSocket != null) {
Socket s = serverSocket.accept();
boolean stop;
synchronized(this) {
openConnectionCount++;
stop = openConnectionCount > maxConnectionCount;
}
FtpControl c = new FtpControl(s, this, stop);
c.start();
}
} catch (Exception e) {
logError(e);
}
}
void closeConnection() {
synchronized(this) {
openConnectionCount--;
}
}
public ServerSocket createDataSocket() throws IOException {
ServerSocket dataSocket = new ServerSocket(0);
return dataSocket;
}
void appendFile(StringBuffer buff, FileObject f) {
buff.append(f.isDirectory() ? 'd' : '-');
buff.append(f.canRead() ? 'r' : '-');
buff.append(f.canWrite() ? 'w' : '-');
buff.append("------- 1 owner group ");
String size = String.valueOf(f.length());
for(int i = size.length(); i < 15; i++) {
buff.append(' ');
}
buff.append(size);
buff.append(' ');
Date now = new Date(), mod = new Date(f.lastModified());
if(mod.after(now) || Math.abs((now.getTime() - mod.getTime())/1000/60/60/24) > 180) {
buff.append(dateFormatOld.format(mod));
} else {
buff.append(dateFormatNew.format(mod));
}
buff.append(' ');
buff.append(f.getName());
buff.append("\r\n");
}
String formatLastModified(FileObject file) {
return dateFormat.format(new Date(file.lastModified()));
}
FileObject getFile(String path) {
if(path.indexOf("..") > 0) {
path = "/";
}
while(path.startsWith("/") && root.endsWith("/")) {
path = path.substring(1);
}
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);
}
}
String getDirectoryListing(FileObject directory, boolean listDirectories) {
FileObject[] list = directory.listFiles();
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);
}
}
return buff.toString();
}
public boolean checkUserPassword(String userName, String param) {
return userName.equals(this.writeUserName) && writePassword.equals(this.writePassword);
}
public boolean checkUserPasswordReadOnly(String userName, String param) {
return userName.equals(this.readUserName);
}
public void init(String[] args) throws Exception {
for(int i=0; args != null && i<args.length; i++) {
if("-ftpPort".equals(args[i])) {
port = MathUtils.decodeInt(args[++i]);
} else if("-ftpDir".equals(args[i])) {
root = args[++i];
} else if("-ftpRead".equals(args[i])) {
readUserName = args[++i];
} else if("-ftpWrite".equals(args[i])) {
writeUserName = args[++i];
} else if("-ftpWritePassword".equals(args[i])) {
writePassword = args[++i];
} else if("-log".equals(args[i])) {
log = Boolean.valueOf(args[++i]).booleanValue();
}
}
if(root.startsWith("jdbc:")) {
org.h2.Driver.load();
Connection conn = DriverManager.getConnection(root);
db = new FileSystemDatabase(conn, log);
root = "/";
}
}
public String getURL() {
return "ftp://localhost:"+port;
}
public void start() throws SQLException {
getFile("").mkdirs();
serverSocket = NetUtils.createServerSocket(port, false);
}
public void stop() {
try {
serverSocket.close();
} catch(IOException e) {
logError(e);
}
serverSocket = null;
}
public boolean isRunning() {
if(serverSocket == null) {
return false;
}
try {
Socket s = NetUtils.createLoopbackSocket(port, false);
s.close();
return true;
} catch(Exception e) {
return false;
}
}
public boolean getAllowOthers() {
return true;
}
public String getType() {
return "FTP";
}
void log(String s) {
if(log) {
System.out.println(s);
}
}
void logError(Throwable e) {
if (log) {
e.printStackTrace();
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import org.h2.engine.Constants;
import org.h2.message.TraceSystem;
import org.h2.util.FileUtils;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils;
public class AppServer {
private static final String[] GENERIC = new String[] {
"Generic Firebird Server|org.firebirdsql.jdbc.FBDriver|jdbc:firebirdsql:localhost:c:/temp/firebird/test|sysdba",
"Generic OneDollarDB|in.co.daffodil.db.jdbc.DaffodilDBDriver|jdbc:daffodilDB_embedded:school;path=C:/temp;create=true|sa",
"Generic DB2|COM.ibm.db2.jdbc.net.DB2Driver|jdbc:db2://<host>/<db>|" ,
"Generic Oracle|oracle.jdbc.driver.OracleDriver|jdbc:oracle:thin:@<host>:1521:<instance>|scott" ,
"Generic PostgreSQL|org.postgresql.Driver|jdbc:postgresql:<db>|" ,
"Generic MS SQL Server|com.microsoft.jdbc.sqlserver.SQLServerDriver|jdbc:Microsoft:sqlserver://localhost:1433;DatabaseName=sqlexpress|sa",
"Generic MS SQL Server 2005|com.microsoft.sqlserver.jdbc.SQLServerDriver|jdbc:sqlserver://localhost;DatabaseName=test|sa",
"Generic MySQL|com.mysql.jdbc.Driver|jdbc:mysql://<host>:<port>/<db>|" ,
"Generic Derby (Embedded)|org.apache.derby.jdbc.EmbeddedDriver|jdbc:derby:test;create=true|sa",
"Generic Derby (Server)|org.apache.derby.jdbc.ClientDriver|jdbc:derby://localhost:1527/test;create=true|sa",
"Generic HSQLDB|org.hsqldb.jdbcDriver|jdbc:hsqldb:test;hsqldb.default_table_type=cached|sa" ,
"Generic H2|org.h2.Driver|jdbc:h2:test|sa",
};
private URLClassLoader urlClassLoader;
private String driverList;
private static int ticker;
private int port;
private boolean allowOthers;
private boolean ssl;
private HashMap connectionInfos = new HashMap();
AppServer(String[] args) {
Properties prop = loadProperties();
driverList = prop.getProperty("drivers");
port = FileUtils.getIntProperty(prop, "webPort", Constants.DEFAULT_HTTP_PORT);
ssl = FileUtils.getBooleanProperty(prop, "webSSL", Constants.DEFAULT_HTTP_SSL);
allowOthers = FileUtils.getBooleanProperty(prop, "webAllowOthers", Constants.DEFAULT_HTTP_ALLOW_OTHERS);
for(int i=0; args != null && i<args.length; i++) {
if("-webPort".equals(args[i])) {
port = MathUtils.decodeInt(args[++i]);
} else if("-webSSL".equals(args[i])) {
ssl = Boolean.valueOf(args[++i]).booleanValue();
} else if("-webAllowOthers".equals(args[i])) {
allowOthers = Boolean.valueOf(args[++i]).booleanValue();
}
}
// TODO gcj: don't load drivers in case of GCJ
if(false) {
if(driverList != null) {
try {
String[] drivers = StringUtils.arraySplit(driverList, ',', false);
URL[] urls = new URL[drivers.length];
for(int i=0; i<drivers.length; i++) {
urls[i] = new URL(drivers[i]);
}
urlClassLoader = URLClassLoader.newInstance(urls);
} catch (MalformedURLException e) {
TraceSystem.traceThrowable(e);
}
}
}
}
void setAllowOthers(boolean b) {
allowOthers = b;
}
void setSSL(boolean b) {
ssl = b;
}
void setPort(int port) {
this.port = port;
}
boolean getAllowOthers() {
return allowOthers;
}
boolean getSSL() {
return ssl;
}
int getPort() {
return port;
}
ConnectionInfo getSetting(String name) {
return (ConnectionInfo)connectionInfos.get(name);
}
void updateSetting(ConnectionInfo info) {
connectionInfos.put(info.name, info);
info.lastAccess = ticker++;
}
void removeSetting(String name) {
connectionInfos.remove(name);
}
private File getPropertiesFile() {
// store the properties in the user directory
return FileUtils.getFileInUserHome(Constants.SERVER_PROPERTIES_FILE);
}
Properties loadProperties() {
File file = getPropertiesFile();
try {
return FileUtils.loadProperties(file);
} catch(IOException e) {
// TODO log exception
return new Properties();
}
}
String[] getSettingNames() {
ArrayList list = getSettings();
String[] names = new String[list.size()];
for(int i=0; i<list.size(); i++) {
names[i] = ((ConnectionInfo)list.get(i)).name;
}
return names;
}
synchronized ArrayList getSettings() {
ArrayList settings = new ArrayList();
if(connectionInfos.size() == 0) {
Properties prop = loadProperties();
if(prop.size() == 0) {
for(int i=0; i<AppServer.GENERIC.length; i++) {
ConnectionInfo info = new ConnectionInfo(AppServer.GENERIC[i]);
settings.add(info);
updateSetting(info);
}
} else {
for(int i=0; ; i++) {
String data = prop.getProperty(String.valueOf(i));
if(data == null) {
break;
}
ConnectionInfo info = new ConnectionInfo(data);
settings.add(info);
updateSetting(info);
}
}
} else {
settings.addAll(connectionInfos.values());
}
sortConnectionInfo(settings);
return settings;
}
void sortConnectionInfo(ArrayList list) {
for (int i = 1, j; i < list.size(); i++) {
ConnectionInfo t = (ConnectionInfo) list.get(i);
for (j = i - 1; j >= 0 && (((ConnectionInfo)list.get(j)).lastAccess < t.lastAccess); j--) {
list.set(j + 1, list.get(j));
}
list.set(j + 1, t);
}
}
synchronized void saveSettings() {
try {
Properties prop = new Properties();
if(driverList != null) {
prop.setProperty("drivers", driverList);
}
prop.setProperty("webPort", String.valueOf(port));
prop.setProperty("webAllowOthers", String.valueOf(allowOthers));
prop.setProperty("webSSL", String.valueOf(ssl));
ArrayList settings = getSettings();
int len = settings.size();
for(int i=0; i<len; i++) {
ConnectionInfo info = (ConnectionInfo) settings.get(i);
if(info != null) {
prop.setProperty(String.valueOf(len - i - 1), info.getString());
}
}
FileOutputStream out = new FileOutputStream(getPropertiesFile());
prop.store(out, Constants.SERVER_PROPERTIES_TITLE);
out.close();
} catch(IOException e) {
TraceSystem.traceThrowable(e);
}
}
// TODO GCJ: if this method is synchronized, then the .exe file fails (probably does not unlock the object)
// and cannot go in here after a class was not found
Connection getConnection(String driver, String url, String user, String password) throws Exception {
driver = driver.trim();
url = url.trim();
user = user.trim();
password = password.trim();
org.h2.Driver.load();
try {
Class.forName(driver);
} catch(ClassNotFoundException e) {
if(urlClassLoader == null) {
throw e;
}
try {
Driver dr = (Driver) urlClassLoader.loadClass(driver).newInstance();
Properties p = new Properties();
p.setProperty("user", user);
p.setProperty("password", password);
return dr.connect(url, p);
} catch(ClassNotFoundException e2) {
throw e2;
}
}
return DriverManager.getConnection(url, user, password);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import org.h2.bnf.Bnf;
import org.h2.message.TraceSystem;
public class AppSession extends WebServerSession {
private static final int MAX_HISTORY = 1000;
private ArrayList commandHistory = new ArrayList();
private Connection conn;
private DatabaseMetaData meta;
private DbContents contents = new DbContents();
private DbContextRule columnRule;
private DbContextRule newAliasRule;
private DbContextRule tableRule;
private DbContextRule aliasRule;
private DbContextRule columnAliasRule;
private Bnf bnf;
Statement executingStatement;
ResultSet result;
AppSession(WebServer server) {
super(server);
}
public Bnf getBnf() {
return bnf;
}
void loadBnf() {
try {
Bnf newBnf = Bnf.getInstance(null);
columnRule = new DbContextRule(contents, DbContextRule.COLUMN);
newAliasRule = new DbContextRule(contents, DbContextRule.NEW_TABLE_ALIAS);
aliasRule = new DbContextRule(contents, DbContextRule.TABLE_ALIAS);
tableRule = new DbContextRule(contents, DbContextRule.TABLE);
columnAliasRule = new DbContextRule(contents, DbContextRule.COLUMN_ALIAS);
// bnf.updateTopic("newTableName", new String[]{"TEST"});
// String[] schemas;
// if(contents.isMySQL) {
// schemas = new String[0];
// } else {
// schemas = new String[contents.schemas.length];
// for(int i=0; i<contents.schemas.length; i++) {
// schemas[i] = contents.schemas[i].quotedName + ".";
// }
// }
// bnf.updateTopic("schemaName", schemas);
newBnf.updateTopic("columnName", columnRule);
newBnf.updateTopic("newTableAlias", newAliasRule);
newBnf.updateTopic("tableAlias", aliasRule);
newBnf.updateTopic("columnAlias", columnAliasRule);
newBnf.updateTopic("tableName", tableRule);
// bnf.updateTopic("name", new String[]{""});
newBnf.linkStatements();
bnf = newBnf;
} catch(Exception e) {
// ok we don't have the bnf
e.printStackTrace();
}
}
String getCommand(int id) {
return (String) commandHistory.get(id);
}
void addCommand(String sql) {
if(sql == null) {
return;
}
sql = sql.trim();
if(sql.length() == 0) {
return;
}
if(commandHistory.size() > MAX_HISTORY) {
commandHistory.remove(0);
}
int idx = commandHistory.indexOf(sql);
if(idx >= 0) {
commandHistory.remove(idx);
}
commandHistory.add(sql);
}
ArrayList getCommands() {
return commandHistory;
}
public HashMap getInfo() {
HashMap m = super.getInfo();
try {
m.put("url", conn == null ? "not connected" : conn.getMetaData().getURL());
m.put("user", conn == null ? "-" : conn.getMetaData().getUserName());
m.put("lastQuery", commandHistory.size()==0 ? "" : commandHistory.get(0));
m.put("executing", executingStatement==null ? "no" : "yes");
} catch (SQLException e) {
TraceSystem.traceThrowable(e);
}
return m;
}
void setConnection(Connection conn) throws SQLException {
this.conn = conn;
if(conn == null) {
meta = null;
} else {
meta = conn.getMetaData();
}
contents = new DbContents();
}
DatabaseMetaData getMetaData() {
return meta;
}
Connection getConnection() {
return conn;
}
public DbContents getContents() {
return contents;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Random;
import org.h2.bnf.Bnf;
import org.h2.tools.SimpleResultSet;
import org.h2.util.MathUtils;
import org.h2.util.MemoryUtils;
import org.h2.util.ObjectArray;
import org.h2.util.ScriptReader;
import org.h2.util.StringUtils;
/**
* @author Thomas
*/
public class AppThread extends WebServerThread {
// TODO web: support online data editing like http://numsum.com/
AppThread(Socket socket, WebServer server) {
super(socket, server);
setName("H2 Console thread");
}
AppSession getAppSession() {
return (AppSession)session;
}
String process(String file) {
server.trace("process " + file);
while(file.endsWith(".do")) {
if(file.equals("login.do")) {
file = login();
} else if(file.equals("index.do")) {
file = index();
} else if(file.equals("logout.do")) {
file = logout();
} else if(file.equals("settingRemove.do")) {
file = settingRemove();
} else if(file.equals("settingSave.do")) {
file = settingSave();
} else if(file.equals("test.do")) {
file = test();
} else if(file.equals("query.do")) {
file = query();
} else if(file.equals("tables.do")) {
file = tables();
} else if(file.equals("editresult.do")) {
file = editResult();
} else if(file.equals("gethistory.do")) {
file = getHistory();
} else if(file.equals("admin.do")) {
file = admin();
} else if(file.equals("adminSave.do")) {
file = adminSave();
} else if(file.equals("adminShutdown.do")) {
file = adminShutdown();
} else if(file.equals("autoCompleteList.do")) {
file = autoCompleteList();
} else {
file = "error.jsp";
}
}
server.trace("return " + file);
return file;
}
private String autoCompleteList() {
String query = (String) attributes.get("query");
boolean lowercase = false;
if(query.trim().length()>0 && Character.isLowerCase(query.trim().charAt(0))) {
lowercase = true;
}
try {
String sql = query;
if(sql.endsWith(";")) {
sql += " ";
}
ScriptReader reader = new ScriptReader(new StringReader(sql));
reader.setSkipRemarks(true);
String lastSql = "";
while(true) {
String n = reader.readStatement();
if(n == null) {
break;
}
lastSql = n;
}
String result = "";
if(reader.isInsideRemark()) {
if(reader.isBlockRemark()) {
result= "1#(End Remark)# */\n" + result;
} else {
result= "1#(Newline)#\n" + result;
}
} else {
sql = lastSql == null ? "" : lastSql;
while(sql.length() > 0 && sql.charAt(0) <= ' ') {
sql = sql.substring(1);
}
if(sql.trim().length()>0 && Character.isLowerCase(sql.trim().charAt(0))) {
lowercase = true;
}
Bnf bnf = getAppSession().getBnf();
if(bnf == null) {
return "autoCompleteList.jsp";
}
HashMap map = bnf.getNextTokenList(sql);
String space = "";
if(sql.length()>0) {
char last = sql.charAt(sql.length()-1);
if(!Character.isWhitespace(last) && (last != '.' && last>=' ' && last != '\'' && last != '"')) {
space = " ";
}
}
ArrayList list = new ArrayList(map.size());
Iterator it = map.keySet().iterator();
while(it.hasNext()) {
String key = (String)it.next();
String type = "" + key.charAt(0);
String value = (String) map.get(key);
key = key.substring(2);
if(Character.isLetter(key.charAt(0)) && lowercase) {
key = StringUtils.toLowerEnglish(key);
value = StringUtils.toLowerEnglish(value);
}
if(key.equals(value) && !value.equals(".")) {
value = space + value;
}
key = StringUtils.urlEncode(key);
key = StringUtils.replaceAll(key, "+", " ");
value = StringUtils.urlEncode(value);
value = StringUtils.replaceAll(value, "+", " ");
list.add(type+"#" + key + "#" + value);
}
Collections.sort(list);
StringBuffer buff = new StringBuffer();
if(query.endsWith("\n") || query.trim().endsWith(";")) {
list.add(0, "1#(Newline)#\n");
}
for(int i=0; i<list.size(); i++) {
if(i>0) {
buff.append('|');
}
buff.append((String) list.get(i));
}
result = buff.toString();
}
session.put("autoCompleteList", result);
} catch(Throwable e) {
e.printStackTrace();
}
return "autoCompleteList.jsp";
}
private String admin() {
AppServer app = server.getAppServer();
session.put("port", ""+app.getPort());
session.put("allowOthers", ""+app.getAllowOthers());
session.put("ssl", String.valueOf(app.getSSL()));
session.put("sessions", server.getSessions());
return "admin.jsp";
}
private String adminSave() {
AppServer app = server.getAppServer();
try {
app.setPort(MathUtils.decodeInt((String)attributes.get("port")));
app.setAllowOthers(Boolean.valueOf((String)attributes.get("allowOthers")).booleanValue());
app.setSSL(Boolean.valueOf((String)attributes.get("ssl")).booleanValue());
app.saveSettings();
} catch(Exception e) {
// TODO ignore error?
}
return admin();
}
private String adminShutdown() {
System.exit(0);
return "admin.jsp";
}
private String index() {
String[][] languageArray = server.getLanguageArray();
String language = (String) attributes.get("language");
Locale locale = session.locale;
if(language != null) {
if(locale == null || !StringUtils.toLowerEnglish(locale.getLanguage()).equals(language)) {
locale = new Locale(language);
server.readTranslations(session, locale.getLanguage());
session.put("language", language);
session.locale = locale;
}
} else {
language = (String) session.get("language");
}
session.put("languageCombo", getCombobox(languageArray, language));
String[] settingNames = server.getAppServer().getSettingNames();
String setting = attributes.getProperty("setting");
if(setting == null && settingNames.length>0) {
setting = settingNames[0];
}
String combobox = getCombobox(settingNames, setting);
session.put("settingsList", combobox);
ConnectionInfo info = server.getAppServer().getSetting(setting);
if(info == null) {
info = new ConnectionInfo();
}
session.put("setting", PageParser.escapeHtml(setting));
session.put("name", PageParser.escapeHtml(setting));
session.put("driver", PageParser.escapeHtml(info.driver));
session.put("url", PageParser.escapeHtml(info.url));
session.put("user", PageParser.escapeHtml(info.user));
return "index.jsp";
}
private String getHistory() {
int id = Integer.parseInt(attributes.getProperty("id"));
String sql = getAppSession().getCommand(id);
session.put("query", PageParser.escapeHtmlNoBreak(sql));
return "query.jsp";
}
private int addColumns(DbTableOrView table, StringBuffer buff, int treeIndex, boolean showColumnTypes, StringBuffer columnsBuffer) throws SQLException {
DbColumn[] columns = table.columns;
for(int i=0; columns != null && i<columns.length; i++) {
DbColumn column = columns[i];
if(columnsBuffer.length()>0) {
columnsBuffer.append(' ');
}
columnsBuffer.append(column.name);
String col = StringUtils.urlEncode(PageParser.escapeJavaScript(column.name));
buff.append("setNode("+treeIndex+", 1, 1, 'column', '" + PageParser.escapeJavaScript(column.name)+ "', 'javascript:ins(\\'"+col+"\\')');\n");
treeIndex++;
if(showColumnTypes) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '" + PageParser.escapeJavaScript(column.dataType)+ "', null);\n");
treeIndex++;
}
}
return treeIndex;
}
private static class IndexInfo {
String name;
String type;
String columns;
}
private int addIndexes(DatabaseMetaData meta, String table, String schema, StringBuffer buff, int treeIndex) throws SQLException {
// index reading is very slow for oracle (2 seconds per index), so don't do it
ResultSet rs = meta.getIndexInfo(null, schema, table, false, false);
HashMap indexMap = new HashMap();
while (rs.next()) {
String name = rs.getString("INDEX_NAME");
IndexInfo info = (IndexInfo) indexMap.get(name);
if (info == null) {
int t = rs.getInt("TYPE");
String type;
if (t == DatabaseMetaData.tableIndexClustered) {
type = "";
} else if (t == DatabaseMetaData.tableIndexHashed) {
type = " (${text.tree.hashed})";
} else if (t == DatabaseMetaData.tableIndexOther) {
type = "";
} else {
type = null;
}
if(name != null && type != null) {
info = new IndexInfo();
info.name = name;
type = (rs.getBoolean("NON_UNIQUE") ? "${text.tree.nonUnique}" : "${text.tree.unique}") + type;
info.type = type;
info.columns = rs.getString("COLUMN_NAME");
indexMap.put(name, info);
}
} else {
info.columns += ", " + rs.getString("COLUMN_NAME");
}
}
if(indexMap.size() > 0) {
buff.append("setNode("+treeIndex+", 1, 1, 'index_az', '${text.tree.indexes}', null);\n");
treeIndex++;
for (Iterator it = indexMap.values().iterator(); it.hasNext();) {
IndexInfo info = (IndexInfo) it.next();
buff.append("setNode("+treeIndex+", 2, 1, 'index', '" + PageParser.escapeJavaScript(info.name)+ "', null);\n");
treeIndex++;
buff.append("setNode("+treeIndex+", 3, 2, 'type', '" + info.type+ "', null);\n");
treeIndex++;
buff.append("setNode("+treeIndex+", 3, 2, 'type', '" + PageParser.escapeJavaScript(info.columns)+ "', null);\n");
treeIndex++;
}
}
return treeIndex;
}
private int addTablesAndViews(DbSchema schema, boolean mainSchema, StringBuffer buff, int treeIndex) throws SQLException {
if(schema == null) {
return treeIndex;
}
AppSession app = getAppSession();
Connection conn = getAppSession().getConnection();
DatabaseMetaData meta = app.getMetaData();
int level = mainSchema ? 0 : 1;
String ident = ", "+level+", "+(level+1)+", ";
String identNode = ", "+(level+1)+", "+(level+1)+", ";
DbTableOrView[] tables = schema.tables;
boolean isOracle = schema.contents.isOracle;
boolean showColumnTypes = tables.length < 100;
for(int i=0; i<tables.length; i++) {
DbTableOrView table = tables[i];
if(table.isView) {
continue;
}
int tableId = treeIndex;
String tab = table.quotedName;
if(!mainSchema) {
tab =schema.quotedName + "." + tab;
}
tab = StringUtils.urlEncode(PageParser.escapeJavaScript(tab));
buff.append("setNode("+treeIndex+ident+" 'table', '" + PageParser.escapeJavaScript(table.name)+ "', 'javascript:ins(\\'"+tab+"\\',true)');\n");
treeIndex++;
if(mainSchema) {
StringBuffer columnsBuffer = new StringBuffer();
treeIndex = addColumns(table, buff, treeIndex, showColumnTypes, columnsBuffer);
if(!isOracle) {
treeIndex = addIndexes(meta, table.name, schema.name, buff, treeIndex);
}
buff.append("addTable('"+PageParser.escapeJavaScript(table.name)+"', '"+PageParser.escapeJavaScript(columnsBuffer.toString())+"', "+tableId+");\n");
}
}
tables = schema.tables;
for(int i=0; i<tables.length; i++) {
DbTableOrView view = tables[i];
if(!view.isView) {
continue;
}
int tableId = treeIndex;
String tab = view.quotedName;
if(!mainSchema) {
tab = view.schema.quotedName + "." + tab;
}
tab = StringUtils.urlEncode(PageParser.escapeJavaScript(tab));
buff.append("setNode("+treeIndex+ident+" 'view', '" + PageParser.escapeJavaScript(view.name)+ "', 'javascript:ins(\\'"+tab+"\\',true)');\n");
treeIndex++;
if(mainSchema) {
StringBuffer columnsBuffer = new StringBuffer();
treeIndex = addColumns(view, buff, treeIndex, showColumnTypes, columnsBuffer);
if(schema.contents.isH2) {
PreparedStatement prep = conn.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?");
prep.setString(1, view.name);
ResultSet rs = prep.executeQuery();
if(rs.next()) {
String sql = rs.getString("SQL");
buff.append("setNode("+treeIndex+ identNode + " 'type', '" + PageParser.escapeJavaScript(sql)+ "', null);\n");
treeIndex++;
}
}
buff.append("addTable('"+PageParser.escapeJavaScript(view.name)+"', '"+PageParser.escapeJavaScript(columnsBuffer.toString())+"', "+tableId+");\n");
}
}
return treeIndex;
}
private String tables() {
AppSession app = getAppSession();
DbContents contents = app.getContents();
try {
contents.readContents(app.getMetaData());
app.loadBnf();
Connection conn = app.getConnection();
DatabaseMetaData meta = app.getMetaData();
boolean isH2 = contents.isH2;
StringBuffer buff = new StringBuffer();
buff.append("setNode(0, 0, 0, 'database', '" + PageParser.escapeJavaScript((String)session.get("url"))+ "', null);\n");
// String version = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion();
// buff.append("setNode(1, 0, 0, 'info', '" + PageParser.escapeJavaScript(version)+ "', null);\n");
//
// int treeIndex = 2;
int treeIndex = 1;
DbSchema defaultSchema = contents.defaultSchema;
treeIndex = addTablesAndViews(defaultSchema, true, buff, treeIndex);
DbSchema[] schemas = contents.schemas;
for(int i=0; i<schemas.length; i++) {
DbSchema schema = schemas[i];
if(schema == defaultSchema || schema == null) {
continue;
}
buff.append("setNode("+treeIndex+", 0, 1, 'folder', '" + PageParser.escapeJavaScript(schema.name)+ "', null);\n");
treeIndex++;
treeIndex = addTablesAndViews(schema, false, buff, treeIndex);
}
if(isH2) {
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA.SEQUENCES ORDER BY SEQUENCE_NAME");
for(int i=0; rs.next(); i++) {
if(i==0) {
buff.append("setNode("+treeIndex+", 0, 1, 'sequences', '${text.tree.sequences}', null);\n");
treeIndex++;
}
String name = rs.getString("SEQUENCE_NAME");
String current = rs.getString("CURRENT_VALUE");
String increment = rs.getString("INCREMENT");
buff.append("setNode("+treeIndex+", 1, 1, 'sequence', '" + PageParser.escapeJavaScript(name)+ "', null);\n");
treeIndex++;
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.current}: " + PageParser.escapeJavaScript(current)+ "', null);\n");
treeIndex++;
if(!increment.equals("1")) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.increment}: " + PageParser.escapeJavaScript(increment)+ "', null);\n");
treeIndex++;
}
}
rs = conn.createStatement().executeQuery("SELECT * FROM INFORMATION_SCHEMA.USERS ORDER BY NAME");
for(int i=0; rs.next(); i++) {
if(i==0) {
buff.append("setNode("+treeIndex+", 0, 1, 'users', '${text.tree.users}', null);\n");
treeIndex++;
}
String name = rs.getString("NAME");
String admin = rs.getString("ADMIN");
buff.append("setNode("+treeIndex+", 1, 1, 'user', '" + PageParser.escapeJavaScript(name)+ "', null);\n");
treeIndex++;
if(admin.equalsIgnoreCase("TRUE")) {
buff.append("setNode("+treeIndex+", 2, 2, 'type', '${text.tree.admin}', null);\n");
treeIndex++;
}
}
}
String version = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion();
buff.append("setNode("+treeIndex+", 0, 0, 'info', '" + PageParser.escapeJavaScript(version)+ "', null);\n");
buff.append("refreshQueryTables();");
session.put("tree", buff.toString());
} catch(Exception e) {
// TODO log error
session.put("tree", "");
session.put("error", getStackTrace(0, e));
}
return "tables.jsp";
}
private String getStackTrace(int id, Throwable e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String s = writer.toString();
s = PageParser.escapeHtml(s);
s = StringUtils.replaceAll(s, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
String message = PageParser.escapeHtml(e.getMessage());
s = "<a class=\"error\" href=\"#\" onclick=\"var x=document.getElementById('st"+id+"').style;x.display=x.display==''?'none':'';\">" + message + "</a><span style=\"display: none;\" id=\"st"+id+"\"><br>"+ s + "</span>";
s = formatAsError(s);
return s;
}
private String formatAsError(String s) {
return "<div class=\"error\">"+s+"</div>";
}
private String test() {
String driver = attributes.getProperty("driver", "");
String url = attributes.getProperty("url", "");
String user = attributes.getProperty("user", "");
String password = attributes.getProperty("password", "");
session.put("driver", driver);
session.put("url", url);
session.put("user", user);
try {
Connection conn = server.getAppServer().getConnection(driver, url, user, password);
try {
conn.close();
} catch(SQLException e2) {
// TODO log error
}
session.put("error", "${text.login.testSuccessful}");
return "index.jsp";
} catch(Exception e) {
session.put("error", getLoginError(e));
return "index.jsp";
}
}
private String getLoginError(Exception e) {
if(e instanceof ClassNotFoundException) {
return "${text.login.driverNotFound}<br>" + getStackTrace(0, e);
} else {
return getStackTrace(0, e);
}
}
private String login() {
String driver = attributes.getProperty("driver", "");
String url = attributes.getProperty("url", "");
String user = attributes.getProperty("user", "");
String password = attributes.getProperty("password", "");
try {
Connection conn = server.getAppServer().getConnection(driver, url, user, password);
AppSession appSession = getAppSession();
appSession.setConnection(conn);
session.put("url", url);
session.put("user", user);
session.put("autocommit", "checked");
session.put("autocomplete", "1");
session.put("maxrows", "1000");
session.remove("error");
settingSave();
return "frame.jsp";
} catch(Exception e) {
session.put("error", getLoginError(e));
return "index.jsp";
}
}
private String logout() {
try {
Connection conn = getAppSession().getConnection();
getAppSession().setConnection(null);
session.remove("conn");
session.remove("result");
session.remove("tables");
session.remove("user");
if(conn != null) {
conn.close();
}
} catch(Exception e) {
// TODO log error
}
return "index.do";
}
private String query() {
String sql = attributes.getProperty("sql").trim();
try {
Connection conn = getAppSession().getConnection();
String result;
if(sql.equals("@AUTOCOMMIT TRUE")) {
conn.setAutoCommit(true);
result = "${text.result.autocommitOn}";
} else if(sql.equals("@AUTOCOMMIT FALSE")) {
conn.setAutoCommit(false);
result = "${text.result.autocommitOff}";
} else if(sql.startsWith("@TRANSACTION_ISOLATION")) {
String s = sql.substring("@TRANSACTION_ISOLATION".length()).trim();
if(s.length()>0) {
int level = Integer.parseInt(s);
conn.setTransactionIsolation(level);
}
result = "Transaction Isolation: " + conn.getTransactionIsolation() + "<br />";
result += Connection.TRANSACTION_READ_UNCOMMITTED + ": READ_UNCOMMITTED<br />";
result += Connection.TRANSACTION_READ_COMMITTED + ": READ_COMMITTED<br />";
result += Connection.TRANSACTION_REPEATABLE_READ + ": REPEATABLE_READ<br />";
result += Connection.TRANSACTION_SERIALIZABLE + ": SERIALIZABLE";
} else if(sql.startsWith("@SET MAXROWS ")) {
int maxrows = Integer.parseInt(sql.substring("@SET MAXROWS ".length()));
session.put("maxrows", ""+maxrows);
result = "${text.result.maxrowsSet}";
} else {
ScriptReader r = new ScriptReader(new StringReader(sql));
ObjectArray list = new ObjectArray();
while(true) {
String s = r.readStatement();
if(s == null) {
break;
}
list.add(s);
}
StringBuffer buff = new StringBuffer();
for(int i=0; i<list.size(); i++) {
String s = (String) list.get(i);
if(!s.startsWith("@")) {
buff.append(PageParser.escapeHtml(s+";"));
buff.append("<br />");
}
buff.append(getResult(conn, i+1, s, list.size()==1));
buff.append("<br />");
}
result = buff.toString();
}
session.put("result", result);
} catch(Throwable e) {
session.put("result", getStackTrace(0, e));
}
return "result.jsp";
}
private String editResult() {
ResultSet rs = getAppSession().result;
int row = Integer.parseInt(attributes.getProperty("row"));
int op = Integer.parseInt(attributes.getProperty("op"));
String result = "", error="";
try {
if(op==1) {
boolean insert = row < 0;
if(insert) {
rs.moveToInsertRow();
} else {
rs.absolute(row);
}
for(int i=0; i<rs.getMetaData().getColumnCount(); i++) {
String x = attributes.getProperty("r"+row+"c"+(i+1));
rs.updateString(i+1, x);
}
if(insert) {
rs.insertRow();
} else {
rs.updateRow();
}
} else if(op==2) {
rs.absolute(row);
rs.deleteRow();
} else if(op==3) {
// cancel
}
} catch(Throwable e) {
result = "<br>"+getStackTrace(0, e);
error = formatAsError(e.getMessage());
}
String sql = "@EDIT " + (String) session.get("resultsetSQL");
Connection conn = getAppSession().getConnection();
result = error + getResult(conn, -1, sql, true) + result;
session.put("result", result);
return "result.jsp";
}
private ResultSet getMetaResultSet(Connection conn, String sql) throws SQLException {
DatabaseMetaData meta = conn.getMetaData();
if(sql.startsWith("@TABLES")) {
String[] p = split(sql);
String[] types = p[4] == null ? null : StringUtils.arraySplit(p[4], ',', false);
return meta.getTables(p[1], p[2], p[3], types);
} else if(sql.startsWith("@COLUMNS")) {
String[] p = split(sql);
return meta.getColumns(p[1], p[2], p[3], p[4]);
} else if(sql.startsWith("@INDEX_INFO")) {
String[] p = split(sql);
boolean unique = p[4] == null ? false : Boolean.valueOf(p[4]).booleanValue();
boolean approx = p[5] == null ? false : Boolean.valueOf(p[5]).booleanValue();
return meta.getIndexInfo(p[1], p[2], p[3], unique, approx);
} else if(sql.startsWith("@PRIMARY_KEYS")) {
String[] p = split(sql);
return meta.getPrimaryKeys(p[1], p[2], p[3]);
} else if(sql.startsWith("@PROCEDURES")) {
String[] p = split(sql);
return meta.getProcedures(p[1], p[2], p[3]);
} else if(sql.startsWith("@PROCEDURE_COLUMNS")) {
String[] p = split(sql);
return meta.getProcedureColumns(p[1], p[2], p[3], p[4]);
} else if(sql.startsWith("@SCHEMAS")) {
return meta.getSchemas();
} else if(sql.startsWith("@CATALOG")) {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("CATALOG", Types.VARCHAR, 0, 0);
rs.addRow(new String[]{conn.getCatalog()});
return rs;
} else if(sql.startsWith("@MEMORY")) {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("Type", Types.VARCHAR, 0, 0);
rs.addColumn("Value", Types.VARCHAR, 0, 0);
rs.addRow(new String[]{"Used Memory", "" + MemoryUtils.getMemoryUsed()});
rs.addRow(new String[]{"Free Memory", "" + MemoryUtils.getMemoryFree()});
return rs;
} else if(sql.startsWith("@INFO")) {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("KEY", Types.VARCHAR, 0, 0);
rs.addColumn("VALUE", Types.VARCHAR, 0, 0);
rs.addRow(new String[]{"conn.getCatalog", conn.getCatalog()});
rs.addRow(new String[]{"conn.getAutoCommit", ""+conn.getAutoCommit()});
rs.addRow(new String[]{"conn.getHoldability", ""+conn.getHoldability()});
rs.addRow(new String[]{"conn.getTransactionIsolation", ""+conn.getTransactionIsolation()});
rs.addRow(new String[]{"conn.getWarnings", ""+conn.getWarnings()});
String map;
try {
map = "" + conn.getTypeMap();
} catch(SQLException e) {
map = e.toString();
}
rs.addRow(new String[]{"conn.getTypeMap", ""+map});
rs.addRow(new String[]{"conn.isReadOnly", ""+conn.isReadOnly()});
rs.addRow(new String[]{"meta.getCatalogSeparator", ""+meta.getCatalogSeparator()});
rs.addRow(new String[]{"meta.getCatalogTerm", ""+meta.getCatalogTerm()});
rs.addRow(new String[]{"meta.getDatabaseMajorVersion", ""+meta.getDatabaseMajorVersion()});
rs.addRow(new String[]{"meta.getDatabaseMinorVersion", ""+meta.getDatabaseMinorVersion()});
rs.addRow(new String[]{"meta.getDatabaseProductName", ""+meta.getDatabaseProductName()});
rs.addRow(new String[]{"meta.getDatabaseProductVersion", ""+meta.getDatabaseProductVersion()});
rs.addRow(new String[]{"meta.getDefaultTransactionIsolation", ""+meta.getDefaultTransactionIsolation()});
rs.addRow(new String[]{"meta.getDriverMajorVersion", ""+meta.getDriverMajorVersion()});
rs.addRow(new String[]{"meta.getDriverMinorVersion", ""+meta.getDriverMinorVersion()});
rs.addRow(new String[]{"meta.getDriverName", ""+meta.getDriverName()});
rs.addRow(new String[]{"meta.getDriverVersion", ""+meta.getDriverVersion()});
rs.addRow(new String[]{"meta.getExtraNameCharacters", ""+meta.getExtraNameCharacters()});
rs.addRow(new String[]{"meta.getIdentifierQuoteString", ""+meta.getIdentifierQuoteString()});
rs.addRow(new String[]{"meta.getJDBCMajorVersion", ""+meta.getJDBCMajorVersion()});
rs.addRow(new String[]{"meta.getJDBCMinorVersion", ""+meta.getJDBCMinorVersion()});
rs.addRow(new String[]{"meta.getMaxBinaryLiteralLength", ""+meta.getMaxBinaryLiteralLength()});
rs.addRow(new String[]{"meta.getMaxCatalogNameLength", ""+meta.getMaxCatalogNameLength()});
rs.addRow(new String[]{"meta.getMaxCharLiteralLength", ""+meta.getMaxCharLiteralLength()});
rs.addRow(new String[]{"meta.getMaxColumnNameLength", ""+meta.getMaxColumnNameLength()});
rs.addRow(new String[]{"meta.getMaxColumnsInGroupBy", ""+meta.getMaxColumnsInGroupBy()});
rs.addRow(new String[]{"meta.getMaxColumnsInIndex", ""+meta.getMaxColumnsInIndex()});
rs.addRow(new String[]{"meta.getMaxColumnsInOrderBy", ""+meta.getMaxColumnsInOrderBy()});
rs.addRow(new String[]{"meta.getMaxColumnsInSelect", ""+meta.getMaxColumnsInSelect()});
rs.addRow(new String[]{"meta.getMaxColumnsInTable", ""+meta.getMaxColumnsInTable()});
rs.addRow(new String[]{"meta.getMaxConnections", ""+meta.getMaxConnections()});
rs.addRow(new String[]{"meta.getMaxCursorNameLength", ""+meta.getMaxCursorNameLength()});
rs.addRow(new String[]{"meta.getMaxIndexLength", ""+meta.getMaxIndexLength()});
rs.addRow(new String[]{"meta.getMaxProcedureNameLength", ""+meta.getMaxProcedureNameLength()});
rs.addRow(new String[]{"meta.getMaxRowSize", ""+meta.getMaxRowSize()});
rs.addRow(new String[]{"meta.getMaxSchemaNameLength", ""+meta.getMaxSchemaNameLength()});
rs.addRow(new String[]{"meta.getMaxStatementLength", ""+meta.getMaxStatementLength()});
rs.addRow(new String[]{"meta.getMaxStatements", ""+meta.getMaxStatements()});
rs.addRow(new String[]{"meta.getMaxTableNameLength", ""+meta.getMaxTableNameLength()});
rs.addRow(new String[]{"meta.getMaxTablesInSelect", ""+meta.getMaxTablesInSelect()});
rs.addRow(new String[]{"meta.getMaxUserNameLength", ""+meta.getMaxUserNameLength()});
rs.addRow(new String[]{"meta.getNumericFunctions", ""+meta.getNumericFunctions()});
rs.addRow(new String[]{"meta.getProcedureTerm", ""+meta.getProcedureTerm()});
rs.addRow(new String[]{"meta.getResultSetHoldability", ""+meta.getResultSetHoldability()});
rs.addRow(new String[]{"meta.getSchemaTerm", ""+meta.getSchemaTerm()});
rs.addRow(new String[]{"meta.getSearchStringEscape", ""+meta.getSearchStringEscape()});
rs.addRow(new String[]{"meta.getSQLKeywords", ""+meta.getSQLKeywords()});
rs.addRow(new String[]{"meta.getSQLStateType", ""+meta.getSQLStateType()});
rs.addRow(new String[]{"meta.getStringFunctions", ""+meta.getStringFunctions()});
rs.addRow(new String[]{"meta.getSystemFunctions", ""+meta.getSystemFunctions()});
rs.addRow(new String[]{"meta.getTimeDateFunctions", ""+meta.getTimeDateFunctions()});
rs.addRow(new String[]{"meta.getURL", ""+meta.getURL()});
rs.addRow(new String[]{"meta.getUserName", ""+meta.getUserName()});
rs.addRow(new String[]{"meta.isCatalogAtStart", ""+meta.isCatalogAtStart()});
rs.addRow(new String[]{"meta.isReadOnly", ""+meta.isReadOnly()});
rs.addRow(new String[]{"meta.allProceduresAreCallable", ""+meta.allProceduresAreCallable()});
rs.addRow(new String[]{"meta.allTablesAreSelectable", ""+meta.allTablesAreSelectable()});
rs.addRow(new String[]{"meta.dataDefinitionCausesTransactionCommit", ""+meta.dataDefinitionCausesTransactionCommit()});
rs.addRow(new String[]{"meta.dataDefinitionIgnoredInTransactions", ""+meta.dataDefinitionIgnoredInTransactions()});
rs.addRow(new String[]{"meta.doesMaxRowSizeIncludeBlobs", ""+meta.doesMaxRowSizeIncludeBlobs()});
rs.addRow(new String[]{"meta.locatorsUpdateCopy", ""+meta.locatorsUpdateCopy()});
rs.addRow(new String[]{"meta.nullPlusNonNullIsNull", ""+meta.nullPlusNonNullIsNull()});
rs.addRow(new String[]{"meta.nullsAreSortedAtEnd", ""+meta.nullsAreSortedAtEnd()});
rs.addRow(new String[]{"meta.nullsAreSortedAtStart", ""+meta.nullsAreSortedAtStart()});
rs.addRow(new String[]{"meta.nullsAreSortedHigh", ""+meta.nullsAreSortedHigh()});
rs.addRow(new String[]{"meta.nullsAreSortedLow", ""+meta.nullsAreSortedLow()});
rs.addRow(new String[]{"meta.storesLowerCaseIdentifiers", ""+meta.storesLowerCaseIdentifiers()});
rs.addRow(new String[]{"meta.storesLowerCaseQuotedIdentifiers", ""+meta.storesLowerCaseQuotedIdentifiers()});
rs.addRow(new String[]{"meta.storesMixedCaseIdentifiers", ""+meta.storesMixedCaseIdentifiers()});
rs.addRow(new String[]{"meta.storesMixedCaseQuotedIdentifiers", ""+meta.storesMixedCaseQuotedIdentifiers()});
rs.addRow(new String[]{"meta.storesUpperCaseIdentifiers", ""+meta.storesUpperCaseIdentifiers()});
rs.addRow(new String[]{"meta.storesUpperCaseQuotedIdentifiers", ""+meta.storesUpperCaseQuotedIdentifiers()});
rs.addRow(new String[]{"meta.supportsAlterTableWithAddColumn", ""+meta.supportsAlterTableWithAddColumn()});
rs.addRow(new String[]{"meta.supportsAlterTableWithDropColumn", ""+meta.supportsAlterTableWithDropColumn()});
rs.addRow(new String[]{"meta.supportsANSI92EntryLevelSQL", ""+meta.supportsANSI92EntryLevelSQL()});
rs.addRow(new String[]{"meta.supportsANSI92FullSQL", ""+meta.supportsANSI92FullSQL()});
rs.addRow(new String[]{"meta.supportsANSI92IntermediateSQL", ""+meta.supportsANSI92IntermediateSQL()});
rs.addRow(new String[]{"meta.supportsBatchUpdates", ""+meta.supportsBatchUpdates()});
rs.addRow(new String[]{"meta.supportsCatalogsInDataManipulation", ""+meta.supportsCatalogsInDataManipulation()});
rs.addRow(new String[]{"meta.supportsCatalogsInIndexDefinitions", ""+meta.supportsCatalogsInIndexDefinitions()});
rs.addRow(new String[]{"meta.supportsCatalogsInPrivilegeDefinitions", ""+meta.supportsCatalogsInPrivilegeDefinitions()});
rs.addRow(new String[]{"meta.supportsCatalogsInProcedureCalls", ""+meta.supportsCatalogsInProcedureCalls()});
rs.addRow(new String[]{"meta.supportsCatalogsInTableDefinitions", ""+meta.supportsCatalogsInTableDefinitions()});
rs.addRow(new String[]{"meta.supportsColumnAliasing", ""+meta.supportsColumnAliasing()});
rs.addRow(new String[]{"meta.supportsConvert", ""+meta.supportsConvert()});
rs.addRow(new String[]{"meta.supportsCoreSQLGrammar", ""+meta.supportsCoreSQLGrammar()});
rs.addRow(new String[]{"meta.supportsCorrelatedSubqueries", ""+meta.supportsCorrelatedSubqueries()});
rs.addRow(new String[]{"meta.supportsDataDefinitionAndDataManipulationTransactions", ""+meta.supportsDataDefinitionAndDataManipulationTransactions()});
rs.addRow(new String[]{"meta.supportsDataManipulationTransactionsOnly", ""+meta.supportsDataManipulationTransactionsOnly()});
rs.addRow(new String[]{"meta.supportsDifferentTableCorrelationNames", ""+meta.supportsDifferentTableCorrelationNames()});
rs.addRow(new String[]{"meta.supportsExpressionsInOrderBy", ""+meta.supportsExpressionsInOrderBy()});
rs.addRow(new String[]{"meta.supportsExtendedSQLGrammar", ""+meta.supportsExtendedSQLGrammar()});
rs.addRow(new String[]{"meta.supportsFullOuterJoins", ""+meta.supportsFullOuterJoins()});
rs.addRow(new String[]{"meta.supportsGetGeneratedKeys", ""+meta.supportsGetGeneratedKeys()});
rs.addRow(new String[]{"meta.supportsGroupBy", ""+meta.supportsGroupBy()});
// TODO meta data: more supports methods (I'm tired now)
rs.addRow(new String[]{"meta.usesLocalFilePerTable", ""+meta.usesLocalFilePerTable()});
rs.addRow(new String[]{"meta.usesLocalFiles", ""+meta.usesLocalFiles()});
return rs;
} else if(sql.startsWith("@CATALOGS")) {
return meta.getCatalogs();
} else if(sql.startsWith("@TABLE_TYPES")) {
return meta.getTableTypes();
} else if(sql.startsWith("@COLUMN_PRIVILEGES")) {
String[] p = split(sql);
return meta.getColumnPrivileges(p[1], p[2], p[3], p[4]);
} else if(sql.startsWith("@TABLE_PRIVILEGES")) {
String[] p = split(sql);
return meta.getTablePrivileges(p[1], p[2], p[3]);
} else if(sql.startsWith("@BEST_ROW_IDENTIFIER")) {
String[] p = split(sql);
int scale = p[4] == null ? 0 : Integer.parseInt(p[4]);
boolean nullable = p[5] == null ? false : Boolean.valueOf(p[5]).booleanValue();
return meta.getBestRowIdentifier(p[1], p[2], p[3], scale, nullable);
} else if(sql.startsWith("@VERSION_COLUMNS")) {
String[] p = split(sql);
return meta.getVersionColumns(p[1], p[2], p[3]);
} else if(sql.startsWith("@IMPORTED_KEYS")) {
String[] p = split(sql);
return meta.getImportedKeys(p[1], p[2], p[3]);
} else if(sql.startsWith("@EXPORTED_KEYS")) {
String[] p = split(sql);
return meta.getExportedKeys(p[1], p[2], p[3]);
} else if(sql.startsWith("@CROSS_REFERENCE")) {
String[] p = split(sql);
return meta.getCrossReference(p[1], p[2], p[3], p[4], p[5], p[6]);
} else if(sql.startsWith("@UDTS")) {
String[] p = split(sql);
int[] types;
if(p[4] == null) {
types = null;
} else {
String[] t = StringUtils.arraySplit(p[4], ',', false);
types = new int[t.length];
for(int i=0; i<t.length; i++) {
types[i] = Integer.parseInt(t[i]);
}
}
return meta.getUDTs(p[1], p[2], p[3], types);
} else if(sql.startsWith("@TYPE_INFO")) {
return meta.getTypeInfo();
} else if(sql.startsWith("@SUPER_TYPES")) {
String[] p = split(sql);
return meta.getSuperTypes(p[1], p[2], p[3]);
} else if(sql.startsWith("@SUPER_TABLES")) {
String[] p = split(sql);
return meta.getSuperTables(p[1], p[2], p[3]);
} else if(sql.startsWith("@ATTRIBUTES")) {
String[] p = split(sql);
return meta.getAttributes(p[1], p[2], p[3], p[4]);
}
return null;
}
private String[] split(String s) {
String[] list = new String[10];
String[] t = StringUtils.arraySplit(s, ' ', true);
System.arraycopy(t, 0, list, 0, t.length);
for(int i=0; i<list.length; i++) {
if("null".equals(list[i])) {
list[i] = null;
}
}
return list;
}
private int getMaxrows() {
String r = (String)session.get("maxrows");
int maxrows = r==null ? 0 : Integer.parseInt(r);
return maxrows;
}
private String getResult(Connection conn, int id, String sql, boolean allowEdit) {
try {
sql = sql.trim();
StringBuffer buff = new StringBuffer();
String sqlUpper = StringUtils.toUpperEnglish(sql);
if(sqlUpper.startsWith("CREATE") || sqlUpper.startsWith("DROP") || sqlUpper.startsWith("ALTER") || sqlUpper.startsWith("RUNSCRIPT")) {
String sessionId = attributes.getProperty("jsessionid");
buff.append("<script type=\"text/javascript\">top['h2menu'].location='tables.do?jsessionid="+sessionId+"';</script>");
}
Statement stat = conn.createStatement();
ResultSet rs;
long time = System.currentTimeMillis();
boolean metadata = false;
boolean edit = false;
if(sql.equals("@CANCEL")) {
stat = getAppSession().executingStatement;
if(stat != null) {
stat.cancel();
buff.append("${text.result.statementWasCancelled}");
} else {
buff.append("${text.result.noRunningStatement}");
}
return buff.toString();
} else if(sql.startsWith("@META")) {
metadata = true;
sql = sql.substring("@META".length()).trim();
} else if(sql.startsWith("@LOOP")) {
metadata = true;
sql = sql.substring("@LOOP".length()).trim();
int idx = sql.indexOf(' ');
int count = MathUtils.decodeInt(sql.substring(0, idx));
sql = sql.substring(idx).trim();
return executeLoop(conn, count, sql);
} else if(sql.startsWith("@EDIT")) {
edit = true;
sql = sql.substring("@EDIT".length()).trim();
session.put("resultsetSQL", sql);
} else if(sql.equals("@HISTORY")) {
buff.append(getHistoryString());
return buff.toString();
}
if(sql.startsWith("@")) {
rs = getMetaResultSet(conn, sql);
if(rs == null) {
buff.append("?: "+sql);
return buff.toString();
}
} else {
int maxrows = getMaxrows();
stat.setMaxRows(maxrows);
getAppSession().executingStatement = stat;
boolean isResultSet = stat.execute(sql);
getAppSession().addCommand(sql);
if(!isResultSet) {
buff.append("${text.result.updateCount}: "+stat.getUpdateCount());
time = System.currentTimeMillis() - time;
buff.append("<br>(");
buff.append(time);
buff.append(" ms)");
stat.close();
return buff.toString();
}
rs = stat.getResultSet();
}
time = System.currentTimeMillis() - time;
buff.append(getResultSet(sql, rs, metadata, edit, time, allowEdit));
if(!edit) {
stat.close();
}
return buff.toString();
} catch(Exception e) {
return getStackTrace(id, e);
} finally {
getAppSession().executingStatement = null;
}
}
private String executeLoop(Connection conn, int count, String sql) throws SQLException {
ArrayList params = new ArrayList();
int idx = 0;
while(true) {
idx = sql.indexOf('?', idx);
if(idx < 0) {
break;
}
if(sql.substring(idx).startsWith("?/*RND*/")) {
params.add(new Integer(1));
sql = sql.substring(0, idx) + "?" + sql.substring(idx+"/*RND*/".length()+1);
} else {
params.add(new Integer(0));
}
idx++;
}
int rows = 0;
boolean prepared;
Random random = new Random(1);
long time = System.currentTimeMillis();
if(sql.startsWith("@STATEMENT")) {
sql = sql.substring("@STATEMENT".length()).trim();
prepared = false;
Statement stat = conn.createStatement();
for(int i=0; i<count; i++) {
String s = sql;
for(int j=0; j<params.size(); j++) {
idx = s.indexOf('?');
Integer type = (Integer) params.get(j);
if(type.intValue() == 1) {
s = s.substring(0, idx) + random.nextInt(count) + s.substring(idx+1);
} else {
s = s.substring(0, idx) + i + s.substring(idx+1);
}
}
if(stat.execute(s)) {
ResultSet rs = stat.getResultSet();
while(rs.next()) {
rows++;
// maybe get the data as well
}
// maybe close result set
}
}
} else {
prepared = true;
PreparedStatement prep = conn.prepareStatement(sql);
for(int i=0; i<count; i++) {
for(int j=0; j<params.size(); j++) {
Integer type = (Integer) params.get(j);
if(type.intValue() == 1) {
prep.setInt(j + 1, random.nextInt(count));
} else {
prep.setInt(j + 1, i);
}
}
if(getAppSession().getContents().isSQLite) {
// SQLite currently throws an exception on prep.execute()
prep.executeUpdate();
} else {
if(prep.execute()) {
ResultSet rs = prep.getResultSet();
while(rs.next()) {
rows++;
// maybe get the data as well
}
}
}
}
}
time = System.currentTimeMillis() - time;
String result = time + " ms: " + count + " * ";
if(prepared) {
result += "(Prepared) ";
} else {
result += "(Statement) ";
}
result+="(";
for(int i=0; i<params.size(); i++) {
if(i>0) {
result+=", ";
}
result += ((Integer)params.get(i)).intValue() == 0 ? "i" : "rnd";
}
result+=") " + sql;
return result;
}
private String getHistoryString() {
StringBuffer buff = new StringBuffer();
ArrayList history = getAppSession().getCommands();
buff.append("<table cellspacing=0 cellpadding=0>");
buff.append("<tr><th></th><th>Command</th></tr>");
for(int i=history.size()-1; i>=0; i--) {
String sql = (String) history.get(i);
buff.append("<tr><td>");
buff.append("<a href=\"gethistory.do?id=");
buff.append(i);
buff.append("&jsessionid=${sessionId}\" target=\"h2query\" ><img width=16 height=16 src=\"ico_write.gif\" onmouseover = \"this.className ='icon_hover'\" onmouseout = \"this.className ='icon'\" class=\"icon\" alt=\"${text.resultEdit.edit}\" title=\"${text.resultEdit.edit}\" border=\"1\"></a>");
buff.append("</td><td>");
buff.append(PageParser.escapeHtml(sql));
buff.append("</td></tr>");
}
buff.append("</t>");
buff.append("</table>");
return buff.toString();
}
private String getResultSet(String sql, ResultSet rs, boolean metadata, boolean edit, long time, boolean allowEdit) throws SQLException {
int maxrows = getMaxrows();
time = System.currentTimeMillis() - time;
StringBuffer buff = new StringBuffer();
if(edit) {
buff.append("<form id=\"editing\" name=\"editing\" method=\"post\" "
+ "action=\"/editresult.do?jsessionid=${sessionId}\" id=\"mainForm\" target=\"h2result\">");
buff.append("<input type=\"hidden\" name=\"op\" value=\"1\">");
buff.append("<input type=\"hidden\" name=\"row\" value=\"\">");
buff.append("<table cellspacing=0 cellpadding=0 id=\"editTable\">");
} else {
buff.append("<table cellspacing=0 cellpadding=0>");
}
ResultSetMetaData meta = rs.getMetaData();
int columns = meta.getColumnCount();
int rows=0;
if(metadata) {
buff.append("<tr><th>i</th><th>label</th><th>cat</th><th>schem</th>");
buff.append("<th>tab</th><th>col</th><th>type</th><th>typeName</th><th>class</th>");
buff.append("<th>prec</th><th>scale</th><th>size</th><th>autoInc</th>");
buff.append("<th>case</th><th>curr</th><th>null</th><th>ro</th>");
buff.append("<th>search</th><th>sig</th><th>w</th><th>defW</th></tr>");
for(int i=1; i<=columns; i++) {
buff.append("<tr>");
buff.append("<td>").append(i).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getColumnLabel(i))).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getCatalogName(i))).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getSchemaName(i))).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getTableName(i))).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getColumnName(i))).append("</td>");
buff.append("<td>").append(meta.getColumnType(i)).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getColumnTypeName(i))).append("</td>");
buff.append("<td>").append(PageParser.escapeHtml(meta.getColumnClassName(i))).append("</td>");
buff.append("<td>").append(meta.getPrecision(i)).append("</td>");
buff.append("<td>").append(meta.getScale(i)).append("</td>");
buff.append("<td>").append(meta.getColumnDisplaySize(i)).append("</td>");
buff.append("<td>").append(meta.isAutoIncrement(i)).append("</td>");
buff.append("<td>").append(meta.isCaseSensitive(i)).append("</td>");
buff.append("<td>").append(meta.isCurrency(i)).append("</td>");
buff.append("<td>").append(meta.isNullable(i)).append("</td>");
buff.append("<td>").append(meta.isReadOnly(i)).append("</td>");
buff.append("<td>").append(meta.isSearchable(i)).append("</td>");
buff.append("<td>").append(meta.isSigned(i)).append("</td>");
buff.append("<td>").append(meta.isWritable(i)).append("</td>");
buff.append("<td>").append(meta.isDefinitelyWritable(i)).append("</td>");
buff.append("</tr>");
}
} else {
buff.append("<tr>");
if(edit) {
buff.append("<th>Action</th>");
}
for(int i=0; i<columns; i++) {
buff.append("<th>");
buff.append(PageParser.escapeHtml(meta.getColumnLabel(i+1)));
buff.append("</th>");
}
buff.append("</tr>");
while(rs.next()) {
if(maxrows > 0 && rows >= maxrows) {
break;
}
rows++;
buff.append("<tr>");
if(edit) {
buff.append("<td>");
buff.append("<img onclick=\"javascript:editRow(");
buff.append(rs.getRow());
buff.append(",'${sessionId}', '${text.resultEdit.save}', '${text.resultEdit.cancel}'");
buff.append(")\" width=16 height=16 src=\"ico_write.gif\" onmouseover = \"this.className ='icon_hover'\" onmouseout = \"this.className ='icon'\" class=\"icon\" alt=\"${text.resultEdit.edit}\" title=\"${text.resultEdit.edit}\" border=\"1\">");
buff.append("<a href=\"editresult.do?op=2&row=");
buff.append(rs.getRow());
buff.append("&jsessionid=${sessionId}\" target=\"h2result\" ><img width=16 height=16 src=\"ico_remove.gif\" onmouseover = \"this.className ='icon_hover'\" onmouseout = \"this.className ='icon'\" class=\"icon\" alt=\"${text.resultEdit.delete}\" title=\"${text.resultEdit.delete}\" border=\"1\"></a>");
buff.append("</td>");
}
for(int i=0; i<columns; i++) {
buff.append("<td>");
buff.append(PageParser.escapeHtml(rs.getString(i+1)));
buff.append("</td>");
}
buff.append("</tr>");
}
}
boolean isUpdatable = rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;
if(edit) {
ResultSet old = getAppSession().result;
if(old != null) {
old.close();
}
getAppSession().result = rs;
} else {
rs.close();
}
if(edit) {
buff.append("<tr><td>");
buff.append("<img onclick=\"javascript:editRow(-1, '${sessionId}', '${text.resultEdit.save}', '${text.resultEdit.cancel}'");
buff.append(")\" width=16 height=16 src=\"ico_add.gif\" onmouseover = \"this.className ='icon_hover'\" onmouseout = \"this.className ='icon'\" class=\"icon\" alt=\"${text.resultEdit.add}\" title=\"${text.resultEdit.add}\" border=\"1\">");
buff.append("</td>");
for(int i=0; i<columns; i++) {
buff.append("<td></td>");
}
buff.append("</tr>");
}
buff.append("</table>");
if(edit) {
buff.append("</form>");
}
if(rows == 0) {
buff.append("(${text.result.noRows}");
} else if(rows == 1) {
buff.append("(${text.result.1row}");
} else {
buff.append("(");
buff.append(rows);
buff.append(" ${text.result.rows}");
}
buff.append(", ");
time = System.currentTimeMillis() - time;
buff.append(time);
buff.append(" ms)");
if(!edit && isUpdatable && allowEdit) {
buff.append("<br><br><form name=\"editResult\" method=\"post\" action=\"/query.do?jsessionid=${sessionId}\" target=\"h2result\">");
buff.append("<input type=\"submit\" class=\"button\" value=\"${text.resultEdit.editResult}\">");
buff.append("<input type=\"hidden\" name=\"sql\" value=\"@EDIT " + PageParser.escapeHtml(sql) +"\">");
buff.append("</form>");
}
return buff.toString();
}
private String settingSave() {
ConnectionInfo info = new ConnectionInfo();
info.name = attributes.getProperty("name", "");
info.driver = attributes.getProperty("driver", "");
info.url = attributes.getProperty("url", "");
info.user = attributes.getProperty("user", "");
server.getAppServer().updateSetting(info);
attributes.put("setting", info.name);
server.getAppServer().saveSettings();
return "index.do";
}
private String settingRemove() {
String setting = attributes.getProperty("name", "");
server.getAppServer().removeSetting(setting);
ArrayList settings = server.getAppServer().getSettings();
if(settings.size() > 0) {
attributes.put("setting", settings.get(0));
}
server.getAppServer().saveSettings();
return "index.do";
}
boolean allow() {
if(server.getAppServer().getAllowOthers()) {
return true;
}
return socket.getInetAddress().isLoopbackAddress();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import org.h2.util.StringUtils;
public class ConnectionInfo {
String name, driver, url, user;
int lastAccess;
ConnectionInfo() {
}
ConnectionInfo(String data) {
String[] array = StringUtils.arraySplit(data, '|', false);
name = get(array, 0);
driver = get(array, 1);
url = get(array, 2);
user = get(array, 3);
}
private String get(String[] array, int i) {
return array != null && array.length>i ? array[i] : "";
}
String getString() {
return StringUtils.arrayCombine(new String[]{name, driver, url, user}, '|');
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DbColumn {
String name;
String dataType;
DbColumn(ResultSet rs) throws SQLException {
name = rs.getString("COLUMN_NAME");
String type = rs.getString("TYPE_NAME");
int size = rs.getInt("COLUMN_SIZE");
if(size > 0) {
type += "("+size;
int prec = rs.getInt("DECIMAL_DIGITS");
if(prec > 0) {
type += ", " + prec;
}
type += ")";
}
if(rs.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls) {
type +=" NOT NULL";
}
dataType = type;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.command.Parser;
import org.h2.util.StringUtils;
public class DbContents {
DbSchema[] schemas;
DbSchema defaultSchema;
boolean isOracle, isH2, isPostgreSQL, isHSQLDB, isMySQL, isDerby, isFirebird, isSQLite;
void readContents(DatabaseMetaData meta) throws SQLException {
String prod = StringUtils.toLowerEnglish(meta.getDatabaseProductName());
isSQLite = prod.indexOf("sqlite") >= 0;
String url = meta.getURL();
if(url != null) {
isH2 = url.startsWith("jdbc:h2:");
isOracle = url.startsWith("jdbc:oracle:");
isPostgreSQL = url.startsWith("jdbc:postgresql:");
isHSQLDB = url.startsWith("jdbc:hsqldb:");
isMySQL = url.startsWith("jdbc:mysql:");
isDerby = url.startsWith("jdbc:derby:");
isFirebird = url.startsWith("jdbc:firebirdsql:");
}
String defaultSchemaName = getDefaultSchemaName(meta);
String[] schemaNames = getSchemaNames(meta);
schemas = new DbSchema[schemaNames.length];
for(int i=0; i<schemaNames.length; i++) {
String schemaName = schemaNames[i];
boolean isDefault = defaultSchemaName==null || defaultSchemaName.equals(schemaName);
DbSchema schema = new DbSchema(this, schemaName, isDefault);
if(schema.isDefault) {
defaultSchema = schema;
}
schemas[i] = schema;
String[] tableTypes = new String[]{"TABLE", "SYSTEM TABLE", "VIEW", "SYSTEM VIEW", "TABLE LINK", "SYNONYM"};
schema.readTables(meta, tableTypes);
}
if(defaultSchema == null) {
for(int i=0; i<schemas.length; i++) {
String best = null;
if("dbo".equals(schemas[i].name)) {
// MS SQL Server
defaultSchema = schemas[i];
break;
}
if(defaultSchema == null || best == null || schemas[i].name.length() < best.length()) {
best = schemas[i].name;
defaultSchema = schemas[i];
}
}
}
}
private String[] getSchemaNames(DatabaseMetaData meta) throws SQLException {
if(isMySQL) {
return new String[]{""};
} else if(isFirebird) {
return new String[]{null};
}
ResultSet rs = meta.getSchemas();
ArrayList schemas = new ArrayList();
while(rs.next()) {
String schema = rs.getString("TABLE_SCHEM");
if(schema == null) {
continue;
}
schemas.add(schema);
}
rs.close();
String[] list = new String[schemas.size()];
schemas.toArray(list);
return list;
}
private String getDefaultSchemaName(DatabaseMetaData meta) throws SQLException {
String defaultSchemaName = "";
try {
if(isOracle) {
return meta.getUserName();
} else if(isPostgreSQL) {
return "public";
} else if(isMySQL) {
return "";
} else if(isDerby) {
return StringUtils.toUpperEnglish(meta.getUserName());
} else if(isFirebird) {
return null;
}
ResultSet rs = meta.getSchemas();
int index = rs.findColumn("IS_DEFAULT");
while(rs.next()) {
if(rs.getBoolean(index)) {
defaultSchemaName = rs.getString("TABLE_SCHEM");
}
}
} catch(SQLException e) {
// IS_DEFAULT not found
}
return defaultSchemaName;
}
String quoteIdentifier(String identifier) {
if(identifier == null) {
return null;
}
if(isH2) {
return Parser.quoteIdentifier(identifier);
} else {
return StringUtils.toUpperEnglish(identifier);
// } else {
// return Generator.quoteIdentifierAlways(identifier);
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.h2.bnf.Bnf;
import org.h2.bnf.Rule;
import org.h2.bnf.Sentence;
import org.h2.command.Parser;
import org.h2.message.Message;
import org.h2.util.StringUtils;
public class DbContextRule implements Rule {
DbContents contents;
int type;
static final int COLUMN = 0, TABLE = 1, TABLE_ALIAS = 2;
public static final int NEW_TABLE_ALIAS = 3;
public static final int COLUMN_ALIAS = 4;
private static boolean SUGGEST_TABLE_ALIAS;
DbContextRule(DbContents contents, int type) {
this.contents = contents;
this.type = type;
}
public String name() {
return null;
}
public String random(Bnf config, int level) {
return null;
}
public Rule last() {
return this;
}
public void setLinks(HashMap ruleMap) {
}
public void addNextTokenList(String query, Sentence sentence) {
switch(type) {
case TABLE:
addTable(query, sentence);
break;
case NEW_TABLE_ALIAS:
addNewTableAlias(query, sentence);
break;
case TABLE_ALIAS:
addTableAlias(query, sentence);
break;
case COLUMN_ALIAS:
// addColumnAlias(query, sentence);
// break;
case COLUMN:
addColumn(query, sentence);
break;
}
}
private void addTableAlias(String query, Sentence sentence) {
String q = StringUtils.toUpperEnglish(query.trim());
HashMap map = sentence.getAliases();
HashSet set = new HashSet();
if(map != null) {
for(Iterator it = map.keySet().iterator(); it.hasNext();) {
String alias = (String)it.next();
DbTableOrView table = (DbTableOrView)map.get(alias);
set.add(StringUtils.toUpperEnglish(table.name));
if(q.length()==0 || alias.startsWith(q)) {
if(q.length() < alias.length()) {
sentence.add(alias + ".", alias.substring(q.length()) + ".", Sentence.CONTEXT);
}
}
}
}
HashSet tables = sentence.getTables();
if(tables != null) {
for(Iterator it = tables.iterator(); it.hasNext(); ) {
DbTableOrView table = (DbTableOrView)it.next();
String tableName = StringUtils.toUpperEnglish(table.name);
//DbTableOrView[] tables = contents.defaultSchema.tables;
//for(int i=0; i<tables.length; i++) {
// DbTableOrView table = tables[i];
// String tableName = StringUtils.toUpperEnglish(table.name);
if(!set.contains(tableName)) {
if(q.length()==0 || tableName.startsWith(q)) {
if(q.length() < tableName.length()) {
sentence.add(tableName + ".", tableName.substring(q.length()) + ".", Sentence.CONTEXT);
}
}
}
}
}
}
private void addNewTableAlias(String query, Sentence sentence) {
if(SUGGEST_TABLE_ALIAS) {
// good when testing!
if (query.length() > 3) {
return;
}
String lastTableName = StringUtils.toUpperEnglish(sentence.getLastTable().name);
if (lastTableName == null) {
return;
}
HashMap map = sentence.getAliases();
String shortName = lastTableName.substring(0, 1);
if (map != null && map.containsKey(shortName)) {
for (int i = 1;; i++) {
if (!map.containsKey(shortName + i)) {
shortName += i;
break;
}
}
}
String q = StringUtils.toUpperEnglish(query.trim());
if (q.length() == 0 || StringUtils.toUpperEnglish(shortName).startsWith(q)) {
if (q.length() < shortName.length()) {
sentence.add(shortName, shortName.substring(q.length()), Sentence.CONTEXT);
}
}
}
}
// private boolean startWithIgnoreCase(String a, String b) {
// if(a.length() < b.length()) {
// return false;
// }
// for(int i=0; i<b.length(); i++) {
// if(Character.toUpperCase(a.charAt(i)) != Character.toUpperCase(b.charAt(i))) {
// return false;
// }
// }
// return true;
// }
private void addTable(String query, Sentence sentence) {
DbSchema schema = contents.defaultSchema;
String text = StringUtils.toUpperEnglish(sentence.text).trim();
if(text.endsWith(".")) {
for(int i=0; i<contents.schemas.length; i++) {
if(text.endsWith(StringUtils.toUpperEnglish(contents.schemas[i].name)+".")) {
schema = contents.schemas[i];
break;
}
}
}
String q = StringUtils.toUpperEnglish(query.trim());
DbTableOrView[] tables = schema.tables;
for(int i=0; i<tables.length; i++) {
DbTableOrView table = tables[i];
if(q.length()==0 || StringUtils.toUpperEnglish(table.name).startsWith(q)) {
if(q.length() < table.quotedName.length()) {
sentence.add(table.quotedName, table.quotedName.substring(q.length()), Sentence.CONTEXT);
}
}
}
}
private void addColumn(String query, Sentence sentence) {
String tableName = query;
String columnPattern = "";
if(query.trim().length()==0) {
tableName = null;
if(sentence.text.trim().endsWith(".")) {
return;
}
} else {
tableName = StringUtils.toUpperEnglish(query.trim());
if(tableName.endsWith(".")) {
tableName = tableName.substring(0, tableName.length()-1);
} else {
columnPattern = StringUtils.toUpperEnglish(query.trim());
tableName = null;
}
}
HashSet set = null;
HashMap aliases = sentence.getAliases();
if(tableName == null && sentence.getTables() != null) {
set = sentence.getTables();
}
DbTableOrView table = null;
if(tableName != null && aliases != null && aliases.get(tableName) != null) {
table = (DbTableOrView) aliases.get(tableName);
tableName = StringUtils.toUpperEnglish(table.name);
}
if(tableName == null) {
if(set == null && aliases == null) {
return;
}
if((set != null && set.size()>1) || (aliases != null && aliases.size()>1)) {
return;
}
}
if(table == null) {
DbTableOrView[] tables = contents.defaultSchema.tables;
for(int i=0; i<tables.length; i++) {
DbTableOrView tab = tables[i];
String t = StringUtils.toUpperEnglish(tab.name);
if(tableName != null && !tableName.equals(t)) {
continue;
}
if(set != null && !set.contains(tab)) {
continue;
}
table = tab;
break;
}
}
if(table != null) {
for(int j=0; j<table.columns.length; j++) {
String columnName = table.columns[j].name;
if(!StringUtils.toUpperEnglish(columnName).startsWith(columnPattern)) {
continue;
}
if(columnPattern.length() < columnName.length()) {
sentence.add(columnName, columnName.substring(columnPattern.length()), Sentence.CONTEXT);
}
}
}
}
public String matchRemove(String query, Sentence sentence) {
if(query.length()==0) {
return null;
}
String s;
switch(type) {
case TABLE:
s = matchTable(query, sentence);
break;
case NEW_TABLE_ALIAS:
s = matchTableAlias(query, sentence, true);
break;
case TABLE_ALIAS:
s = matchTableAlias(query, sentence, false);
break;
case COLUMN_ALIAS:
s = matchColumnAlias(query, sentence, false);
break;
case COLUMN:
s = matchColumn(query, sentence);
break;
default:
throw Message.getInternalError("type="+type);
}
return s;
}
public String matchTable(String query, Sentence sentence) {
String up = StringUtils.toUpperEnglish(query);
DbTableOrView[] tables = contents.defaultSchema.tables;
String best = null;
DbTableOrView bestTable = null;
for(int i=0; i<tables.length; i++) {
DbTableOrView table = tables[i];
String tableName = StringUtils.toUpperEnglish(table.name);
if(up.startsWith(tableName)) {
if(best == null || tableName.length() > best.length()) {
best = tableName;
bestTable = table;
}
}
}
if(best == null) {
return null;
}
sentence.addTable(bestTable);
query = query.substring(best.length());
// while(query.length()>0 && Character.isWhitespace(query.charAt(0))) {
// query = query.substring(1);
// }
return query;
}
public String matchColumnAlias(String query, Sentence sentence, boolean add) {
String up = StringUtils.toUpperEnglish(query);
int i=0;
if(query.indexOf(' ')<0) {
return null;
}
for(; i<up.length(); i++) {
char ch = up.charAt(i);
if(ch != '_' && !Character.isLetterOrDigit(ch)) {
break;
}
}
if(i==0) {
return null;
}
String alias = up.substring(0, i);
if(Parser.isKeyword(alias)) {
return null;
}
return query.substring(alias.length());
}
public String matchTableAlias(String query, Sentence sentence, boolean add) {
String up = StringUtils.toUpperEnglish(query);
int i=0;
if(query.indexOf(' ')<0) {
return null;
}
for(; i<up.length(); i++) {
char ch = up.charAt(i);
if(ch != '_' && !Character.isLetterOrDigit(ch)) {
break;
}
}
if(i==0) {
return null;
}
String alias = up.substring(0, i);
if(Parser.isKeyword(alias)) {
return null;
}
if(add) {
sentence.addAlias(alias, sentence.getLastTable());
}
HashMap map = sentence.getAliases();
if((map != null && map.containsKey(alias)) || (sentence.getLastTable() == null)) {
if(add && query.length() == alias.length()) {
return query;
}
query = query.substring(alias.length());
return query;
} else {
HashSet tables = sentence.getTables();
if(tables != null) {
String best = null;
for(Iterator it = tables.iterator(); it.hasNext(); ) {
DbTableOrView table = (DbTableOrView)it.next();
String tableName = StringUtils.toUpperEnglish(table.name);
//DbTableOrView[] tables = contents.defaultSchema.tables;
//for(int i=0; i<tables.length; i++) {
// DbTableOrView table = tables[i];
// String tableName = StringUtils.toUpperEnglish(table.name);
if(alias.startsWith(tableName) && (best==null || tableName.length()>best.length())) {
best = tableName;
}
}
if(best != null) {
query = query.substring(best.length());
return query;
}
}
return null;
}
}
public String matchColumn(String query, Sentence sentence) {
String up = StringUtils.toUpperEnglish(query);
HashSet set = sentence.getTables();
DbTableOrView[] tables = contents.defaultSchema.tables;
String best = null;
for(int i=0; i<tables.length; i++) {
DbTableOrView table = tables[i];
if(set != null && !set.contains(table)) {
continue;
}
for(int j=0; j<table.columns.length; j++) {
String name = StringUtils.toUpperEnglish(table.columns[j].name);
if(up.startsWith(name)) {
String b = query.substring(name.length());
if(best == null || b.length() < best.length()) {
best = b;
}
}
}
}
return best;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class DbSchema {
DbContents contents;
String name;
String quotedName;
DbTableOrView[] tables;
public boolean isDefault;
DbSchema(DbContents contents, String name, boolean isDefault) throws SQLException {
this.contents = contents;
this.name = name;
this.quotedName = contents.quoteIdentifier(name);
this.isDefault = isDefault;
}
public void readTables(DatabaseMetaData meta, String[] tableTypes) throws SQLException {
ResultSet rs = meta.getTables(null, name, null, tableTypes);
ArrayList list = new ArrayList();
while(rs.next()) {
DbTableOrView table = new DbTableOrView(this, rs);
list.add(table);
}
rs.close();
tables = new DbTableOrView[list.size()];
list.toArray(tables);
// if(isDefault) {
for(int i=0; i<tables.length; i++) {
DbTableOrView tab = tables[i];
tab.readColumns(meta);
}
// }
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class DbTableOrView {
DbSchema schema;
String name;
String quotedName;
boolean isView;
DbColumn[] columns;
DbTableOrView(DbSchema schema, ResultSet rs) throws SQLException {
this.schema = schema;
name = rs.getString("TABLE_NAME");
String type = rs.getString("TABLE_TYPE");
isView = "VIEW".equals(type);
quotedName = schema.contents.quoteIdentifier(name);
}
public void readColumns(DatabaseMetaData meta) throws SQLException {
ResultSet rs = meta.getColumns(null, schema.name, name, null);
ArrayList list = new ArrayList();
while(rs.next()) {
DbColumn column = new DbColumn(rs);
list.add(column);
}
rs.close();
columns = new DbColumn[list.size()];
list.toArray(columns);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.util.ArrayList;
import java.util.HashMap;
public class PageParser {
private WebServer server;
private String page;
private int pos;
private HashMap settings;
private int len;
private StringBuffer result;
public static String parse(WebServer server, String page, HashMap settings) {
PageParser block = new PageParser(server, page, settings, 0);
return block.parse();
}
private PageParser(WebServer server, String page, HashMap settings, int pos) {
this.server = server;
this.page = page;
this.pos = pos;
this.len = page.length();
this.settings = settings;
result = new StringBuffer(len);
}
private void setError(int i) {
String s = page.substring(0, i) + "####BUG####" + page.substring(i);
s = PageParser.escapeHtml(s);
result = new StringBuffer(s);
}
private String parseBlockUntil(String end) throws Exception {
PageParser block = new PageParser(server, page, settings, pos);
block.parseAll();
if (!block.readIf(end)) {
throw new Exception();
}
pos = block.pos;
return block.result.toString();
}
public String parse() {
try {
parseAll();
if (pos != len) {
setError(pos);
}
} catch (Exception e) {
// TODO log error
setError(pos);
}
return result.toString();
}
private void parseAll() throws Exception {
StringBuffer buff = result;
String p = page;
int i = pos;
for (; i < len; i++) {
char c = p.charAt(i);
switch (c) {
case '<': {
if (p.charAt(i + 1) == '%') {
if (p.charAt(i + 2) == '@') {
i += 3;
pos = i;
read("include");
String file = readParam("file");
read("%>");
String s = server.getTextFile(file);
append(s);
i = pos;
} else {
setError(i);
return;
}
break;
} else if (p.charAt(i + 3) == ':' && p.charAt(i + 1) == '/') {
// end tag
pos = i;
return;
} else if (p.charAt(i + 2) == ':') {
pos = i;
if (readIf("<c:forEach")) {
String var = readParam("var");
String items = readParam("items");
read(">");
int start = pos;
ArrayList list = (ArrayList) get(items);
if (list == null) {
result.append("?items?");
list = new ArrayList();
}
if (list.size() == 0) {
parseBlockUntil("</c:forEach>");
}
for (int j = 0; j < list.size(); j++) {
settings.put(var, list.get(j));
pos = start;
String block = parseBlockUntil("</c:forEach>");
result.append(block);
}
} else if (readIf("<c:if")) {
String test = readParam("test");
int eq = test.indexOf("=='");
if (eq < 0) {
setError(i);
return;
}
String val = test.substring(eq + 3, test.length() - 1);
test = test.substring(0, eq);
String value = (String) get(test);
read(">");
String block = parseBlockUntil("</c:if>");
pos--;
if (value.equals(val)) {
result.append(block);
}
} else {
setError(i);
return;
}
i = pos;
} else {
buff.append(c);
}
break;
}
case '$':
if (p.charAt(i + 1) == '{') {
i += 2;
int j = p.indexOf('}', i);
if (j < 0) {
setError(i);
return;
}
String item = p.substring(i, j).trim();
i = j;
String s = (String) get(item);
append(s);
}
break;
default:
buff.append(c);
}
}
pos = i;
}
private Object get(String item) {
int dot = item.indexOf('.');
if (dot >= 0) {
String sub = item.substring(dot + 1);
item = item.substring(0, dot);
HashMap map = (HashMap) settings.get(item);
if (map == null) {
return "?" + item + "?";
}
return map.get(sub);
} else {
return settings.get(item);
}
}
private void append(String s) {
if (s != null) {
result.append(PageParser.parse(server, s, settings));
}
}
private String readParam(String name) throws Exception {
read(name);
read("=");
read("\"");
int start = pos;
while (page.charAt(pos) != '"') {
pos++;
}
int end = pos;
read("\"");
String s = page.substring(start, end);
return PageParser.parse(server, s, settings);
}
private void skipSpaces() {
while (page.charAt(pos) == ' ') {
pos++;
}
}
private void read(String s) throws Exception {
if (!readIf(s)) {
throw new Exception();
}
}
private boolean readIf(String s) {
skipSpaces();
if (page.regionMatches(pos, s, 0, s.length())) {
pos += s.length();
skipSpaces();
return true;
}
return false;
}
public static String escapeHtmlNoBreak(String s) {
return escapeHtml(s, false);
}
public static String escapeHtml(String s) {
return escapeHtml(s, true);
}
public static String escapeHtml(String s, boolean convertBreak) {
if (s == null) {
return null;
}
if (s.length() == 0) {
return "&nbsp;";
}
StringBuffer buff = new StringBuffer(s.length());
boolean leadingSpace = true;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (leadingSpace) {
if (c == ' ') {
buff.append("&nbsp;");
continue;
} else {
leadingSpace = false;
}
}
switch (c) {
case '$':
// so that ${ } in the text is interpreted correctly
buff.append("&#36;");
break;
case '<':
buff.append("&lt;");
break;
case '>':
buff.append("&gt;");
break;
case '&':
buff.append("&amp;");
break;
case '"':
buff.append("&quot;");
break;
case '\'':
buff.append("&#39;");
break;
case '\n':
if (convertBreak) {
buff.append("<br>");
leadingSpace = true;
} else {
buff.append(c);
}
break;
default:
if (c >= 128) {
buff.append("&#");
buff.append((int) c);
buff.append(';');
} else {
buff.append(c);
}
}
}
return buff.toString();
}
public static String escapeJavaScript(String s) {
if (s == null) {
return null;
}
if (s.length() == 0) {
return "";
}
StringBuffer buff = new StringBuffer(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '"':
buff.append("\\\"");
break;
case '\'':
buff.append("\\'");
break;
case '\\':
buff.append("\\\\");
break;
case '\n':
buff.append("\\n");
break;
case '\r':
buff.append("\\r");
break;
case '\t':
buff.append("\\t");
break;
default:
buff.append(c);
}
}
return buff.toString();
// return escapeHtml(buff.toString());
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
import org.h2.message.TraceSystem;
import org.h2.server.Service;
import org.h2.util.ByteUtils;
import org.h2.util.NetUtils;
import org.h2.util.RandomUtils;
import org.h2.util.Resources;
public class WebServer implements Service {
// TODO tool: implement a watchdog for a server
private static final String DEFAULT_LANGUAGE = "en";
private static final String[][] LANGUAGES = {
{ "en", "English" },
{ "de", "Deutsch" },
{ "fr", "Fran\u00e7ais" },
{ "es", "Espa\u00f1ol" },
{ "zh_CN", "\u4E2D\u6587"},
};
// String lang =
// 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();
private HashSet languages = new HashSet();
private String startDateTime;
private AppServer appServer;
private ServerSocket serverSocket;
private boolean ssl;
private int port;
private String url;
byte[] getFile(String file) throws IOException {
trace("getFile <"+file+">");
byte[] data = Resources.get("/org/h2/server/web/res/"+file);
if(data == null) {
trace(" null");
} else {
trace(" size="+data.length);
}
return data;
}
String getTextFile(String file) throws IOException {
byte[] bytes = getFile(file);
return new String(bytes);
}
private String generateSessionId() {
byte[] buff = RandomUtils.getSecureBytes(16);
return ByteUtils.convertBytesToString(buff);
}
AppServer getAppServer() {
return appServer;
}
WebServerSession getSession(String sessionId) {
long now = System.currentTimeMillis();
if(lastTimeoutCheck + SESSION_TIMEOUT < now) {
Object[] list = sessions.keySet().toArray();
for(int i=0; i<list.length; i++) {
String id = (String) list[i];
WebServerSession session = (WebServerSession)sessions.get(id);
Long last = (Long) session.get("lastAccess");
if(last != null && last.longValue() + SESSION_TIMEOUT < now) {
trace("timeout for " + id);
sessions.remove(id);
}
}
lastTimeoutCheck = now;
}
WebServerSession session = (WebServerSession)sessions.get(sessionId);
if(session != null) {
session.lastAccess = System.currentTimeMillis();
}
return session;
}
WebServerSession createNewSession(Socket socket) {
String newId;
do {
newId = generateSessionId();
} while(sessions.get(newId) != null);
WebServerSession session = new AppSession(this);
session.put("sessionId", newId);
//session.put("ip", socket.getInetAddress().getCanonicalHostName());
session.put("ip", socket.getInetAddress().getHostName());
session.put("language", DEFAULT_LANGUAGE);
sessions.put(newId, session);
// always read the english translation, to that untranslated text appears at least in english
readTranslations(session, DEFAULT_LANGUAGE);
return getSession(newId);
}
String getStartDateTime() {
return startDateTime;
}
public void init(String[] args) throws Exception {
// TODO web: support using a different properties file
appServer = new AppServer(args);
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", new Locale("en", ""));
format.setTimeZone(TimeZone.getTimeZone("GMT"));
startDateTime = format.format(new Date());
trace(startDateTime);
for(int i=0; i<LANGUAGES.length; i++) {
languages.add(LANGUAGES[i][0]);
}
port = appServer.getPort();
ssl = appServer.getSSL();
url = (ssl?"https":"http") + "://localhost:"+port;
}
public String getURL() {
return url;
}
public void start() throws SQLException {
serverSocket = NetUtils.createServerSocket(port, ssl);
}
public void listen() {
try {
while (serverSocket != null) {
Socket s = serverSocket.accept();
WebServerThread c = new AppThread(s, this);
c.start();
}
} catch (Exception e) {
// TODO log exception
}
}
public boolean isRunning() {
if(serverSocket == null) {
return false;
}
try {
Socket s = NetUtils.createLoopbackSocket(port, ssl);
s.close();
return true;
} catch(Exception e) {
return false;
}
}
public void stop() {
try {
serverSocket.close();
} catch(IOException e) {
// TODO log exception
}
serverSocket = null;
}
void trace(String s) {
// System.out.println(s);
}
public boolean supportsLanguage(String language) {
return languages.contains(language);
}
public void readTranslations(WebServerSession session, String language) {
Properties text = new Properties();
try {
trace("translation: "+language);
byte[] trans = getFile("_text_"+language+".properties");
trace(" "+trans);
text.load(new ByteArrayInputStream(trans));
} catch (IOException e) {
TraceSystem.traceThrowable(e);
}
session.put("text", new HashMap(text));
}
public String[][] getLanguageArray() {
return LANGUAGES;
}
public ArrayList getSessions() {
ArrayList list = new ArrayList(sessions.values());
for(int i=0; i<list.size(); i++) {
WebServerSession s = (WebServerSession) list.get(i);
list.set(i, s.getInfo());
}
return list;
}
public boolean getAllowOthers() {
return appServer.getAllowOthers();
}
public String getType() {
return "Web";
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Locale;
public class WebServerSession {
long lastAccess;
HashMap map = new HashMap();
Locale locale;
WebServer server;
WebServerSession(WebServer server) {
this.server = server;
}
public void put(String key, Object value) {
map.put(key, value);
}
public Object get(String key) {
if("sessions".equals(key)) {
return server.getSessions();
}
return map.get(key);
}
public void remove(String key) {
map.remove(key);
}
public HashMap getInfo() {
HashMap m = new HashMap();
m.putAll(map);
m.put("lastAccess", new Timestamp(lastAccess).toString());
return m;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import org.h2.message.TraceSystem;
import org.h2.util.StringUtils;
abstract class WebServerThread extends Thread {
protected WebServer server;
protected WebServerSession session;
protected Properties attributes;
protected Socket socket;
private InputStream input;
private String ifModifiedSince;
WebServerThread(Socket socket, WebServer server) {
this.server = server;
this.socket = socket;
}
abstract String process(String file);
protected String getCombobox(String[] elements, String selected) {
StringBuffer buff = new StringBuffer();
for(int i=0; i<elements.length; i++) {
String value = elements[i];
buff.append("<option value=\"");
buff.append(PageParser.escapeHtml(value));
buff.append("\"");
if(value.equals(selected)) {
buff.append(" selected");
}
buff.append(">");
buff.append(PageParser.escapeHtml(value));
buff.append("</option>");
}
return buff.toString();
}
protected String getCombobox(String[][] elements, String selected) {
StringBuffer buff = new StringBuffer();
for(int i=0; i<elements.length; i++) {
String[] n = elements[i];
buff.append("<option value=\"");
buff.append(PageParser.escapeHtml(n[0]));
buff.append("\"");
if(n[0].equals(selected)) {
buff.append(" selected");
}
buff.append(">");
buff.append(PageParser.escapeHtml(n[1]));
buff.append("</option>");
}
return buff.toString();
}
public void run() {
try {
input = socket.getInputStream();
String head = readHeaderLine();
if(head.startsWith("GET ") || head.startsWith("POST ")) {
int begin = head.indexOf('/'), end = head.lastIndexOf(' ');
String file = head.substring(begin+1, end).trim();
if(file.length() == 0) {
file = "index.do";
}
if(!allow()) {
file = "notAllowed.jsp";
}
server.trace(head + " :" + file);
attributes = new Properties();
int paramIndex = file.indexOf("?");
session = null;
if(paramIndex >= 0) {
String attrib = file.substring(paramIndex+1);
parseAttributes(attrib);
String sessionId = attributes.getProperty("jsessionid");
file = file.substring(0, paramIndex);
session = server.getSession(sessionId);
}
// TODO web: support errors
String mimeType;
boolean cache;
if(file.endsWith(".ico")) {
mimeType = "image/x-icon";
cache=true;
} else if(file.endsWith(".gif")) {
mimeType = "image/gif";
cache=true;
} else if(file.endsWith(".css")) {
cache=true;
mimeType = "text/css";
} else if(file.endsWith(".html") || file.endsWith(".do") || file.endsWith(".jsp")) {
cache=false;
mimeType = "text/html";
if (session == null) {
session = server.createNewSession(socket);
if (!file.equals("notAllowed.jsp")) {
file = "index.do";
}
}
} else if(file.endsWith(".js")) {
cache=true;
mimeType = "text/javascript";
} else {
cache = false;
mimeType = "text/html";
file = "error.jsp";
server.trace("unknown mime type, file "+file);
}
server.trace("mimeType="+mimeType);
parseHeader();
server.trace(file);
if(file.endsWith(".do")) {
file = process(file);
}
String message;
byte[] bytes;
if(cache && ifModifiedSince!=null && ifModifiedSince.equals(server.getStartDateTime())) {
bytes = null;
message = "HTTP/1.1 304 Not Modified\n";
} else {
bytes = server.getFile(file);
if(bytes == null) {
message = "HTTP/1.0 404 Not Found\n";
bytes = StringUtils.utf8Encode("File not found: "+file);
} else {
if(session != null && file.endsWith(".jsp")) {
bytes = StringUtils.utf8Encode(fill(StringUtils.utf8Decode(bytes)));
}
message = "HTTP/1.1 200 OK\n";
message += "Content-Type: "+mimeType+"\n";
if(!cache) {
message += "Cache-Control: no-cache\n";
} else {
message += "Cache-Control: max-age=10\n";
message += "Last-Modified: "+server.getStartDateTime()+"\n";
}
}
}
message += "\n";
server.trace(message);
DataOutputStream output;
output = new DataOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
output.write(message.getBytes());
if(bytes!=null) {
output.write(bytes);
}
output.flush();
output.close();
output.close();
socket.close();
return;
}
} catch (Exception e) {
TraceSystem.traceThrowable(e);
}
}
abstract boolean allow();
private String readHeaderLine() throws IOException {
StringBuffer buff=new StringBuffer();
while (true) {
int i = input.read();
if (i == -1) {
throw new IOException("Unexpected EOF");
} else if (i == '\r' && input.read()=='\n') {
return buff.length() > 0 ? buff.toString() : null;
} else {
buff.append((char)i);
}
}
}
private void parseAttributes(String s) throws Exception {
server.trace("data="+s);
while(s != null) {
int idx = s.indexOf('=');
if(idx>=0) {
String property = s.substring(0, idx);
s = s.substring(idx+1);
idx = s.indexOf('&');
String value;
if(idx >= 0) {
value = s.substring(0, idx);
s = s.substring(idx+1);
} else {
value = s;
}
// TODO compatibility problem with JDK 1.3
//String attr = URLDecoder.decode(value, "UTF-8");
// String attr = URLDecoder.decode(value);
String attr = StringUtils.urlDecode(value);
attributes.put(property, attr);
} else {
break;
}
}
server.trace(attributes.toString());
}
private void parseHeader() throws Exception {
server.trace("parseHeader");
int len = 0;
ifModifiedSince = null;
while(true) {
String line = readHeaderLine();
if(line == null) {
break;
}
server.trace(" "+line);
String lower = StringUtils.toLowerEnglish(line);
if(lower.startsWith("if-modified-since")) {
ifModifiedSince = line.substring(line.indexOf(':')+1).trim();
} else if(lower.startsWith("content-length")) {
len = Integer.parseInt(line.substring(line.indexOf(':')+1).trim());
server.trace("len="+len);
} else if(lower.startsWith("accept-language")) {
if(session != null) {
Locale locale = session.locale;
if(locale == null) {
String languages = line.substring(line.indexOf(':')+1).trim();
StringTokenizer tokenizer = new StringTokenizer(languages, ",;");
while(tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if(!token.startsWith("q=")) {
if(server.supportsLanguage(token)) {
int dash = token.indexOf('-');
if(dash >= 0) {
String language = token.substring(0, dash);
String country = token.substring(dash+1);
locale = new Locale(language, country);
} else {
locale = new Locale(token, "");
}
session.locale = locale;
String language = locale.getLanguage();
session.put("language", language);
server.readTranslations(session, language);
break;
}
}
}
}
}
} else if(line.trim().length()==0) {
break;
}
}
if(session != null && len > 0) {
byte[] bytes = new byte[len];
for (int pos = 0; pos < len;) {
pos += input.read(bytes, pos, len - pos);
}
String s = new String(bytes);
parseAttributes(s);
}
}
private String fill(String page) {
return PageParser.parse(server, page, session.map);
}
}
# Use the PropertiesToUTF8 tool to translate the files to UTF-8 and back
a.help=Hilfe
a.language=Deutsch
a.lynxNotSupported=Dieser Browser unterst&uuml;tzt keine Frames. Frames (und Javascript) werden ben&ouml;tigt.
a.password=Passwort
a.remoteConnectionsDisabled=Verbindungen von anderen Rechnern sind nicht freigegeben ('webAllowOthers').
a.title=H2 Console
a.user=Benutzername
admin.executing=Aktiv
admin.ip=IP
admin.lastAccess=Letzter Zugriff
admin.lastQuery=Letzter Befehl
admin.url=URL
adminAllow=Zugelassene Verbindungen
adminConnection=Verbindungs-Sicherheit
adminHttp=Unverschl&uuml;sselte HTTP Verbindungen
adminHttps=Verschl&uuml;sselte HTTPS Verbindungen
adminLocal=Nur lokale Verbindungen erlauben
adminLogin=Administration Login
adminLoginCancel=Abbrechen
adminLoginOk=OK
adminLogout=Beenden
adminOthers=Verbindungen von anderen Computern erlauben
adminPort=Web-Server Port
adminRestart=&Auml;nderungen werden nach einem Neustart des Servers aktiv.
adminSave=Speichern
adminSessions=Aktive Verbindungen
adminShutdown=Shutdown
adminTitle=H2 Console Optionen
helpAction=Aktion
helpAddAnotherRow=F&uuml;gt einen weiteren Datensatz hinzu
helpAddDrivers=Datenbank Treiber hinzuf&uuml;gen
helpAddDriversOnlyJava=Zus&auml;liche Treiber werden nur von der Java Version unterst&uuml;zt (nicht von der Native Version).
helpAddDriversText=Es ist m&ouml;glich zus&auml;tzliche Datenbank-Treiber zu laden, indem die Pfade der Treiber-Dateien in den Umgebungsvariablen H2DRIVERS oder CLASSPATH eingetragen werden. Beispiel (Windows): Um den Datenbank-Treiber mit dem Jar-File C:\\Programs\\hsqldb\\lib\\hsqldb.jar hinzuzuf&uuml;gen, setzen Sie den die Umgebungvariable H2DRIVERS auf C:\\Programs\\hsqldb\\lib\\hsqldb.jar.
helpAddRow=F&uuml;gt einen Datensatz hinzu
helpCommandHistory=Zeigt die Befehls-Chronik
helpCreateTable=Erzeugt eine neue Tabelle
helpDeleteRow=Entfernt einen Datensatz
helpDisconnect=Trennt die Verbindung zur Datenbank
helpDisplayThis=Zeigt diese Hilfe Seite
helpDropTable=L&ouml;scht die Tabelle falls es sie gibt
helpExecuteCurrent=F&uuml;hrt den aktuellen SQL Befehl aus
helpIcon=Schaltfl&auml;che
helpImportantCommands=Wichtige Befehle
helpOperations=Operationen
helpQuery=Fragt die Tabelle ab
helpSampleSQL=Beispiel SQL Skript
helpStatements=SQL Befehle
helpUpdate=&Auml;ndert Daten in einer Zeile
helpWithColumnsIdName=mit zwei Spalten
login.connect=Verbinden
login.driverClass=Datenbank-Treiber Klasse
login.driverNotFound=Datenbank-Treiber nicht gefunden<br>F&uuml;r Informationen zum Hinzuf&uuml;gen von Treibern siehe Hilfe
login.goAdmin=Optionen
login.jdbcUrl=JDBC URL
login.language=Sprache
login.login=Login
login.remove=Entfernen
login.save=Speichern
login.savedSetting=Gespeicherte Einstellung
login.settingName=Einstellungs-Name
login.testConnection=Verbindung testen
login.testSuccessful=Test erfolgreich
login.welcome=H2 Console
result.1row=1 Datensatz
result.autocommitOff=Auto-Commit ist jetzt ausgeschaltet
result.autocommitOn=Auto-Commit ist jetzt eingeschaltet
result.maxrowsSet=Maximale Anzahl Zeilen ist jetzt gesetzt
result.noRows=keine Datens&auml;tze
result.noRunningStatement=Im Moment wird kein Befehl ausgef&uuml;hrt
result.rows=Datens&auml;tze
result.statementWasCancelled=Der Befehl wurde abgebrochen
result.updateCount=&Auml;nderungen
resultEdit.add=Hinzuf&uuml;gen
resultEdit.cancel=Abbrechen
resultEdit.delete=L&ouml;schen
resultEdit.edit=Bearbeiten
resultEdit.editResult=Bearbeiten
resultEdit.save=Speichern
toolbar.all=Alle
toolbar.autocommit=Auto-Commit
toolbar.autocomplete=Auto-Complete
toolbar.autocomplete.off=Aus
toolbar.autocomplete.normal=Normal
toolbar.autocomplete.full=Alles
toolbar.cancelStatement=Laufenden Befehl abbrechen
toolbar.clear=Leeren
toolbar.commit=Commit (Abschliessen/Speichern)
toolbar.disconnect=Verbindung trennen
toolbar.history=Befehls-Chronik
toolbar.maxRows=Maximale Anzahl Zeilen
toolbar.refresh=Aktualisieren
toolbar.rollback=Rollback (R&uuml;ckg&auml;ngig)
toolbar.run=Ausf&uuml;hren (Strg+Enter)
toolbar.sqlStatement=SQL Befehl
tree.admin=Administrator
tree.current=Aktueller Wert
tree.hashed=Hash-basiert
tree.increment=Inkrement
tree.indexes=Indexe
tree.nonUnique=nicht eindeutig
tree.sequences=Sequenzen
tree.unique=eindeutig
tree.users=Benutzer
# Use the PropertiesToUTF8 tool to translate the files to UTF-8 and back
a.help=Help
a.language=English
a.lynxNotSupported=Sorry, Lynx not supported yet
a.password=Password
a.remoteConnectionsDisabled=Sorry, remote connections ('webAllowOthers') are disabled on this server.
a.title=H2 Console
a.user=User Name
admin.executing=Executing
admin.ip=IP
admin.lastAccess=Last Access
admin.lastQuery=Last Query
admin.url=URL
adminAllow=Allowed clients
adminConnection=Connection security
adminHttp=Use unencrypted HTTP connections
adminHttps=Use encrypted SSL (HTTPS) connections
adminLocal=Only allow local connections
adminLogin=Administration Login
adminLoginCancel=Cancel
adminLoginOk=OK
adminLogout=Logout
adminOthers=Allow connections from other computers
adminPort=Web server port number
adminRestart=Changes take effect after restarting the server.
adminSave=Save
adminSessions=Active Sessions
adminShutdown=Shutdown
adminTitle=H2 Console Preferences
helpAction=Action
helpAddAnotherRow=Add another row
helpAddDrivers=Adding Database Drivers
helpAddDriversOnlyJava=Only the Java version supports additional drivers (this feature is not supported by the Native version).
helpAddDriversText=Additional database drivers can be registerd by adding the Jar file location of the driver to the the environment variables H2DRIVERS or CLASSPATH. Example (Windows): To add the database driver library C:\\Programs\\hsqldb\\lib\\hsqldb.jar, set the environment variable H2DRIVERS to C:\\Programs\\hsqldb\\lib\\hsqldb.jar.
helpAddRow=Add a new row
helpCommandHistory=Shows the Command History
helpCreateTable=Create a new table
helpDeleteRow=Remove a row
helpDisconnect=Disconnects from the database
helpDisplayThis=Displays this Help Page
helpDropTable=Delete the table if it exists
helpExecuteCurrent=Executes the current SQL statement
helpIcon=Icon
helpImportantCommands=Important Commands
helpOperations=Operations
helpQuery=Query the table
helpSampleSQL=Sample SQL Script
helpStatements=SQL statements
helpUpdate=Change data in a row
helpWithColumnsIdName=with ID and NAME columns
login.connect=Connect
login.driverClass=Driver Class
login.driverNotFound=Database driver not found<br>See in the Help for how to add drivers
login.goAdmin=Preferences
login.jdbcUrl=JDBC URL
login.language=Language
login.login=Login
login.remove=Remove
login.save=Save
login.savedSetting=Saved Settings
login.settingName=Setting Name
login.testConnection=Test Connection
login.testSuccessful=Test successful
login.welcome=H2 Console
result.1row=1 row
result.autocommitOff=Autocommit is now OFF
result.autocommitOn=Autocommit is now ON
result.maxrowsSet=Max rowcount is set
result.noRows=no rows
result.noRunningStatement=There is currently no running statement
result.rows=rows
result.statementWasCancelled=The statement was cancelled
result.updateCount=Update Count
resultEdit.add=Add
resultEdit.cancel=Cancel
resultEdit.delete=Delete
resultEdit.edit=Edit
resultEdit.editResult=Edit
resultEdit.save=Save
toolbar.all=All
toolbar.autocommit=Autocommit
toolbar.autocomplete=Auto-Complete
toolbar.autocomplete.off=Off
toolbar.autocomplete.normal=Normal
toolbar.autocomplete.full=Full
toolbar.cancelStatement=Cancel the current statement
toolbar.clear=Clear
toolbar.commit=Commit
toolbar.disconnect=Disconnect
toolbar.history=Command History
toolbar.maxRows=Max Rows
toolbar.refresh=Refresh
toolbar.rollback=Rollback
toolbar.run=Run (Ctrl+Enter)
toolbar.sqlStatement=SQL statement
tree.admin=Admin
tree.current=Current value
tree.hashed=Hashed
tree.increment=Increment
tree.indexes=Indexes
tree.nonUnique=Non-Unique
tree.sequences=Sequences
tree.unique=Unique
tree.users=Users
# Use the PropertiesToUTF8 tool to translate the files to UTF-8 and back
# translator: Miguel Angel
a.help=Ayuda
a.language=Espa&ntilde;ol
a.lynxNotSupported=Lo sentimos, Lynx no est&aacute; soportado todav&iacute;a
a.password=Contrase&ntilde;a
a.remoteConnectionsDisabled=Conexiones remotas desactivadas
a.title=H2 Console
a.user=Nombre de usuario
admin.executing=Ejecutando
admin.ip=IP
admin.lastAccess=&Uacute;ltimo acceso
admin.lastQuery=&Uacute;ltima consulta
admin.url=URL
adminAllow=Clientes permitidos
adminConnection=Conexi&oacute;n segura
adminHttp=Usar conexiones HTTP desencriptadas
adminHttps=Usar conexiones HTTPS (SSL) encriptadas
adminLocal=Permitir &uacute;nicamente conexiones locales
adminLogin=Registrar administraci&oacute;n
adminLoginCancel=Cancelar
adminLoginOk=Aceptar
adminLogout=Desconectar
adminOthers=Permitir conexiones desde otros ordenadores
adminPort=Puerto del servidor Web
adminRestart=Los cambios tendr&aacute;n efecto al reiniciar el servidor.
adminSave=Guardar
adminSessions=Sesiones activas
adminShutdown=Parar servidor
adminTitle=Preferencias de H2 Consola
helpAction=Action
helpAddAnotherRow=A&ntilde;adir otra fila
helpAddDrivers=A&ntilde;adiendo drivers de base de datos
helpAddDriversOnlyJava=Solo la versi&oacute;n Java soporta otros drivers (esta caracteristica no esta soportada por la versi&oacute;n nativa).
helpAddDriversText=Se pueden registrar otros drivers a&ntilde;adiendo el archivo Jar del driver a la variable de entorno H2DRIVERS o CLASSPATH. Por ejemplo (Windows): Para a&ntilde;adir la librer&iacute;a del driver de base de datos C:\\Programs\\hsqldb\\lib\\hsqldb.jar, hay que establecer la variable de entorno H2DRIVERS a C:\\Programs\\hsqldb\\lib\\hsqldb.jar.
helpAddRow=A&ntilde;adir una fila nueva
helpCommandHistory=Ver hist&oacute;rico de comandos
helpCreateTable=Crear una tabla nueva
helpDeleteRow=Borrar una fila
helpDisconnect=Desconectar de la base de datos.
helpDisplayThis=Visualizar esta p&aacute;gina de ayuda.
helpDropTable=Borrar la tabla si existe
helpExecuteCurrent=Ejecuta la actual sentencia SQL
helpIcon=Icon
helpImportantCommands=Comandos importantes
helpOperations=Operaciones
helpQuery=Consulta la tabla
helpSampleSQL=Ejemplo SQL Script
helpStatements=Sentencias SQL
helpUpdate=Modificar datos en una fila
helpWithColumnsIdName=con las columnas ID y NAME
login.connect=Conectar
login.driverClass=Controlador
login.driverNotFound=Controlador no encontrado
login.goAdmin=Preferencias
login.jdbcUrl=URL JDBC
login.language=Idioma
login.login=Registrar
login.remove=Eliminar
login.save=Guardar
login.savedSetting=Configuraciones guardadas
login.settingName=Nombre de la configuraci&oacute;n
login.testConnection=Probar la conexi&oacute;n
login.testSuccessful=Prueba correcta
login.welcome=H2 Consola
result.1row=1 fila
result.autocommitOff=El autocommit no est&aacute; activo
result.autocommitOn=El autocommit est&aacute; activo
result.maxrowsSet=N&uacute;mero m&aacute;ximo de filas modificado
result.noRows=No se han recuperado filas
result.noRunningStatement=No hay una instrucci&oacute;n ejecut&aacute;ndose
result.rows=filas
result.statementWasCancelled=La instrucci&oacute;n fue cancelada
result.updateCount=Modificaciones
resultEdit.add=A&ntilde;adir
resultEdit.cancel=Cancelar
resultEdit.delete=Eliminar
resultEdit.edit=Editar
resultEdit.editResult=Editar
resultEdit.save=Guardar
toolbar.all=Todos
toolbar.autocommit=Autocommit
toolbar.autocomplete=Auto-Completado
toolbar.autocomplete.off=Desactivado
toolbar.autocomplete.normal=Normal
toolbar.autocomplete.full=Completo
toolbar.cancelStatement=Cancelar la instrucci&oacute;n actual
toolbar.clear=Eliminar
toolbar.commit=Commit
toolbar.disconnect=Desconectar
toolbar.history=Hist&oacute;rico comandos
toolbar.maxRows=N&uacute;mero m&aacute;ximo de filas
toolbar.refresh=Actualizar
toolbar.rollback=Rollback
toolbar.run=Ejecutar (Ctrl+Enter)
toolbar.sqlStatement=Instrucci&oacute;n SQL
tree.admin=Administrador
tree.current=Valor actual
tree.hashed=Hash
tree.increment=Incremento
tree.indexes=&Iacute;ndices
tree.nonUnique=No &uacute;nico
tree.sequences=Secuencias
tree.unique=&Uacute;nico
tree.users=Usuarios
# Use the PropertiesToUTF8 tool to translate the files to UTF-8 and back
a.help=Aide
a.language=Fran&ccedil;ais
a.lynxNotSupported=D&eacute;sol&eacute;, Lynx n'est pas encore support&eacute;
a.password=Mot de passe
a.remoteConnectionsDisabled=D&eacute;sol&eacute;, la gestion des connexions provenant de machines distantes est d&eacute;sactiv&eacute;e sur ce serveur ('webAllowOthers').
a.title=Console H2
a.user=Nom d'utilisateur
admin.executing=#Executing
admin.ip=#IP
admin.lastAccess=#Last Access
admin.lastQuery=#Last Query
admin.url=#URL
adminAllow=Clients autoris&eacute;s
adminConnection=S&eacute;curit&eacute; des connexions
adminHttp=Utiliser des connexions HTTP non s&eacute;curis&eacute;es
adminHttps=Utiliser des connexions s&eacute;curis&eacute;es
adminLocal=Autoriser uniquement les connexions locales
adminLogin=Login administrateur
adminLoginCancel=Annuler
adminLoginOk=OK
adminLogout=D&eacute;connexion
adminOthers=Autoriser les connexions d'ordinateurs distants
adminPort=Num&eacute;ro de port du serveur Web
adminRestart=Modifications effectu&eacute;es apr&egrave; red&eacute;marrage du serveur.
adminSave=Enregistrer
adminSessions=Sessions actives
adminShutdown=#Shutdown
adminTitle=Console H2 de param&eacute;trage des options
helpAction=Action
helpAddAnotherRow=Ajouter un autre enregistrement
helpAddDrivers=Ajouter de drivers de base de donn&eacute;es
helpAddDriversOnlyJava=Seule la version Java permet d'ajouter des drivers suppl&eacute;mentaires. (Cette fonctionnalit&eacute; n'est pas support&eacute;e dans la version Native).
helpAddDriversText=Des drivers additionels peuvent &ecirc;tre configur&eacute;s en d&eacute;clarant l'emplacement du fichier Jar contenant ces drivers dans les variables d'environnement H2DRIVERS ou CLASSPATH. Exemple (Windows): Pour ajouter la librairie C:\\Programs\\hsqldb\\lib\\hsqldb.jar, d&eacute;finir la valeur de la variable d'environnement H2DRIVERS en C:\\Programs\\hsqldb\\lib\\hsqldb.jar.
helpAddRow=Ajouter un nouvel enregistrement
helpCommandHistory=Affiche l'historique des commandes
helpCreateTable=Cr&eacute;er une nouvelle table
helpDeleteRow=Effacer un enregistrement
helpDisconnect=D&eacute;connexion de la base de donn&eacute;es
helpDisplayThis=Affiche cette page d'aide
helpDropTable=Effacer une table si elle existe
helpExecuteCurrent=Ex&eacute;cute la commande courante
helpIcon=Icone
helpImportantCommands=Commandes principales
helpOperations=Op&eacute;rations
helpQuery=Requ&ecirc;ter une table
helpSampleSQL=Exemple de script SQL
helpStatements=Instructions SQL
helpUpdate=Modifier un enregistrement
helpWithColumnsIdName=avec les colonnes ID et NAME
login.connect=Connecter
login.driverClass=Pilote JDBC
login.driverNotFound=Driver non trouv&eacute;.<br>Veuillez consulter dans l'aide la proc&eacute;dure d'ajout de drivers.
login.goAdmin=Options
login.jdbcUrl=URL JDBC
login.language=Langue
login.login=Connexion
login.remove=Supprimer
login.save=Enregistrer
login.savedSetting=Configuration enregistr&eacute;e
login.settingName=Nom de configuration
login.testConnection=Test de connexion
login.testSuccessful=Succ&egrave;s
login.welcome=Console H2
result.1row=1 enregistrement
result.autocommitOff=Validation automatique non activ&eacute;e
result.autocommitOn=Validation automatique activ&eacute;e
result.maxrowsSet=Nombre max d'enregistrements d&eacute;fini
result.noRows=Aucun enregistrement
result.noRunningStatement=Pas d'instruction en cours
result.rows=enregistrements
result.statementWasCancelled=L'instruction a &eacute;t&eacute; annul&eacute;e
result.updateCount=Nombre de modifications
resultEdit.add=Ajouter
resultEdit.cancel=Annuler
resultEdit.delete=Supprimer
resultEdit.edit=Editer
resultEdit.editResult=Editer
resultEdit.save=Enregistrer
toolbar.all=Tous
toolbar.autocommit=Validation automatique (autocommit)
toolbar.autocomplete=#Auto-Complete
toolbar.autocomplete.off=#Off
toolbar.autocomplete.normal=#Normal
toolbar.autocomplete.full=#Full
toolbar.cancelStatement=Annuler l'instruction en cours
toolbar.clear=Effacer
toolbar.commit=Valider
toolbar.disconnect=D&eacute;connecter
toolbar.history=Historique des instructions
toolbar.maxRows=Max lignes
toolbar.refresh=Rafra&icirc;chir
toolbar.rollback=Revenir en arri&egrave;re
toolbar.run=Ex&eacute;cuter (Ctrl+Enter)
toolbar.sqlStatement=Instruction SQL
tree.admin=Administrateur
tree.current=Valeur actuelle
tree.hashed=Hach&eacute; (hashed)
tree.increment=Increment
tree.indexes=Indexes
tree.nonUnique=Non unique
tree.sequences=S&eacute;quences
tree.unique=Unique
tree.users=Utilisateurs
# Use the PropertiesToUTF8 tool to translate the files to UTF-8 and back
#Created by JInto - www.guh-software.de
#Mon Apr 10 14:14:45 CST 2006
#Author: junheng.song
#Email sjh21 (at) hot mail (dot) com
a.help=\u5E2E\u52A9
a.language=\u4E2D\u6587
a.lynxNotSupported=\u62B1\u6B49, \u76EE\u524D\u8FD8\u4E0D\u652F\u6301Lynx
a.password=\u5BC6\u7801
a.remoteConnectionsDisabled=\u62B1\u6B49, \u670D\u52A1\u5668\u4E0A\u7684\u8FDC\u7A0B\u8BA1\u7B97\u673A\u8FDE\u63A5\u88AB\u7981\u7528.
a.title=H2 \u63A7\u5236\u53F0
a.user=\u7528\u6237\u540D
admin.executing=\u6267\u884C
admin.ip=IP\u5730\u5740
admin.lastAccess=\u6700\u540E\u8BBF\u95EE
admin.lastQuery=\u6700\u540E\u67E5\u8BE2
admin.url=URL
adminAllow=\u5141\u8BB8\u8FDE\u63A5\u7684\u5BA2\u6237\u7AEF
adminConnection=\u8FDE\u63A5\u5B89\u5168
adminHttp=\u4F7F\u7528\u975E\u52A0\u5BC6\u7684 HTTP \u8FDE\u63A5
adminHttps=\u4F7F\u7528\u52A0\u5BC6\u7684 SSL (HTTPS) \u8FDE\u63A5
adminLocal=\u53EA\u5141\u8BB8\u672C\u5730\u8FDE\u63A5
adminLogin=\u7BA1\u7406\u5458\u767B\u5F55
adminLoginCancel=\u53D6\u6D88
adminLoginOk=\u786E\u8BA4
adminLogout=\u6CE8\u9500
adminOthers=\u5141\u8BB8\u6765\u81EA\u5176\u4ED6\u8FDC\u7A0B\u8BA1\u7B97\u673A\u7684\u8FDE\u63A5
adminPort=Web server \u7AEF\u53E3\u53F7
adminRestart=\u91CD\u542F\u670D\u52A1\u5668\u540E\u4FEE\u6539\u914D\u7F6E\u5C06\u751F\u6548.
adminSave=\u4FDD\u5B58
adminSessions=\u6D3B\u52A8\u7684\u4F1A\u8BDD
adminShutdown=\u5173\u95ED
adminTitle=H2 \u63A7\u5236\u53F0\u914D\u7F6E
helpAction=\u6D3B\u52A8
helpAddAnotherRow=\u589E\u52A0\u53E6\u4E00\u884C
helpAddDrivers=\u589E\u52A0\u6570\u636E\u5E93\u9A71\u52A8
helpAddDriversOnlyJava=\u53EA\u6709Java\u7248\u672C\u652F\u6301\u589E\u52A0\u9A71\u52A8\uFF08\u672C\u5730\u7248\u672C\u4E0D\u652F\u6301\u8FD9\u4E2A\u7279\u6027\uFF09\u3002
helpAddDriversText=\u53EF\u4EE5\u901A\u8FC7\u6DFB\u52A0\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CFH2DRIVERS \u6216\u8005 CLASSPATH \u6765\u589E\u52A0\u6570\u636E\u5E93\u9A71\u52A8\u6CE8\u518C\u3002\u4F8B\u5982\uFF08Windows\uFF09\uFF1A\u8981\u589E\u52A0\u6570\u636E\u5E93\u9A71\u52A8C:\\Programs\\hsqldb\\lib\\hsqldb.jar\uFF0C\u53EF\u4EE5\u589E\u52A0\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CFH2DRIVERS\u5E76\u8BBE\u7F6E\u5230C:\\Programs\\hsqldb\\lib\\hsqldb.jar\u3002
helpAddRow=\u589E\u52A0\u65B0\u7684\u4E00\u884C
helpCommandHistory=\u663E\u793A\u5386\u53F2SQL\u547D\u4EE4
helpCreateTable=\u521B\u5EFA\u4E00\u4E2A\u65B0\u8868
helpDeleteRow=\u5220\u9664\u4E00\u884C
helpDisconnect=\u65AD\u5F00\u6570\u636E\u5E93\u8FDE\u63A5
helpDisplayThis=\u663E\u793A\u5E2E\u52A9\u9875
helpDropTable=\u5982\u679C\u8868\u5B58\u5728\u5220\u9664\u5B83
helpExecuteCurrent=\u6267\u884C\u5F53\u524DSQL\u8BED\u53E5
helpIcon=\u56FE\u6807
helpImportantCommands=\u91CD\u8981\u7684\u547D\u4EE4
helpOperations=\u64CD\u4F5C
helpQuery=\u67E5\u8BE2\u8868
helpSampleSQL=\u6837\u4F8BSQL\u811A\u672C
helpStatements=SQL \u8BED\u53E5
helpUpdate=\u6539\u53D8\u4E00\u884C\u6570\u636E
helpWithColumnsIdName=\u7528ID\u548CNAME\u5217
login.connect=\u8FDE\u63A5
login.driverClass=\u9A71\u52A8\u7C7B
login.driverNotFound=\u6570\u636E\u5E93\u9A71\u52A8\u6CA1\u6709\u53D1\u73B0<br>\u8BF7\u53C2\u8003\u5E2E\u52A9\u53BB\u6DFB\u52A0\u6570\u636E\u5E93\u9A71\u52A8
login.goAdmin=\u914D\u7F6E
login.jdbcUrl=JDBC URL
login.language=\u8BED\u8A00
login.login=\u767B\u5F55
login.remove=\u5220\u9664
login.save=\u4FDD\u5B58
login.savedSetting=\u4FDD\u5B58\u7684\u8FDE\u63A5\u8BBE\u7F6E
login.settingName=\u8FDE\u63A5\u8BBE\u7F6E\u540D\u79F0
login.testConnection=\u6D4B\u8BD5\u8FDE\u63A5
login.testSuccessful=\u6D4B\u8BD5\u6210\u529F
login.welcome=H2 \u63A7\u5236\u53F0
result.1row=1 \u884C
result.autocommitOff=\u81EA\u52A8\u63D0\u4EA4\u73B0\u5728\u4E3A\u5173\u95ED
result.autocommitOn=\u81EA\u52A8\u63D0\u4EA4\u73B0\u5728\u4E3A\u6253\u5F00
result.maxrowsSet=\u6700\u5927\u8FD4\u56DE\u884C\u6570\u88AB\u8BBE\u7F6E
result.noRows=\u65E0\u8FD4\u56DE\u884C
result.noRunningStatement=\u5F53\u524D\u6CA1\u6709\u6B63\u5728\u6267\u884C\u7684SQL\u8BED\u53E5
result.rows=\u884C
result.statementWasCancelled=SQL \u8BED\u53E5\u88AB\u53D6\u6D88
result.updateCount=\u66F4\u65B0\u884C\u6570
resultEdit.add=\u589E\u52A0
resultEdit.cancel=\u53D6\u6D88
resultEdit.delete=\u5220\u9664
resultEdit.edit=\u7F16\u8F91
resultEdit.editResult=\u7F16\u8F91\u7ED3\u679C\u96C6
resultEdit.save=\u4FDD\u5B58
toolbar.all=\u5168\u90E8
toolbar.autocommit=\u81EA\u52A8\u63D0\u4EA4
toolbar.autocomplete=#Auto-Complete
toolbar.autocomplete.off=#Off
toolbar.autocomplete.normal=#Normal
toolbar.autocomplete.full=#Full
toolbar.cancelStatement=\u53D6\u6D88\u5F53\u524D\u7684\u6267\u884C\u8BED\u53E5
toolbar.clear=\u6E05\u9664
toolbar.commit=\u63D0\u4EA4
toolbar.disconnect=\u65AD\u5F00\u8FDE\u63A5
toolbar.history=\u5386\u53F2SQL\u547D\u4EE4
toolbar.maxRows=\u6700\u5927\u884C\u6570
toolbar.refresh=\u5237\u65B0
toolbar.rollback=\u56DE\u6EDA
toolbar.run=\u6267\u884C (Ctrl+Enter)
toolbar.sqlStatement=SQL \u8BED\u53E5
tree.admin=\u7BA1\u7406
tree.current=\u5F53\u524D\u503C
tree.hashed=\u6742\u4E71\u7684
tree.increment=\u589E\u52A0
tree.indexes=\u7D22\u5F15
tree.nonUnique=\u4E0D\u552F\u4E00
tree.sequences=\u5E8F\u5217
tree.unique=\u552F\u4E00
tree.users=\u7528\u6237
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript">
<!--
if(self != top) {
top.location = "admin.jsp";
}
//-->
</script>
</head>
<body style="margin: 20px">
<h1>
${text.adminTitle}
</h1>
<p>
<a href="index.do?jsessionid=${sessionId}">${text.adminLogout}</a>
</p>
<hr>
<form name="admin" method="post" action="/adminSave.do?jsessionid=${sessionId}">
<h3>
${text.adminAllow}
</h3>
<p>
<input type="radio" name="allowOthers" value="false" <c:if test="allowOthers=='false'">checked</c:if>> ${text.adminLocal}<br>
<input type="radio" name="allowOthers" value="true" <c:if test="allowOthers=='true'">checked</c:if>> ${text.adminOthers}<br>
</p>
<h3>
${text.adminConnection}
</h3>
<p>
<input type="radio" name="ssl" value="false" <c:if test="ssl=='false'">checked</c:if>> ${text.adminHttp}<br>
<input type="radio" name="ssl" value="true" <c:if test="ssl=='true'">checked</c:if>> ${text.adminHttps}<br>
</p>
<h3>
Port number
</h3>
<p>
${text.adminPort}: <input type="text" name="port" value="${port}">
</p>
<hr>
<p>
<input type="submit" class="button" value="${text.adminSave}">
</p>
<p>
${text.adminRestart}
</p>
<hr>
<h3>
${text.adminSessions}
</h3>
<table>
<tr>
<th>${text.admin.ip}</th>
<th>${text.admin.url}</th>
<th>${text.a.user}</th>
<th>${text.admin.executing}</th>
<th>${text.admin.lastAccess}</th>
<th>${text.admin.lastQuery}</th>
</tr>
<c:forEach var="item" items="sessions">
<tr>
<td>
${item.ip}
</td>
<td>
${item.url}
</td>
<td>
${item.user}
</td>
<td>
${item.executing}
</td>
<td>
${item.lastAccess}
</td>
<td>
${item.lastQuery}
</td>
</tr>
</c:forEach>
</table>
<p>
<a href="adminShutdown.do?jsessionid=${sessionId}">${text.adminShutdown}</a>
</p>
</form>
</body>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript">
<!--
if(self != top) {
top.location = "adminLogin.jsp";
}
//-->
</script>
</head>
<body style="margin: 20px">
<form name="adminLogin" method="post" action="/admin.do?jsessionid=${sessionId}">
<table class="login" cellspacing=0 cellpadding=0>
<tr class="login">
<th class="login">${text.adminLogin}</th>
<th class="login"></th>
</tr>
<tr><td class="login" colspan=2></td></tr>
<tr class="login">
<td class="login">${text.a.password}:</td>
<td class="login"><input type="password" name="password" value="" style="width:200px;"></td>
</tr>
<tr class="login">
<td class="login"></td>
<td class="login">
<input type="submit" class="button" value="${text.adminLoginOk}">
&nbsp;
<input type="button" class="button" value="${text.adminLoginCancel}" onclick="javascript:document.adminLogin.action='/index.do?jsessionid=${sessionId}';submit()">
<br>
<br>
</td>
</tr>
</table>
<br>
<p class="error">${error}</p>
</form>
<script type="text/javascript">
<!--
document.adminLogin.password.focus();
//-->
</script>
</body>
\ No newline at end of file
${autoCompleteList}
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body margin=10>
<p class="error">
${error}
</p>
</body>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<frameset cols="*" rows="36,*" frameborder="2" framespacing="4" border="4" >
<frame noresize frameborder="0" marginheight=0 marginwidth=0 src="header.jsp?jsessionid=${sessionId}" name="header" scrolling="no">
<frameset cols="200,*" rows="*" frameborder="2" framespacing="4" border="4" >
<frame frameborder="0" marginheight=0 marginwidth=0 src="tables.do?jsessionid=${sessionId}" name="h2menu">
<frameset rows="180,*" frameborder="2" framespacing="4" border="4" >
<frame frameborder="0" marginheight=0 marginwidth=0 src="query.jsp?jsessionid=${sessionId}" name="h2query" scrolling="no">
<frame frameborder="0" marginheight=0 marginwidth=0 src="resultHelp.jsp?jsessionid=${sessionId}" name="h2result">
</frameset>
</frameset>
</frameset>
<noframes>
<body>
${text.a.lynxNotSupported}
</body>
</noframes>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body bgcolor="#FF00FF" class="toolbar">
<form name="header" method="post" action="/header.jsp?jsessionid=${sessionId}">
<table class="toolbar" cellspacing=0 cellpadding=0><tr class="toolbar"><td class="toolbar"
><a href="logout.do?jsessionid=${sessionId}" target="_top"
><img src="icon_disconnect.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.disconnect}" title="${text.toolbar.disconnect}" border="1"/></a
><img src="icon_line.gif" class="iconLine" alt=""
/><a href="tables.do?jsessionid=${sessionId}" target="h2menu"
><img src="icon_refresh.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.refresh}" title="${text.toolbar.refresh}" border="1"/></a
><img src="icon_line.gif" class="iconLine" alt=""
/></td><td class="toolbar"><input type="checkbox" name="autocommit" value="autocommit" ${autocommit}
onclick="javascript:if(document.header.autocommit.checked)
top.frames['h2result'].document.location='query.do?jsessionid=${sessionId}&amp;sql=@AUTOCOMMIT+TRUE';
else
top.frames['h2result'].document.location='query.do?jsessionid=${sessionId}&amp;sql=@AUTOCOMMIT+FALSE';
"
></td><td class="toolbar">${text.toolbar.autocommit}&nbsp;</td><td class="toolbar"
><a href="query.do?jsessionid=${sessionId}&amp;sql=ROLLBACK" target="h2result"
><img src="icon_rollback.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.rollback}" title="${text.toolbar.rollback}" border="1"/></a
><a href="query.do?jsessionid=${sessionId}&amp;sql=COMMIT" target="h2result"
><img src="icon_commit.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.commit}" title="${text.toolbar.commit}" border="1"/></a
><img src="icon_line.gif" class="iconLine" alt=""
/></td><td class="toolbar">&nbsp;${text.toolbar.maxRows}:&nbsp;</td><td class="toolbar"
><select name="rowcount" size="1"
onchange="javascript:top.frames['h2result'].document.location='query.do?jsessionid=${sessionId}&amp;sql=@SET+MAXROWS+'+header.rowcount.value;"
><option value="0">${text.toolbar.all}</option><option value="10000">10000</option><option selected value="1000">1000</option><option value="100"
>100</option><option value="10">10</option></select
>&nbsp;</td><td class="toolbar"><a href="javascript:top.frames['h2query'].document.forms['h2query'].submit();"
><img src="icon_run.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.run}" title="${text.toolbar.run}" border="1"/></a
></td><td class="toolbar"><a href="query.do?jsessionid=${sessionId}&amp;sql=@CANCEL" target="h2result"
><img src="icon_stop.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.cancelStatement}" title="${text.toolbar.cancelStatement}" border="1"/></a
><img src="icon_line.gif" class="iconLine" alt=""
/><a href="query.do?jsessionid=${sessionId}&amp;sql=@HISTORY" target="h2result"
><img src="icon_history.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.toolbar.history}" title="${text.toolbar.history}" border="1"/></a
><img src="icon_line.gif" class="iconLine" alt=""
/></td><td class="toolbar">${text.toolbar.autocomplete}&nbsp;<select name="autocomplete" size="1"
onchange="javascript:top.frames['h2query'].setAutocomplete(this.value)"
><option value="0">${text.toolbar.autocomplete.off}</option>
<option selected value="1">${text.toolbar.autocomplete.normal}</option>
<option value="2">${text.toolbar.autocomplete.full}</option>
</select
></td
><td class="toolbar"
><a href="resultHelp.jsp?jsessionid=${sessionId}" target="h2result"
><img src="icon_help.gif"
onmouseover = "this.className ='icon_hover'"
onmouseout = "this.className ='icon'"
class="icon" alt="${text.a.help}" title="${text.a.help}" border="1"/></a
></td></tr></table>
</form>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body style="margin: 10px;">
<%@ include file="help.txt" %>
</body>
<script type="text/javascript">
<!--
function set(s) {
top.h2query.document.h2query.sql.value = s;
}
//-->
</script>
<h3>${text.helpImportantCommands}</h3>
<table>
<tr><th>${text.helpIcon}</th><th>${text.helpAction}</th></tr>
<tr>
<td style="padding:0px"><img src="icon_help.gif" alt="${text.a.help}"></td>
<td style="vertical-align: middle;">
${text.helpDisplayThis}
</td>
</tr>
<tr>
<td style="padding:0px"><img src="icon_history.gif" alt="${text.toolbar.history}"></td>
<td style="vertical-align: middle;">
${text.helpCommandHistory}
</td>
</tr>
<tr>
<td style="padding:0px"><img src="icon_run.gif" alt="${text.toolbar.run}"></td>
<td style="vertical-align: middle;">
${text.helpExecuteCurrent}
</td>
</tr>
<tr>
<td style="padding:0px"><img src="icon_disconnect.gif" alt="${text.toolbar.disconnect}"></td>
<td style="vertical-align: middle;">
${text.helpDisconnect}
</td>
</tr>
</table>
<h3>${text.helpSampleSQL}</h3>
<table><tr><th>${text.helpOperations}</th><th>${text.helpStatements}</th></tr>
<tr><td><a href="javascript:set('DROP TABLE IF EXISTS TEST;\rCREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));\rINSERT INTO TEST VALUES(1, \'Hello\');\rINSERT INTO TEST VALUES(2, \'World\');\rSELECT * FROM TEST ORDER BY ID;\rUPDATE TEST SET NAME=\'Hi\' WHERE ID=1;\rDELETE FROM TEST WHERE ID=2;');">
${text.helpDropTable}<br>
${text.helpCreateTable}<br>
&nbsp;&nbsp;${text.helpWithColumnsIdName}<br>
${text.helpAddRow}<br>
${text.helpAddAnotherRow}<br>
${text.helpQuery}<br>
${text.helpUpdate}<br>
${text.helpDeleteRow}
</a></td><td>
DROP TABLE IF EXISTS TEST;<br>
CREATE TABLE TEST(ID INT PRIMARY KEY,<br>
&nbsp;&nbsp; NAME VARCHAR(255));<br>
INSERT INTO TEST VALUES(1, 'Hello');<br>
INSERT INTO TEST VALUES(2, 'World');<br>
SELECT * FROM TEST ORDER BY ID;<br>
UPDATE TEST SET NAME='Hi' WHERE ID=1;<br>
DELETE FROM TEST WHERE ID=2;
</td></tr>
</table>
<h3>${text.helpAddDrivers}</h3>
${text.helpAddDriversText}
<p>
${text.helpAddDriversOnlyJava}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript">
location.href = 'login.jsp?jsessionid=${sessionId}';
</script>
</head>
<body style="margin: 20px;">
<h1>Welcome to H2</h1>
<h2>No Javascript</h2>
If you are not automatically redirected to the login page, then
Javascript is currently disabled or your browser does not support Javascript.
For this application to work, Javascript is essential.
Please enable Javascript now, or use another web browser that supports it.
</body>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.login.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript">
if(self != top) {
top.location = "login.jsp";
}
</script>
</head>
<body style="margin: 20px">
<form name="login" method="post" action="/login.do?jsessionid=${sessionId}" id="login">
<p> <select name="language" size="1"
onchange="javascript:document.location='index.do?jsessionid=${sessionId}&amp;language='+login.language.value;"
>
${languageCombo}
</select>
&nbsp;&nbsp; <a href="admin.do?jsessionid=${sessionId}">${text.login.goAdmin}</a>
&nbsp;&nbsp; <a href="help.jsp?jsessionid=${sessionId}">${text.a.help}</a>
</p>
<table class="login" cellspacing=0 cellpadding=0>
<tr class="login">
<th class="login">${text.login.login}</th>
<th class="login"></th>
</tr>
<tr><td class="login" colspan=2></td></tr>
<tr class="login">
<td class="login">${text.login.savedSetting}:</td>
<td class="login">
<select name="setting" size="1"
style="width:300px"
onchange="javascript:document.location='index.do?jsessionid=${sessionId}&amp;setting='+login.setting.value;"
>
${settingsList}
</select>
</td>
</tr>
<tr class="login">
<td class="login">${text.login.settingName}:</td>
<td class="login">
<input type="text" name="name" value="${name}" style="width:200px;">
<input type="button" class="button" value="${text.login.save}" onclick="javascript:document.login.action='/settingSave.do?jsessionid=${sessionId}';submit()">
<input type="button" class="button" value="${text.login.remove}" onclick="javascript:document.login.action='/settingRemove.do?jsessionid=${sessionId}';submit()">
</td>
</tr>
<tr class="login">
<td class="login" colspan=2>
<hr>
</td>
</tr>
<tr class="login">
<td class="login">${text.login.driverClass}:</td>
<td class="login"><input type="text" name="driver" value="${driver}" style="width:300px;"></td>
</tr>
<tr class="login">
<td class="login">${text.login.jdbcUrl}:</td>
<td class="login"><input type="text" name="url" value="${url}" style="width:300px;"></td>
</tr>
<tr class="login">
<td class="login">${text.a.user}:</td>
<td class="login"><input type="text" name="user" value="${user}" style="width:200px;"></td>
</tr>
<tr class="login">
<td class="login">${text.a.password}:</td>
<td class="login"><input type="password" name="password" value="" style="width:200px;"></td>
</tr>
<tr class="login">
<td class="login"></td>
<td class="login">
<input type="submit" class="button" value="${text.login.connect}">
&nbsp;
<input type="button" class="button" value="${text.login.testConnection}" onclick="javascript:document.login.action='/test.do?jsessionid=${sessionId}';submit()">
<br>
<br>
</td>
</tr>
</table>
<br>
<p class="error">${error}</p>
</form>
</body>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript">
<!--
if(self != top) {
top.location = "main.jsp";
}
//-->
</script>
</head>
<body margin=10>
<h1>Welcome to H2</h1>
<h2><a href="index.jsp">Connect</a></h2>
Login to a database.
<h2><a href="docs.jsp">Documentation</a></h2>
View the online documentation.
<h2><a href="admin.jsp">Preferences</a></h2>
Allows to you to view and change server settings.
</body>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
</head>
<body style="margin: 20px">
<h1>${text.a.title}</h1>
<p>
${text.a.remoteConnectionsDisabled}
</p>
</body>
\ No newline at end of file
<!-- can not use doctype -->
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<script type="text/javascript">
var agent=navigator.userAgent.toLowerCase();
var is_opera = agent.indexOf("opera") >= 0;
var autocomplete = 1;
var selectedRow = -1;
var lastList = '';
var lastQuery = null;
var columnsByTable = new Object();
var tableAliases = new Object();
var showAutocompleteWait = 0;
var req;
function refreshTables() {
columnsByTable = new Object();
var tables = top.frames['h2menu'].tables;
for(var i=0; i<tables.length; i++) {
columnsByTable[tables[i].name] = tables[i].columns;
}
}
function sizeTextArea() {
var height=document.body.clientHeight;
var sql = document.h2query.sql;
sql.style.height=(height-sql.offsetTop)+'px';
}
function buildTableAliases(input) {
tableAliases = new Object();
var list = splitSQL(input);
var last = "";
for(var i=0; i<list.length; i++) {
var word = list[i].toUpperCase();
if(word != "AS") {
if(columnsByTable[last]) {
tableAliases[word] = last;
}
last = word;
}
}
}
function splitSQL(s) {
var list = new Array();
s = s.toUpperCase() + ' ';
var e = s.length;
for(var i=0; i<e; i++) {
var ch = s.charAt(i);
if(ch == '_' || (ch >= 'A' && ch <= 'Z')) {
var start = i;
do {
ch = s.charAt(++i);
} while(ch == '_' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z'));
list[list.length] = s.substring(start, i);
}
}
return list;
}
function help() {
var input = document.h2query.sql;
setSelection(input);
var pos = input.selectionStart;
if(pos > 0) {
var s = input.value.substring(0, pos).toUpperCase();
var e = pos-1;
for(; e>=0; e--) {
var ch = s.charAt(e);
if(ch != '_' && (ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z')) {
break;
}
}
s = s.substring(e+1, s.length);
buildTableAliases(input.value);
if(!columnsByTable[s]) {
s = tableAliases[s];
}
if(columnsByTable[s]) {
if(top.h2menu.goToTable(s)) {
top.h2menu.document.location='tables.do?jsessionid=${sessionId}#' + s;
// top.h2menu.window.blur();
document.h2query.sql.focus();
}
}
}
}
function setSelection(element) {
if(document.all && !is_opera) {
var range = document.selection.createRange();
var copy = range.duplicate();
copy.moveToElementText(element);
copy.setEndPoint('EndToEnd', range);
element.selectionStart = copy.text.length - range.text.length;
element.selectionEnd = element.selectionStart + range.text.length;
}
}
function set(field, combo) {
field.value=combo.value;
combo.value='';
field.focus();
}
function trim(s) {
while(s.charAt(0)==' ' && s.length>0) {
s=s.substring(1);
}
while(s.charAt(s.length-1)==' ' && s.length>0) {
s=s.substring(0, s.length-1);
}
return s;
}
function trimCommas(s) {
while(s.charAt(0)==',' && s.length>0) {
s=s.substring(1);
}
while(s.charAt(s.length-1)==',' && s.length>0) {
s=s.substring(0, s.length-1);
}
return s;
}
function insert(field, combo) {
insertText(combo.value);
combo.value='';
}
function insertText(s, isTable) {
s = decodeURIComponent(s);
var field = document.h2query.sql;
var last = s.substring(s.length-1);
if(last != '.' && last != '\'' && last != '"' && last > ' ') {
s += ' ';
}
if(isTable && trim(field.value)=='') {
field.value = 'SELECT * FROM ' + s;
} else {
if (document.selection) {
// IE
field.focus();
sel = document.selection.createRange();
sel.text = s;
} else if (field.selectionStart || field.selectionStart == '0') {
// Firefox
var startPos = field.selectionStart;
var endPos = field.selectionEnd;
field.value = field.value.substring(0, startPos) + s + field.value.substring(endPos, field.value.length);
var pos = endPos + s.length;
field.selectionStart = pos;
field.selectionEnd = pos;
} else {
field.value += s;
}
}
field.focus();
}
function keyUp() {
if(autocomplete != 0) {
showAutocomplete();
}
return true;
}
function showAutocomplete() {
if(showAutocompleteWait==0) {
showAutocompleteWait=5;
setTimeout('showAutocompleteNow()', 100);
} else {
showAutocompleteWait--;
}
}
function showAutocompleteNow() {
var input = document.h2query.sql;
setSelection(input);
var pos = input.selectionStart;
var s = input.value.substring(0, pos);
if(s != lastQuery) {
lastQuery = s;
retrieveList(s);
}
showAutocompleteWait = 0;
}
function keyDown(event) {
var key=event.keyCode? event.keyCode : event.charCode;
if(key == null) {
return false;
}
if (key == 13 && event.ctrlKey) {
document.h2query.submit();
return false;
} else if(key == 32 && event.ctrlKey) {
showAutocomplete();
return false;
} else if(key == 190 && autocomplete==0) {
help();
return true;
}
var table = getAutocompleteTable();
if(table.rows.length > 0) {
if(key == 27) {
while(table.rows.length > 0) {
table.deleteRow(0);
}
showOutput('');
return false;
} else if((key == 13 && !event.shiftKey) || (key==9 && !event.shiftKey)) {
if(table.rows.length > selectedRow) {
var row = table.rows[selectedRow];
if(row.cells.length>1) {
insertText(row.cells[1].innerHTML);
}
if(autocomplete == 0) {
setAutocomplete(0);
}
return false;
}
} else if(key == 38 && !event.shiftKey) {
if(table.rows.length > selectedRow) {
selectedRow = selectedRow <= 0 ? table.rows.length-1 : selectedRow-1;
highlightRow(selectedRow);
}
return false;
} else if(key == 40 && !event.shiftKey) {
if(table.rows.length > selectedRow) {
selectedRow = selectedRow >= table.rows.length-1 ? 0 : selectedRow+1;
highlightRow(selectedRow);
}
return false;
}
}
return true;
// alert('key:' + key);
// bs:8 ret:13 lt:37 up:38 rt:39 dn:40 tab:9
// pgup:33 pgdn:34 home:36 end:35 del:46 shift:16
// ctrl,altgr:17 alt:18 caps:20 5(num):12 ins:45
// pause:19 f1..13:112..123 win-start:91 win-ctx:93 esc:27
}
function setAutocomplete(value) {
autocomplete = value;
if(value != 1) {
var s = lastList;
lastList = '';
showList(s);
} else {
var table = getAutocompleteTable();
while(table.rows.length > 0) {
table.deleteRow(0);
}
showOutput('');
}
}
function highlightRow(row) {
if(row != null) {
selectedRow = row;
}
var table = getAutocompleteTable();
highlightThisRow(table.rows[selectedRow]);
}
function highlightThisRow(row) {
var table = getAutocompleteTable();
for(var i=0; i<table.rows.length; i++) {
var r = table.rows[i];
var col = (r == row) ? '#95beff' : '';
var cells = r.cells;
if(cells.length > 0) {
cells[0].style.backgroundColor = col;
}
}
showOutput('none');
}
function getAutocompleteTable() {
return top.h2result.document.getElementById('h2auto');
// return top.frames['h2result'].document.getElementById('h2auto');
// return top.h2menu.h2result.document.getElementById('h2auto');
}
function showOutput(x) {
// top.h2result.document.getElementById('output').style.display=x;
}
function showList(s) {
if(lastList == s) {
return;
}
lastList = s;
var list = s.length == 0 ? null : s.split('|');
var table = getAutocompleteTable();
if(table == null) {
return;
}
while(table.rows.length > 0) {
table.deleteRow(0);
}
if(autocomplete==0) {
return;
}
selectedRow = 0;
var count = 0;
var doc = top.h2result.document;
var tbody = table.tBodies[0];
for(var i=0; list != null && i<list.length; i++) {
var kv = list[i].split('#');
var type = kv[0];
if(type > 0 && autocomplete != 2) {
continue;
}
var row = doc.createElement("tr");
tbody.appendChild(row);
var cell = doc.createElement("td");
var key = kv[1];
var value = kv[2];
if(!key || !value) {
break;
}
count++;
cell.className = 'autocomp' + type;
key = decodeURIComponent(key);
row.onmouseover = function(){highlightThisRow(this)};
if(!document.all || is_opera) {
row.onclick = function(){insertText(this.cells[1].innerHTML);keyUp()};
}
// addEvent(row, "click", function(e){var row=e?e.target:window.event.srcElement;alert(row);insertText(row.cells[1].innerHTML)});
// addEvent(row, "mouseover", function(e){var row=e?e.target:window.event.srcElement;alert(row);highlightThisRow(row)});
// addEvent(row, "click", function(e){var row=e?e.target:window.event.srcElement;alert(row);insertText(row.cells[1].innerHTML)});
// addEvent(row, "mouseover", eval('function(){highlightRow('+i+')}'));
// addEvent(row, "click", eval('function(){insertText(\''+value+'\')}'));
var text = doc.createTextNode(key);
cell.appendChild(text);
row.appendChild(cell);
cell = doc.createElement("td");
cell.style.display='none';
text = doc.createTextNode(value);
cell.appendChild(text);
row.appendChild(cell);
}
if(count > 0) {
highlightRow();
showOutput('none');
} else {
showOutput('');
}
}
function retrieveList(s) {
sendAsyncRequest('/autoCompleteList.do?jsessionid=${sessionId}&query=' + encodeURIComponent(s));
}
function addEvent(element, eventType, fn) {
// cross-browser event handling for IE5+, NS6 and Mozilla by Scott Andrew
if(fn == null) {
return;
}
if (element.addEventListener) {
element.addEventListener(eventType, fn, true);
return true;
} else if (element.attachEvent){
return element.attachEvent('on'+eventType, fn);
} else {
alert('Event handler could not be added');
}
}
function sendAsyncRequest(url) {
req = false;
if(window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch(e) {
req = false;
}
} else if(window.ActiveXObject) {
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
req = false;
}
}
}
if(req) {
req.onreadystatechange = processAsyncResponse;
req.open("GET", url, true);
req.send("");
} else {
var getlist = document.getElementById('h2iframeTransport');
getlist.src = url;
}
}
function processAsyncResponse() {
if (req.readyState == 4) {
if (req.status == 200) {
showList(req.responseText);
} else {
// alert('Could not retrieve data');
}
}
}
</script>
</head>
<body onresize="sizeTextArea();" onload="sizeTextArea();" style="margin: 0px; padding: 0px;">
<form name="h2query" method="post" action="/query.do?jsessionid=${sessionId}" target="h2result">
<input type="button" class="button" value="${text.toolbar.run}" onclick="javascript:submit();sql.focus();return true;">
<input type="button" class="button" value="${text.toolbar.clear}" onclick="javascript:sql.value='';keyUp();sql.focus();return true;">
${text.toolbar.sqlStatement}:
<div style="display:none">
<iframe id="h2iframeTransport" src="" onload="showList(this.contentWindow.document.body.innerHTML);"></iframe>
</div>
<textarea id="sql" name="sql" cols="80" rows="5" onkeydown="return keyDown(event)" onkeyup="return keyUp()"
onfocus="keyUp()" onchange="return keyUp()">${query}</textarea>
</form>
</body>
</html>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript" src="table.js"></script>
</head>
<body class="result">
<div id="output">
${result}
</div>
<table id="h2auto" name="h2auto" class="autocomp"><tbody></tbody></table>
</body></html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body class="result">
<div id="output">
<%@ include file="help.txt" %>
</div>
<table id="h2auto" name="h2auto" class="autocomp"><tbody></tbody></table>
</body></html>
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
td, input, select, textarea, body, code, pre {
font-family: Tahoma, helvetica, sans-serif;
font-size: 8pt;
}
body {
margin: 4px;
}
h1 {
border-bottom: 1px solid #CCC;
color: #800;
font-size: 16pt;
line-height: normal;
}
h2 {
border-bottom: 1px solid #CCC;
color: #800;
font-size: 13pt;
}
h3 {
color: #800;
font-size: 10pt;
}
ul {
list-style-type: circle;
list-style-position: outside;
padding-left: 20px;
}
li {
margin-top: 6px;
}
.toolbar {
background-color: #ece9d8;
}
.result {
background-color: #f4f0e0;
margin: 10px;
}
table.toolbar {
background-color: #ffffff;
border-collapse: collapse;
border: 0px;
padding: 0px 0px;
}
th.toolbar {
border: 0px;
}
tr.toolbar {
border: 0px;
}
td.toolbar {
vertical-align: middle;
border: 0px;
padding: 0px 0px;
}
table.login {
background-color: #ece9d8;
border:1px solid #aca899;
}
tr.login {
border: 0px;
}
th.login {
color: #ffffff;
font-size: 10pt;
text-align: left;
border: 0px;
background-color: #ece9d8;
padding: 5px 10px;
background-image: url(background.gif);
}
td.login {
background-color: #ece9d8;
font-size: 8pt;
padding: 5px 10px;
text-align: left;
border: 0px;
}
.iconLine {
border-width:0px;
border-style:solid;
}
.icon {
border-top-color:#ece9d8;
border-left-color:#ece9d8;
border-right-color:#ece9d8;
border-bottom-color:#ece9d8;
border-width:1px;
border-style:solid;
}
.icon_hover {
border-top-color:#ffffff;
border-left-color:#ffffff;
border-right-color:#aca899;
border-bottom-color:#aca899;
border-width:1px;
border-style:solid;
}
table.empty {
background-color: #ffffff;
border: 0px;
}
td.empty {
background-color: #ffffff;
border: 0px;
font-size: 8pt;
padding: 5px 10px;
text-align: left;
}
.error {
color: #ff0000;
}
p.error {
color: #ff0000;
}
table {
background-color: #ffffff;
border-collapse: collapse;
border: 1px solid #aca899;
}
th {
font-size: 8pt;
font-weight: normal;
text-align: left;
background-color: #ece9d8;
padding: 2px;
border: 1px solid #aca899;
}
td {
background-color: #ffffff;
font-size: 8pt;
padding: 2px;
text-align: left;
vertical-align:top;
border: 1px solid #aca899;
}
form {
}
textarea {
width: 100%;
overflow: auto;
}
input.button {
padding: 1px;
}
/*
border-style: solid;
border-width: 1px;
background-color: #eeeeee;
border-top-color: #aaaaaa;
border-left-color: #aaaaaa;
border-bottom-color: #222222;
border-right-color: #222222;
*/
textarea {
}
select {
}
ul {
list-style-type: disc;
list-style-position: outside;
}
li {
}
ol {
list-style-type: upper-roman;
list-style-position: outside;
}
a {
text-decoration: none;
color: #0000ff;
}
a:hover {
text-decoration: underline;
}
.tree {
border: 0px;
vertical-align: middle;
white-space: nowrap;
}
.tree img {
height: 18px;
width: 18px;
border: 0px;
vertical-align: middle;
}
.tree a {
border: 0px;
text-decoration: none;
vertical-align: middle;
white-space: nowrap;
color: #000000;
}
.tree a:hover {
color: #345373;
}
table.content {
width: 100%;
height: 100%;
border: 0px;
}
tr.content {
border:0px;
border-left:1px solid #aca899;
}
td.content {
border:0px;
border-left:1px solid #aca899;
}
tr.contentResult {
border:0px;
border-top:1px solid #aca899;
border-left:1px solid #aca899;
}
td.contentResult {
border:0px;
border-top:1px solid #aca899;
border-left:1px solid #aca899;
}
.contentDiv {
margin:10px;
}
table.autocomp {
background-color: #e0ecff;
border: 1px solid #7f9db9;
cursor: pointer;
position: absolute;
top: 1px;
left: 1px;
z-index:0;
padding: 0px;
margin: 0px;
border-spacing:2px;
}
td.autocomp0 {
border-spacing: 0px;
padding: 1px 8px;
background-color: #cce0ff;
border: 0px;
}
td.autocomp1 {
border-spacing: 0px;
padding: 1px 8px;
background-color: #e7f0ff;
border: 0px;
}
td.autocomp2 {
border-spacing: 0px;
padding: 1px 8px;
background-color: #ffffff;
border: 0px;
}
td.autocompHide {
padding: 2px;
display: none;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
addEvent(window, "load", initSort);
function addEvent(elm, evType, fn, useCapture) {
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
if (elm.addEventListener){
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent){
var r = elm.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be added");
}
}
function initSort() {
if(document.getElementById('editing') != undefined) {
// don't allow sorting while editing
return;
}
var tables = document.getElementsByTagName("table");
for (var i=0; i<tables.length; i++) {
table = tables[i];
if (table.rows && table.rows.length > 0) {
var header = table.rows[0];
for(var j=0;j<header.cells.length;j++) {
var cell = header.cells[j];
var text = cell.innerHTML;
cell.innerHTML = '<a href="#" style="text-decoration: none;" class="sortheader" onclick="resortTable(this);">'+text+'<span class="sortarrow">&nbsp;&nbsp;</span></a>';
}
}
}
}
function editRow(row, session, write, undo) {
var table = document.getElementById('editTable');
var y = row < 0 ? table.rows.length - 1 : row;
var i;
for(i=1; i<table.rows.length; i++) {
var cell = table.rows[i].cells[0];
if(i == y) {
var edit = '<img width=16 height=16 src="ico_ok.gif" onclick="javascript:editing.op.value=\'1\';editing.row.value=\''+row+'\';editing.submit()" onmouseover = "this.className =\'icon_hover\'" onmouseout = "this.className=\'icon\'" class="icon" alt="'+write+'" title="'+write+'" border="1">';
var undo = '<img width=16 height=16 src="ico_undo.gif" onclick="javascript:editing.op.value=\'3\';editing.row.value=\''+row+'\';editing.submit()" onmouseover = "this.className =\'icon_hover\'" onmouseout = "this.className=\'icon\'" class="icon" alt="'+undo+'" title="'+undo+'" border="1">';
cell.innerHTML = edit + undo;
} else {
cell.innerHTML = '';
}
}
var cells = table.rows[y].cells;
for(i=1; i<cells.length; i++) {
var cell = cells[i];
var text = getInnerText(cell);
cell.innerHTML = '<input type="text" name="r'+row+'c' + i + '" value="'+text+'" size="' + (text.length+5) + '">';
}
}
function getInnerText(el) {
if (typeof el == "string") return el;
if (typeof el == "undefined") { return el };
if (el.innerText) {
// not needed but it is faster
return el.innerText;
}
var str = "";
var cs = el.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
str += getInnerText(cs[i]);
break;
case 3: //TEXT_NODE
str += cs[i].nodeValue;
break;
}
}
return str;
}
function resortTable(lnk) {
// get the span
var span;
for (var ci=0;ci<lnk.childNodes.length;ci++) {
if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') {
span = lnk.childNodes[ci];
}
}
var spantext = getInnerText(span);
var td = lnk.parentNode;
var column = td.cellIndex;
var table = getParent(td,'TABLE');
if (table.rows.length <= 1) return;
// detect sort type
var sortNumeric = false;
var x = getInnerText(table.rows[1].cells[column]);
if (x.match(/^[\d\.]+$/)) {
sortNumeric = true;
}
//alert("start copy");
var newRows = new Array();
var rows = table.rows;
for (i=1; i<rows.length; i++) {
var o = new Object();
o.data = rows[i];
o.id = i;
if(sortNumeric) {
o.sort = parseFloat(getInnerText(o.data.cells[column]));
if (isNaN(o.sort)) o.sort = 0;
} else {
o.sort = getInnerText(o.data.cells[column]);
}
newRows[i-1] = o;
}
//alert("start sort");
newRows.sort(sortCallback);
var arrow;
if (span.getAttribute("sortdir") == 'down') {
arrow = '&nbsp;<img src="sort_up.gif" with=7 height=10 border=0>';
newRows.reverse();
span.setAttribute('sortdir','up');
} else {
arrow = '&nbsp;<img src="sort_down.gif" with=7 height=10 border=0>';
span.setAttribute('sortdir','down');
}
//alert("start move");
// we appendChild rows that already exist to the tbody,
// so it moves them rather than creating new ones
var body = table.tBodies[0];
for (i=0; i<newRows.length; i++) {
body.appendChild(newRows[i].data);
}
//alert("end");
// delete any other arrows there may be showing
var allspans = document.getElementsByTagName("span");
for (var i=0;i<allspans.length;i++) {
if (allspans[i].className == 'sortarrow') {
// in the same table as us?
if (getParent(allspans[i],"table") == getParent(lnk,"table")) {
allspans[i].innerHTML = '&nbsp;&nbsp;';
}
}
}
span.innerHTML = arrow;
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
// Gecko bug, supposed to be uppercase
return el;
} else {
return getParent(el.parentNode, pTagName);
}
}
function sortCallback(ra, rb) {
return (ra.sort==rb.sort) ? (ra.id-rb.id) : (ra.sort<rb.sort ? -1 : 1);
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
Initial Developer: H2 Group
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>${text.a.title}</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<script type="text/javascript" src="tree.js"></script>
<script type="text/javascript">
<!--
${tree}
//-->
</script>
</head>
<body>
<div class="tree">
<script type="text/javascript">
<!--
writeTree();
//-->
</script>
</div>
<p class="error">
${error}
</p>
</body>
</html>
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
var nodeList = new Array();
var icons = new Array();
var tables = new Array();
var tablesByName = new Object();
function Table(name, columns, i) {
this.name = name;
this.columns = columns;
this.id = i;
}
function addTable(name, columns, i) {
var t = new Table(name, columns, i);
tables[tables.length] = t;
tablesByName[name] = t;
}
function ins(s, isTable) {
if(top.h2query) {
if(top.h2query.insertText) {
top.h2query.insertText(s, isTable);
}
}
}
function refreshQueryTables() {
if(top.frames['h2query']) {
if(top.frames['h2query'].refreshTables) {
top.frames['h2query'].refreshTables();
}
}
}
function goToTable(s) {
var t = tablesByName[s];
if(t) {
hitOpen(t.id);
return true;
}
return false;
}
function loadIcons() {
icons[0] = new Image();
icons[0].src = "tree_minus.gif";
icons[1] = new Image();
icons[1].src = "tree_plus.gif";
}
function Node(level, type, icon, text, link) {
this.level = level;
this.type = type;
this.icon = icon;
this.text = text;
this.link = link;
}
function setNode(id, level, type, icon, text, link) {
nodeList[id] = new Node(level, type, icon, text, link);
}
function writeDiv(i, level, dist) {
if(dist>0) {
document.write("<div id=\"div"+(i-1)+"\" style=\"display: none;\">");
} else {
while(dist++<0) {
document.write("</div>");
}
}
}
function writeTree() {
loadIcons();
var last=nodeList[0];
for (var i=0; i<nodeList.length; i++) {
var node=nodeList[i];
writeDiv(i, node.level, node.level-last.level);
last=node;
var j=node.level;
while(j-->0) {
document.write("<img src=\"tree_empty.gif\"/>");
}
if (node.type==1) {
if( i < nodeList.length-1 && nodeList[i+1].level > node.level) {
document.write("<img onclick=\"hit("+i+");\" id=\"join"+i+"\" src=\"tree_plus.gif\"/>");
} else {
document.write("<img src=\"tree_empty.gif\"/>");
}
}
document.write("<img src=\"tree_"+node.icon+".gif\"/>&nbsp;");
if(node.link==null) {
document.write(node.text);
} else {
document.write("<a name='"+node.text+"' href=\""+node.link+"\" >"+node.text+"</a>");
}
document.write("<br>");
}
writeDiv(0, 0, -last.type);
}
function hit(i) {
var theDiv = document.getElementById("div"+i);
var theJoin = document.getElementById("join"+i);
if (theDiv.style.display == 'none') {
theJoin.src = icons[0].src;
theDiv.style.display = '';
} else {
theJoin.src = icons[1].src;
theDiv.style.display = 'none';
}
}
function hitOpen(i) {
var theDiv = document.getElementById("div"+i);
var theJoin = document.getElementById("join"+i);
theJoin.src = icons[0].src;
theDiv.style.display = '';
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论