提交 3468848d authored 作者: Thomas Mueller's avatar Thomas Mueller

allow to start the H2 Console using an existing, open connection

上级 c1a0ab19
...@@ -27,10 +27,10 @@ import org.h2.constant.SysProperties; ...@@ -27,10 +27,10 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.Message; import org.h2.message.Message;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.tools.Server;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
import org.h2.util.Tool;
/** /**
* The TCP server implements the native H2 database server protocol. * The TCP server implements the native H2 database server protocol.
...@@ -155,11 +155,11 @@ public class TcpServer implements Service { ...@@ -155,11 +155,11 @@ public class TcpServer implements Service {
if ("-trace".equals(a)) { if ("-trace".equals(a)) {
trace = true; trace = true;
} else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) { } else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) {
trace = Server.readArgBoolean(args, i) == 1; trace = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else if ("-tcpSSL".equals(a)) { } else if ("-tcpSSL".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
ssl = Server.readArgBoolean(args, i) == 1; ssl = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
ssl = true; ssl = true;
...@@ -171,15 +171,15 @@ public class TcpServer implements Service { ...@@ -171,15 +171,15 @@ public class TcpServer implements Service {
} else if ("-baseDir".equals(a)) { } else if ("-baseDir".equals(a)) {
baseDir = args[++i]; baseDir = args[++i];
} else if ("-tcpAllowOthers".equals(a)) { } else if ("-tcpAllowOthers".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
allowOthers = Server.readArgBoolean(args, i) == 1; allowOthers = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
allowOthers = true; allowOthers = true;
} }
} else if ("-ifExists".equals(a)) { } else if ("-ifExists".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
ifExists = Server.readArgBoolean(args, i) == 1; ifExists = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
ifExists = true; ifExists = true;
......
...@@ -23,12 +23,12 @@ import org.h2.constant.SysProperties; ...@@ -23,12 +23,12 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.server.Service; import org.h2.server.Service;
import org.h2.store.fs.FileSystem; import org.h2.store.fs.FileSystem;
import org.h2.tools.Server;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
import org.h2.util.SortedProperties; import org.h2.util.SortedProperties;
import org.h2.util.Tool;
/** /**
* Small FTP Server. Intended for ad-hoc networks in a secure environment. * Small FTP Server. Intended for ad-hoc networks in a secure environment.
...@@ -235,7 +235,7 @@ public class FtpServer implements Service { ...@@ -235,7 +235,7 @@ public class FtpServer implements Service {
} else if ("-trace".equals(a)) { } else if ("-trace".equals(a)) {
trace = true; trace = true;
} else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) { } else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) {
trace = Server.readArgBoolean(args, i) == 1; trace = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else if ("-ftpTask".equals(a)) { } else if ("-ftpTask".equals(a)) {
allowTask = true; allowTask = true;
......
...@@ -22,9 +22,9 @@ import java.util.Set; ...@@ -22,9 +22,9 @@ import java.util.Set;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.server.Service; import org.h2.server.Service;
import org.h2.tools.Server;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
import org.h2.util.Tool;
/** /**
* This class implements a subset of the PostgreSQL protocol as described here: * This class implements a subset of the PostgreSQL protocol as described here:
...@@ -54,22 +54,22 @@ public class PgServer implements Service { ...@@ -54,22 +54,22 @@ public class PgServer implements Service {
if ("-trace".equals(a)) { if ("-trace".equals(a)) {
trace = true; trace = true;
} else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) { } else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) {
trace = Server.readArgBoolean(args, i) == 1; trace = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else if ("-pgPort".equals(a)) { } else if ("-pgPort".equals(a)) {
port = MathUtils.decodeInt(args[++i]); port = MathUtils.decodeInt(args[++i]);
} else if ("-baseDir".equals(a)) { } else if ("-baseDir".equals(a)) {
baseDir = args[++i]; baseDir = args[++i];
} else if ("-pgAllowOthers".equals(a)) { } else if ("-pgAllowOthers".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
allowOthers = Server.readArgBoolean(args, i) == 1; allowOthers = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
allowOthers = true; allowOthers = true;
} }
} else if ("-ifExists".equals(a)) { } else if ("-ifExists".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
ifExists = Server.readArgBoolean(args, i) == 1; ifExists = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
ifExists = true; ifExists = true;
......
...@@ -33,7 +33,6 @@ import org.h2.engine.Constants; ...@@ -33,7 +33,6 @@ import org.h2.engine.Constants;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.server.Service; import org.h2.server.Service;
import org.h2.server.ShutdownHandler; import org.h2.server.ShutdownHandler;
import org.h2.tools.Server;
import org.h2.util.ByteUtils; import org.h2.util.ByteUtils;
import org.h2.util.FileUtils; import org.h2.util.FileUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
...@@ -42,6 +41,7 @@ import org.h2.util.NetUtils; ...@@ -42,6 +41,7 @@ import org.h2.util.NetUtils;
import org.h2.util.RandomUtils; import org.h2.util.RandomUtils;
import org.h2.util.Resources; import org.h2.util.Resources;
import org.h2.util.SortedProperties; import org.h2.util.SortedProperties;
import org.h2.util.Tool;
/** /**
* The web server is a simple standalone HTTP server that implements the H2 * The web server is a simple standalone HTTP server that implements the H2
...@@ -224,15 +224,15 @@ public class WebServer implements Service { ...@@ -224,15 +224,15 @@ public class WebServer implements Service {
if ("-webPort".equals(a)) { if ("-webPort".equals(a)) {
port = MathUtils.decodeInt(args[++i]); port = MathUtils.decodeInt(args[++i]);
} else if ("-webSSL".equals(a)) { } else if ("-webSSL".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
ssl = Server.readArgBoolean(args, i) == 1; ssl = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
ssl = true; ssl = true;
} }
} else if ("-webAllowOthers".equals(a)) { } else if ("-webAllowOthers".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
allowOthers = Server.readArgBoolean(args, i) == 1; allowOthers = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
allowOthers = true; allowOthers = true;
...@@ -243,8 +243,8 @@ public class WebServer implements Service { ...@@ -243,8 +243,8 @@ public class WebServer implements Service {
String baseDir = args[++i]; String baseDir = args[++i];
SysProperties.setBaseDir(baseDir); SysProperties.setBaseDir(baseDir);
} else if ("-ifExists".equals(a)) { } else if ("-ifExists".equals(a)) {
if (Server.readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
ifExists = Server.readArgBoolean(args, i) == 1; ifExists = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
ifExists = true; ifExists = true;
...@@ -252,7 +252,7 @@ public class WebServer implements Service { ...@@ -252,7 +252,7 @@ public class WebServer implements Service {
} else if ("-trace".equals(a)) { } else if ("-trace".equals(a)) {
trace = true; trace = true;
} else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) { } else if ("-log".equals(a) && SysProperties.OLD_COMMAND_LINE_OPTIONS) {
trace = Server.readArgBoolean(args, i) == 1; trace = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} }
} }
...@@ -278,15 +278,21 @@ public class WebServer implements Service { ...@@ -278,15 +278,21 @@ public class WebServer implements Service {
for (int i = 0; i < LANGUAGES.length; i++) { for (int i = 0; i < LANGUAGES.length; i++) {
languages.add(LANGUAGES[i][0]); languages.add(LANGUAGES[i][0]);
} }
url = (ssl ? "https" : "http") + "://" + NetUtils.getLocalAddress() + ":" + port; updateURL();
} }
public String getURL() { public String getURL() {
return url; return url;
} }
private void updateURL() {
url = (ssl ? "https" : "http") + "://" + NetUtils.getLocalAddress() + ":" + port;
}
public void start() throws SQLException { public void start() throws SQLException {
serverSocket = NetUtils.createServerSocket(port, ssl); serverSocket = NetUtils.createServerSocket(port, ssl);
port = serverSocket.getLocalPort();
updateURL();
} }
public void listen() { public void listen() {
...@@ -645,4 +651,19 @@ public class WebServer implements Service { ...@@ -645,4 +651,19 @@ public class WebServer implements Service {
return allowScript; return allowScript;
} }
/**
* Create a session with a given connection.
*
* @param conn the connection
* @return the URL of the web site to access this connection
*/
public String addSession(Connection conn) throws SQLException {
WebSession session = createNewSession("local");
session.setShutdownServerOnDisconnect();
session.setConnection(conn);
session.put("url", conn.getMetaData().getURL());
String s = (String) session.get("sessionId");
return url + "/frame.jsp?jsessionid=" + s;
}
} }
...@@ -66,6 +66,7 @@ class WebSession { ...@@ -66,6 +66,7 @@ class WebSession {
private DbContextRule aliasRule; private DbContextRule aliasRule;
private DbContextRule columnAliasRule; private DbContextRule columnAliasRule;
private Bnf bnf; private Bnf bnf;
private boolean shutdownServerOnDisconnect;
WebSession(WebServer server) { WebSession(WebServer server) {
this.server = server; this.server = server;
...@@ -233,5 +234,16 @@ class WebSession { ...@@ -233,5 +234,16 @@ class WebSession {
DbContents getContents() { DbContents getContents() {
return contents; return contents;
} }
/**
* Shutdown the server when disconnecting.
*/
void setShutdownServerOnDisconnect() {
this.shutdownServerOnDisconnect = true;
}
boolean getShutdownServerOnDisconnect() {
return shutdownServerOnDisconnect;
}
} }
...@@ -119,6 +119,11 @@ class WebThread extends Thread implements DatabaseEventListener { ...@@ -119,6 +119,11 @@ class WebThread extends Thread implements DatabaseEventListener {
*/ */
void stopNow() { void stopNow() {
this.stop = true; this.stop = true;
try {
socket.close();
} catch (IOException e) {
// ignore
}
} }
private String getAllowedFile(String requestedFile) { private String getAllowedFile(String requestedFile) {
...@@ -1197,7 +1202,11 @@ class WebThread extends Thread implements DatabaseEventListener { ...@@ -1197,7 +1202,11 @@ class WebThread extends Thread implements DatabaseEventListener {
session.remove("user"); session.remove("user");
session.remove("tool"); session.remove("tool");
if (conn != null) { if (conn != null) {
conn.close(); if (session.getShutdownServerOnDisconnect()) {
server.shutdown();
} else {
conn.close();
}
} }
} catch (Exception e) { } catch (Exception e) {
trace(e.toString()); trace(e.toString());
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
package org.h2.tools; package org.h2.tools;
import java.io.PrintStream; import java.io.PrintStream;
import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
...@@ -21,6 +22,7 @@ import org.h2.server.ftp.FtpServer; ...@@ -21,6 +22,7 @@ import org.h2.server.ftp.FtpServer;
import org.h2.server.pg.PgServer; import org.h2.server.pg.PgServer;
import org.h2.server.web.WebServer; import org.h2.server.web.WebServer;
import org.h2.util.StartBrowser; import org.h2.util.StartBrowser;
import org.h2.util.Tool;
/** /**
* This tool can be used to start various database servers (listeners). * This tool can be used to start various database servers (listeners).
...@@ -129,12 +131,12 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -129,12 +131,12 @@ public class Server implements Runnable, ShutdownHandler {
* @param args the command line arguments * @param args the command line arguments
* @throws SQLException * @throws SQLException
*/ */
public static void main(String[] args) throws SQLException { // public static void main(String[] args) throws SQLException {
int exitCode = new Server().run(args, System.out); // int exitCode = new Server().run(args, System.out);
if (exitCode != 0) { // if (exitCode != 0) {
System.exit(exitCode); // System.exit(exitCode);
} // }
} // }
/** /**
* INTERNAL * INTERNAL
...@@ -158,11 +160,11 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -158,11 +160,11 @@ public class Server implements Runnable, ShutdownHandler {
startDefaultServers = false; startDefaultServers = false;
webStart = true; webStart = true;
} else if ("-webAllowOthers".equals(arg)) { } else if ("-webAllowOthers".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-webSSL".equals(arg)) { } else if ("-webSSL".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-webPort".equals(arg)) { } else if ("-webPort".equals(arg)) {
...@@ -181,11 +183,11 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -181,11 +183,11 @@ public class Server implements Runnable, ShutdownHandler {
startDefaultServers = false; startDefaultServers = false;
tcpStart = true; tcpStart = true;
} else if ("-tcpAllowOthers".equals(arg)) { } else if ("-tcpAllowOthers".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-tcpSSL".equals(arg)) { } else if ("-tcpSSL".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-tcpPort".equals(arg)) { } else if ("-tcpPort".equals(arg)) {
...@@ -197,8 +199,8 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -197,8 +199,8 @@ public class Server implements Runnable, ShutdownHandler {
tcpShutdown = true; tcpShutdown = true;
tcpShutdownServer = args[++i]; tcpShutdownServer = args[++i];
} else if ("-tcpShutdownForce".equals(arg)) { } else if ("-tcpShutdownForce".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
tcpShutdownForce = readArgBoolean(args, i) == 1; tcpShutdownForce = Tool.readArgBoolean(args, i) == 1;
i++; i++;
} else { } else {
tcpShutdownForce = true; tcpShutdownForce = true;
...@@ -212,7 +214,7 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -212,7 +214,7 @@ public class Server implements Runnable, ShutdownHandler {
startDefaultServers = false; startDefaultServers = false;
pgStart = true; pgStart = true;
} else if ("-pgAllowOthers".equals(arg)) { } else if ("-pgAllowOthers".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-pgPort".equals(arg)) { } else if ("-pgPort".equals(arg)) {
...@@ -246,7 +248,7 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -246,7 +248,7 @@ public class Server implements Runnable, ShutdownHandler {
} else if ("-log".equals(arg) && SysProperties.OLD_COMMAND_LINE_OPTIONS) { } else if ("-log".equals(arg) && SysProperties.OLD_COMMAND_LINE_OPTIONS) {
i++; i++;
} else if ("-ifExists".equals(arg)) { } else if ("-ifExists".equals(arg)) {
if (readArgBoolean(args, i) != 0) { if (Tool.readArgBoolean(args, i) != 0) {
i++; i++;
} }
} else if ("-baseDir".equals(arg)) { } else if ("-baseDir".equals(arg)) {
...@@ -322,29 +324,6 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -322,29 +324,6 @@ public class Server implements Runnable, ShutdownHandler {
return exitCode; return exitCode;
} }
/**
* Read an argument and check if it is true (1), false (-1), or not (0).
* This method is used for compatibility with older versions only.
*
* @param args the list of arguments
* @param i the index - 1
* @return 1, -1, or 0
*/
public static int readArgBoolean(String[] args, int i) {
if (!SysProperties.OLD_COMMAND_LINE_OPTIONS) {
return 0;
}
if (i + 1 < args.length) {
String a = args[++i];
if ("true".equals(a)) {
return 1;
} else if ("false".equals(a)) {
return -1;
}
}
return 0;
}
/** /**
* Shutdown a TCP server. If force is set to false, the server will not * Shutdown a TCP server. If force is set to false, the server will not
* allow new connections, but not kill existing connections, instead it will * allow new connections, but not kill existing connections, instead it will
...@@ -564,4 +543,36 @@ public class Server implements Runnable, ShutdownHandler { ...@@ -564,4 +543,36 @@ public class Server implements Runnable, ShutdownHandler {
public Service getService() { public Service getService() {
return service; return service;
} }
/**
* Start a web server and a browser that uses the given connection. The
* current transaction is preserved. This is specially useful to manually
* inspect the database when debugging.
*
* @param conn the database connection (the database must be open)
*/
public static void startWebServer(Connection conn) throws SQLException {
final Object waitUntilDisconnected = new Object();
WebServer webServer = new WebServer();
Server server = new Server(webServer, new String[] { "-webPort", "0" });
webServer.setShutdownHandler(new ShutdownHandler() {
public void shutdown() {
synchronized (waitUntilDisconnected) {
waitUntilDisconnected.notifyAll();
}
}
});
server.start();
String url = webServer.addSession(conn);
StartBrowser.openURL(url);
synchronized (waitUntilDisconnected) {
try {
waitUntilDisconnected.wait();
} catch (InterruptedException e) {
// ignore
}
}
webServer.stop();
}
} }
...@@ -9,6 +9,8 @@ package org.h2.util; ...@@ -9,6 +9,8 @@ package org.h2.util;
import java.io.PrintStream; import java.io.PrintStream;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.constant.SysProperties;
/** /**
* Command line tools implement the tool interface so that they can be used in * Command line tools implement the tool interface so that they can be used in
* the H2 Console. * the H2 Console.
...@@ -54,5 +56,28 @@ public abstract class Tool { ...@@ -54,5 +56,28 @@ public abstract class Tool {
} }
out.println(buff.toString()); out.println(buff.toString());
} }
/**
* Read an argument and check if it is true (1), false (-1), or not (0).
* This method is used for compatibility with older versions only.
*
* @param args the list of arguments
* @param i the index - 1
* @return 1 for true, -1 for false, or 0 for not read
*/
public static int readArgBoolean(String[] args, int i) {
if (!SysProperties.OLD_COMMAND_LINE_OPTIONS) {
return 0;
}
if (i + 1 < args.length) {
String a = args[++i];
if ("true".equals(a)) {
return 1;
} else if ("false".equals(a)) {
return -1;
}
}
return 0;
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论