JR Utily

simplify H2 console, and deploy it only when in Integration project stage

1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.ConnectionInfo
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -//package org.h2.server.web;
9 -
10 - import org.h2.util.MathUtils;
11 - import org.h2.util.StringUtils;
12 -
13 -/**
14 - * The connection info object is a wrapper for database connection information
15 - * such as the database URL, user name and password.
16 - * This class is used by the H2 Console.
17 - */
18 -public class ConnectionInfo implements Comparable<ConnectionInfo> {
19 - /**
20 - * The driver class name.
21 - */
22 - public String driver;
23 -
24 - /**
25 - * The database URL.
26 - */
27 - public String url;
28 -
29 - /**
30 - * The user name.
31 - */
32 - public String user;
33 -
34 - /**
35 - * The connection display name.
36 - */
37 - String name;
38 -
39 - /**
40 - * The last time this connection was used.
41 - */
42 - int lastAccess;
43 -
44 - ConnectionInfo() {
45 - // nothing to do
46 - }
47 -
48 - public ConnectionInfo(String data) {
49 - String[] array = StringUtils.arraySplit(data, '|', false);
50 - name = get(array, 0);
51 - driver = get(array, 1);
52 - url = get(array, 2);
53 - user = get(array, 3);
54 - }
55 -
56 - private static String get(String[] array, int i) {
57 - return array != null && array.length > i ? array[i] : "";
58 - }
59 -
60 - String getString() {
61 - return StringUtils.arrayCombine(new String[] { name, driver, url, user }, '|');
62 - }
63 -
64 - @Override
65 - public int compareTo(ConnectionInfo o) {
66 - return -MathUtils.compareInt(lastAccess, o.lastAccess);
67 - }
68 -
69 -}
...\ No newline at end of file ...\ No newline at end of file
1 package org.legrog.util; 1 package org.legrog.util;
2 2
3 -import javax.servlet.annotation.WebServlet; 3 +import org.apache.deltaspike.core.api.projectstage.ProjectStage;
4 - 4 +import org.apache.deltaspike.core.util.ProjectStageProducer;
5 -import java.io.IOException; 5 +import org.slf4j.Logger;
6 -import java.net.InetAddress; 6 +import org.slf4j.LoggerFactory;
7 -import java.net.UnknownHostException;
8 -import java.util.ArrayList;
9 -import java.util.Enumeration;
10 -import java.util.Properties;
11 7
12 -import javax.servlet.ServletConfig; 8 +import javax.servlet.annotation.WebInitParam;
13 -import javax.servlet.ServletOutputStream; 9 +import javax.servlet.annotation.WebServlet;
14 -import javax.servlet.http.HttpServlet;
15 -import javax.servlet.http.HttpServletRequest;
16 -import javax.servlet.http.HttpServletResponse;
17 10
18 -import org.h2.engine.Constants; 11 +import static org.legrog.util.H2ConsoleServlet.CONSOLE_MAPPING;
19 -import org.h2.server.web.PageParser;
20 -import org.h2.util.New;
21 12
22 13
23 -@WebServlet(urlPatterns="/console/*", name="H2Console", loadOnStartup=1) 14 +@WebServlet(
24 -public class H2ConsoleServlet extends HttpServlet { 15 + urlPatterns = CONSOLE_MAPPING,
25 -// Code copied from org.h2.server.web.WebServlet 16 + name = "H2Console",
26 - private static final long serialVersionUID = 1L; 17 + loadOnStartup = 1,
27 - private transient WebServer server; 18 + initParams = {@WebInitParam(name = "webAllowOthers", value = ""), @WebInitParam(name = "trace", value = "")}
19 +)
20 +public class H2ConsoleServlet extends org.h2.server.web.WebServlet {
21 + static final String CONSOLE_MAPPING = "/console/*";
22 + private Logger logger = LoggerFactory.getLogger(getClass());
28 23
29 @Override 24 @Override
30 public void init() { 25 public void init() {
31 - ServletConfig config = getServletConfig(); 26 + ProjectStage projectStage = ProjectStageProducer.getInstance().getProjectStage();
32 - Enumeration<?> en = config.getInitParameterNames(); 27 + if (projectStage == ProjectStage.IntegrationTest) {
33 - ArrayList<String> list = New.arrayList(); 28 + logger.info("Create a H2 Console Servlet mapped to {}", CONSOLE_MAPPING);
34 - while (en.hasMoreElements()) { 29 + super.init();
35 - String name = en.nextElement().toString();
36 - String value = config.getInitParameter(name);
37 - if (!name.startsWith("-")) {
38 - name = "-" + name;
39 - }
40 - list.add(name);
41 - if (value.length() > 0) {
42 - list.add(value);
43 - }
44 - }
45 - String[] args = new String[list.size()];
46 - list.toArray(args);
47 - server = new WebServer();
48 - server.setAllowChunked(false);
49 - server.init(args);
50 - }
51 -
52 - @Override
53 - public void destroy() {
54 - server.stop();
55 - }
56 -
57 - private boolean allow(HttpServletRequest req) {
58 - if (server.getAllowOthers()) {
59 - return true;
60 - }
61 - String addr = req.getRemoteAddr();
62 - try {
63 - InetAddress address = InetAddress.getByName(addr);
64 - return address.isLoopbackAddress();
65 - } catch (UnknownHostException e) {
66 - return false;
67 - } catch (NoClassDefFoundError e) {
68 - // Google App Engine does not allow java.net.InetAddress
69 - return false;
70 - }
71 - }
72 -
73 - private String getAllowedFile(HttpServletRequest req, String requestedFile) {
74 - if (!allow(req)) {
75 - return "notAllowed.jsp";
76 - }
77 - if (requestedFile.length() == 0) {
78 - return "index.do";
79 - }
80 - return requestedFile;
81 - }
82 -
83 - @Override
84 - public void doGet(HttpServletRequest req, HttpServletResponse resp)
85 - throws IOException {
86 - req.setCharacterEncoding("utf-8");
87 - String file = req.getPathInfo();
88 - if (file == null) {
89 - resp.sendRedirect(req.getRequestURI() + "/");
90 - return;
91 - } else if (file.startsWith("/")) {
92 - file = file.substring(1);
93 - }
94 - file = getAllowedFile(req, file);
95 -
96 - // extract the request attributes
97 - Properties attributes = new Properties();
98 - Enumeration<?> en = req.getAttributeNames();
99 - while (en.hasMoreElements()) {
100 - String name = en.nextElement().toString();
101 - String value = req.getAttribute(name).toString();
102 - attributes.put(name, value);
103 - }
104 - en = req.getParameterNames();
105 - while (en.hasMoreElements()) {
106 - String name = en.nextElement().toString();
107 - String value = req.getParameter(name);
108 - attributes.put(name, value);
109 - }
110 -
111 - WebSession session = null;
112 - String sessionId = attributes.getProperty("jsessionid");
113 - if (sessionId != null) {
114 - session = server.getSession(sessionId);
115 - }
116 - WebApp app = new WebApp(server);
117 - app.setSession(session, attributes);
118 - String ifModifiedSince = req.getHeader("if-modified-since");
119 -
120 - String hostAddr = req.getRemoteAddr();
121 - file = app.processRequest(file, hostAddr);
122 - session = app.getSession();
123 -
124 - String mimeType = app.getMimeType();
125 - boolean cache = app.getCache();
126 -
127 - if (cache && server.getStartDateTime().equals(ifModifiedSince)) {
128 - resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
129 - return;
130 - }
131 - byte[] bytes = server.getFile(file);
132 - if (bytes == null) {
133 - resp.sendError(HttpServletResponse.SC_NOT_FOUND);
134 - bytes = ("File not found: " + file).getBytes(Constants.UTF8);
135 } else { 30 } else {
136 - if (session != null && file.endsWith(".jsp")) { 31 + logger.info("Skipping H2 Console Servlet creation");
137 - String page = new String(bytes, Constants.UTF8);
138 - page = PageParser.parse(page, session.map);
139 - bytes = page.getBytes(Constants.UTF8);
140 - }
141 - resp.setContentType(mimeType);
142 - if (!cache) {
143 - resp.setHeader("Cache-Control", "no-cache");
144 - } else {
145 - resp.setHeader("Cache-Control", "max-age=10");
146 - resp.setHeader("Last-Modified", server.getStartDateTime());
147 - }
148 } 32 }
149 - if (bytes != null) {
150 - ServletOutputStream out = resp.getOutputStream();
151 - out.write(bytes);
152 - }
153 - }
154 33
155 - @Override
156 - public void doPost(HttpServletRequest req, HttpServletResponse resp)
157 - throws IOException {
158 - doGet(req, resp);
159 } 34 }
160 } 35 }
36 +
......
1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.PageParser
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -//package org.h2.server.web;
9 -
10 - import java.text.ParseException;
11 - import java.util.HashMap;
12 - import java.util.List;
13 - import java.util.Map;
14 - import org.h2.util.New;
15 -
16 -/**
17 - * A page parser can parse an HTML page and replace the tags there.
18 - * This class is used by the H2 Console.
19 - */
20 -public class PageParser {
21 - private static final int TAB_WIDTH = 4;
22 -
23 - private final String page;
24 - private int pos;
25 - private final Map<String, Object> settings;
26 - private final int len;
27 - private StringBuilder result;
28 -
29 - private PageParser(String page, Map<String, Object> settings, int pos) {
30 - this.page = page;
31 - this.pos = pos;
32 - this.len = page.length();
33 - this.settings = settings;
34 - result = new StringBuilder(len);
35 - }
36 -
37 - /**
38 - * Replace the tags in the HTML page with the given settings.
39 - *
40 - * @param page the HTML page
41 - * @param settings the settings
42 - * @return the converted page
43 - */
44 - public static String parse(String page, Map<String, Object> settings) {
45 - PageParser block = new PageParser(page, settings, 0);
46 - return block.replaceTags();
47 - }
48 -
49 - private void setError(int i) {
50 - String s = page.substring(0, i) + "####BUG####" + page.substring(i);
51 - s = PageParser.escapeHtml(s);
52 - result = new StringBuilder();
53 - result.append(s);
54 - }
55 -
56 - private String parseBlockUntil(String end) throws ParseException {
57 - PageParser block = new PageParser(page, settings, pos);
58 - block.parseAll();
59 - if (!block.readIf(end)) {
60 - throw new ParseException(page, block.pos);
61 - }
62 - pos = block.pos;
63 - return block.result.toString();
64 - }
65 -
66 - private String replaceTags() {
67 - try {
68 - parseAll();
69 - if (pos != len) {
70 - setError(pos);
71 - }
72 - } catch (ParseException e) {
73 - setError(pos);
74 - }
75 - return result.toString();
76 - }
77 -
78 - @SuppressWarnings("unchecked")
79 - private void parseAll() throws ParseException {
80 - StringBuilder buff = result;
81 - String p = page;
82 - int i = pos;
83 - for (; i < len; i++) {
84 - char c = p.charAt(i);
85 - switch (c) {
86 - case '<': {
87 - if (p.charAt(i + 3) == ':' && p.charAt(i + 1) == '/') {
88 - // end tag
89 - pos = i;
90 - return;
91 - } else if (p.charAt(i + 2) == ':') {
92 - pos = i;
93 - if (readIf("<c:forEach")) {
94 - String var = readParam("var");
95 - String items = readParam("items");
96 - read(">");
97 - int start = pos;
98 - List<Object> list = (List<Object>) get(items);
99 - if (list == null) {
100 - result.append("?items?");
101 - list = New.arrayList();
102 - }
103 - if (list.size() == 0) {
104 - parseBlockUntil("</c:forEach>");
105 - }
106 - for (Object o : list) {
107 - settings.put(var, o);
108 - pos = start;
109 - String block = parseBlockUntil("</c:forEach>");
110 - result.append(block);
111 - }
112 - } else if (readIf("<c:if")) {
113 - String test = readParam("test");
114 - int eq = test.indexOf("=='");
115 - if (eq < 0) {
116 - setError(i);
117 - return;
118 - }
119 - String val = test.substring(eq + 3, test.length() - 1);
120 - test = test.substring(0, eq);
121 - String value = (String) get(test);
122 - read(">");
123 - String block = parseBlockUntil("</c:if>");
124 - pos--;
125 - if (value.equals(val)) {
126 - result.append(block);
127 - }
128 - } else {
129 - setError(i);
130 - return;
131 - }
132 - i = pos;
133 - } else {
134 - buff.append(c);
135 - }
136 - break;
137 - }
138 - case '$':
139 - if (p.length() > i + 1 && p.charAt(i + 1) == '{') {
140 - i += 2;
141 - int j = p.indexOf('}', i);
142 - if (j < 0) {
143 - setError(i);
144 - return;
145 - }
146 - String item = p.substring(i, j).trim();
147 - i = j;
148 - String s = (String) get(item);
149 - replaceTags(s);
150 - } else {
151 - buff.append(c);
152 - }
153 - break;
154 - default:
155 - buff.append(c);
156 - break;
157 - }
158 - }
159 - pos = i;
160 - }
161 -
162 - @SuppressWarnings("unchecked")
163 - private Object get(String item) {
164 - int dot = item.indexOf('.');
165 - if (dot >= 0) {
166 - String sub = item.substring(dot + 1);
167 - item = item.substring(0, dot);
168 - HashMap<String, Object> map = (HashMap<String, Object>) settings.get(item);
169 - if (map == null) {
170 - return "?" + item + "?";
171 - }
172 - return map.get(sub);
173 - }
174 - return settings.get(item);
175 - }
176 -
177 - private void replaceTags(String s) {
178 - if (s != null) {
179 - result.append(PageParser.parse(s, settings));
180 - }
181 - }
182 -
183 - private String readParam(String name) throws ParseException {
184 - read(name);
185 - read("=");
186 - read("\"");
187 - int start = pos;
188 - while (page.charAt(pos) != '"') {
189 - pos++;
190 - }
191 - int end = pos;
192 - read("\"");
193 - String s = page.substring(start, end);
194 - return PageParser.parse(s, settings);
195 - }
196 -
197 - private void skipSpaces() {
198 - while (page.charAt(pos) == ' ') {
199 - pos++;
200 - }
201 - }
202 -
203 - private void read(String s) throws ParseException {
204 - if (!readIf(s)) {
205 - throw new ParseException(s, pos);
206 - }
207 - }
208 -
209 - private boolean readIf(String s) {
210 - skipSpaces();
211 - if (page.regionMatches(pos, s, 0, s.length())) {
212 - pos += s.length();
213 - skipSpaces();
214 - return true;
215 - }
216 - return false;
217 - }
218 -
219 - /**
220 - * Convert data to HTML, but don't convert newlines and multiple spaces.
221 - *
222 - * @param s the data
223 - * @return the escaped html text
224 - */
225 - static String escapeHtmlData(String s) {
226 - return escapeHtml(s, false);
227 - }
228 -
229 - /**
230 - * Convert data to HTML, including newlines and multiple spaces.
231 - *
232 - * @param s the data
233 - * @return the escaped html text
234 - */
235 - public static String escapeHtml(String s) {
236 - return escapeHtml(s, true);
237 - }
238 -
239 - private static String escapeHtml(String s, boolean convertBreakAndSpace) {
240 - if (s == null) {
241 - return null;
242 - }
243 - if (convertBreakAndSpace) {
244 - if (s.length() == 0) {
245 - return "&nbsp;";
246 - }
247 - }
248 - StringBuilder buff = new StringBuilder(s.length());
249 - boolean convertSpace = true;
250 - for (int i = 0; i < s.length(); i++) {
251 - char c = s.charAt(i);
252 - if (c == ' ' || c == '\t') {
253 - // convert tabs into spaces
254 - for (int j = 0; j < (c == ' ' ? 1 : TAB_WIDTH); j++) {
255 - if (convertSpace && convertBreakAndSpace) {
256 - buff.append("&nbsp;");
257 - } else {
258 - buff.append(' ');
259 - convertSpace = true;
260 - }
261 - }
262 - continue;
263 - }
264 - convertSpace = false;
265 - switch (c) {
266 - case '$':
267 - // so that ${ } in the text is interpreted correctly
268 - buff.append("&#36;");
269 - break;
270 - case '<':
271 - buff.append("&lt;");
272 - break;
273 - case '>':
274 - buff.append("&gt;");
275 - break;
276 - case '&':
277 - buff.append("&amp;");
278 - break;
279 - case '"':
280 - buff.append("&quot;");
281 - break;
282 - case '\'':
283 - buff.append("&#39;");
284 - break;
285 - case '\n':
286 - if (convertBreakAndSpace) {
287 - buff.append("<br />");
288 - convertSpace = true;
289 - } else {
290 - buff.append(c);
291 - }
292 - break;
293 - default:
294 - if (c >= 128) {
295 - buff.append("&#").append((int) c).append(';');
296 - } else {
297 - buff.append(c);
298 - }
299 - break;
300 - }
301 - }
302 - return buff.toString();
303 - }
304 -
305 - /**
306 - * Escape text as a the javascript string.
307 - *
308 - * @param s the text
309 - * @return the javascript string
310 - */
311 - static String escapeJavaScript(String s) {
312 - if (s == null) {
313 - return null;
314 - }
315 - if (s.length() == 0) {
316 - return "";
317 - }
318 - StringBuilder buff = new StringBuilder(s.length());
319 - for (int i = 0; i < s.length(); i++) {
320 - char c = s.charAt(i);
321 - switch (c) {
322 - case '"':
323 - buff.append("\\\"");
324 - break;
325 - case '\'':
326 - buff.append("\\'");
327 - break;
328 - case '\\':
329 - buff.append("\\\\");
330 - break;
331 - case '\n':
332 - buff.append("\\n");
333 - break;
334 - case '\r':
335 - buff.append("\\r");
336 - break;
337 - case '\t':
338 - buff.append("\\t");
339 - break;
340 - default:
341 - buff.append(c);
342 - break;
343 - }
344 - }
345 - return buff.toString();
346 - }
347 -}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.WebApp
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -//package org.h2.server.web;
9 -
10 - import java.io.ByteArrayOutputStream;
11 - import java.io.PrintStream;
12 - import java.io.PrintWriter;
13 - import java.io.StringReader;
14 - import java.io.StringWriter;
15 - import java.lang.reflect.InvocationTargetException;
16 - import java.lang.reflect.Method;
17 - import java.math.BigDecimal;
18 - import java.sql.Connection;
19 - import java.sql.DatabaseMetaData;
20 - import java.sql.ParameterMetaData;
21 - import java.sql.PreparedStatement;
22 - import java.sql.ResultSet;
23 - import java.sql.ResultSetMetaData;
24 - import java.sql.SQLException;
25 - import java.sql.Statement;
26 - import java.sql.Types;
27 - import java.util.ArrayList;
28 - import java.util.Arrays;
29 - import java.util.Collections;
30 - import java.util.Comparator;
31 - import java.util.HashMap;
32 - import java.util.Iterator;
33 - import java.util.Locale;
34 - import java.util.Map;
35 - import java.util.Properties;
36 - import java.util.Random;
37 - import org.h2.api.ErrorCode;
38 - import org.h2.bnf.Bnf;
39 - import org.h2.bnf.context.DbColumn;
40 - import org.h2.bnf.context.DbContents;
41 - import org.h2.bnf.context.DbSchema;
42 - import org.h2.bnf.context.DbTableOrView;
43 - import org.h2.engine.Constants;
44 - import org.h2.engine.SysProperties;
45 - import org.h2.jdbc.JdbcSQLException;
46 - import org.h2.message.DbException;
47 - import org.h2.security.SHA256;
48 - import org.h2.tools.Backup;
49 - import org.h2.tools.ChangeFileEncryption;
50 - import org.h2.tools.ConvertTraceFile;
51 - import org.h2.tools.CreateCluster;
52 - import org.h2.tools.DeleteDbFiles;
53 - import org.h2.tools.Recover;
54 - import org.h2.tools.Restore;
55 - import org.h2.tools.RunScript;
56 - import org.h2.tools.Script;
57 - import org.h2.tools.SimpleResultSet;
58 - import org.h2.util.JdbcUtils;
59 - import org.h2.util.New;
60 - import org.h2.util.Profiler;
61 - import org.h2.util.ScriptReader;
62 - import org.h2.util.SortedProperties;
63 - import org.h2.util.StatementBuilder;
64 - import org.h2.util.StringUtils;
65 - import org.h2.util.Tool;
66 - import org.h2.util.Utils;
67 -
68 -/**
69 - * For each connection to a session, an object of this class is created.
70 - * This class is used by the H2 Console.
71 - */
72 -public class WebApp {
73 -
74 - /**
75 - * The web server.
76 - */
77 - protected final WebServer server;
78 -
79 - /**
80 - * The session.
81 - */
82 - protected WebSession session;
83 -
84 - /**
85 - * The session attributes
86 - */
87 - protected Properties attributes;
88 -
89 - /**
90 - * The mime type of the current response.
91 - */
92 - protected String mimeType;
93 -
94 - /**
95 - * Whether the response can be cached.
96 - */
97 - protected boolean cache;
98 -
99 - /**
100 - * Whether to close the connection.
101 - */
102 - protected boolean stop;
103 -
104 - /**
105 - * The language in the HTTP header.
106 - */
107 - protected String headerLanguage;
108 -
109 - private Profiler profiler;
110 -
111 - WebApp(WebServer server) {
112 - this.server = server;
113 - }
114 -
115 - /**
116 - * Set the web session and attributes.
117 - *
118 - * @param session the session
119 - * @param attributes the attributes
120 - */
121 - void setSession(WebSession session, Properties attributes) {
122 - this.session = session;
123 - this.attributes = attributes;
124 - }
125 -
126 - /**
127 - * Process an HTTP request.
128 - *
129 - * @param file the file that was requested
130 - * @param hostAddr the host address
131 - * @return the name of the file to return to the client
132 - */
133 - String processRequest(String file, String hostAddr) {
134 - int index = file.lastIndexOf('.');
135 - String suffix;
136 - if (index >= 0) {
137 - suffix = file.substring(index + 1);
138 - } else {
139 - suffix = "";
140 - }
141 - if ("ico".equals(suffix)) {
142 - mimeType = "image/x-icon";
143 - cache = true;
144 - } else if ("gif".equals(suffix)) {
145 - mimeType = "image/gif";
146 - cache = true;
147 - } else if ("css".equals(suffix)) {
148 - cache = true;
149 - mimeType = "text/css";
150 - } else if ("html".equals(suffix) ||
151 - "do".equals(suffix) ||
152 - "jsp".equals(suffix)) {
153 - cache = false;
154 - mimeType = "text/html";
155 - if (session == null) {
156 - session = server.createNewSession(hostAddr);
157 - if (!"notAllowed.jsp".equals(file)) {
158 - file = "index.do";
159 - }
160 - }
161 - } else if ("js".equals(suffix)) {
162 - cache = true;
163 - mimeType = "text/javascript";
164 - } else {
165 - cache = true;
166 - mimeType = "application/octet-stream";
167 - }
168 - trace("mimeType=" + mimeType);
169 - trace(file);
170 - if (file.endsWith(".do")) {
171 - file = process(file);
172 - }
173 - return file;
174 - }
175 -
176 - private static String getComboBox(String[] elements, String selected) {
177 - StringBuilder buff = new StringBuilder();
178 - for (String value : elements) {
179 - buff.append("<option value=\"").
180 - append(PageParser.escapeHtmlData(value)).
181 - append('\"');
182 - if (value.equals(selected)) {
183 - buff.append(" selected");
184 - }
185 - buff.append('>').
186 - append(PageParser.escapeHtml(value)).
187 - append("</option>");
188 - }
189 - return buff.toString();
190 - }
191 -
192 - private static String getComboBox(String[][] elements, String selected) {
193 - StringBuilder buff = new StringBuilder();
194 - for (String[] n : elements) {
195 - buff.append("<option value=\"").
196 - append(PageParser.escapeHtmlData(n[0])).
197 - append('\"');
198 - if (n[0].equals(selected)) {
199 - buff.append(" selected");
200 - }
201 - buff.append('>').
202 - append(PageParser.escapeHtml(n[1])).
203 - append("</option>");
204 - }
205 - return buff.toString();
206 - }
207 -
208 - private String process(String file) {
209 - trace("process " + file);
210 - while (file.endsWith(".do")) {
211 - if ("login.do".equals(file)) {
212 - file = login();
213 - } else if ("index.do".equals(file)) {
214 - file = index();
215 - } else if ("logout.do".equals(file)) {
216 - file = logout();
217 - } else if ("settingRemove.do".equals(file)) {
218 - file = settingRemove();
219 - } else if ("settingSave.do".equals(file)) {
220 - file = settingSave();
221 - } else if ("test.do".equals(file)) {
222 - file = test();
223 - } else if ("query.do".equals(file)) {
224 - file = query();
225 - } else if ("tables.do".equals(file)) {
226 - file = tables();
227 - } else if ("editResult.do".equals(file)) {
228 - file = editResult();
229 - } else if ("getHistory.do".equals(file)) {
230 - file = getHistory();
231 - } else if ("admin.do".equals(file)) {
232 - file = admin();
233 - } else if ("adminSave.do".equals(file)) {
234 - file = adminSave();
235 - } else if ("adminStartTranslate.do".equals(file)) {
236 - file = adminStartTranslate();
237 - } else if ("adminShutdown.do".equals(file)) {
238 - file = adminShutdown();
239 - } else if ("autoCompleteList.do".equals(file)) {
240 - file = autoCompleteList();
241 - } else if ("tools.do".equals(file)) {
242 - file = tools();
243 - } else {
244 - file = "error.jsp";
245 - }
246 - }
247 - trace("return " + file);
248 - return file;
249 - }
250 -
251 - private String autoCompleteList() {
252 - String query = (String) attributes.get("query");
253 - boolean lowercase = false;
254 - if (query.trim().length() > 0 &&
255 - Character.isLowerCase(query.trim().charAt(0))) {
256 - lowercase = true;
257 - }
258 - try {
259 - String sql = query;
260 - if (sql.endsWith(";")) {
261 - sql += " ";
262 - }
263 - ScriptReader reader = new ScriptReader(new StringReader(sql));
264 - reader.setSkipRemarks(true);
265 - String lastSql = "";
266 - while (true) {
267 - String n = reader.readStatement();
268 - if (n == null) {
269 - break;
270 - }
271 - lastSql = n;
272 - }
273 - String result = "";
274 - if (reader.isInsideRemark()) {
275 - if (reader.isBlockRemark()) {
276 - result = "1#(End Remark)# */\n" + result;
277 - } else {
278 - result = "1#(Newline)#\n" + result;
279 - }
280 - } else {
281 - sql = lastSql;
282 - while (sql.length() > 0 && sql.charAt(0) <= ' ') {
283 - sql = sql.substring(1);
284 - }
285 - if (sql.trim().length() > 0 && Character.isLowerCase(sql.trim().charAt(0))) {
286 - lowercase = true;
287 - }
288 - Bnf bnf = session.getBnf();
289 - if (bnf == null) {
290 - return "autoCompleteList.jsp";
291 - }
292 - HashMap<String, String> map = bnf.getNextTokenList(sql);
293 - String space = "";
294 - if (sql.length() > 0) {
295 - char last = sql.charAt(sql.length() - 1);
296 - if (!Character.isWhitespace(last) && (last != '.' &&
297 - last >= ' ' && last != '\'' && last != '"')) {
298 - space = " ";
299 - }
300 - }
301 - ArrayList<String> list = New.arrayList(map.size());
302 - for (Map.Entry<String, String> entry : map.entrySet()) {
303 - String key = entry.getKey();
304 - String value = entry.getValue();
305 - String type = "" + key.charAt(0);
306 - if (Integer.parseInt(type) > 2) {
307 - continue;
308 - }
309 - key = key.substring(2);
310 - if (Character.isLetter(key.charAt(0)) && lowercase) {
311 - key = StringUtils.toLowerEnglish(key);
312 - value = StringUtils.toLowerEnglish(value);
313 - }
314 - if (key.equals(value) && !".".equals(value)) {
315 - value = space + value;
316 - }
317 - key = StringUtils.urlEncode(key);
318 - key = StringUtils.replaceAll(key, "+", " ");
319 - value = StringUtils.urlEncode(value);
320 - value = StringUtils.replaceAll(value, "+", " ");
321 - list.add(type + "#" + key + "#" + value);
322 - }
323 - Collections.sort(list);
324 - if (query.endsWith("\n") || query.trim().endsWith(";")) {
325 - list.add(0, "1#(Newline)#\n");
326 - }
327 - StatementBuilder buff = new StatementBuilder();
328 - for (String s : list) {
329 - buff.appendExceptFirst("|");
330 - buff.append(s);
331 - }
332 - result = buff.toString();
333 - }
334 - session.put("autoCompleteList", result);
335 - } catch (Throwable e) {
336 - server.traceError(e);
337 - }
338 - return "autoCompleteList.jsp";
339 - }
340 -
341 - private String admin() {
342 - session.put("port", "" + server.getPort());
343 - session.put("allowOthers", "" + server.getAllowOthers());
344 - session.put("ssl", String.valueOf(server.getSSL()));
345 - session.put("sessions", server.getSessions());
346 - return "admin.jsp";
347 - }
348 -
349 - private String adminSave() {
350 - try {
351 - Properties prop = new SortedProperties();
352 - int port = Integer.decode((String) attributes.get("port"));
353 - prop.setProperty("webPort", String.valueOf(port));
354 - server.setPort(port);
355 - boolean allowOthers = Boolean.parseBoolean(
356 - (String) attributes.get("allowOthers"));
357 - prop.setProperty("webAllowOthers", String.valueOf(allowOthers));
358 - server.setAllowOthers(allowOthers);
359 - boolean ssl = Boolean.parseBoolean(
360 - (String) attributes.get("ssl"));
361 - prop.setProperty("webSSL", String.valueOf(ssl));
362 - server.setSSL(ssl);
363 - server.saveProperties(prop);
364 - } catch (Exception e) {
365 - trace(e.toString());
366 - }
367 - return admin();
368 - }
369 -
370 - private String tools() {
371 - try {
372 - String toolName = (String) attributes.get("tool");
373 - session.put("tool", toolName);
374 - String args = (String) attributes.get("args");
375 - String[] argList = StringUtils.arraySplit(args, ',', false);
376 - Tool tool = null;
377 - if ("Backup".equals(toolName)) {
378 - tool = new Backup();
379 - } else if ("Restore".equals(toolName)) {
380 - tool = new Restore();
381 - } else if ("Recover".equals(toolName)) {
382 - tool = new Recover();
383 - } else if ("DeleteDbFiles".equals(toolName)) {
384 - tool = new DeleteDbFiles();
385 - } else if ("ChangeFileEncryption".equals(toolName)) {
386 - tool = new ChangeFileEncryption();
387 - } else if ("Script".equals(toolName)) {
388 - tool = new Script();
389 - } else if ("RunScript".equals(toolName)) {
390 - tool = new RunScript();
391 - } else if ("ConvertTraceFile".equals(toolName)) {
392 - tool = new ConvertTraceFile();
393 - } else if ("CreateCluster".equals(toolName)) {
394 - tool = new CreateCluster();
395 - } else {
396 - throw DbException.throwInternalError(toolName);
397 - }
398 - ByteArrayOutputStream outBuff = new ByteArrayOutputStream();
399 - PrintStream out = new PrintStream(outBuff, false, "UTF-8");
400 - tool.setOut(out);
401 - try {
402 - tool.runTool(argList);
403 - out.flush();
404 - String o = new String(outBuff.toByteArray(), Constants.UTF8);
405 - String result = PageParser.escapeHtml(o);
406 - session.put("toolResult", result);
407 - } catch (Exception e) {
408 - session.put("toolResult", getStackTrace(0, e, true));
409 - }
410 - } catch (Exception e) {
411 - server.traceError(e);
412 - }
413 - return "tools.jsp";
414 - }
415 -
416 - private String adminStartTranslate() {
417 - Map<?, ?> p = Map.class.cast(session.map.get("text"));
418 - @SuppressWarnings("unchecked")
419 - Map<Object, Object> p2 = (Map<Object, Object>) p;
420 - String file = server.startTranslate(p2);
421 - session.put("translationFile", file);
422 - return "helpTranslate.jsp";
423 - }
424 -
425 - /**
426 - * Stop the application and the server.
427 - *
428 - * @return the page to display
429 - */
430 - protected String adminShutdown() {
431 - server.shutdown();
432 - return "admin.jsp";
433 - }
434 -
435 - private String index() {
436 - String[][] languageArray = WebServer.LANGUAGES;
437 - String language = (String) attributes.get("language");
438 - Locale locale = session.locale;
439 - if (language != null) {
440 - if (locale == null || !StringUtils.toLowerEnglish(
441 - locale.getLanguage()).equals(language)) {
442 - locale = new Locale(language, "");
443 - server.readTranslations(session, locale.getLanguage());
444 - session.put("language", language);
445 - session.locale = locale;
446 - }
447 - } else {
448 - language = (String) session.get("language");
449 - }
450 - if (language == null) {
451 - // if the language is not yet known
452 - // use the last header
453 - language = headerLanguage;
454 - }
455 - session.put("languageCombo", getComboBox(languageArray, language));
456 - String[] settingNames = server.getSettingNames();
457 - String setting = attributes.getProperty("setting");
458 - if (setting == null && settingNames.length > 0) {
459 - setting = settingNames[0];
460 - }
461 - String combobox = getComboBox(settingNames, setting);
462 - session.put("settingsList", combobox);
463 - ConnectionInfo info = server.getSetting(setting);
464 - if (info == null) {
465 - info = new ConnectionInfo();
466 - }
467 - session.put("setting", PageParser.escapeHtmlData(setting));
468 - session.put("name", PageParser.escapeHtmlData(setting));
469 - session.put("driver", PageParser.escapeHtmlData(info.driver));
470 - session.put("url", PageParser.escapeHtmlData(info.url));
471 - session.put("user", PageParser.escapeHtmlData(info.user));
472 - return "index.jsp";
473 - }
474 -
475 - private String getHistory() {
476 - int id = Integer.parseInt(attributes.getProperty("id"));
477 - String sql = session.getCommand(id);
478 - session.put("query", PageParser.escapeHtmlData(sql));
479 - return "query.jsp";
480 - }
481 -
482 - private static int addColumns(boolean mainSchema, DbTableOrView table,
483 - StringBuilder buff, int treeIndex, boolean showColumnTypes,
484 - StringBuilder columnsBuffer) {
485 - DbColumn[] columns = table.getColumns();
486 - for (int i = 0; columns != null && i < columns.length; i++) {
487 - DbColumn column = columns[i];
488 - if (columnsBuffer.length() > 0) {
489 - columnsBuffer.append(' ');
490 - }
491 - columnsBuffer.append(column.getName());
492 - String col = escapeIdentifier(column.getName());
493 - String level = mainSchema ? ", 1, 1" : ", 2, 2";
494 - buff.append("setNode(" + treeIndex + level + ", 'column', '" +
495 - PageParser.escapeJavaScript(column.getName()) +
496 - "', 'javascript:ins(\\'" + col + "\\')');\n");
497 - treeIndex++;
498 - if (mainSchema && showColumnTypes) {
499 - buff.append("setNode(" + treeIndex + ", 2, 2, 'type', '" +
500 - PageParser.escapeJavaScript(column.getDataType()) +
501 - "', null);\n");
502 - treeIndex++;
503 - }
504 - }
505 - return treeIndex;
506 - }
507 -
508 - private static String escapeIdentifier(String name) {
509 - return StringUtils.urlEncode(
510 - PageParser.escapeJavaScript(name)).replace('+', ' ');
511 - }
512 -
513 - /**
514 - * This class represents index information for the GUI.
515 - */
516 - static class IndexInfo {
517 -
518 - /**
519 - * The index name.
520 - */
521 - String name;
522 -
523 - /**
524 - * The index type name.
525 - */
526 - String type;
527 -
528 - /**
529 - * The indexed columns.
530 - */
531 - String columns;
532 - }
533 -
534 - private static int addIndexes(boolean mainSchema, DatabaseMetaData meta,
535 - String table, String schema, StringBuilder buff, int treeIndex)
536 - throws SQLException {
537 - ResultSet rs;
538 - try {
539 - rs = meta.getIndexInfo(null, schema, table, false, true);
540 - } catch (SQLException e) {
541 - // SQLite
542 - return treeIndex;
543 - }
544 - HashMap<String, IndexInfo> indexMap = New.hashMap();
545 - while (rs.next()) {
546 - String name = rs.getString("INDEX_NAME");
547 - IndexInfo info = indexMap.get(name);
548 - if (info == null) {
549 - int t = rs.getInt("TYPE");
550 - String type;
551 - if (t == DatabaseMetaData.tableIndexClustered) {
552 - type = "";
553 - } else if (t == DatabaseMetaData.tableIndexHashed) {
554 - type = " (${text.tree.hashed})";
555 - } else if (t == DatabaseMetaData.tableIndexOther) {
556 - type = "";
557 - } else {
558 - type = null;
559 - }
560 - if (name != null && type != null) {
561 - info = new IndexInfo();
562 - info.name = name;
563 - type = (rs.getBoolean("NON_UNIQUE") ?
564 - "${text.tree.nonUnique}" : "${text.tree.unique}") + type;
565 - info.type = type;
566 - info.columns = rs.getString("COLUMN_NAME");
567 - indexMap.put(name, info);
568 - }
569 - } else {
570 - info.columns += ", " + rs.getString("COLUMN_NAME");
571 - }
572 - }
573 - rs.close();
574 - if (indexMap.size() > 0) {
575 - String level = mainSchema ? ", 1, 1" : ", 2, 1";
576 - String levelIndex = mainSchema ? ", 2, 1" : ", 3, 1";
577 - String levelColumnType = mainSchema ? ", 3, 2" : ", 4, 2";
578 - buff.append("setNode(" + treeIndex + level +
579 - ", 'index_az', '${text.tree.indexes}', null);\n");
580 - treeIndex++;
581 - for (IndexInfo info : indexMap.values()) {
582 - buff.append("setNode(" + treeIndex + levelIndex +
583 - ", 'index', '" +
584 - PageParser.escapeJavaScript(info.name) + "', null);\n");
585 - treeIndex++;
586 - buff.append("setNode(" + treeIndex + levelColumnType +
587 - ", 'type', '" + info.type + "', null);\n");
588 - treeIndex++;
589 - buff.append("setNode(" + treeIndex + levelColumnType +
590 - ", 'type', '" +
591 - PageParser.escapeJavaScript(info.columns) +
592 - "', null);\n");
593 - treeIndex++;
594 - }
595 - }
596 - return treeIndex;
597 - }
598 -
599 - private int addTablesAndViews(DbSchema schema, boolean mainSchema,
600 - StringBuilder buff, int treeIndex) throws SQLException {
601 - if (schema == null) {
602 - return treeIndex;
603 - }
604 - Connection conn = session.getConnection();
605 - DatabaseMetaData meta = session.getMetaData();
606 - int level = mainSchema ? 0 : 1;
607 - boolean showColumns = mainSchema || !schema.isSystem;
608 - String indentation = ", " + level + ", " + (showColumns ? "1" : "2") + ", ";
609 - String indentNode = ", " + (level + 1) + ", 2, ";
610 - DbTableOrView[] tables = schema.getTables();
611 - if (tables == null) {
612 - return treeIndex;
613 - }
614 - boolean isOracle = schema.getContents().isOracle();
615 - boolean notManyTables = tables.length < SysProperties.CONSOLE_MAX_TABLES_LIST_INDEXES;
616 - for (DbTableOrView table : tables) {
617 - if (table.isView()) {
618 - continue;
619 - }
620 - int tableId = treeIndex;
621 - String tab = table.getQuotedName();
622 - if (!mainSchema) {
623 - tab = schema.quotedName + "." + tab;
624 - }
625 - tab = escapeIdentifier(tab);
626 - buff.append("setNode(" + treeIndex + indentation + " 'table', '" +
627 - PageParser.escapeJavaScript(table.getName()) +
628 - "', 'javascript:ins(\\'" + tab + "\\',true)');\n");
629 - treeIndex++;
630 - if (mainSchema || showColumns) {
631 - StringBuilder columnsBuffer = new StringBuilder();
632 - treeIndex = addColumns(mainSchema, table, buff, treeIndex,
633 - notManyTables, columnsBuffer);
634 - if (!isOracle && notManyTables) {
635 - treeIndex = addIndexes(mainSchema, meta, table.getName(),
636 - schema.name, buff, treeIndex);
637 - }
638 - buff.append("addTable('" +
639 - PageParser.escapeJavaScript(table.getName()) + "', '" +
640 - PageParser.escapeJavaScript(columnsBuffer.toString()) +
641 - "', " + tableId + ");\n");
642 - }
643 - }
644 - tables = schema.getTables();
645 - for (DbTableOrView view : tables) {
646 - if (!view.isView()) {
647 - continue;
648 - }
649 - int tableId = treeIndex;
650 - String tab = view.getQuotedName();
651 - if (!mainSchema) {
652 - tab = view.getSchema().quotedName + "." + tab;
653 - }
654 - tab = escapeIdentifier(tab);
655 - buff.append("setNode(" + treeIndex + indentation + " 'view', '" +
656 - PageParser.escapeJavaScript(view.getName()) +
657 - "', 'javascript:ins(\\'" + tab + "\\',true)');\n");
658 - treeIndex++;
659 - if (mainSchema) {
660 - StringBuilder columnsBuffer = new StringBuilder();
661 - treeIndex = addColumns(mainSchema, view, buff,
662 - treeIndex, notManyTables, columnsBuffer);
663 - if (schema.getContents().isH2()) {
664 -
665 - try (PreparedStatement prep = conn.prepareStatement("SELECT * FROM " +
666 - "INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?")) {
667 - prep.setString(1, view.getName());
668 - ResultSet rs = prep.executeQuery();
669 - if (rs.next()) {
670 - String sql = rs.getString("SQL");
671 - buff.append("setNode(" + treeIndex + indentNode +
672 - " 'type', '" +
673 - PageParser.escapeJavaScript(sql) +
674 - "', null);\n");
675 - treeIndex++;
676 - }
677 - rs.close();
678 - }
679 - }
680 - buff.append("addTable('" +
681 - PageParser.escapeJavaScript(view.getName()) + "', '" +
682 - PageParser.escapeJavaScript(columnsBuffer.toString()) +
683 - "', " + tableId + ");\n");
684 - }
685 - }
686 - return treeIndex;
687 - }
688 -
689 - private String tables() {
690 - DbContents contents = session.getContents();
691 - boolean isH2 = false;
692 - try {
693 - String url = (String) session.get("url");
694 - Connection conn = session.getConnection();
695 - contents.readContents(url, conn);
696 - session.loadBnf();
697 - isH2 = contents.isH2();
698 -
699 - StringBuilder buff = new StringBuilder();
700 - buff.append("setNode(0, 0, 0, 'database', '" + PageParser.escapeJavaScript(url)
701 - + "', null);\n");
702 - int treeIndex = 1;
703 -
704 - DbSchema defaultSchema = contents.getDefaultSchema();
705 - treeIndex = addTablesAndViews(defaultSchema, true, buff, treeIndex);
706 - DbSchema[] schemas = contents.getSchemas();
707 - for (DbSchema schema : schemas) {
708 - if (schema == defaultSchema || schema == null) {
709 - continue;
710 - }
711 - buff.append("setNode(" + treeIndex + ", 0, 1, 'folder', '" +
712 - PageParser.escapeJavaScript(schema.name) +
713 - "', null);\n");
714 - treeIndex++;
715 - treeIndex = addTablesAndViews(schema, false, buff, treeIndex);
716 - }
717 - if (isH2) {
718 - try (Statement stat = conn.createStatement()) {
719 - ResultSet rs = stat.executeQuery("SELECT * FROM " +
720 - "INFORMATION_SCHEMA.SEQUENCES ORDER BY SEQUENCE_NAME");
721 - for (int i = 0; rs.next(); i++) {
722 - if (i == 0) {
723 - buff.append("setNode(" + treeIndex +
724 - ", 0, 1, 'sequences', '${text.tree.sequences}', null);\n");
725 - treeIndex++;
726 - }
727 - String name = rs.getString("SEQUENCE_NAME");
728 - String current = rs.getString("CURRENT_VALUE");
729 - String increment = rs.getString("INCREMENT");
730 - buff.append("setNode(" + treeIndex +
731 - ", 1, 1, 'sequence', '" +
732 - PageParser.escapeJavaScript(name) +
733 - "', null);\n");
734 - treeIndex++;
735 - buff.append("setNode(" + treeIndex +
736 - ", 2, 2, 'type', '${text.tree.current}: " +
737 - PageParser.escapeJavaScript(current) +
738 - "', null);\n");
739 - treeIndex++;
740 - if (!"1".equals(increment)) {
741 - buff.append("setNode(" +
742 - treeIndex +
743 - ", 2, 2, 'type', '${text.tree.increment}: " +
744 - PageParser.escapeJavaScript(increment) +
745 - "', null);\n");
746 - treeIndex++;
747 - }
748 - }
749 - rs.close();
750 - rs = stat.executeQuery("SELECT * FROM " +
751 - "INFORMATION_SCHEMA.USERS ORDER BY NAME");
752 - for (int i = 0; rs.next(); i++) {
753 - if (i == 0) {
754 - buff.append("setNode(" + treeIndex +
755 - ", 0, 1, 'users', '${text.tree.users}', null);\n");
756 - treeIndex++;
757 - }
758 - String name = rs.getString("NAME");
759 - String admin = rs.getString("ADMIN");
760 - buff.append("setNode(" + treeIndex +
761 - ", 1, 1, 'user', '" +
762 - PageParser.escapeJavaScript(name) +
763 - "', null);\n");
764 - treeIndex++;
765 - if (admin.equalsIgnoreCase("TRUE")) {
766 - buff.append("setNode(" + treeIndex +
767 - ", 2, 2, 'type', '${text.tree.admin}', null);\n");
768 - treeIndex++;
769 - }
770 - }
771 - rs.close();
772 - }
773 - }
774 - DatabaseMetaData meta = session.getMetaData();
775 - String version = meta.getDatabaseProductName() + " " +
776 - meta.getDatabaseProductVersion();
777 - buff.append("setNode(" + treeIndex + ", 0, 0, 'info', '" +
778 - PageParser.escapeJavaScript(version) + "', null);\n");
779 - buff.append("refreshQueryTables();");
780 - session.put("tree", buff.toString());
781 - } catch (Exception e) {
782 - session.put("tree", "");
783 - session.put("error", getStackTrace(0, e, isH2));
784 - }
785 - return "tables.jsp";
786 - }
787 -
788 - private String getStackTrace(int id, Throwable e, boolean isH2) {
789 - try {
790 - StringWriter writer = new StringWriter();
791 - e.printStackTrace(new PrintWriter(writer));
792 - String stackTrace = writer.toString();
793 - stackTrace = PageParser.escapeHtml(stackTrace);
794 - if (isH2) {
795 - stackTrace = linkToSource(stackTrace);
796 - }
797 - stackTrace = StringUtils.replaceAll(stackTrace, "\t",
798 - "&nbsp;&nbsp;&nbsp;&nbsp;");
799 - String message = PageParser.escapeHtml(e.getMessage());
800 - String error = "<a class=\"error\" href=\"#\" " +
801 - "onclick=\"var x=document.getElementById('st" + id +
802 - "').style;x.display=x.display==''?'none':'';\">" + message +
803 - "</a>";
804 - if (e instanceof SQLException) {
805 - SQLException se = (SQLException) e;
806 - error += " " + se.getSQLState() + "/" + se.getErrorCode();
807 - if (isH2) {
808 - int code = se.getErrorCode();
809 - error += " <a href=\"http://h2database.com/javadoc/" +
810 - "org/h2/api/ErrorCode.html#c" + code +
811 - "\">(${text.a.help})</a>";
812 - }
813 - }
814 - error += "<span style=\"display: none;\" id=\"st" + id +
815 - "\"><br />" + stackTrace + "</span>";
816 - error = formatAsError(error);
817 - return error;
818 - } catch (OutOfMemoryError e2) {
819 - server.traceError(e);
820 - return e.toString();
821 - }
822 - }
823 -
824 - private static String linkToSource(String s) {
825 - try {
826 - StringBuilder result = new StringBuilder(s.length());
827 - int idx = s.indexOf("<br />");
828 - result.append(s.substring(0, idx));
829 - while (true) {
830 - int start = s.indexOf("org.h2.", idx);
831 - if (start < 0) {
832 - result.append(s.substring(idx));
833 - break;
834 - }
835 - result.append(s.substring(idx, start));
836 - int end = s.indexOf(')', start);
837 - if (end < 0) {
838 - result.append(s.substring(idx));
839 - break;
840 - }
841 - String element = s.substring(start, end);
842 - int open = element.lastIndexOf('(');
843 - int dotMethod = element.lastIndexOf('.', open - 1);
844 - int dotClass = element.lastIndexOf('.', dotMethod - 1);
845 - String packageName = element.substring(0, dotClass);
846 - int colon = element.lastIndexOf(':');
847 - String file = element.substring(open + 1, colon);
848 - String lineNumber = element.substring(colon + 1, element.length());
849 - String fullFileName = packageName.replace('.', '/') + "/" + file;
850 - result.append("<a href=\"http://h2database.com/html/source.html?file=");
851 - result.append(fullFileName);
852 - result.append("&line=");
853 - result.append(lineNumber);
854 - result.append("&build=");
855 - result.append(Constants.BUILD_ID);
856 - result.append("\">");
857 - result.append(element);
858 - result.append("</a>");
859 - idx = end;
860 - }
861 - return result.toString();
862 - } catch (Throwable t) {
863 - return s;
864 - }
865 - }
866 -
867 - private static String formatAsError(String s) {
868 - return "<div class=\"error\">" + s + "</div>";
869 - }
870 -
871 - private String test() {
872 - String driver = attributes.getProperty("driver", "");
873 - String url = attributes.getProperty("url", "");
874 - String user = attributes.getProperty("user", "");
875 - String password = attributes.getProperty("password", "");
876 - session.put("driver", driver);
877 - session.put("url", url);
878 - session.put("user", user);
879 - boolean isH2 = url.startsWith("jdbc:h2:");
880 - try {
881 - long start = System.currentTimeMillis();
882 - String profOpen = "", profClose = "";
883 - Profiler prof = new Profiler();
884 - prof.startCollecting();
885 - Connection conn;
886 - try {
887 - conn = server.getConnection(driver, url, user, password);
888 - } finally {
889 - prof.stopCollecting();
890 - profOpen = prof.getTop(3);
891 - }
892 - prof = new Profiler();
893 - prof.startCollecting();
894 - try {
895 - JdbcUtils.closeSilently(conn);
896 - } finally {
897 - prof.stopCollecting();
898 - profClose = prof.getTop(3);
899 - }
900 - long time = System.currentTimeMillis() - start;
901 - String success;
902 - if (time > 1000) {
903 - success = "<a class=\"error\" href=\"#\" " +
904 - "onclick=\"var x=document.getElementById('prof').style;x." +
905 - "display=x.display==''?'none':'';\">" +
906 - "${text.login.testSuccessful}</a>" +
907 - "<span style=\"display: none;\" id=\"prof\"><br />" +
908 - PageParser.escapeHtml(profOpen) +
909 - "<br />" +
910 - PageParser.escapeHtml(profClose) +
911 - "</span>";
912 - } else {
913 - success = "${text.login.testSuccessful}";
914 - }
915 - session.put("error", success);
916 - // session.put("error", "${text.login.testSuccessful}");
917 - return "login.jsp";
918 - } catch (Exception e) {
919 - session.put("error", getLoginError(e, isH2));
920 - return "login.jsp";
921 - }
922 - }
923 -
924 - /**
925 - * Get the formatted login error message.
926 - *
927 - * @param e the exception
928 - * @param isH2 if the current database is a H2 database
929 - * @return the formatted error message
930 - */
931 - private String getLoginError(Exception e, boolean isH2) {
932 - if (e instanceof JdbcSQLException &&
933 - ((JdbcSQLException) e).getErrorCode() == ErrorCode.CLASS_NOT_FOUND_1) {
934 - return "${text.login.driverNotFound}<br />" + getStackTrace(0, e, isH2);
935 - }
936 - return getStackTrace(0, e, isH2);
937 - }
938 -
939 - private String login() {
940 - String driver = attributes.getProperty("driver", "");
941 - String url = attributes.getProperty("url", "");
942 - String user = attributes.getProperty("user", "");
943 - String password = attributes.getProperty("password", "");
944 - session.put("autoCommit", "checked");
945 - session.put("autoComplete", "1");
946 - session.put("maxrows", "1000");
947 - boolean isH2 = url.startsWith("jdbc:h2:");
948 - try {
949 - Connection conn = server.getConnection(driver, url, user, password);
950 - session.setConnection(conn);
951 - session.put("url", url);
952 - session.put("user", user);
953 - session.remove("error");
954 - settingSave();
955 - return "frame.jsp";
956 - } catch (Exception e) {
957 - session.put("error", getLoginError(e, isH2));
958 - return "login.jsp";
959 - }
960 - }
961 -
962 - private String logout() {
963 - try {
964 - Connection conn = session.getConnection();
965 - session.setConnection(null);
966 - session.remove("conn");
967 - session.remove("result");
968 - session.remove("tables");
969 - session.remove("user");
970 - session.remove("tool");
971 - if (conn != null) {
972 - if (session.getShutdownServerOnDisconnect()) {
973 - server.shutdown();
974 - } else {
975 - conn.close();
976 - }
977 - }
978 - } catch (Exception e) {
979 - trace(e.toString());
980 - }
981 - return "index.do";
982 - }
983 -
984 - private String query() {
985 - String sql = attributes.getProperty("sql").trim();
986 - try {
987 - ScriptReader r = new ScriptReader(new StringReader(sql));
988 - final ArrayList<String> list = New.arrayList();
989 - while (true) {
990 - String s = r.readStatement();
991 - if (s == null) {
992 - break;
993 - }
994 - list.add(s);
995 - }
996 - final Connection conn = session.getConnection();
997 - if (SysProperties.CONSOLE_STREAM && server.getAllowChunked()) {
998 - String page = new String(server.getFile("result.jsp"), Constants.UTF8);
999 - int idx = page.indexOf("${result}");
1000 - // the first element of the list is the header, the last the
1001 - // footer
1002 - list.add(0, page.substring(0, idx));
1003 - list.add(page.substring(idx + "${result}".length()));
1004 - session.put("chunks", new Iterator<String>() {
1005 - private int i;
1006 - @Override
1007 - public boolean hasNext() {
1008 - return i < list.size();
1009 - }
1010 - @Override
1011 - public String next() {
1012 - String s = list.get(i++);
1013 - if (i == 1 || i == list.size()) {
1014 - return s;
1015 - }
1016 - StringBuilder b = new StringBuilder();
1017 - query(conn, s, i - 1, list.size() - 2, b);
1018 - return b.toString();
1019 - }
1020 - @Override
1021 - public void remove() {
1022 - throw new UnsupportedOperationException();
1023 - }
1024 - });
1025 - return "result.jsp";
1026 - }
1027 - String result;
1028 - StringBuilder buff = new StringBuilder();
1029 - for (int i = 0; i < list.size(); i++) {
1030 - String s = list.get(i);
1031 - query(conn, s, i, list.size(), buff);
1032 - }
1033 - result = buff.toString();
1034 - session.put("result", result);
1035 - } catch (Throwable e) {
1036 - session.put("result", getStackTrace(0, e, session.getContents().isH2()));
1037 - }
1038 - return "result.jsp";
1039 - }
1040 -
1041 - /**
1042 - * Execute a query and append the result to the buffer.
1043 - *
1044 - * @param conn the connection
1045 - * @param s the statement
1046 - * @param i the index
1047 - * @param size the number of statements
1048 - * @param buff the target buffer
1049 - */
1050 - void query(Connection conn, String s, int i, int size, StringBuilder buff) {
1051 - if (!(s.startsWith("@") && s.endsWith("."))) {
1052 - buff.append(PageParser.escapeHtml(s + ";")).append("<br />");
1053 - }
1054 - boolean forceEdit = s.startsWith("@edit");
1055 - buff.append(getResult(conn, i + 1, s, size == 1, forceEdit)).
1056 - append("<br />");
1057 - }
1058 -
1059 - private String editResult() {
1060 - ResultSet rs = session.result;
1061 - int row = Integer.parseInt(attributes.getProperty("row"));
1062 - int op = Integer.parseInt(attributes.getProperty("op"));
1063 - String result = "", error = "";
1064 - try {
1065 - if (op == 1) {
1066 - boolean insert = row < 0;
1067 - if (insert) {
1068 - rs.moveToInsertRow();
1069 - } else {
1070 - rs.absolute(row);
1071 - }
1072 - for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
1073 - String x = attributes.getProperty("r" + row + "c" + (i + 1));
1074 - unescapeData(x, rs, i + 1);
1075 - }
1076 - if (insert) {
1077 - rs.insertRow();
1078 - } else {
1079 - rs.updateRow();
1080 - }
1081 - } else if (op == 2) {
1082 - rs.absolute(row);
1083 - rs.deleteRow();
1084 - } else if (op == 3) {
1085 - // cancel
1086 - }
1087 - } catch (Throwable e) {
1088 - result = "<br />" + getStackTrace(0, e, session.getContents().isH2());
1089 - error = formatAsError(e.getMessage());
1090 - }
1091 - String sql = "@edit " + (String) session.get("resultSetSQL");
1092 - Connection conn = session.getConnection();
1093 - result = error + getResult(conn, -1, sql, true, true) + result;
1094 - session.put("result", result);
1095 - return "result.jsp";
1096 - }
1097 -
1098 - private ResultSet getMetaResultSet(Connection conn, String sql)
1099 - throws SQLException {
1100 - DatabaseMetaData meta = conn.getMetaData();
1101 - if (isBuiltIn(sql, "@best_row_identifier")) {
1102 - String[] p = split(sql);
1103 - int scale = p[4] == null ? 0 : Integer.parseInt(p[4]);
1104 - boolean nullable = p[5] == null ? false : Boolean.parseBoolean(p[5]);
1105 - return meta.getBestRowIdentifier(p[1], p[2], p[3], scale, nullable);
1106 - } else if (isBuiltIn(sql, "@catalogs")) {
1107 - return meta.getCatalogs();
1108 - } else if (isBuiltIn(sql, "@columns")) {
1109 - String[] p = split(sql);
1110 - return meta.getColumns(p[1], p[2], p[3], p[4]);
1111 - } else if (isBuiltIn(sql, "@column_privileges")) {
1112 - String[] p = split(sql);
1113 - return meta.getColumnPrivileges(p[1], p[2], p[3], p[4]);
1114 - } else if (isBuiltIn(sql, "@cross_references")) {
1115 - String[] p = split(sql);
1116 - return meta.getCrossReference(p[1], p[2], p[3], p[4], p[5], p[6]);
1117 - } else if (isBuiltIn(sql, "@exported_keys")) {
1118 - String[] p = split(sql);
1119 - return meta.getExportedKeys(p[1], p[2], p[3]);
1120 - } else if (isBuiltIn(sql, "@imported_keys")) {
1121 - String[] p = split(sql);
1122 - return meta.getImportedKeys(p[1], p[2], p[3]);
1123 - } else if (isBuiltIn(sql, "@index_info")) {
1124 - String[] p = split(sql);
1125 - boolean unique = p[4] == null ? false : Boolean.parseBoolean(p[4]);
1126 - boolean approx = p[5] == null ? false : Boolean.parseBoolean(p[5]);
1127 - return meta.getIndexInfo(p[1], p[2], p[3], unique, approx);
1128 - } else if (isBuiltIn(sql, "@primary_keys")) {
1129 - String[] p = split(sql);
1130 - return meta.getPrimaryKeys(p[1], p[2], p[3]);
1131 - } else if (isBuiltIn(sql, "@procedures")) {
1132 - String[] p = split(sql);
1133 - return meta.getProcedures(p[1], p[2], p[3]);
1134 - } else if (isBuiltIn(sql, "@procedure_columns")) {
1135 - String[] p = split(sql);
1136 - return meta.getProcedureColumns(p[1], p[2], p[3], p[4]);
1137 - } else if (isBuiltIn(sql, "@schemas")) {
1138 - return meta.getSchemas();
1139 - } else if (isBuiltIn(sql, "@tables")) {
1140 - String[] p = split(sql);
1141 - String[] types = p[4] == null ? null : StringUtils.arraySplit(p[4], ',', false);
1142 - return meta.getTables(p[1], p[2], p[3], types);
1143 - } else if (isBuiltIn(sql, "@table_privileges")) {
1144 - String[] p = split(sql);
1145 - return meta.getTablePrivileges(p[1], p[2], p[3]);
1146 - } else if (isBuiltIn(sql, "@table_types")) {
1147 - return meta.getTableTypes();
1148 - } else if (isBuiltIn(sql, "@type_info")) {
1149 - return meta.getTypeInfo();
1150 - } else if (isBuiltIn(sql, "@udts")) {
1151 - String[] p = split(sql);
1152 - int[] types;
1153 - if (p[4] == null) {
1154 - types = null;
1155 - } else {
1156 - String[] t = StringUtils.arraySplit(p[4], ',', false);
1157 - types = new int[t.length];
1158 - for (int i = 0; i < t.length; i++) {
1159 - types[i] = Integer.parseInt(t[i]);
1160 - }
1161 - }
1162 - return meta.getUDTs(p[1], p[2], p[3], types);
1163 - } else if (isBuiltIn(sql, "@version_columns")) {
1164 - String[] p = split(sql);
1165 - return meta.getVersionColumns(p[1], p[2], p[3]);
1166 - } else if (isBuiltIn(sql, "@memory")) {
1167 - SimpleResultSet rs = new SimpleResultSet();
1168 - rs.addColumn("Type", Types.VARCHAR, 0, 0);
1169 - rs.addColumn("KB", Types.VARCHAR, 0, 0);
1170 - rs.addRow("Used Memory", "" + Utils.getMemoryUsed());
1171 - rs.addRow("Free Memory", "" + Utils.getMemoryFree());
1172 - return rs;
1173 - } else if (isBuiltIn(sql, "@info")) {
1174 - SimpleResultSet rs = new SimpleResultSet();
1175 - rs.addColumn("KEY", Types.VARCHAR, 0, 0);
1176 - rs.addColumn("VALUE", Types.VARCHAR, 0, 0);
1177 - rs.addRow("conn.getCatalog", conn.getCatalog());
1178 - rs.addRow("conn.getAutoCommit", "" + conn.getAutoCommit());
1179 - rs.addRow("conn.getTransactionIsolation", "" + conn.getTransactionIsolation());
1180 - rs.addRow("conn.getWarnings", "" + conn.getWarnings());
1181 - String map;
1182 - try {
1183 - map = "" + conn.getTypeMap();
1184 - } catch (SQLException e) {
1185 - map = e.toString();
1186 - }
1187 - rs.addRow("conn.getTypeMap", "" + map);
1188 - rs.addRow("conn.isReadOnly", "" + conn.isReadOnly());
1189 - rs.addRow("conn.getHoldability", "" + conn.getHoldability());
1190 - addDatabaseMetaData(rs, meta);
1191 - return rs;
1192 - } else if (isBuiltIn(sql, "@attributes")) {
1193 - String[] p = split(sql);
1194 - return meta.getAttributes(p[1], p[2], p[3], p[4]);
1195 - } else if (isBuiltIn(sql, "@super_tables")) {
1196 - String[] p = split(sql);
1197 - return meta.getSuperTables(p[1], p[2], p[3]);
1198 - } else if (isBuiltIn(sql, "@super_types")) {
1199 - String[] p = split(sql);
1200 - return meta.getSuperTypes(p[1], p[2], p[3]);
1201 - } else if (isBuiltIn(sql, "@prof_stop")) {
1202 - if (profiler != null) {
1203 - profiler.stopCollecting();
1204 - SimpleResultSet rs = new SimpleResultSet();
1205 - rs.addColumn("Top Stack Trace(s)", Types.VARCHAR, 0, 0);
1206 - rs.addRow(profiler.getTop(3));
1207 - profiler = null;
1208 - return rs;
1209 - }
1210 - }
1211 - return null;
1212 - }
1213 -
1214 - private static void addDatabaseMetaData(SimpleResultSet rs,
1215 - DatabaseMetaData meta) {
1216 - Method[] methods = DatabaseMetaData.class.getDeclaredMethods();
1217 - Arrays.sort(methods, new Comparator<Method>() {
1218 - @Override
1219 - public int compare(Method o1, Method o2) {
1220 - return o1.toString().compareTo(o2.toString());
1221 - }
1222 - });
1223 - for (Method m : methods) {
1224 - if (m.getParameterTypes().length == 0) {
1225 - try {
1226 - Object o = m.invoke(meta);
1227 - rs.addRow("meta." + m.getName(), "" + o);
1228 - } catch (InvocationTargetException e) {
1229 - rs.addRow("meta." + m.getName(), e.getTargetException().toString());
1230 - } catch (Exception e) {
1231 - rs.addRow("meta." + m.getName(), e.toString());
1232 - }
1233 - }
1234 - }
1235 - }
1236 -
1237 - private static String[] split(String s) {
1238 - String[] list = new String[10];
1239 - String[] t = StringUtils.arraySplit(s, ' ', true);
1240 - System.arraycopy(t, 0, list, 0, t.length);
1241 - for (int i = 0; i < list.length; i++) {
1242 - if ("null".equals(list[i])) {
1243 - list[i] = null;
1244 - }
1245 - }
1246 - return list;
1247 - }
1248 -
1249 - private int getMaxrows() {
1250 - String r = (String) session.get("maxrows");
1251 - int maxrows = r == null ? 0 : Integer.parseInt(r);
1252 - return maxrows;
1253 - }
1254 -
1255 - private String getResult(Connection conn, int id, String sql,
1256 - boolean allowEdit, boolean forceEdit) {
1257 - try {
1258 - sql = sql.trim();
1259 - StringBuilder buff = new StringBuilder();
1260 - String sqlUpper = StringUtils.toUpperEnglish(sql);
1261 - if (sqlUpper.contains("CREATE") ||
1262 - sqlUpper.contains("DROP") ||
1263 - sqlUpper.contains("ALTER") ||
1264 - sqlUpper.contains("RUNSCRIPT")) {
1265 - String sessionId = attributes.getProperty("jsessionid");
1266 - buff.append("<script type=\"text/javascript\">" +
1267 - "parent['h2menu'].location='tables.do?jsessionid="
1268 - + sessionId + "';</script>");
1269 - }
1270 - Statement stat;
1271 - DbContents contents = session.getContents();
1272 - if (forceEdit || (allowEdit && contents.isH2())) {
1273 - stat = conn.createStatement(
1274 - ResultSet.TYPE_SCROLL_INSENSITIVE,
1275 - ResultSet.CONCUR_UPDATABLE);
1276 - } else {
1277 - stat = conn.createStatement();
1278 - }
1279 - ResultSet rs;
1280 - long time = System.currentTimeMillis();
1281 - boolean metadata = false;
1282 - boolean generatedKeys = false;
1283 - boolean edit = false;
1284 - boolean list = false;
1285 - if (isBuiltIn(sql, "@autocommit_true")) {
1286 - conn.setAutoCommit(true);
1287 - return "${text.result.autoCommitOn}";
1288 - } else if (isBuiltIn(sql, "@autocommit_false")) {
1289 - conn.setAutoCommit(false);
1290 - return "${text.result.autoCommitOff}";
1291 - } else if (isBuiltIn(sql, "@cancel")) {
1292 - stat = session.executingStatement;
1293 - if (stat != null) {
1294 - stat.cancel();
1295 - buff.append("${text.result.statementWasCanceled}");
1296 - } else {
1297 - buff.append("${text.result.noRunningStatement}");
1298 - }
1299 - return buff.toString();
1300 - } else if (isBuiltIn(sql, "@edit")) {
1301 - edit = true;
1302 - sql = sql.substring("@edit".length()).trim();
1303 - session.put("resultSetSQL", sql);
1304 - }
1305 - if (isBuiltIn(sql, "@list")) {
1306 - list = true;
1307 - sql = sql.substring("@list".length()).trim();
1308 - }
1309 - if (isBuiltIn(sql, "@meta")) {
1310 - metadata = true;
1311 - sql = sql.substring("@meta".length()).trim();
1312 - }
1313 - if (isBuiltIn(sql, "@generated")) {
1314 - generatedKeys = true;
1315 - sql = sql.substring("@generated".length()).trim();
1316 - } else if (isBuiltIn(sql, "@history")) {
1317 - buff.append(getCommandHistoryString());
1318 - return buff.toString();
1319 - } else if (isBuiltIn(sql, "@loop")) {
1320 - sql = sql.substring("@loop".length()).trim();
1321 - int idx = sql.indexOf(' ');
1322 - int count = Integer.decode(sql.substring(0, idx));
1323 - sql = sql.substring(idx).trim();
1324 - return executeLoop(conn, count, sql);
1325 - } else if (isBuiltIn(sql, "@maxrows")) {
1326 - int maxrows = (int) Double.parseDouble(
1327 - sql.substring("@maxrows".length()).trim());
1328 - session.put("maxrows", "" + maxrows);
1329 - return "${text.result.maxrowsSet}";
1330 - } else if (isBuiltIn(sql, "@parameter_meta")) {
1331 - sql = sql.substring("@parameter_meta".length()).trim();
1332 - PreparedStatement prep = conn.prepareStatement(sql);
1333 - buff.append(getParameterResultSet(prep.getParameterMetaData()));
1334 - return buff.toString();
1335 - } else if (isBuiltIn(sql, "@password_hash")) {
1336 - sql = sql.substring("@password_hash".length()).trim();
1337 - String[] p = split(sql);
1338 - return StringUtils.convertBytesToHex(
1339 - SHA256.getKeyPasswordHash(p[0], p[1].toCharArray()));
1340 - } else if (isBuiltIn(sql, "@prof_start")) {
1341 - if (profiler != null) {
1342 - profiler.stopCollecting();
1343 - }
1344 - profiler = new Profiler();
1345 - profiler.startCollecting();
1346 - return "Ok";
1347 - } else if (isBuiltIn(sql, "@sleep")) {
1348 - String s = sql.substring("@sleep".length()).trim();
1349 - int sleep = 1;
1350 - if (s.length() > 0) {
1351 - sleep = Integer.parseInt(s);
1352 - }
1353 - Thread.sleep(sleep * 1000);
1354 - return "Ok";
1355 - } else if (isBuiltIn(sql, "@transaction_isolation")) {
1356 - String s = sql.substring("@transaction_isolation".length()).trim();
1357 - if (s.length() > 0) {
1358 - int level = Integer.parseInt(s);
1359 - conn.setTransactionIsolation(level);
1360 - }
1361 - buff.append("Transaction Isolation: " +
1362 - conn.getTransactionIsolation() + "<br />");
1363 - buff.append(Connection.TRANSACTION_READ_UNCOMMITTED +
1364 - ": read_uncommitted<br />");
1365 - buff.append(Connection.TRANSACTION_READ_COMMITTED +
1366 - ": read_committed<br />");
1367 - buff.append(Connection.TRANSACTION_REPEATABLE_READ +
1368 - ": repeatable_read<br />");
1369 - buff.append(Connection.TRANSACTION_SERIALIZABLE +
1370 - ": serializable");
1371 - }
1372 - if (sql.startsWith("@")) {
1373 - rs = getMetaResultSet(conn, sql);
1374 - if (rs == null) {
1375 - buff.append("?: " + sql);
1376 - return buff.toString();
1377 - }
1378 - } else {
1379 - int maxrows = getMaxrows();
1380 - stat.setMaxRows(maxrows);
1381 - session.executingStatement = stat;
1382 - boolean isResultSet = stat.execute(sql);
1383 - session.addCommand(sql);
1384 - if (generatedKeys) {
1385 - rs = null;
1386 - rs = stat.getGeneratedKeys();
1387 - } else {
1388 - if (!isResultSet) {
1389 - buff.append("${text.result.updateCount}: " + stat.getUpdateCount());
1390 - time = System.currentTimeMillis() - time;
1391 - buff.append("<br />(").append(time).append(" ms)");
1392 - stat.close();
1393 - return buff.toString();
1394 - }
1395 - rs = stat.getResultSet();
1396 - }
1397 - }
1398 - time = System.currentTimeMillis() - time;
1399 - buff.append(getResultSet(sql, rs, metadata, list, edit, time, allowEdit));
1400 - // SQLWarning warning = stat.getWarnings();
1401 - // if (warning != null) {
1402 - // buff.append("<br />Warning:<br />").
1403 - // append(getStackTrace(id, warning));
1404 - // }
1405 - if (!edit) {
1406 - stat.close();
1407 - }
1408 - return buff.toString();
1409 - } catch (Throwable e) {
1410 - // throwable: including OutOfMemoryError and so on
1411 - return getStackTrace(id, e, session.getContents().isH2());
1412 - } finally {
1413 - session.executingStatement = null;
1414 - }
1415 - }
1416 -
1417 - private static boolean isBuiltIn(String sql, String builtIn) {
1418 - return StringUtils.startsWithIgnoreCase(sql, builtIn);
1419 - }
1420 -
1421 - private String executeLoop(Connection conn, int count, String sql)
1422 - throws SQLException {
1423 - ArrayList<Integer> params = New.arrayList();
1424 - int idx = 0;
1425 - while (!stop) {
1426 - idx = sql.indexOf('?', idx);
1427 - if (idx < 0) {
1428 - break;
1429 - }
1430 - if (isBuiltIn(sql.substring(idx), "?/*rnd*/")) {
1431 - params.add(1);
1432 - sql = sql.substring(0, idx) + "?" + sql.substring(idx + "/*rnd*/".length() + 1);
1433 - } else {
1434 - params.add(0);
1435 - }
1436 - idx++;
1437 - }
1438 - boolean prepared;
1439 - Random random = new Random(1);
1440 - long time = System.currentTimeMillis();
1441 - if (isBuiltIn(sql, "@statement")) {
1442 - sql = sql.substring("@statement".length()).trim();
1443 - prepared = false;
1444 - Statement stat = conn.createStatement();
1445 - for (int i = 0; !stop && i < count; i++) {
1446 - String s = sql;
1447 - for (Integer type : params) {
1448 - idx = s.indexOf('?');
1449 - if (type.intValue() == 1) {
1450 - s = s.substring(0, idx) + random.nextInt(count) + s.substring(idx + 1);
1451 - } else {
1452 - s = s.substring(0, idx) + i + s.substring(idx + 1);
1453 - }
1454 - }
1455 - if (stat.execute(s)) {
1456 - ResultSet rs = stat.getResultSet();
1457 - while (!stop && rs.next()) {
1458 - // maybe get the data as well
1459 - }
1460 - rs.close();
1461 - }
1462 - }
1463 - } else {
1464 - prepared = true;
1465 - PreparedStatement prep = conn.prepareStatement(sql);
1466 - for (int i = 0; !stop && i < count; i++) {
1467 - for (int j = 0; j < params.size(); j++) {
1468 - Integer type = params.get(j);
1469 - if (type.intValue() == 1) {
1470 - prep.setInt(j + 1, random.nextInt(count));
1471 - } else {
1472 - prep.setInt(j + 1, i);
1473 - }
1474 - }
1475 - if (session.getContents().isSQLite()) {
1476 - // SQLite currently throws an exception on prep.execute()
1477 - prep.executeUpdate();
1478 - } else {
1479 - if (prep.execute()) {
1480 - ResultSet rs = prep.getResultSet();
1481 - while (!stop && rs.next()) {
1482 - // maybe get the data as well
1483 - }
1484 - rs.close();
1485 - }
1486 - }
1487 - }
1488 - }
1489 - time = System.currentTimeMillis() - time;
1490 - StatementBuilder buff = new StatementBuilder();
1491 - buff.append(time).append(" ms: ").append(count).append(" * ");
1492 - if (prepared) {
1493 - buff.append("(Prepared) ");
1494 - } else {
1495 - buff.append("(Statement) ");
1496 - }
1497 - buff.append('(');
1498 - for (int p : params) {
1499 - buff.appendExceptFirst(", ");
1500 - buff.append(p == 0 ? "i" : "rnd");
1501 - }
1502 - return buff.append(") ").append(sql).toString();
1503 - }
1504 -
1505 - private String getCommandHistoryString() {
1506 - StringBuilder buff = new StringBuilder();
1507 - ArrayList<String> history = session.getCommandHistory();
1508 - buff.append("<table cellspacing=0 cellpadding=0>" +
1509 - "<tr><th></th><th>Command</th></tr>");
1510 - for (int i = history.size() - 1; i >= 0; i--) {
1511 - String sql = history.get(i);
1512 - buff.append("<tr><td><a href=\"getHistory.do?id=").
1513 - append(i).
1514 - append("&jsessionid=${sessionId}\" target=\"h2query\" >").
1515 - append("<img width=16 height=16 src=\"ico_write.gif\" " +
1516 - "onmouseover = \"this.className ='icon_hover'\" ").
1517 - append("onmouseout = \"this.className ='icon'\" " +
1518 - "class=\"icon\" alt=\"${text.resultEdit.edit}\" ").
1519 - append("title=\"${text.resultEdit.edit}\" border=\"1\"/></a>").
1520 - append("</td><td>").
1521 - append(PageParser.escapeHtml(sql)).
1522 - append("</td></tr>");
1523 - }
1524 - buff.append("</table>");
1525 - return buff.toString();
1526 - }
1527 -
1528 - private static String getParameterResultSet(ParameterMetaData meta)
1529 - throws SQLException {
1530 - StringBuilder buff = new StringBuilder();
1531 - if (meta == null) {
1532 - return "No parameter meta data";
1533 - }
1534 - buff.append("<table cellspacing=0 cellpadding=0>").
1535 - append("<tr><th>className</th><th>mode</th><th>type</th>").
1536 - append("<th>typeName</th><th>precision</th><th>scale</th></tr>");
1537 - for (int i = 0; i < meta.getParameterCount(); i++) {
1538 - buff.append("</tr><td>").
1539 - append(meta.getParameterClassName(i + 1)).
1540 - append("</td><td>").
1541 - append(meta.getParameterMode(i + 1)).
1542 - append("</td><td>").
1543 - append(meta.getParameterType(i + 1)).
1544 - append("</td><td>").
1545 - append(meta.getParameterTypeName(i + 1)).
1546 - append("</td><td>").
1547 - append(meta.getPrecision(i + 1)).
1548 - append("</td><td>").
1549 - append(meta.getScale(i + 1)).
1550 - append("</td></tr>");
1551 - }
1552 - buff.append("</table>");
1553 - return buff.toString();
1554 - }
1555 -
1556 - private String getResultSet(String sql, ResultSet rs, boolean metadata,
1557 - boolean list, boolean edit, long time, boolean allowEdit)
1558 - throws SQLException {
1559 - int maxrows = getMaxrows();
1560 - time = System.currentTimeMillis() - time;
1561 - StringBuilder buff = new StringBuilder();
1562 - if (edit) {
1563 - buff.append("<form id=\"editing\" name=\"editing\" method=\"post\" " +
1564 - "action=\"editResult.do?jsessionid=${sessionId}\" " +
1565 - "id=\"mainForm\" target=\"h2result\">" +
1566 - "<input type=\"hidden\" name=\"op\" value=\"1\" />" +
1567 - "<input type=\"hidden\" name=\"row\" value=\"\" />" +
1568 - "<table cellspacing=0 cellpadding=0 id=\"editTable\">");
1569 - } else {
1570 - buff.append("<table cellspacing=0 cellpadding=0>");
1571 - }
1572 - if (metadata) {
1573 - SimpleResultSet r = new SimpleResultSet();
1574 - r.addColumn("#", Types.INTEGER, 0, 0);
1575 - r.addColumn("label", Types.VARCHAR, 0, 0);
1576 - r.addColumn("catalog", Types.VARCHAR, 0, 0);
1577 - r.addColumn("schema", Types.VARCHAR, 0, 0);
1578 - r.addColumn("table", Types.VARCHAR, 0, 0);
1579 - r.addColumn("column", Types.VARCHAR, 0, 0);
1580 - r.addColumn("type", Types.INTEGER, 0, 0);
1581 - r.addColumn("typeName", Types.VARCHAR, 0, 0);
1582 - r.addColumn("class", Types.VARCHAR, 0, 0);
1583 - r.addColumn("precision", Types.INTEGER, 0, 0);
1584 - r.addColumn("scale", Types.INTEGER, 0, 0);
1585 - r.addColumn("displaySize", Types.INTEGER, 0, 0);
1586 - r.addColumn("autoIncrement", Types.BOOLEAN, 0, 0);
1587 - r.addColumn("caseSensitive", Types.BOOLEAN, 0, 0);
1588 - r.addColumn("currency", Types.BOOLEAN, 0, 0);
1589 - r.addColumn("nullable", Types.INTEGER, 0, 0);
1590 - r.addColumn("readOnly", Types.BOOLEAN, 0, 0);
1591 - r.addColumn("searchable", Types.BOOLEAN, 0, 0);
1592 - r.addColumn("signed", Types.BOOLEAN, 0, 0);
1593 - r.addColumn("writable", Types.BOOLEAN, 0, 0);
1594 - r.addColumn("definitelyWritable", Types.BOOLEAN, 0, 0);
1595 - ResultSetMetaData m = rs.getMetaData();
1596 - for (int i = 1; i <= m.getColumnCount(); i++) {
1597 - r.addRow(i,
1598 - m.getColumnLabel(i),
1599 - m.getCatalogName(i),
1600 - m.getSchemaName(i),
1601 - m.getTableName(i),
1602 - m.getColumnName(i),
1603 - m.getColumnType(i),
1604 - m.getColumnTypeName(i),
1605 - m.getColumnClassName(i),
1606 - m.getPrecision(i),
1607 - m.getScale(i),
1608 - m.getColumnDisplaySize(i),
1609 - m.isAutoIncrement(i),
1610 - m.isCaseSensitive(i),
1611 - m.isCurrency(i),
1612 - m.isNullable(i),
1613 - m.isReadOnly(i),
1614 - m.isSearchable(i),
1615 - m.isSigned(i),
1616 - m.isWritable(i),
1617 - m.isDefinitelyWritable(i));
1618 - }
1619 - rs = r;
1620 - }
1621 - ResultSetMetaData meta = rs.getMetaData();
1622 - int columns = meta.getColumnCount();
1623 - int rows = 0;
1624 - if (list) {
1625 - buff.append("<tr><th>Column</th><th>Data</th></tr><tr>");
1626 - while (rs.next()) {
1627 - if (maxrows > 0 && rows >= maxrows) {
1628 - break;
1629 - }
1630 - rows++;
1631 - buff.append("<tr><td>Row #</td><td>").
1632 - append(rows).append("</tr>");
1633 - for (int i = 0; i < columns; i++) {
1634 - buff.append("<tr><td>").
1635 - append(PageParser.escapeHtml(meta.getColumnLabel(i + 1))).
1636 - append("</td><td>").
1637 - append(escapeData(rs, i + 1)).
1638 - append("</td></tr>");
1639 - }
1640 - }
1641 - } else {
1642 - buff.append("<tr>");
1643 - if (edit) {
1644 - buff.append("<th>${text.resultEdit.action}</th>");
1645 - }
1646 - for (int i = 0; i < columns; i++) {
1647 - buff.append("<th>").
1648 - append(PageParser.escapeHtml(meta.getColumnLabel(i + 1))).
1649 - append("</th>");
1650 - }
1651 - buff.append("</tr>");
1652 - while (rs.next()) {
1653 - if (maxrows > 0 && rows >= maxrows) {
1654 - break;
1655 - }
1656 - rows++;
1657 - buff.append("<tr>");
1658 - if (edit) {
1659 - buff.append("<td>").
1660 - append("<img onclick=\"javascript:editRow(").
1661 - append(rs.getRow()).
1662 - append(",'${sessionId}', '${text.resultEdit.save}', " +
1663 - "'${text.resultEdit.cancel}'").
1664 - append(")\" width=16 height=16 src=\"ico_write.gif\" " +
1665 - "onmouseover = \"this.className ='icon_hover'\" " +
1666 - "onmouseout = \"this.className ='icon'\" " +
1667 - "class=\"icon\" alt=\"${text.resultEdit.edit}\" " +
1668 - "title=\"${text.resultEdit.edit}\" border=\"1\"/>").
1669 - append("<a href=\"editResult.do?op=2&row=").
1670 - append(rs.getRow()).
1671 - append("&jsessionid=${sessionId}\" target=\"h2result\" >" +
1672 - "<img width=16 height=16 src=\"ico_remove.gif\" " +
1673 - "onmouseover = \"this.className ='icon_hover'\" " +
1674 - "onmouseout = \"this.className ='icon'\" " +
1675 - "class=\"icon\" alt=\"${text.resultEdit.delete}\" " +
1676 - "title=\"${text.resultEdit.delete}\" border=\"1\" /></a>").
1677 - append("</td>");
1678 - }
1679 - for (int i = 0; i < columns; i++) {
1680 - buff.append("<td>").
1681 - append(escapeData(rs, i + 1)).
1682 - append("</td>");
1683 - }
1684 - buff.append("</tr>");
1685 - }
1686 - }
1687 - boolean isUpdatable = false;
1688 - try {
1689 - if (!session.getContents().isDB2()) {
1690 - isUpdatable = rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE
1691 - && rs.getType() != ResultSet.TYPE_FORWARD_ONLY;
1692 - }
1693 - } catch (NullPointerException e) {
1694 - // ignore
1695 - // workaround for a JDBC-ODBC bridge problem
1696 - }
1697 - if (edit) {
1698 - ResultSet old = session.result;
1699 - if (old != null) {
1700 - old.close();
1701 - }
1702 - session.result = rs;
1703 - } else {
1704 - rs.close();
1705 - }
1706 - if (edit) {
1707 - buff.append("<tr><td>").
1708 - append("<img onclick=\"javascript:editRow(-1, " +
1709 - "'${sessionId}', '${text.resultEdit.save}', '${text.resultEdit.cancel}'").
1710 - append(")\" width=16 height=16 src=\"ico_add.gif\" " +
1711 - "onmouseover = \"this.className ='icon_hover'\" " +
1712 - "onmouseout = \"this.className ='icon'\" " +
1713 - "class=\"icon\" alt=\"${text.resultEdit.add}\" " +
1714 - "title=\"${text.resultEdit.add}\" border=\"1\"/>").
1715 - append("</td>");
1716 - for (int i = 0; i < columns; i++) {
1717 - buff.append("<td></td>");
1718 - }
1719 - buff.append("</tr>");
1720 - }
1721 - buff.append("</table>");
1722 - if (edit) {
1723 - buff.append("</form>");
1724 - }
1725 - if (rows == 0) {
1726 - buff.append("(${text.result.noRows}");
1727 - } else if (rows == 1) {
1728 - buff.append("(${text.result.1row}");
1729 - } else {
1730 - buff.append('(').append(rows).append(" ${text.result.rows}");
1731 - }
1732 - buff.append(", ");
1733 - time = System.currentTimeMillis() - time;
1734 - buff.append(time).append(" ms)");
1735 - if (!edit && isUpdatable && allowEdit) {
1736 - buff.append("<br /><br />" +
1737 - "<form name=\"editResult\" method=\"post\" " +
1738 - "action=\"query.do?jsessionid=${sessionId}\" target=\"h2result\">" +
1739 - "<input type=\"submit\" class=\"button\" " +
1740 - "value=\"${text.resultEdit.editResult}\" />" +
1741 - "<input type=\"hidden\" name=\"sql\" value=\"@edit ").
1742 - append(PageParser.escapeHtmlData(sql)).
1743 - append("\" /></form>");
1744 - }
1745 - return buff.toString();
1746 - }
1747 -
1748 - /**
1749 - * Save the current connection settings to the properties file.
1750 - *
1751 - * @return the file to open afterwards
1752 - */
1753 - private String settingSave() {
1754 - ConnectionInfo info = new ConnectionInfo();
1755 - info.name = attributes.getProperty("name", "");
1756 - info.driver = attributes.getProperty("driver", "");
1757 - info.url = attributes.getProperty("url", "");
1758 - info.user = attributes.getProperty("user", "");
1759 - server.updateSetting(info);
1760 - attributes.put("setting", info.name);
1761 - server.saveProperties(null);
1762 - return "index.do";
1763 - }
1764 -
1765 - private static String escapeData(ResultSet rs, int columnIndex)
1766 - throws SQLException {
1767 - String d = rs.getString(columnIndex);
1768 - if (d == null) {
1769 - return "<i>null</i>";
1770 - } else if (d.length() > 100000) {
1771 - String s;
1772 - if (isBinary(rs.getMetaData().getColumnType(columnIndex))) {
1773 - s = PageParser.escapeHtml(d.substring(0, 6)) +
1774 - "... (" + (d.length() / 2) + " ${text.result.bytes})";
1775 - } else {
1776 - s = PageParser.escapeHtml(d.substring(0, 100)) +
1777 - "... (" + d.length() + " ${text.result.characters})";
1778 - }
1779 - return "<div style='display: none'>=+</div>" + s;
1780 - } else if (d.equals("null") || d.startsWith("= ") || d.startsWith("=+")) {
1781 - return "<div style='display: none'>= </div>" + PageParser.escapeHtml(d);
1782 - } else if (d.equals("")) {
1783 - // PageParser.escapeHtml replaces "" with a non-breaking space
1784 - return "";
1785 - }
1786 - return PageParser.escapeHtml(d);
1787 - }
1788 -
1789 - private static boolean isBinary(int sqlType) {
1790 - switch (sqlType) {
1791 - case Types.BINARY:
1792 - case Types.BLOB:
1793 - case Types.JAVA_OBJECT:
1794 - case Types.LONGVARBINARY:
1795 - case Types.OTHER:
1796 - case Types.VARBINARY:
1797 - return true;
1798 - }
1799 - return false;
1800 - }
1801 -
1802 - private void unescapeData(String x, ResultSet rs, int columnIndex)
1803 - throws SQLException {
1804 - if (x.equals("null")) {
1805 - rs.updateNull(columnIndex);
1806 - return;
1807 - } else if (x.startsWith("=+")) {
1808 - // don't update
1809 - return;
1810 - } else if (x.equals("=*")) {
1811 - // set an appropriate default value
1812 - int type = rs.getMetaData().getColumnType(columnIndex);
1813 - switch (type) {
1814 - case Types.TIME:
1815 - rs.updateString(columnIndex, "12:00:00");
1816 - break;
1817 - case Types.TIMESTAMP:
1818 - case Types.DATE:
1819 - rs.updateString(columnIndex, "2001-01-01");
1820 - break;
1821 - default:
1822 - rs.updateString(columnIndex, "1");
1823 - break;
1824 - }
1825 - return;
1826 - } else if (x.startsWith("= ")) {
1827 - x = x.substring(2);
1828 - }
1829 - ResultSetMetaData meta = rs.getMetaData();
1830 - int type = meta.getColumnType(columnIndex);
1831 - if (session.getContents().isH2()) {
1832 - rs.updateString(columnIndex, x);
1833 - return;
1834 - }
1835 - switch (type) {
1836 - case Types.BIGINT:
1837 - rs.updateLong(columnIndex, Long.decode(x));
1838 - break;
1839 - case Types.DECIMAL:
1840 - rs.updateBigDecimal(columnIndex, new BigDecimal(x));
1841 - break;
1842 - case Types.DOUBLE:
1843 - case Types.FLOAT:
1844 - rs.updateDouble(columnIndex, Double.parseDouble(x));
1845 - break;
1846 - case Types.REAL:
1847 - rs.updateFloat(columnIndex, Float.parseFloat(x));
1848 - break;
1849 - case Types.INTEGER:
1850 - rs.updateInt(columnIndex, Integer.decode(x));
1851 - break;
1852 - case Types.TINYINT:
1853 - rs.updateShort(columnIndex, Short.decode(x));
1854 - break;
1855 - default:
1856 - rs.updateString(columnIndex, x);
1857 - }
1858 - }
1859 -
1860 - private String settingRemove() {
1861 - String setting = attributes.getProperty("name", "");
1862 - server.removeSetting(setting);
1863 - ArrayList<ConnectionInfo> settings = server.getSettings();
1864 - if (settings.size() > 0) {
1865 - attributes.put("setting", settings.get(0));
1866 - }
1867 - server.saveProperties(null);
1868 - return "index.do";
1869 - }
1870 -
1871 - /**
1872 - * Get the current mime type.
1873 - *
1874 - * @return the mime type
1875 - */
1876 - String getMimeType() {
1877 - return mimeType;
1878 - }
1879 -
1880 - boolean getCache() {
1881 - return cache;
1882 - }
1883 -
1884 - WebSession getSession() {
1885 - return session;
1886 - }
1887 -
1888 - private void trace(String s) {
1889 - server.trace(s);
1890 - }
1891 -
1892 -}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.WebServer
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -//package org.h2.server.web;
9 -
10 - import java.io.File;
11 - import java.io.IOException;
12 - import java.io.InputStream;
13 - import java.io.OutputStream;
14 - import java.net.ServerSocket;
15 - import java.net.Socket;
16 - import java.sql.Connection;
17 - import java.sql.SQLException;
18 - import java.text.SimpleDateFormat;
19 - import java.util.ArrayList;
20 - import java.util.Collections;
21 - import java.util.HashMap;
22 - import java.util.HashSet;
23 - import java.util.Locale;
24 - import java.util.Map;
25 - import java.util.Map.Entry;
26 - import java.util.Properties;
27 - import java.util.Set;
28 - import java.util.TimeZone;
29 -
30 - import org.h2.engine.Constants;
31 - import org.h2.engine.SysProperties;
32 - import org.h2.message.DbException;
33 - import org.h2.server.Service;
34 - import org.h2.server.ShutdownHandler;
35 - import org.h2.store.fs.FileUtils;
36 - import org.h2.util.JdbcUtils;
37 - import org.h2.util.MathUtils;
38 - import org.h2.util.NetUtils;
39 - import org.h2.util.New;
40 - import org.h2.util.SortedProperties;
41 - import org.h2.util.StringUtils;
42 - import org.h2.util.Tool;
43 - import org.h2.util.Utils;
44 -
45 -/**
46 - * The web server is a simple standalone HTTP server that implements the H2
47 - * Console application. It is not optimized for performance.
48 - */
49 -public class WebServer implements Service {
50 -
51 - static final String[][] LANGUAGES = {
52 - { "cs", "\u010ce\u0161tina" },
53 - { "de", "Deutsch" },
54 - { "en", "English" },
55 - { "es", "Espa\u00f1ol" },
56 - { "fr", "Fran\u00e7ais" },
57 - { "hu", "Magyar"},
58 - { "ko", "\ud55c\uad6d\uc5b4"},
59 - { "in", "Indonesia"},
60 - { "it", "Italiano"},
61 - { "ja", "\u65e5\u672c\u8a9e"},
62 - { "nl", "Nederlands"},
63 - { "pl", "Polski"},
64 - { "pt_BR", "Portugu\u00eas (Brasil)"},
65 - { "pt_PT", "Portugu\u00eas (Europeu)"},
66 - { "ru", "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"},
67 - { "sk", "Slovensky"},
68 - { "tr", "T\u00fcrk\u00e7e"},
69 - { "uk", "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"},
70 - { "zh_CN", "\u4e2d\u6587 (\u7b80\u4f53)"},
71 - { "zh_TW", "\u4e2d\u6587 (\u7e41\u9ad4)"},
72 - };
73 -
74 - private static final String COMMAND_HISTORY = "commandHistory";
75 -
76 - private static final String DEFAULT_LANGUAGE = "en";
77 -
78 - private static final String[] GENERIC = {
79 - "Generic JNDI Data Source|javax.naming.InitialContext|" +
80 - "java:comp/env/jdbc/Test|sa",
81 - "Generic Firebird Server|org.firebirdsql.jdbc.FBDriver|" +
82 - "jdbc:firebirdsql:localhost:c:/temp/firebird/test|sysdba",
83 - "Generic SQLite|org.sqlite.JDBC|" +
84 - "jdbc:sqlite:test|sa",
85 - "Generic DB2|com.ibm.db2.jcc.DB2Driver|" +
86 - "jdbc:db2://localhost/test|" ,
87 - "Generic Oracle|oracle.jdbc.driver.OracleDriver|" +
88 - "jdbc:oracle:thin:@localhost:1521:XE|sa" ,
89 - "Generic MS SQL Server 2000|com.microsoft.jdbc.sqlserver.SQLServerDriver|" +
90 - "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=sqlexpress|sa",
91 - "Generic MS SQL Server 2005|com.microsoft.sqlserver.jdbc.SQLServerDriver|" +
92 - "jdbc:sqlserver://localhost;DatabaseName=test|sa",
93 - "Generic PostgreSQL|org.postgresql.Driver|" +
94 - "jdbc:postgresql:test|" ,
95 - "Generic MySQL|com.mysql.jdbc.Driver|" +
96 - "jdbc:mysql://localhost:3306/test|" ,
97 - "Generic HSQLDB|org.hsqldb.jdbcDriver|" +
98 - "jdbc:hsqldb:test;hsqldb.default_table_type=cached|sa" ,
99 - "Generic Derby (Server)|org.apache.derby.jdbc.ClientDriver|" +
100 - "jdbc:derby://localhost:1527/test;create=true|sa",
101 - "Generic Derby (Embedded)|org.apache.derby.jdbc.EmbeddedDriver|" +
102 - "jdbc:derby:test;create=true|sa",
103 - "Generic H2 (Server)|org.h2.Driver|" +
104 - "jdbc:h2:tcp://localhost/~/test|sa",
105 - // this will be listed on top for new installations
106 - "Generic H2 (Embedded)|org.h2.Driver|" +
107 - "jdbc:h2:~/test|sa",
108 - };
109 -
110 - private static int ticker;
111 -
112 - /**
113 - * The session timeout (the default is 30 minutes).
114 - */
115 - private static final long SESSION_TIMEOUT = SysProperties.CONSOLE_TIMEOUT;
116 -
117 -// public static void main(String... args) throws IOException {
118 -// String s = IOUtils.readStringAndClose(new java.io.FileReader(
119 -// // "src/main/org/h2/server/web/res/_text_cs.prop"), -1);
120 -// "src/main/org/h2/res/_messages_cs.prop"), -1);
121 -// System.out.println(StringUtils.javaEncode("..."));
122 -// String[] list = Locale.getISOLanguages();
123 -// for (int i = 0; i < list.length; i++) {
124 -// System.out.print(list[i] + " ");
125 -// }
126 -// System.out.println();
127 -// String l = "de";
128 -// String lang = new java.util.Locale(l).
129 -// getDisplayLanguage(new java.util.Locale(l));
130 -// System.out.println(new java.util.Locale(l).getDisplayLanguage());
131 -// System.out.println(lang);
132 -// java.util.Locale.CHINESE.getDisplayLanguage(java.util.Locale.CHINESE);
133 -// for (int i = 0; i < lang.length(); i++) {
134 -// System.out.println(Integer.toHexString(lang.charAt(i)) + " ");
135 -// }
136 -// }
137 -
138 - // private URLClassLoader urlClassLoader;
139 - private int port;
140 - private boolean allowOthers;
141 - private boolean isDaemon;
142 - private final Set<WebThread> running =
143 - Collections.synchronizedSet(new HashSet<WebThread>());
144 - private boolean ssl;
145 - private final HashMap<String, ConnectionInfo> connInfoMap = New.hashMap();
146 -
147 - private long lastTimeoutCheck;
148 - private final HashMap<String, WebSession> sessions = New.hashMap();
149 - private final HashSet<String> languages = New.hashSet();
150 - private String startDateTime;
151 - private ServerSocket serverSocket;
152 - private String url;
153 - private ShutdownHandler shutdownHandler;
154 - private Thread listenerThread;
155 - private boolean ifExists;
156 - private boolean trace;
157 - private TranslateThread translateThread;
158 - private boolean allowChunked = true;
159 - private String serverPropertiesDir = Constants.SERVER_PROPERTIES_DIR;
160 - // null means the history is not allowed to be stored
161 - private String commandHistoryString;
162 -
163 - /**
164 - * Read the given file from the file system or from the resources.
165 - *
166 - * @param file the file name
167 - * @return the data
168 - */
169 - byte[] getFile(String file) throws IOException {
170 - trace("getFile <" + file + ">");
171 - byte[] data = Utils.getResource("/org/h2/server/web/res/" + file);
172 - if (data == null) {
173 - trace(" null");
174 - } else {
175 - trace(" size=" + data.length);
176 - }
177 - return data;
178 - }
179 -
180 - /**
181 - * Check if this is a simple name (only contains '.', '-', '_', letters, or
182 - * digits).
183 - *
184 - * @param s the string
185 - * @return true if it's a simple name
186 - */
187 - static boolean isSimpleName(String s) {
188 - for (char c : s.toCharArray()) {
189 - if (c != '.' && c != '_' && c != '-' && !Character.isLetterOrDigit(c)) {
190 - return false;
191 - }
192 - }
193 - return true;
194 - }
195 -
196 - /**
197 - * Remove this web thread from the set of running threads.
198 - *
199 - * @param t the thread to remove
200 - */
201 - synchronized void remove(WebThread t) {
202 - running.remove(t);
203 - }
204 -
205 - private static String generateSessionId() {
206 - byte[] buff = MathUtils.secureRandomBytes(16);
207 - return StringUtils.convertBytesToHex(buff);
208 - }
209 -
210 - /**
211 - * Get the web session object for the given session id.
212 - *
213 - * @param sessionId the session id
214 - * @return the web session or null
215 - */
216 - WebSession getSession(String sessionId) {
217 - long now = System.currentTimeMillis();
218 - if (lastTimeoutCheck + SESSION_TIMEOUT < now) {
219 - for (String id : New.arrayList(sessions.keySet())) {
220 - WebSession session = sessions.get(id);
221 - if (session.lastAccess + SESSION_TIMEOUT < now) {
222 - trace("timeout for " + id);
223 - sessions.remove(id);
224 - }
225 - }
226 - lastTimeoutCheck = now;
227 - }
228 - WebSession session = sessions.get(sessionId);
229 - if (session != null) {
230 - session.lastAccess = System.currentTimeMillis();
231 - }
232 - return session;
233 - }
234 -
235 - /**
236 - * Create a new web session id and object.
237 - *
238 - * @param hostAddr the host address
239 - * @return the web session object
240 - */
241 - WebSession createNewSession(String hostAddr) {
242 - String newId;
243 - do {
244 - newId = generateSessionId();
245 - } while (sessions.get(newId) != null);
246 - WebSession session = new WebSession(this);
247 - session.lastAccess = System.currentTimeMillis();
248 - session.put("sessionId", newId);
249 - session.put("ip", hostAddr);
250 - session.put("language", DEFAULT_LANGUAGE);
251 - session.put("frame-border", "0");
252 - session.put("frameset-border", "4");
253 - sessions.put(newId, session);
254 - // always read the english translation,
255 - // so that untranslated text appears at least in english
256 - readTranslations(session, DEFAULT_LANGUAGE);
257 - return getSession(newId);
258 - }
259 -
260 - String getStartDateTime() {
261 - if (startDateTime == null) {
262 - SimpleDateFormat format = new SimpleDateFormat(
263 - "EEE, d MMM yyyy HH:mm:ss z", new Locale("en", ""));
264 - format.setTimeZone(TimeZone.getTimeZone("GMT"));
265 - startDateTime = format.format(System.currentTimeMillis());
266 - }
267 - return startDateTime;
268 - }
269 -
270 - @Override
271 - public void init(String... args) {
272 - // set the serverPropertiesDir, because it's used in loadProperties()
273 - for (int i = 0; args != null && i < args.length; i++) {
274 - if ("-properties".equals(args[i])) {
275 - serverPropertiesDir = args[++i];
276 - }
277 - }
278 - Properties prop = loadProperties();
279 - port = SortedProperties.getIntProperty(prop,
280 - "webPort", Constants.DEFAULT_HTTP_PORT);
281 - ssl = SortedProperties.getBooleanProperty(prop,
282 - "webSSL", false);
283 - allowOthers = SortedProperties.getBooleanProperty(prop,
284 - "webAllowOthers", false);
285 - commandHistoryString = prop.getProperty(COMMAND_HISTORY);
286 - for (int i = 0; args != null && i < args.length; i++) {
287 - String a = args[i];
288 - if (Tool.isOption(a, "-webPort")) {
289 - port = Integer.decode(args[++i]);
290 - } else if (Tool.isOption(a, "-webSSL")) {
291 - ssl = true;
292 - } else if (Tool.isOption(a, "-webAllowOthers")) {
293 - allowOthers = true;
294 - } else if (Tool.isOption(a, "-webDaemon")) {
295 - isDaemon = true;
296 - } else if (Tool.isOption(a, "-baseDir")) {
297 - String baseDir = args[++i];
298 - SysProperties.setBaseDir(baseDir);
299 - } else if (Tool.isOption(a, "-ifExists")) {
300 - ifExists = true;
301 - } else if (Tool.isOption(a, "-properties")) {
302 - // already set
303 - i++;
304 - } else if (Tool.isOption(a, "-trace")) {
305 - trace = true;
306 - }
307 - }
308 -// if (driverList != null) {
309 -// try {
310 -// String[] drivers =
311 -// StringUtils.arraySplit(driverList, ',', false);
312 -// URL[] urls = new URL[drivers.length];
313 -// for(int i=0; i<drivers.length; i++) {
314 -// urls[i] = new URL(drivers[i]);
315 -// }
316 -// urlClassLoader = URLClassLoader.newInstance(urls);
317 -// } catch (MalformedURLException e) {
318 -// TraceSystem.traceThrowable(e);
319 -// }
320 -// }
321 - for (String[] lang : LANGUAGES) {
322 - languages.add(lang[0]);
323 - }
324 - updateURL();
325 - }
326 -
327 - @Override
328 - public String getURL() {
329 - updateURL();
330 - return url;
331 - }
332 -
333 - private void updateURL() {
334 - try {
335 - url = (ssl ? "https" : "http") + "://" +
336 - NetUtils.getLocalAddress() + ":" + port;
337 - } catch (NoClassDefFoundError e) {
338 - // Google App Engine does not allow java.net.InetAddress
339 - }
340 - }
341 -
342 - @Override
343 - public void start() {
344 - serverSocket = NetUtils.createServerSocket(port, ssl);
345 - port = serverSocket.getLocalPort();
346 - updateURL();
347 - }
348 -
349 - @Override
350 - public void listen() {
351 - this.listenerThread = Thread.currentThread();
352 - try {
353 - while (serverSocket != null) {
354 - Socket s = serverSocket.accept();
355 - WebThread c = new WebThread(s, this);
356 - running.add(c);
357 - c.start();
358 - }
359 - } catch (Exception e) {
360 - trace(e.toString());
361 - }
362 - }
363 -
364 - @Override
365 - public boolean isRunning(boolean traceError) {
366 - if (serverSocket == null) {
367 - return false;
368 - }
369 - try {
370 - Socket s = NetUtils.createLoopbackSocket(port, ssl);
371 - s.close();
372 - return true;
373 - } catch (Exception e) {
374 - if (traceError) {
375 - traceError(e);
376 - }
377 - return false;
378 - }
379 - }
380 -
381 - public boolean isStopped() {
382 - return serverSocket == null;
383 - }
384 -
385 - @Override
386 - public void stop() {
387 - if (serverSocket != null) {
388 - try {
389 - serverSocket.close();
390 - } catch (IOException e) {
391 - traceError(e);
392 - }
393 - serverSocket = null;
394 - }
395 - if (listenerThread != null) {
396 - try {
397 - listenerThread.join(1000);
398 - } catch (InterruptedException e) {
399 - DbException.traceThrowable(e);
400 - }
401 - }
402 - // TODO server: using a boolean 'now' argument? a timeout?
403 - for (WebSession session : New.arrayList(sessions.values())) {
404 - session.close();
405 - }
406 - for (WebThread c : New.arrayList(running)) {
407 - try {
408 - c.stopNow();
409 - c.join(100);
410 - } catch (Exception e) {
411 - traceError(e);
412 - }
413 - }
414 - }
415 -
416 - /**
417 - * Write trace information if trace is enabled.
418 - *
419 - * @param s the message to write
420 - */
421 - void trace(String s) {
422 - if (trace) {
423 - System.out.println(s);
424 - }
425 - }
426 -
427 - /**
428 - * Write the stack trace if trace is enabled.
429 - *
430 - * @param e the exception
431 - */
432 - void traceError(Throwable e) {
433 - if (trace) {
434 - e.printStackTrace();
435 - }
436 - }
437 -
438 - /**
439 - * Check if this language is supported / translated.
440 - *
441 - * @param language the language
442 - * @return true if a translation is available
443 - */
444 - boolean supportsLanguage(String language) {
445 - return languages.contains(language);
446 - }
447 -
448 - /**
449 - * Read the translation for this language and save them in the 'text'
450 - * property of this session.
451 - *
452 - * @param session the session
453 - * @param language the language
454 - */
455 - void readTranslations(WebSession session, String language) {
456 - Properties text = new Properties();
457 - try {
458 - trace("translation: "+language);
459 - byte[] trans = getFile("_text_"+language+".prop");
460 - trace(" "+new String(trans));
461 - text = SortedProperties.fromLines(new String(trans, Constants.UTF8));
462 - // remove starting # (if not translated yet)
463 - for (Entry<Object, Object> entry : text.entrySet()) {
464 - String value = (String) entry.getValue();
465 - if (value.startsWith("#")) {
466 - entry.setValue(value.substring(1));
467 - }
468 - }
469 - } catch (IOException e) {
470 - DbException.traceThrowable(e);
471 - }
472 - session.put("text", new HashMap<Object, Object>(text));
473 - }
474 -
475 - ArrayList<HashMap<String, Object>> getSessions() {
476 - ArrayList<HashMap<String, Object>> list = New.arrayList();
477 - for (WebSession s : sessions.values()) {
478 - list.add(s.getInfo());
479 - }
480 - return list;
481 - }
482 -
483 - @Override
484 - public String getType() {
485 - return "Web Console";
486 - }
487 -
488 - @Override
489 - public String getName() {
490 - return "H2 Console Server";
491 - }
492 -
493 - void setAllowOthers(boolean b) {
494 - allowOthers = b;
495 - }
496 -
497 - @Override
498 - public boolean getAllowOthers() {
499 - return allowOthers;
500 - }
501 -
502 - void setSSL(boolean b) {
503 - ssl = b;
504 - }
505 -
506 - void setPort(int port) {
507 - this.port = port;
508 - }
509 -
510 - boolean getSSL() {
511 - return ssl;
512 - }
513 -
514 - @Override
515 - public int getPort() {
516 - return port;
517 - }
518 -
519 - public boolean isCommandHistoryAllowed() {
520 - return commandHistoryString != null;
521 - }
522 -
523 - public void setCommandHistoryAllowed(boolean allowed) {
524 - if (allowed) {
525 - if (commandHistoryString == null) {
526 - commandHistoryString = "";
527 - }
528 - } else {
529 - commandHistoryString = null;
530 - }
531 - }
532 -
533 - public ArrayList<String> getCommandHistoryList() {
534 - ArrayList<String> result = New.arrayList();
535 - if (commandHistoryString == null) {
536 - return result;
537 - }
538 -
539 - // Split the commandHistoryString on non-escaped semicolons
540 - // and unescape it.
541 - StringBuilder sb = new StringBuilder();
542 - for (int end = 0;; end++) {
543 - if (end == commandHistoryString.length() ||
544 - commandHistoryString.charAt(end) == ';') {
545 - if (sb.length() > 0) {
546 - result.add(sb.toString());
547 - sb.delete(0, sb.length());
548 - }
549 - if (end == commandHistoryString.length()) {
550 - break;
551 - }
552 - } else if (commandHistoryString.charAt(end) == '\\' &&
553 - end < commandHistoryString.length() - 1) {
554 - sb.append(commandHistoryString.charAt(++end));
555 - } else {
556 - sb.append(commandHistoryString.charAt(end));
557 - }
558 - }
559 - return result;
560 - }
561 -
562 - /**
563 - * Save the command history to the properties file.
564 - *
565 - * @param commandHistory the history
566 - */
567 - public void saveCommandHistoryList(ArrayList<String> commandHistory) {
568 - StringBuilder sb = new StringBuilder();
569 - for (String s : commandHistory) {
570 - if (sb.length() > 0) {
571 - sb.append(';');
572 - }
573 - sb.append(s.replace("\\", "\\\\").replace(";", "\\;"));
574 - }
575 - commandHistoryString = sb.toString();
576 - saveProperties(null);
577 - }
578 -
579 - /**
580 - * Get the connection information for this setting.
581 - *
582 - * @param name the setting name
583 - * @return the connection information
584 - */
585 - ConnectionInfo getSetting(String name) {
586 - return connInfoMap.get(name);
587 - }
588 -
589 - /**
590 - * Update a connection information setting.
591 - *
592 - * @param info the connection information
593 - */
594 - void updateSetting(ConnectionInfo info) {
595 - connInfoMap.put(info.name, info);
596 - info.lastAccess = ticker++;
597 - }
598 -
599 - /**
600 - * Remove a connection information setting from the list
601 - *
602 - * @param name the setting to remove
603 - */
604 - void removeSetting(String name) {
605 - connInfoMap.remove(name);
606 - }
607 -
608 - private Properties loadProperties() {
609 - try {
610 - if ("null".equals(serverPropertiesDir)) {
611 - return new Properties();
612 - }
613 - return SortedProperties.loadProperties(
614 - serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME);
615 - } catch (Exception e) {
616 - DbException.traceThrowable(e);
617 - return new Properties();
618 - }
619 - }
620 -
621 - /**
622 - * Get the list of connection information setting names.
623 - *
624 - * @return the connection info names
625 - */
626 - String[] getSettingNames() {
627 - ArrayList<ConnectionInfo> list = getSettings();
628 - String[] names = new String[list.size()];
629 - for (int i = 0; i < list.size(); i++) {
630 - names[i] = list.get(i).name;
631 - }
632 - return names;
633 - }
634 -
635 - /**
636 - * Get the list of connection info objects.
637 - *
638 - * @return the list
639 - */
640 - synchronized ArrayList<ConnectionInfo> getSettings() {
641 - ArrayList<ConnectionInfo> settings = New.arrayList();
642 - if (connInfoMap.size() == 0) {
643 - Properties prop = loadProperties();
644 - if (prop.size() == 0) {
645 - for (String gen : GENERIC) {
646 - ConnectionInfo info = new ConnectionInfo(gen);
647 - settings.add(info);
648 - updateSetting(info);
649 - }
650 - } else {
651 - for (int i = 0;; i++) {
652 - String data = prop.getProperty(String.valueOf(i));
653 - if (data == null) {
654 - break;
655 - }
656 - ConnectionInfo info = new ConnectionInfo(data);
657 - settings.add(info);
658 - updateSetting(info);
659 - }
660 - }
661 - } else {
662 - settings.addAll(connInfoMap.values());
663 - }
664 - Collections.sort(settings);
665 - return settings;
666 - }
667 -
668 - /**
669 - * Save the settings to the properties file.
670 - *
671 - * @param prop null or the properties webPort, webAllowOthers, and webSSL
672 - */
673 - synchronized void saveProperties(Properties prop) {
674 - try {
675 - if (prop == null) {
676 - Properties old = loadProperties();
677 - prop = new SortedProperties();
678 - prop.setProperty("webPort",
679 - "" + SortedProperties.getIntProperty(old,
680 - "webPort", port));
681 - prop.setProperty("webAllowOthers",
682 - "" + SortedProperties.getBooleanProperty(old,
683 - "webAllowOthers", allowOthers));
684 - prop.setProperty("webSSL",
685 - "" + SortedProperties.getBooleanProperty(old,
686 - "webSSL", ssl));
687 - if (commandHistoryString != null) {
688 - prop.setProperty(COMMAND_HISTORY, commandHistoryString);
689 - }
690 - }
691 - ArrayList<ConnectionInfo> settings = getSettings();
692 - int len = settings.size();
693 - for (int i = 0; i < len; i++) {
694 - ConnectionInfo info = settings.get(i);
695 - if (info != null) {
696 - prop.setProperty(String.valueOf(len - i - 1), info.getString());
697 - }
698 - }
699 - if (!"null".equals(serverPropertiesDir)) {
700 - OutputStream out = FileUtils.newOutputStream(
701 - serverPropertiesDir + "/" + Constants.SERVER_PROPERTIES_NAME, false);
702 - prop.store(out, "H2 Server Properties");
703 - out.close();
704 - }
705 - } catch (Exception e) {
706 - DbException.traceThrowable(e);
707 - }
708 - }
709 -
710 - /**
711 - * Open a database connection.
712 - *
713 - * @param driver the driver class name
714 - * @param databaseUrl the database URL
715 - * @param user the user name
716 - * @param password the password
717 - * @return the database connection
718 - */
719 - Connection getConnection(String driver, String databaseUrl, String user,
720 - String password) throws SQLException {
721 - driver = driver.trim();
722 - databaseUrl = databaseUrl.trim();
723 - org.h2.Driver.load();
724 - Properties p = new Properties();
725 - p.setProperty("user", user.trim());
726 - // do not trim the password, otherwise an
727 - // encrypted H2 database with empty user password doesn't work
728 - p.setProperty("password", password);
729 - if (databaseUrl.startsWith("jdbc:h2:")) {
730 - if (ifExists) {
731 - databaseUrl += ";IFEXISTS=TRUE";
732 - }
733 - // PostgreSQL would throw a NullPointerException
734 - // if it is loaded before the H2 driver
735 - // because it can't deal with non-String objects in the connection
736 - // Properties
737 - return org.h2.Driver.load().connect(databaseUrl, p);
738 - }
739 -// try {
740 -// Driver dr = (Driver) urlClassLoader.
741 -// loadClass(driver).newInstance();
742 -// return dr.connect(url, p);
743 -// } catch(ClassNotFoundException e2) {
744 -// throw e2;
745 -// }
746 - return JdbcUtils.getConnection(driver, databaseUrl, p);
747 - }
748 -
749 - /**
750 - * Shut down the web server.
751 - */
752 - void shutdown() {
753 - if (shutdownHandler != null) {
754 - shutdownHandler.shutdown();
755 - }
756 - }
757 -
758 - public void setShutdownHandler(ShutdownHandler shutdownHandler) {
759 - this.shutdownHandler = shutdownHandler;
760 - }
761 -
762 - /**
763 - * Create a session with a given connection.
764 - *
765 - * @param conn the connection
766 - * @return the URL of the web site to access this connection
767 - */
768 - public String addSession(Connection conn) throws SQLException {
769 - WebSession session = createNewSession("local");
770 - session.setShutdownServerOnDisconnect();
771 - session.setConnection(conn);
772 - session.put("url", conn.getMetaData().getURL());
773 - String s = (String) session.get("sessionId");
774 - return url + "/frame.jsp?jsessionid=" + s;
775 - }
776 -
777 - /**
778 - * The translate thread reads and writes the file translation.properties
779 - * once a second.
780 - */
781 - private class TranslateThread extends Thread {
782 -
783 - private final File file = new File("translation.properties");
784 - private final Map<Object, Object> translation;
785 - private volatile boolean stopNow;
786 -
787 - TranslateThread(Map<Object, Object> translation) {
788 - this.translation = translation;
789 - }
790 -
791 - public String getFileName() {
792 - return file.getAbsolutePath();
793 - }
794 -
795 - public void stopNow() {
796 - this.stopNow = true;
797 - try {
798 - join();
799 - } catch (InterruptedException e) {
800 - // ignore
801 - }
802 - }
803 -
804 - @Override
805 - public void run() {
806 - while (!stopNow) {
807 - try {
808 - SortedProperties sp = new SortedProperties();
809 - if (file.exists()) {
810 - InputStream in = FileUtils.newInputStream(file.getName());
811 - sp.load(in);
812 - translation.putAll(sp);
813 - } else {
814 - OutputStream out = FileUtils.newOutputStream(file.getName(), false);
815 - sp.putAll(translation);
816 - sp.store(out, "Translation");
817 - }
818 - Thread.sleep(1000);
819 - } catch (Exception e) {
820 - traceError(e);
821 - }
822 - }
823 - }
824 -
825 - }
826 -
827 - /**
828 - * Start the translation thread that reads the file once a second.
829 - *
830 - * @param translation the translation map
831 - * @return the name of the file to translate
832 - */
833 - String startTranslate(Map<Object, Object> translation) {
834 - if (translateThread != null) {
835 - translateThread.stopNow();
836 - }
837 - translateThread = new TranslateThread(translation);
838 - translateThread.setDaemon(true);
839 - translateThread.start();
840 - return translateThread.getFileName();
841 - }
842 -
843 - @Override
844 - public boolean isDaemon() {
845 - return isDaemon;
846 - }
847 -
848 - void setAllowChunked(boolean allowChunked) {
849 - this.allowChunked = allowChunked;
850 - }
851 -
852 - boolean getAllowChunked() {
853 - return allowChunked;
854 - }
855 -
856 -}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.WebSession
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -///package org.h2.server.web;
9 -
10 - import java.sql.Connection;
11 - import java.sql.DatabaseMetaData;
12 - import java.sql.ResultSet;
13 - import java.sql.SQLException;
14 - import java.sql.Statement;
15 - import java.sql.Timestamp;
16 - import java.util.ArrayList;
17 - import java.util.HashMap;
18 - import java.util.Locale;
19 -
20 - import org.h2.bnf.Bnf;
21 - import org.h2.bnf.context.DbContents;
22 - import org.h2.bnf.context.DbContextRule;
23 - import org.h2.message.DbException;
24 - import org.h2.util.New;
25 -
26 -/**
27 - * The web session keeps all data of a user session.
28 - * This class is used by the H2 Console.
29 - */
30 -class WebSession {
31 -
32 - private static final int MAX_HISTORY = 1000;
33 -
34 - /**
35 - * The last time this client sent a request.
36 - */
37 - long lastAccess;
38 -
39 - /**
40 - * The session attribute map.
41 - */
42 - final HashMap<String, Object> map = New.hashMap();
43 -
44 - /**
45 - * The current locale.
46 - */
47 - Locale locale;
48 -
49 - /**
50 - * The currently executing statement.
51 - */
52 - Statement executingStatement;
53 -
54 - /**
55 - * The current updatable result set.
56 - */
57 - ResultSet result;
58 -
59 - private final WebServer server;
60 -
61 - private final ArrayList<String> commandHistory;
62 -
63 - private Connection conn;
64 - private DatabaseMetaData meta;
65 - private DbContents contents = new DbContents();
66 - private Bnf bnf;
67 - private boolean shutdownServerOnDisconnect;
68 -
69 - WebSession(WebServer server) {
70 - this.server = server;
71 - // This must be stored in the session rather than in the server.
72 - // Otherwise, one client could allow
73 - // saving history for others (insecure).
74 - this.commandHistory = server.getCommandHistoryList();
75 - }
76 -
77 - /**
78 - * Put an attribute value in the map.
79 - *
80 - * @param key the key
81 - * @param value the new value
82 - */
83 - void put(String key, Object value) {
84 - map.put(key, value);
85 - }
86 -
87 - /**
88 - * Get the value for the given key.
89 - *
90 - * @param key the key
91 - * @return the value
92 - */
93 - Object get(String key) {
94 - if ("sessions".equals(key)) {
95 - return server.getSessions();
96 - }
97 - return map.get(key);
98 - }
99 -
100 - /**
101 - * Remove a session attribute from the map.
102 - *
103 - * @param key the key
104 - */
105 - void remove(String key) {
106 - map.remove(key);
107 - }
108 -
109 - /**
110 - * Get the BNF object.
111 - *
112 - * @return the BNF object
113 - */
114 - Bnf getBnf() {
115 - return bnf;
116 - }
117 -
118 - /**
119 - * Load the SQL grammar BNF.
120 - */
121 - void loadBnf() {
122 - try {
123 - Bnf newBnf = Bnf.getInstance(null);
124 - DbContextRule columnRule =
125 - new DbContextRule(contents, DbContextRule.COLUMN);
126 - DbContextRule newAliasRule =
127 - new DbContextRule(contents, DbContextRule.NEW_TABLE_ALIAS);
128 - DbContextRule aliasRule =
129 - new DbContextRule(contents, DbContextRule.TABLE_ALIAS);
130 - DbContextRule tableRule =
131 - new DbContextRule(contents, DbContextRule.TABLE);
132 - DbContextRule schemaRule =
133 - new DbContextRule(contents, DbContextRule.SCHEMA);
134 - DbContextRule columnAliasRule =
135 - new DbContextRule(contents, DbContextRule.COLUMN_ALIAS);
136 - DbContextRule procedure =
137 - new DbContextRule(contents, DbContextRule.PROCEDURE);
138 - newBnf.updateTopic("procedure", procedure);
139 - newBnf.updateTopic("column_name", columnRule);
140 - newBnf.updateTopic("new_table_alias", newAliasRule);
141 - newBnf.updateTopic("table_alias", aliasRule);
142 - newBnf.updateTopic("column_alias", columnAliasRule);
143 - newBnf.updateTopic("table_name", tableRule);
144 - newBnf.updateTopic("schema_name", schemaRule);
145 - newBnf.linkStatements();
146 - bnf = newBnf;
147 - } catch (Exception e) {
148 - // ok we don't have the bnf
149 - server.traceError(e);
150 - }
151 - }
152 -
153 - /**
154 - * Get the SQL statement from history.
155 - *
156 - * @param id the history id
157 - * @return the SQL statement
158 - */
159 - String getCommand(int id) {
160 - return commandHistory.get(id);
161 - }
162 -
163 - /**
164 - * Add a SQL statement to the history.
165 - *
166 - * @param sql the SQL statement
167 - */
168 - void addCommand(String sql) {
169 - if (sql == null) {
170 - return;
171 - }
172 - sql = sql.trim();
173 - if (sql.length() == 0) {
174 - return;
175 - }
176 - if (commandHistory.size() > MAX_HISTORY) {
177 - commandHistory.remove(0);
178 - }
179 - int idx = commandHistory.indexOf(sql);
180 - if (idx >= 0) {
181 - commandHistory.remove(idx);
182 - }
183 - commandHistory.add(sql);
184 - if (server.isCommandHistoryAllowed()) {
185 - server.saveCommandHistoryList(commandHistory);
186 - }
187 - }
188 -
189 - /**
190 - * Get the list of SQL statements in the history.
191 - *
192 - * @return the commands
193 - */
194 - ArrayList<String> getCommandHistory() {
195 - return commandHistory;
196 - }
197 -
198 - /**
199 - * Update session meta data information and get the information in a map.
200 - *
201 - * @return a map containing the session meta data
202 - */
203 - HashMap<String, Object> getInfo() {
204 - HashMap<String, Object> m = New.hashMap();
205 - m.putAll(map);
206 - m.put("lastAccess", new Timestamp(lastAccess).toString());
207 - try {
208 - m.put("url", conn == null ?
209 - "${text.admin.notConnected}" : conn.getMetaData().getURL());
210 - m.put("user", conn == null ?
211 - "-" : conn.getMetaData().getUserName());
212 - m.put("lastQuery", commandHistory.size() == 0 ?
213 - "" : commandHistory.get(0));
214 - m.put("executing", executingStatement == null ?
215 - "${text.admin.no}" : "${text.admin.yes}");
216 - } catch (SQLException e) {
217 - DbException.traceThrowable(e);
218 - }
219 - return m;
220 - }
221 -
222 - void setConnection(Connection conn) throws SQLException {
223 - this.conn = conn;
224 - if (conn == null) {
225 - meta = null;
226 - } else {
227 - meta = conn.getMetaData();
228 - }
229 - contents = new DbContents();
230 - }
231 -
232 - DatabaseMetaData getMetaData() {
233 - return meta;
234 - }
235 -
236 - Connection getConnection() {
237 - return conn;
238 - }
239 -
240 - DbContents getContents() {
241 - return contents;
242 - }
243 -
244 - /**
245 - * Shutdown the server when disconnecting.
246 - */
247 - void setShutdownServerOnDisconnect() {
248 - this.shutdownServerOnDisconnect = true;
249 - }
250 -
251 - boolean getShutdownServerOnDisconnect() {
252 - return shutdownServerOnDisconnect;
253 - }
254 -
255 - /**
256 - * Close the connection and stop the statement if one is currently
257 - * executing.
258 - */
259 - void close() {
260 - if (executingStatement != null) {
261 - try {
262 - executingStatement.cancel();
263 - } catch (Exception e) {
264 - // ignore
265 - }
266 - }
267 - if (conn != null) {
268 - try {
269 - conn.close();
270 - } catch (Exception e) {
271 - // ignore
272 - }
273 - }
274 -
275 - }
276 -
277 -}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.legrog.util;
2 -// Code copied from org.h2.server.web.WebThread
3 -/*
4 - * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
5 - * and the EPL 1.0 (http://h2database.com/html/license.html).
6 - * Initial Developer: H2 Group
7 - */
8 -//package org.h2.server.web;
9 -
10 - import java.io.BufferedInputStream;
11 - import java.io.BufferedOutputStream;
12 - import java.io.IOException;
13 - import java.io.InputStream;
14 - import java.io.OutputStream;
15 - import java.net.Socket;
16 - import java.net.UnknownHostException;
17 - import java.util.Iterator;
18 - import java.util.Locale;
19 - import java.util.Properties;
20 - import java.util.StringTokenizer;
21 - import org.h2.engine.Constants;
22 - import org.h2.engine.SysProperties;
23 - import org.h2.message.DbException;
24 - import org.h2.mvstore.DataUtils;
25 - import org.h2.util.IOUtils;
26 - import org.h2.util.NetUtils;
27 - import org.h2.util.StringUtils;
28 -//import org.h2.server.web.*;
29 -
30 -/**
31 - * For each connection to a session, an object of this class is created.
32 - * This class is used by the H2 Console.
33 - */
34 -class WebThread extends WebApp implements Runnable {
35 -
36 - protected OutputStream output;
37 - protected final Socket socket;
38 - private final Thread thread;
39 - private InputStream input;
40 - private String ifModifiedSince;
41 -
42 - WebThread(Socket socket, WebServer server) {
43 - super(server);
44 - this.socket = socket;
45 - thread = new Thread(this, "H2 Console thread");
46 - }
47 -
48 - /**
49 - * Start the thread.
50 - */
51 - void start() {
52 - thread.start();
53 - }
54 -
55 - /**
56 - * Wait until the thread is stopped.
57 - *
58 - * @param millis the maximum number of milliseconds to wait
59 - */
60 - void join(int millis) throws InterruptedException {
61 - thread.join(millis);
62 - }
63 -
64 - /**
65 - * Close the connection now.
66 - */
67 - void stopNow() {
68 - this.stop = true;
69 - try {
70 - socket.close();
71 - } catch (IOException e) {
72 - // ignore
73 - }
74 - }
75 -
76 - private String getAllowedFile(String requestedFile) {
77 - if (!allow()) {
78 - return "notAllowed.jsp";
79 - }
80 - if (requestedFile.length() == 0) {
81 - return "index.do";
82 - }
83 - return requestedFile;
84 - }
85 -
86 - @Override
87 - public void run() {
88 - try {
89 - input = new BufferedInputStream(socket.getInputStream());
90 - output = new BufferedOutputStream(socket.getOutputStream());
91 - while (!stop) {
92 - if (!process()) {
93 - break;
94 - }
95 - }
96 - } catch (Exception e) {
97 - DbException.traceThrowable(e);
98 - }
99 - IOUtils.closeSilently(output);
100 - IOUtils.closeSilently(input);
101 - try {
102 - socket.close();
103 - } catch (IOException e) {
104 - // ignore
105 - } finally {
106 - server.remove(this);
107 - }
108 - }
109 -
110 - @SuppressWarnings("unchecked")
111 - private boolean process() throws IOException {
112 - boolean keepAlive = false;
113 - String head = readHeaderLine();
114 - if (head.startsWith("GET ") || head.startsWith("POST ")) {
115 - int begin = head.indexOf('/'), end = head.lastIndexOf(' ');
116 - String file;
117 - if (begin < 0 || end < begin) {
118 - file = "";
119 - } else {
120 - file = head.substring(begin + 1, end).trim();
121 - }
122 - trace(head + ": " + file);
123 - file = getAllowedFile(file);
124 - attributes = new Properties();
125 - int paramIndex = file.indexOf("?");
126 - session = null;
127 - if (paramIndex >= 0) {
128 - String attrib = file.substring(paramIndex + 1);
129 - parseAttributes(attrib);
130 - String sessionId = attributes.getProperty("jsessionid");
131 - file = file.substring(0, paramIndex);
132 - session = server.getSession(sessionId);
133 - }
134 - keepAlive = parseHeader();
135 - String hostAddr = socket.getInetAddress().getHostAddress();
136 - file = processRequest(file, hostAddr);
137 - if (file.length() == 0) {
138 - // asynchronous request
139 - return true;
140 - }
141 - String message;
142 - byte[] bytes;
143 - if (cache && ifModifiedSince != null &&
144 - ifModifiedSince.equals(server.getStartDateTime())) {
145 - bytes = null;
146 - message = "HTTP/1.1 304 Not Modified\r\n";
147 - } else {
148 - bytes = server.getFile(file);
149 - if (bytes == null) {
150 - message = "HTTP/1.1 404 Not Found\r\n";
151 - bytes = ("File not found: " + file).getBytes(Constants.UTF8);
152 - message += "Content-Length: " + bytes.length + "\r\n";
153 - } else {
154 - if (session != null && file.endsWith(".jsp")) {
155 - String page = new String(bytes, Constants.UTF8);
156 - if (SysProperties.CONSOLE_STREAM) {
157 - Iterator<String> it = (Iterator<String>) session.map.remove("chunks");
158 - if (it != null) {
159 - message = "HTTP/1.1 200 OK\r\n";
160 - message += "Content-Type: " + mimeType + "\r\n";
161 - message += "Cache-Control: no-cache\r\n";
162 - message += "Transfer-Encoding: chunked\r\n";
163 - message += "\r\n";
164 - trace(message);
165 - output.write(message.getBytes());
166 - while (it.hasNext()) {
167 - String s = it.next();
168 - s = PageParser.parse(s, session.map);
169 - bytes = s.getBytes(Constants.UTF8);
170 - if (bytes.length == 0) {
171 - continue;
172 - }
173 - output.write(Integer.toHexString(bytes.length).getBytes());
174 - output.write("\r\n".getBytes());
175 - output.write(bytes);
176 - output.write("\r\n".getBytes());
177 - output.flush();
178 - }
179 - output.write("0\r\n\r\n".getBytes());
180 - output.flush();
181 - return keepAlive;
182 - }
183 - }
184 - page = PageParser.parse(page, session.map);
185 - bytes = page.getBytes(Constants.UTF8);
186 - }
187 - message = "HTTP/1.1 200 OK\r\n";
188 - message += "Content-Type: " + mimeType + "\r\n";
189 - if (!cache) {
190 - message += "Cache-Control: no-cache\r\n";
191 - } else {
192 - message += "Cache-Control: max-age=10\r\n";
193 - message += "Last-Modified: " + server.getStartDateTime() + "\r\n";
194 - }
195 - message += "Content-Length: " + bytes.length + "\r\n";
196 - }
197 - }
198 - message += "\r\n";
199 - trace(message);
200 - output.write(message.getBytes());
201 - if (bytes != null) {
202 - output.write(bytes);
203 - }
204 - output.flush();
205 - }
206 - return keepAlive;
207 - }
208 -
209 - private String readHeaderLine() throws IOException {
210 - StringBuilder buff = new StringBuilder();
211 - while (true) {
212 - int c = input.read();
213 - if (c == -1) {
214 - throw new IOException("Unexpected EOF");
215 - } else if (c == '\r') {
216 - if (input.read() == '\n') {
217 - return buff.length() > 0 ? buff.toString() : null;
218 - }
219 - } else if (c == '\n') {
220 - return buff.length() > 0 ? buff.toString() : null;
221 - } else {
222 - buff.append((char) c);
223 - }
224 - }
225 - }
226 -
227 - private void parseAttributes(String s) {
228 - trace("data=" + s);
229 - while (s != null) {
230 - int idx = s.indexOf('=');
231 - if (idx >= 0) {
232 - String property = s.substring(0, idx);
233 - s = s.substring(idx + 1);
234 - idx = s.indexOf('&');
235 - String value;
236 - if (idx >= 0) {
237 - value = s.substring(0, idx);
238 - s = s.substring(idx + 1);
239 - } else {
240 - value = s;
241 - }
242 - String attr = StringUtils.urlDecode(value);
243 - attributes.put(property, attr);
244 - } else {
245 - break;
246 - }
247 - }
248 - trace(attributes.toString());
249 - }
250 -
251 - private boolean parseHeader() throws IOException {
252 - boolean keepAlive = false;
253 - trace("parseHeader");
254 - int len = 0;
255 - ifModifiedSince = null;
256 - boolean multipart = false;
257 - while (true) {
258 - String line = readHeaderLine();
259 - if (line == null) {
260 - break;
261 - }
262 - trace(" " + line);
263 - String lower = StringUtils.toLowerEnglish(line);
264 - if (lower.startsWith("if-modified-since")) {
265 - ifModifiedSince = getHeaderLineValue(line);
266 - } else if (lower.startsWith("connection")) {
267 - String conn = getHeaderLineValue(line);
268 - if ("keep-alive".equals(conn)) {
269 - keepAlive = true;
270 - }
271 - } else if (lower.startsWith("content-type")) {
272 - String type = getHeaderLineValue(line);
273 - if (type.startsWith("multipart/form-data")) {
274 - multipart = true;
275 - }
276 - } else if (lower.startsWith("content-length")) {
277 - len = Integer.parseInt(getHeaderLineValue(line));
278 - trace("len=" + len);
279 - } else if (lower.startsWith("user-agent")) {
280 - boolean isWebKit = lower.contains("webkit/");
281 - if (isWebKit && session != null) {
282 - // workaround for what seems to be a WebKit bug:
283 - // http://code.google.com/p/chromium/issues/detail?id=6402
284 - session.put("frame-border", "1");
285 - session.put("frameset-border", "2");
286 - }
287 - } else if (lower.startsWith("accept-language")) {
288 - Locale locale = session == null ? null : session.locale;
289 - if (locale == null) {
290 - String languages = getHeaderLineValue(line);
291 - StringTokenizer tokenizer = new StringTokenizer(languages, ",;");
292 - while (tokenizer.hasMoreTokens()) {
293 - String token = tokenizer.nextToken();
294 - if (!token.startsWith("q=")) {
295 - if (server.supportsLanguage(token)) {
296 - int dash = token.indexOf('-');
297 - if (dash >= 0) {
298 - String language = token.substring(0, dash);
299 - String country = token.substring(dash + 1);
300 - locale = new Locale(language, country);
301 - } else {
302 - locale = new Locale(token, "");
303 - }
304 - headerLanguage = locale.getLanguage();
305 - if (session != null) {
306 - session.locale = locale;
307 - session.put("language", headerLanguage);
308 - server.readTranslations(session, headerLanguage);
309 - }
310 - break;
311 - }
312 - }
313 - }
314 - }
315 - } else if (line.trim().length() == 0) {
316 - break;
317 - }
318 - }
319 - if (multipart) {
320 - // not supported
321 - } else if (session != null && len > 0) {
322 - byte[] bytes = DataUtils.newBytes(len);
323 - for (int pos = 0; pos < len;) {
324 - pos += input.read(bytes, pos, len - pos);
325 - }
326 - String s = new String(bytes);
327 - parseAttributes(s);
328 - }
329 - return keepAlive;
330 - }
331 -
332 - private static String getHeaderLineValue(String line) {
333 - return line.substring(line.indexOf(':') + 1).trim();
334 - }
335 -
336 - @Override
337 - protected String adminShutdown() {
338 - stopNow();
339 - return super.adminShutdown();
340 - }
341 -
342 - private boolean allow() {
343 - if (server.getAllowOthers()) {
344 - return true;
345 - }
346 - try {
347 - return NetUtils.isLocalAddress(socket);
348 - } catch (UnknownHostException e) {
349 - server.traceError(e);
350 - return false;
351 - }
352 - }
353 -
354 - private void trace(String s) {
355 - server.trace(s);
356 - }
357 -}
...\ No newline at end of file ...\ No newline at end of file