`
yuanyu5237
  • 浏览: 162853 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

h2 database源码分析·(一)

 
阅读更多

先来无事,发现之前下载的h2 database源码还在source insight里放着,就打开看看。

h2 database是一个开源的,用java写的,支持jdbc连接的内存数据库,提供浏览器模式的控制台。

其源码结构(我用的版本是1.3.154)如下(进入到src目录下,src/org/h2/)

Api   

Bnf

Command

Compress

Constant

Constraint

Engine

Expression

Fulltext

Index

Jdbc

Jdbcx

Jmx

Message

Res

Result

Schema

Security

Server

Store

Table

Tools 工具类,其中有数据库的入口Server.main()

Upgrade

Util

Value

driver.java

从main函数开始说起

 

new Server().runTool(args);

 

 调用runTool()方法,在该方法中,会首先设置一些默认启动参数,然后根据传入的args修改这些默认参数,最后按顺序启动webserver,browser,tcpserver和pgserver,典型代码:

 

if (startDefaultServers) {
            tcpStart = true;
            pgStart = true;
            webStart = true;
            browserStart = true;
}
/*-----------------------------------*/
try {
            if (webStart) {
                web = createWebServer(args);
                web.setShutdownHandler(this);
                SQLException result = null;
                try {
                    web.start();
                } catch (Exception e) {
                    result = DbException.toSQLException(e);
                }
                out.println(web.getStatus());
// start browser in any case (even if the server is already running)
// because some people don't look at the output,
// but are wondering why nothing happens
                if (browserStart) {
                    try {
                        openBrowser(web.getURL());
                    } catch (Exception e) {
                        out.println(e.getMessage());
                    }
                }
                if (result != null) {
                    throw result;
                }
            }
            if (tcpStart) {
                tcp = createTcpServer(args);
                tcp.start();
                out.println(tcp.getStatus());
                tcp.setShutdownHandler(this);
            }
            if (pgStart) {
                pg = createPgServer(args);
                pg.start();
                out.println(pg.getStatus());
            }
} catch (SQLException e) {
            stopAll();
            throw e;
}
 

下面分别来看看这3个server和1个browser:

1WebServer

 

public static Server createWebServer(String... args){
        WebServer service = new WebServer();
        Server server = new Server(service, args);
        service.setShutdownHandler(server);
        return server;
}

 2TcpServer

public static Server createTcpServer(String... args) {
        TcpServer service = new TcpServer();
        Server server = new Server(service, args);
        service.setShutdownHandler(server);
        return server;
}

 3PgServer

public static Server createPgServer(String... args){
        return new Server(new PgServer(), args);
}

 3个server都只是创建,要启动server,都需要调用start()方法,在start方法中,调用各自的service类,start各自的server,然后创建单独的线程执行运行该server,若为守护进程,还需要将其设置为守护进程:

public Server start() throws SQLException {
        try {
            started = true;
            service.start();
            Thread t = new Thread(this);
            t.setDaemon(service.isDaemon());
            String name = service.getName() + " (" + service.getURL() + ")";
            t.setName(name);
            t.start();
            for (int i = 1; i < 64; i += i) {
                wait(i);
                if (isRunning(false)) {
                    return this;
                }
            }
            if (isRunning(true)) {
                return this;
            }
            throw DbException.get(ErrorCode.EXCEPTION_OPENING_PORT_2, name, "timeout");
        } catch (DbException e) {
            throw DbException.toSQLException(e);
        }
}

 最后,是openBrowser(),根据指定的URL打开一个浏览器窗口或者标签页。

public static void openBrowser(String url) throws Exception {
        try {
            String osName = SysProperties.getStringSetting("os.name", "linux").toLowerCase();
            Runtime rt = Runtime.getRuntime();
            String browser = System.getProperty(SysProperties.H2_BROWSER);
            if (browser != null) {
                if (browser.startsWith("call:")) {
                    browser = browser.substring("call:".length());
                    Utils.callStaticMethod(browser, url);
                } else if (browser.indexOf("%url") >= 0) {
                    String[] args = StringUtils.arraySplit(browser, ',', false);
                    for (int i = 0; i < args.length; i++) {
                        args[i] = StringUtils.replaceAll(args[i], "%url", url);
                    }
                    rt.exec(args);
                } else if (osName.indexOf("windows") >= 0) {
                    rt.exec(new String[] { "cmd.exe", "/C",  browser, url });
                } else {
                    rt.exec(new String[] { browser, url });
                }
                return;
            }
            try {
                Class<?> desktopClass = Class.forName("java.awt.Desktop");
                // Desktop.isDesktopSupported()
                Boolean supported = (Boolean) desktopClass.
                    getMethod("isDesktopSupported").
                    invoke(null, new Object[0]);
                URI uri = new URI(url);
                if (supported) {
                    // Desktop.getDesktop();
                    Object desktop = desktopClass.getMethod("getDesktop").
                        invoke(null, new Object[0]);
                    // desktop.browse(uri);
                    desktopClass.getMethod("browse", URI.class).
                        invoke(desktop, uri);
                    return;
                }
            } catch (Exception e) {
                // ignore
            }
            if (osName.indexOf("windows") >= 0) {
                rt.exec(new String[] { "rundll32", "url.dll,FileProtocolHandler", url });
            } else if (osName.indexOf("mac") >= 0 || osName.indexOf("darwin") >= 0) {
                // Mac OS: to open a page with Safari, use "open -a Safari"
                Runtime.getRuntime().exec(new String[] { "open", url });
            } else {
                String[] browsers = { "firefox", "mozilla-firefox", "mozilla", "konqueror", "netscape", "opera" };
                boolean ok = false;
                for (String b : browsers) {
                    try {
                        rt.exec(new String[] { b, url });
                        ok = true;
                        break;
                    } catch (Exception e) {
                        // ignore and try the next
                    }
                }
                if (!ok) {
                    // No success in detection.
                    throw new Exception("Browser detection failed and system property " + SysProperties.H2_BROWSER + " not set");
                }
            }
        } catch (Exception e) {
            throw new Exception("Failed to start a browser to open the URL " + url + ": " + e.getMessage());
        }
}

 这段代码其实挺有意思的,就是打开了一个浏览器,参考了这段代码的实现,并阅读了util下的New, Util, StringUtil三个类得部分代码和constant下的SysProperties类,拼凑了下面的一段程序,可直接运行,就能打开浏览器。

 

package org.h2.test;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.util.ArrayList;

public class OpenBrowserTest {

	public static void main(String[] args) throws Exception {
		openBrowser("http://www.baidu.com");
	}

	public static void openBrowser(String url) throws Exception {
        try {
        	String s = System.getProperty("os.name");
            String osName = (s == null ? "linux" : s).toLowerCase();
            Runtime rt = Runtime.getRuntime();
            String browser = System.getProperty("h2.browser");
            if (browser != null) {
                if (browser.startsWith("call:")) {
                    browser = browser.substring("call:".length());
                    callStaticMethod(browser, url);
                } else if (browser.indexOf("%url") >= 0) {
                    String[] args = arraySplit(browser, ',', false);
                    for (int i = 0; i < args.length; i++) {
                        args[i] = replaceAll(args[i], "%url", url);
                    }
                    rt.exec(args);
                } else if (osName.indexOf("windows") >= 0) {
                    rt.exec(new String[] { "cmd.exe", "/C",  browser, url });
                } else {
                    rt.exec(new String[] { browser, url });
                }
                return;
            }
            try {
                Class<?> desktopClass = Class.forName("java.awt.Desktop");
                // Desktop.isDesktopSupported()
                Boolean supported = (Boolean) desktopClass.
                    getMethod("isDesktopSupported").
                    invoke(null, new Object[0]);
                URI uri = new URI(url);
                if (supported) {
                    // Desktop.getDesktop();
                    Object desktop = desktopClass.getMethod("getDesktop").
                        invoke(null, new Object[0]);
                    // desktop.browse(uri);
                    desktopClass.getMethod("browse", URI.class).
                        invoke(desktop, uri);
                    return;
                }
            } catch (Exception e) {
                // ignore
            }
            if (osName.indexOf("windows") >= 0) {
                rt.exec(new String[] { "rundll32", "url.dll,FileProtocolHandler", url });
            } else if (osName.indexOf("mac") >= 0 || osName.indexOf("darwin") >= 0) {
                // Mac OS: to open a page with Safari, use "open -a Safari"
                Runtime.getRuntime().exec(new String[] { "open", url });
            } else {
                String[] browsers = { "firefox", "mozilla-firefox", "mozilla", "konqueror", "netscape", "opera" };
                boolean ok = false;
                for (String b : browsers) {
                    try {
                        rt.exec(new String[] { b, url });
                        ok = true;
                        break;
                    } catch (Exception e) {
                        // ignore and try the next
                    }
                }
                if (!ok) {
                    // No success in detection.
                    throw new Exception("Browser detection failed and system property " + "h2.browser" + " not set");
                }
            }
        } catch (Exception e) {
            throw new Exception("Failed to start a browser to open the URL " + url + ": " + e.getMessage());
        }
    }
	
	public static Object callStaticMethod(String classAndMethod, Object... params) throws Exception {
        int lastDot = classAndMethod.lastIndexOf('.');
        String className = classAndMethod.substring(0, lastDot);
        String methodName = classAndMethod.substring(lastDot + 1);
        return classMethodInternal(methodName, Class.forName(className), null, params);
    }
	
	private static Object classMethodInternal(String methodName, Class<?> clazz, Object instance, Object... params) throws Exception {
        Method best = null;
        int bestMatch = 0;
        boolean isStatic = instance == null;
        for (Method m : clazz.getMethods()) {
            if (Modifier.isStatic(m.getModifiers()) == isStatic && m.getName().equals(methodName)) {
                int p = match(m.getParameterTypes(), params);
                if (p > bestMatch) {
                    bestMatch = p;
                    best = m;
                }
            }
        }
        if (best == null) {
            throw new NoSuchMethodException(methodName);
        }
        return best.invoke(instance, params);
    }
	
	private static int match(Class<?>[] params, Object[] values) {
        int len = params.length;
        if (len == values.length) {
            int points = 1;
            for (int i = 0; i < len; i++) {
                Class<?> pc = getNonPrimitiveClass(params[i]);
                Class<?> vc = values[i].getClass();
                if (pc == vc) {
                    points++;
                } else if (!pc.isAssignableFrom(vc)) {
                    return 0;
                }
            }
            return points;
        }
        return 0;
    }
	
	public static Class<?> getNonPrimitiveClass(Class<?> clazz) {
        if (!clazz.isPrimitive()) {
            return clazz;
        } else if (clazz == boolean.class) {
            return Boolean.class;
        } else if (clazz == byte.class) {
            return Byte.class;
        } else if (clazz == char.class) {
            return Character.class;
        } else if (clazz == double.class) {
            return Double.class;
        } else if (clazz == float.class) {
            return Float.class;
        } else if (clazz == int.class) {
            return Integer.class;
        } else if (clazz == long.class) {
            return Long.class;
        } else if (clazz == short.class) {
            return Short.class;
        } else if (clazz == void.class) {
            return Void.class;
        }
        return clazz;
    }
	
	public static String[] arraySplit(String s, char separatorChar, boolean trim) {
        if (s == null) {
            return null;
        }
        int length = s.length();
        if (length == 0) {
            return new String[0];
        }
        ArrayList<String> list = new ArrayList<String>();
        StringBuilder buff = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            char c = s.charAt(i);
            if (c == separatorChar) {
                String e = buff.toString();
                list.add(trim ? e.trim() : e);
                buff.setLength(0);
            } else if (c == '\\' && i < length - 1) {
                buff.append(s.charAt(++i));
            } else {
                buff.append(c);
            }
        }
        String e = buff.toString();
        list.add(trim ? e.trim() : e);
        String[] array = new String[list.size()];
        list.toArray(array);
        return array;
    }
	
	public static String replaceAll(String s, String before, String after) {
        int next = s.indexOf(before);
        if (next < 0) {
            return s;
        }
        StringBuilder buff = new StringBuilder(s.length() - before.length() + after.length());
        int index = 0;
        while (true) {
            buff.append(s.substring(index, next)).append(after);
            index = next + before.length();
            next = s.indexOf(before, index);
            if (next < 0) {
                buff.append(s.substring(index));
                break;
            }
        }
        return buff.toString();
    }
}
 

 

分享到:
评论

相关推荐

    h2database嵌入式数据库引擎 v2.2.224.zip

    java -cp h2database-version-2.2.224.jar org.h2.tools.RunScript -url jdbc:h2:~/test -user sa -password -script create.sql ``` 5. **数据操作** H2支持标准的SQL语句进行数据的增删改查,例如插入数据: ...

    guinsoo:Guinsoo-基于h2数据库的数据库

    健索 欢迎使用Guinsoo,这是一个基于H2的数据库,它是Java SQL数据库。 H2的主要特点是: 非常快速的开源JDBC API 嵌入式和服务器模式;... &lt; groupId&gt;com.h2database&lt;/ groupId&gt; &lt; artifactId&gt;h2&lt;/ artifactId

    基于jetty嵌入式容器的java性能分析工具,内嵌H2 database,以图表形式直观展现应用当前性能数据详细文档+全部资料+高分项目+源码.zip

    基于jetty嵌入式容器的java性能分析工具,内嵌H2 database,以图表形式直观展现应用当前性能数据详细文档+全部资料+高分项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95...

    H2数据库中文资料

    `H2Database聚合函数.doc`介绍了如COUNT、SUM、AVG、MAX和MIN等常用的聚合函数,它们用于对一组数据进行统计计算。掌握这些函数可以让你在数据分析和报表生成中更加得心应手。 总之,这份H2数据库中文资料集合涵盖...

    h2.rar_MyEclipse Java_h2_h2 jsp_java h2

    这个压缩包中的源码是一个很好的学习资源,你可以通过阅读和分析代码来提升你的Java数据库编程和MyEclipse使用技能。同时,对于H2数据库的使用也会有更深入的理解,特别是对于那些需要快速搭建测试数据库或者开发轻...

    H2 数据库使用

    源码分析** 由于H2是开源的,开发者可以深入研究其源码,了解其内部工作机制,甚至根据需求进行定制。 总的来说,H2数据库因其轻量级、高效、易用的特性,在许多开发场景中成为首选。无论是用于快速原型开发,...

    用Swing做的H2管理器

    通过查看和分析这些源代码,开发者可以深入理解如何将Swing和H2数据库API整合在一起,实现一个功能完备的数据库管理工具。 总结来说,这个主题涵盖了以下知识点: 1. **H2数据库**:了解其特性和用法,包括创建...

    JAVA 构建动态表格,数据统计处理利用内存数据库H2研究

    在Java项目中,可以通过JDBC(Java Database Connectivity)API连接到H2数据库。首先,需要在项目中添加H2的依赖,然后创建数据库连接,执行SQL语句进行数据操作。例如: ```java Class.forName("org.h2.Driver"); ...

    课程设计---Java swingKTV点歌系统源码(含数据库+截图).rar

    5. 源码分析:对源代码的学习和研究,有助于理解Java程序的架构和实现细节。 这个项目对于学习Java GUI编程和数据库集成的人来说是一个很好的实践案例,可以帮助他们巩固理论知识,并提升实际开发能力。

    基于b树的小型数据库源码

    在IT领域,数据库是至关...通过分析源码,你可以了解B树的插入、删除、查找和更新算法,以及如何将这些算法应用于数据库索引中。对于软件开发人员,尤其是对数据库系统感兴趣的开发者,这是一个很好的实践和学习资源。

    图书管理系统完整版,javaswing源码

    《图书管理系统完整版,javaswing源码》是一款基于Java Swing技术开发的桌面应用程序,它提供了全面的图书管理功能,...通过分析和理解源码,不仅可以提升Java Swing的运用能力,还能增强数据库管理和软件设计的技巧。

    基于java的图书管理系统源码_successfullqi_JAVA图书管理_java源码网站_基于java的图书管理系统源码_

    本系统可能使用了如MySQL、Oracle或H2等关系型数据库,通过JDBC(Java Database Connectivity)接口与数据库进行交互。数据库建模文件(如ER图)用于描述实体间的关系,确保数据结构的合理性。 3. 业务逻辑:这部分...

    saiku源代码修改与运行.docx

    - 注释掉`h2database`配置。 - 添加`mysqlDatabase`配置。 - 更新`licenseBean`中的`databaseManager`属性为`mysqlDatabase`。 3. **修改saiku-beans.properties**: - 更新`userdao.driverclass`, `userdao.url...

    NetBeans平台开发的开源股票软件

    5. `org-h2database`:H2数据库引擎的目录,表明AIOTrade可能使用H2作为其后端数据库,H2是一款轻量级、高性能的关系型数据库,适用于内存或磁盘存储,适用于小型应用或测试环境。 6. `aiotrade-platform-core`与`...

    迅友通讯录

    源码分析可以帮助我们理解如何设计数据库结构(如表的创建、字段定义等)、如何执行CRUD(创建、读取、更新、删除)操作,以及如何优化查询性能。此外,源码可能还涉及了事务处理、错误处理和数据安全方面的编程实践...

    【Java项目源码】校园超市购物系统.zip

    【Java项目源码】校园超市购物系统是一个典型的Java Web应用程序,旨在模拟并实现校园内的超市购物体验。...通过分析和实践这个源码,学生可以深入理解Web开发的各个环节,并为未来的职业发展打下坚实基础。

    ASP源码—蓝木大学ASP新闻网 奥运纪念版.zip

    【ASP技术概述】 ASP(Active Server Pages)是微软公司推出的一种服务器端脚本环境,用于创建动态交互...通过学习和分析这个源码,开发者可以深入理解ASP和VBScript在实际项目中的应用,同时掌握动态网站的构建方法。

    JAVA guestbook

    虽然题目中没有明确指出使用了哪种数据库,但在一个典型的Guestbook应用中,数据通常会存储在一个数据库中,如MySQL、SQLite或H2。这些数据可能包含用户的姓名、留言内容和时间戳等。Java通过JDBC(Java Database ...

    geo-api:GeoAPI是一个项目,旨在在创建需要与西班牙地理相关的数据(例如街道名称,邮政编码,城镇和漫长的历史等)的不同组件时,方便程序员的工作。

    8. **H2 Database**:这是一个轻量级的内存数据库,常用于开发和测试环境,因为它启动快速且易于集成。 9. **SonarCloud**:这是一个代码质量管理平台,用于代码审查、静态分析和漏洞检测,确保代码质量和安全性。 ...

    javalist源码-IMDb-film-list-UI:带有UI的Java列表管理程序。用户能够在源代码中创建的默认数据库上存储,删除,添加

    《Java List 源码分析:构建IMDb电影列表UI》 在IT行业中,Java是一种广泛应用的编程语言,尤其在构建用户界面(UI)和数据管理方面。本项目"javalist源码-IMDb-film-list-UI"提供了一个基于Java实现的电影列表管理...

Global site tag (gtag.js) - Google Analytics