EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.tools]

COVERAGE SUMMARY FOR SOURCE FILE [Server.java]

nameclass, %method, %block, %line, %
Server.java100% (1/1)96%  (22/23)66%  (827/1257)72%  (220.6/307)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Server100% (1/1)96%  (22/23)66%  (827/1257)72%  (220.6/307)
main (String []): void 0%   (0/1)0%   (0/6)0%   (0/2)
openBrowser (String): void 100% (1/1)11%  (35/308)20%  (9/46)
run (): void 100% (1/1)62%  (5/8)60%  (3/5)
start (): Server 100% (1/1)69%  (53/77)79%  (11.9/15)
Server (Service, String []): void 100% (1/1)76%  (13/17)75%  (6/8)
verifyArgs (String []): void 100% (1/1)78%  (179/230)77%  (44.5/58)
runTool (String []): void 100% (1/1)81%  (288/355)76%  (78.2/103)
wait (int): void 100% (1/1)91%  (10/11)80%  (4/5)
startWebServer (Connection): void 100% (1/1)98%  (46/47)92%  (12/13)
Server (): void 100% (1/1)100% (6/6)100% (3/3)
createPgServer (String []): Server 100% (1/1)100% (8/8)100% (1/1)
createTcpServer (String []): Server 100% (1/1)100% (15/15)100% (4/4)
createWebServer (String []): Server 100% (1/1)100% (15/15)100% (4/4)
getPort (): int 100% (1/1)100% (4/4)100% (1/1)
getService (): Service 100% (1/1)100% (3/3)100% (1/1)
getStatus (): String 100% (1/1)100% (65/65)100% (11/11)
getURL (): String 100% (1/1)100% (4/4)100% (1/1)
isRunning (boolean): boolean 100% (1/1)100% (5/5)100% (1/1)
setShutdownHandler (ShutdownHandler): void 100% (1/1)100% (4/4)100% (2/2)
shutdown (): void 100% (1/1)100% (10/10)100% (4/4)
shutdownTcpServer (String, String, boolean, boolean): void 100% (1/1)100% (6/6)100% (2/2)
stop (): void 100% (1/1)100% (10/10)100% (4/4)
stopAll (): void 100% (1/1)100% (43/43)100% (13/13)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.tools;
7 
8import java.net.URI;
9import java.sql.Connection;
10import java.sql.SQLException;
11 
12import org.h2.api.ErrorCode;
13import org.h2.engine.SysProperties;
14import org.h2.message.DbException;
15import org.h2.server.Service;
16import org.h2.server.ShutdownHandler;
17import org.h2.server.TcpServer;
18import org.h2.server.pg.PgServer;
19import org.h2.server.web.WebServer;
20import org.h2.util.StringUtils;
21import org.h2.util.Tool;
22import org.h2.util.Utils;
23 
24/**
25 * Starts the H2 Console (web-) server, TCP, and PG server.
26 * @h2.resource
27 */
28public class Server extends Tool implements Runnable, ShutdownHandler {
29 
30    private final Service service;
31    private Server web, tcp, pg;
32    private ShutdownHandler shutdownHandler;
33    private boolean started;
34 
35    public Server() {
36        // nothing to do
37        this.service = null;
38    }
39 
40    /**
41     * Create a new server for the given service.
42     *
43     * @param service the service
44     * @param args the command line arguments
45     */
46    public Server(Service service, String... args) throws SQLException {
47        verifyArgs(args);
48        this.service = service;
49        try {
50            service.init(args);
51        } catch (Exception e) {
52            throw DbException.toSQLException(e);
53        }
54    }
55 
56    /**
57     * When running without options, -tcp, -web, -browser and -pg are started.
58     * <br />
59     * Options are case sensitive. Supported options are:
60     * <table>
61     * <tr><td>[-help] or [-?]</td>
62     * <td>Print the list of options</td></tr>
63     * <tr><td>[-web]</td>
64     * <td>Start the web server with the H2 Console</td></tr>
65     * <tr><td>[-webAllowOthers]</td>
66     * <td>Allow other computers to connect - see below</td></tr>
67     * <tr><td>[-webDaemon]</td>
68     * <td>Use a daemon thread</td></tr>
69     * <tr><td>[-webPort &lt;port&gt;]</td>
70     * <td>The port (default: 8082)</td></tr>
71     * <tr><td>[-webSSL]</td>
72     * <td>Use encrypted (HTTPS) connections</td></tr>
73     * <tr><td>[-browser]</td>
74     * <td>Start a browser connecting to the web server</td></tr>
75     * <tr><td>[-tcp]</td>
76     * <td>Start the TCP server</td></tr>
77     * <tr><td>[-tcpAllowOthers]</td>
78     * <td>Allow other computers to connect - see below</td></tr>
79     * <tr><td>[-tcpDaemon]</td>
80     * <td>Use a daemon thread</td></tr>
81     * <tr><td>[-tcpPort &lt;port&gt;]</td>
82     * <td>The port (default: 9092)</td></tr>
83     * <tr><td>[-tcpSSL]</td>
84     * <td>Use encrypted (SSL) connections</td></tr>
85     * <tr><td>[-tcpPassword &lt;pwd&gt;]</td>
86     * <td>The password for shutting down a TCP server</td></tr>
87     * <tr><td>[-tcpShutdown "&lt;url&gt;"]</td>
88     * <td>Stop the TCP server; example: tcp://localhost</td></tr>
89     * <tr><td>[-tcpShutdownForce]</td>
90     * <td>Do not wait until all connections are closed</td></tr>
91     * <tr><td>[-pg]</td>
92     * <td>Start the PG server</td></tr>
93     * <tr><td>[-pgAllowOthers]</td>
94     * <td>Allow other computers to connect - see below</td></tr>
95     * <tr><td>[-pgDaemon]</td>
96     * <td>Use a daemon thread</td></tr>
97     * <tr><td>[-pgPort &lt;port&gt;]</td>
98     * <td>The port (default: 5435)</td></tr>
99     * <tr><td>[-properties "&lt;dir&gt;"]</td>
100     * <td>Server properties (default: ~, disable: null)</td></tr>
101     * <tr><td>[-baseDir &lt;dir&gt;]</td>
102     * <td>The base directory for H2 databases (all servers)</td></tr>
103     * <tr><td>[-ifExists]</td>
104     * <td>Only existing databases may be opened (all servers)</td></tr>
105     * <tr><td>[-trace]</td>
106     * <td>Print additional trace information (all servers)</td></tr>
107     * <tr><td>[-key &lt;from&gt; &lt;to&gt;]</td>
108     * <td>Allows to map a database name to another (all servers)</td></tr>
109     * </table>
110     * The options -xAllowOthers are potentially risky.
111     * <br />
112     * For details, see Advanced Topics / Protection against Remote Access.
113     * @h2.resource
114     *
115     * @param args the command line arguments
116     */
117    public static void main(String... args) throws SQLException {
118        new Server().runTool(args);
119    }
120 
121    private void verifyArgs(String... args) throws SQLException {
122        for (int i = 0; args != null && i < args.length; i++) {
123            String arg = args[i];
124            if (arg == null) {
125                continue;
126            } else if ("-?".equals(arg) || "-help".equals(arg)) {
127                // ok
128            } else if (arg.startsWith("-web")) {
129                if ("-web".equals(arg)) {
130                    // ok
131                } else if ("-webAllowOthers".equals(arg)) {
132                    // no parameters
133                } else if ("-webDaemon".equals(arg)) {
134                    // no parameters
135                } else if ("-webSSL".equals(arg)) {
136                    // no parameters
137                } else if ("-webPort".equals(arg)) {
138                    i++;
139                } else {
140                    throwUnsupportedOption(arg);
141                }
142            } else if ("-browser".equals(arg)) {
143                // ok
144            } else if (arg.startsWith("-tcp")) {
145                if ("-tcp".equals(arg)) {
146                    // ok
147                } else if ("-tcpAllowOthers".equals(arg)) {
148                    // no parameters
149                } else if ("-tcpDaemon".equals(arg)) {
150                    // no parameters
151                } else if ("-tcpSSL".equals(arg)) {
152                    // no parameters
153                } else if ("-tcpPort".equals(arg)) {
154                    i++;
155                } else if ("-tcpPassword".equals(arg)) {
156                    i++;
157                } else if ("-tcpShutdown".equals(arg)) {
158                    i++;
159                } else if ("-tcpShutdownForce".equals(arg)) {
160                    // ok
161                } else {
162                    throwUnsupportedOption(arg);
163                }
164            } else if (arg.startsWith("-pg")) {
165                if ("-pg".equals(arg)) {
166                    // ok
167                } else if ("-pgAllowOthers".equals(arg)) {
168                    // no parameters
169                } else if ("-pgDaemon".equals(arg)) {
170                    // no parameters
171                } else if ("-pgPort".equals(arg)) {
172                    i++;
173                } else {
174                    throwUnsupportedOption(arg);
175                }
176            } else if (arg.startsWith("-ftp")) {
177                if ("-ftpPort".equals(arg)) {
178                    i++;
179                } else if ("-ftpDir".equals(arg)) {
180                    i++;
181                } else if ("-ftpRead".equals(arg)) {
182                    i++;
183                } else if ("-ftpWrite".equals(arg)) {
184                    i++;
185                } else if ("-ftpWritePassword".equals(arg)) {
186                    i++;
187                } else if ("-ftpTask".equals(arg)) {
188                    // no parameters
189                } else {
190                    throwUnsupportedOption(arg);
191                }
192            } else if ("-properties".equals(arg)) {
193                i++;
194            } else if ("-trace".equals(arg)) {
195                // no parameters
196            } else if ("-ifExists".equals(arg)) {
197                // no parameters
198            } else if ("-baseDir".equals(arg)) {
199                i++;
200            } else if ("-key".equals(arg)) {
201                i += 2;
202            } else if ("-tool".equals(arg)) {
203                // no parameters
204            } else {
205                throwUnsupportedOption(arg);
206            }
207        }
208    }
209 
210    @Override
211    public void runTool(String... args) throws SQLException {
212        boolean tcpStart = false, pgStart = false, webStart = false;
213        boolean browserStart = false;
214        boolean tcpShutdown = false, tcpShutdownForce = false;
215        String tcpPassword = "";
216        String tcpShutdownServer = "";
217        boolean startDefaultServers = true;
218        for (int i = 0; args != null && i < args.length; i++) {
219            String arg = args[i];
220            if (arg == null) {
221                continue;
222            } else if ("-?".equals(arg) || "-help".equals(arg)) {
223                showUsage();
224                return;
225            } else if (arg.startsWith("-web")) {
226                if ("-web".equals(arg)) {
227                    startDefaultServers = false;
228                    webStart = true;
229                } else if ("-webAllowOthers".equals(arg)) {
230                    // no parameters
231                } else if ("-webDaemon".equals(arg)) {
232                    // no parameters
233                } else if ("-webSSL".equals(arg)) {
234                    // no parameters
235                } else if ("-webPort".equals(arg)) {
236                    i++;
237                } else {
238                    showUsageAndThrowUnsupportedOption(arg);
239                }
240            } else if ("-browser".equals(arg)) {
241                startDefaultServers = false;
242                browserStart = true;
243            } else if (arg.startsWith("-tcp")) {
244                if ("-tcp".equals(arg)) {
245                    startDefaultServers = false;
246                    tcpStart = true;
247                } else if ("-tcpAllowOthers".equals(arg)) {
248                    // no parameters
249                } else if ("-tcpDaemon".equals(arg)) {
250                    // no parameters
251                } else if ("-tcpSSL".equals(arg)) {
252                    // no parameters
253                } else if ("-tcpPort".equals(arg)) {
254                    i++;
255                } else if ("-tcpPassword".equals(arg)) {
256                    tcpPassword = args[++i];
257                } else if ("-tcpShutdown".equals(arg)) {
258                    startDefaultServers = false;
259                    tcpShutdown = true;
260                    tcpShutdownServer = args[++i];
261                } else if ("-tcpShutdownForce".equals(arg)) {
262                    tcpShutdownForce = true;
263                } else {
264                    showUsageAndThrowUnsupportedOption(arg);
265                }
266            } else if (arg.startsWith("-pg")) {
267                if ("-pg".equals(arg)) {
268                    startDefaultServers = false;
269                    pgStart = true;
270                } else if ("-pgAllowOthers".equals(arg)) {
271                    // no parameters
272                } else if ("-pgDaemon".equals(arg)) {
273                    // no parameters
274                } else if ("-pgPort".equals(arg)) {
275                    i++;
276                } else {
277                    showUsageAndThrowUnsupportedOption(arg);
278                }
279            } else if ("-properties".equals(arg)) {
280                i++;
281            } else if ("-trace".equals(arg)) {
282                // no parameters
283            } else if ("-ifExists".equals(arg)) {
284                // no parameters
285            } else if ("-baseDir".equals(arg)) {
286                i++;
287            } else if ("-key".equals(arg)) {
288                i += 2;
289            } else {
290                showUsageAndThrowUnsupportedOption(arg);
291            }
292        }
293        verifyArgs(args);
294        if (startDefaultServers) {
295            tcpStart = true;
296            pgStart = true;
297            webStart = true;
298            browserStart = true;
299        }
300        // TODO server: maybe use one single properties file?
301        if (tcpShutdown) {
302            out.println("Shutting down TCP Server at " + tcpShutdownServer);
303            shutdownTcpServer(tcpShutdownServer, tcpPassword,
304                    tcpShutdownForce, false);
305        }
306        try {
307            if (tcpStart) {
308                tcp = createTcpServer(args);
309                tcp.start();
310                out.println(tcp.getStatus());
311                tcp.setShutdownHandler(this);
312            }
313            if (pgStart) {
314                pg = createPgServer(args);
315                pg.start();
316                out.println(pg.getStatus());
317            }
318            if (webStart) {
319                web = createWebServer(args);
320                web.setShutdownHandler(this);
321                SQLException result = null;
322                try {
323                    web.start();
324                } catch (Exception e) {
325                    result = DbException.toSQLException(e);
326                }
327                out.println(web.getStatus());
328                // start browser in any case (even if the server is already
329                // running) because some people don't look at the output, but
330                // are wondering why nothing happens
331                if (browserStart) {
332                    try {
333                        openBrowser(web.getURL());
334                    } catch (Exception e) {
335                        out.println(e.getMessage());
336                    }
337                }
338                if (result != null) {
339                    throw result;
340                }
341            } else if (browserStart) {
342                out.println("The browser can only start if a web server is started (-web)");
343            }
344        } catch (SQLException e) {
345            stopAll();
346            throw e;
347        }
348    }
349 
350    /**
351     * Shutdown one or all TCP server. If force is set to false, the server will
352     * not allow new connections, but not kill existing connections, instead it
353     * will stop if the last connection is closed. If force is set to true,
354     * existing connections are killed. After calling the method with
355     * force=false, it is not possible to call it again with force=true because
356     * new connections are not allowed. Example:
357     *
358     * <pre>
359     * Server.shutdownTcpServer(&quot;tcp://localhost:9094&quot;,
360     *         password, true, false);
361     * </pre>
362     *
363     * @param url example: tcp://localhost:9094
364     * @param password the password to use ("" for no password)
365     * @param force the shutdown (don't wait)
366     * @param all whether all TCP servers that are running in the JVM should be
367     *            stopped
368     */
369    public static void shutdownTcpServer(String url, String password,
370            boolean force, boolean all) throws SQLException {
371        TcpServer.shutdown(url, password, force, all);
372    }
373 
374    /**
375     * Get the status of this server.
376     *
377     * @return the status
378     */
379    public String getStatus() {
380        StringBuilder buff = new StringBuilder();
381        if (!started) {
382            buff.append("Not started");
383        } else if (isRunning(false)) {
384            buff.append(service.getType()).
385                append(" server running at ").
386                append(service.getURL()).
387                append(" (");
388            if (service.getAllowOthers()) {
389                buff.append("others can connect");
390            } else {
391                buff.append("only local connections");
392            }
393            buff.append(')');
394        } else {
395            buff.append("The ").
396                append(service.getType()).
397                append(" server could not be started. " +
398                        "Possible cause: another server is already running at ").
399                append(service.getURL());
400        }
401        return buff.toString();
402    }
403 
404    /**
405     * Create a new web server, but does not start it yet. Example:
406     *
407     * <pre>
408     * Server server = Server.createWebServer("-trace").start();
409     * </pre>
410     * Supported options are:
411     * -webPort, -webSSL, -webAllowOthers, -webDaemon,
412     * -trace, -ifExists, -baseDir, -properties.
413     * See the main method for details.
414     *
415     * @param args the argument list
416     * @return the server
417     */
418    public static Server createWebServer(String... args) throws SQLException {
419        WebServer service = new WebServer();
420        Server server = new Server(service, args);
421        service.setShutdownHandler(server);
422        return server;
423    }
424 
425    /**
426     * Create a new TCP server, but does not start it yet. Example:
427     *
428     * <pre>
429     * Server server = Server.createTcpServer(
430     *     "-tcpPort", "9123", "-tcpAllowOthers").start();
431     * </pre>
432     * Supported options are:
433     * -tcpPort, -tcpSSL, -tcpPassword, -tcpAllowOthers, -tcpDaemon,
434     * -trace, -ifExists, -baseDir, -key.
435     * See the main method for details.
436     *
437     * @param args the argument list
438     * @return the server
439     */
440    public static Server createTcpServer(String... args) throws SQLException {
441        TcpServer service = new TcpServer();
442        Server server = new Server(service, args);
443        service.setShutdownHandler(server);
444        return server;
445    }
446 
447    /**
448     * Create a new PG server, but does not start it yet.
449     * Example:
450     * <pre>
451     * Server server =
452     *     Server.createPgServer("-pgAllowOthers").start();
453     * </pre>
454     * Supported options are:
455     * -pgPort, -pgAllowOthers, -pgDaemon,
456     * -trace, -ifExists, -baseDir, -key.
457     * See the main method for details.
458     *
459     * @param args the argument list
460     * @return the server
461     */
462    public static Server createPgServer(String... args) throws SQLException {
463        return new Server(new PgServer(), args);
464    }
465 
466    /**
467     * Tries to start the server.
468     * @return the server if successful
469     * @throws SQLException if the server could not be started
470     */
471    public Server start() throws SQLException {
472        try {
473            started = true;
474            service.start();
475            String name = service.getName() + " (" + service.getURL() + ")";
476            Thread t = new Thread(this, name);
477            t.setDaemon(service.isDaemon());
478            t.start();
479            for (int i = 1; i < 64; i += i) {
480                wait(i);
481                if (isRunning(false)) {
482                    return this;
483                }
484            }
485            if (isRunning(true)) {
486                return this;
487            }
488            throw DbException.get(ErrorCode.EXCEPTION_OPENING_PORT_2,
489                    name, "timeout; " +
490                    "please check your network configuration, specially the file /etc/hosts");
491        } catch (DbException e) {
492            throw DbException.toSQLException(e);
493        }
494    }
495 
496    private static void wait(int i) {
497        try {
498            // sleep at most 4096 ms
499            long sleep = (long) i * (long) i;
500            Thread.sleep(sleep);
501        } catch (InterruptedException e) {
502            // ignore
503        }
504    }
505 
506    private void stopAll() {
507        Server s = web;
508        if (s != null && s.isRunning(false)) {
509            s.stop();
510            web = null;
511        }
512        s = tcp;
513        if (s != null && s.isRunning(false)) {
514            s.stop();
515            tcp = null;
516        }
517        s = pg;
518        if (s != null && s.isRunning(false)) {
519            s.stop();
520            pg = null;
521        }
522    }
523 
524    /**
525     * Checks if the server is running.
526     *
527     * @param traceError if errors should be written
528     * @return if the server is running
529     */
530    public boolean isRunning(boolean traceError) {
531        return service.isRunning(traceError);
532    }
533 
534    /**
535     * Stops the server.
536     */
537    public void stop() {
538        started = false;
539        if (service != null) {
540            service.stop();
541        }
542    }
543 
544    /**
545     * Gets the URL of this server.
546     *
547     * @return the url
548     */
549    public String getURL() {
550        return service.getURL();
551    }
552 
553    /**
554     * Gets the port this server is listening on.
555     *
556     * @return the port
557     */
558    public int getPort() {
559        return service.getPort();
560    }
561 
562    /**
563     * INTERNAL
564     */
565    @Override
566    public void run() {
567        try {
568            service.listen();
569        } catch (Exception e) {
570            DbException.traceThrowable(e);
571        }
572    }
573 
574    /**
575     * INTERNAL
576     */
577    public void setShutdownHandler(ShutdownHandler shutdownHandler) {
578        this.shutdownHandler = shutdownHandler;
579    }
580 
581    /**
582     * INTERNAL
583     */
584    @Override
585    public void shutdown() {
586        if (shutdownHandler != null) {
587            shutdownHandler.shutdown();
588        } else {
589            stopAll();
590        }
591    }
592 
593    /**
594     * Get the service attached to this server.
595     *
596     * @return the service
597     */
598    public Service getService() {
599        return service;
600    }
601 
602    /**
603     * Open a new browser tab or window with the given URL.
604     *
605     * @param url the URL to open
606     */
607    public static void openBrowser(String url) throws Exception {
608        try {
609            String osName = StringUtils.toLowerEnglish(
610                    Utils.getProperty("os.name", "linux"));
611            Runtime rt = Runtime.getRuntime();
612            String browser = Utils.getProperty(SysProperties.H2_BROWSER, null);
613            if (browser == null) {
614                // under Linux, this will point to the default system browser
615                try {
616                    browser = System.getenv("BROWSER");
617                } catch (SecurityException se) {
618                    // ignore
619                }
620            }
621            if (browser != null) {
622                if (browser.startsWith("call:")) {
623                    browser = browser.substring("call:".length());
624                    Utils.callStaticMethod(browser, url);
625                } else if (browser.contains("%url")) {
626                    String[] args = StringUtils.arraySplit(browser, ',', false);
627                    for (int i = 0; i < args.length; i++) {
628                        args[i] = StringUtils.replaceAll(args[i], "%url", url);
629                    }
630                    rt.exec(args);
631                } else if (osName.contains("windows")) {
632                    rt.exec(new String[] { "cmd.exe", "/C",  browser, url });
633                } else {
634                    rt.exec(new String[] { browser, url });
635                }
636                return;
637            }
638            try {
639                Class<?> desktopClass = Class.forName("java.awt.Desktop");
640                // Desktop.isDesktopSupported()
641                Boolean supported = (Boolean) desktopClass.
642                    getMethod("isDesktopSupported").
643                    invoke(null, new Object[0]);
644                URI uri = new URI(url);
645                if (supported) {
646                    // Desktop.getDesktop();
647                    Object desktop = desktopClass.getMethod("getDesktop").
648                        invoke(null, new Object[0]);
649                    // desktop.browse(uri);
650                    desktopClass.getMethod("browse", URI.class).
651                        invoke(desktop, uri);
652                    return;
653                }
654            } catch (Exception e) {
655                // ignore
656            }
657            if (osName.contains("windows")) {
658                rt.exec(new String[] { "rundll32", "url.dll,FileProtocolHandler", url });
659            } else if (osName.contains("mac") || osName.contains("darwin")) {
660                // Mac OS: to open a page with Safari, use "open -a Safari"
661                Runtime.getRuntime().exec(new String[] { "open", url });
662            } else {
663                String[] browsers = { "chromium", "google-chrome", "firefox",
664                        "mozilla-firefox", "mozilla", "konqueror", "netscape",
665                        "opera", "midori" };
666                boolean ok = false;
667                for (String b : browsers) {
668                    try {
669                        rt.exec(new String[] { b, url });
670                        ok = true;
671                        break;
672                    } catch (Exception e) {
673                        // ignore and try the next
674                    }
675                }
676                if (!ok) {
677                    // No success in detection.
678                    throw new Exception(
679                            "Browser detection failed and system property " +
680                            SysProperties.H2_BROWSER + " not set");
681                }
682            }
683        } catch (Exception e) {
684            throw new Exception(
685                    "Failed to start a browser to open the URL " +
686            url + ": " + e.getMessage());
687        }
688    }
689 
690    /**
691     * Start a web server and a browser that uses the given connection. The
692     * current transaction is preserved. This is specially useful to manually
693     * inspect the database when debugging. This method return as soon as the
694     * user has disconnected.
695     *
696     * @param conn the database connection (the database must be open)
697     */
698    public static void startWebServer(Connection conn) throws SQLException {
699        WebServer webServer = new WebServer();
700        Server web = new Server(webServer, new String[] { "-webPort", "0" });
701        web.start();
702        Server server = new Server();
703        server.web = web;
704        webServer.setShutdownHandler(server);
705        String url = webServer.addSession(conn);
706        try {
707            Server.openBrowser(url);
708            while (!webServer.isStopped()) {
709                Thread.sleep(1000);
710            }
711        } catch (Exception e) {
712            // ignore
713        }
714    }
715 
716}

[all classes][org.h2.tools]
EMMA 2.0.5312 (C) Vladimir Roubtsov