首页
/ DBeaver 源码工程指南:基于 OSGi/Tycho 的构建体系、代码规范与协作约定详解

DBeaver 源码工程指南:基于 OSGi/Tycho 的构建体系、代码规范与协作约定详解

2026-09-05 20:18:52作者:伍霜盼Ellen

DBeaver 是一个用 Java 21 编写的免费开源跨平台数据库管理工具,支持 100+ 数据库驱动(以 JDBC 为主),构建于 Eclipse RCP 之上的 OSGi 插件架构。仓库根目录的 AGENTS.md 是一份面向 AI Agent 与人类贡献者的工程说明文档,系统定义了 DBeaver 社区版(CE)的仓库布局、Maven + Tycho 构建流程、单元测试运行方式、插件打包规则、编码/日志/异常/NLS 等代码规范,以及 Git 分支与 PR 协作约定。读完本文,你将能够独立理解 DBeaver 的多仓库聚合构建机制、P2 依赖解析原理,并遵循其既有约定对 OSGi 插件进行阅读、构建与合规修改。

一、项目定位与仓库布局

DBeaver CE 与商业产品共享同一套模型层:浏览器端对应仓库为 cloudbeaver,命令行工具对应仓库为 dbvr(这两个仓库均不在本仓库内)。本仓库内部由四部分构成:

目录 职责 对应文件形态
plugins/ 主源码,全部为 OSGi bundle(插件) 每个插件含 META-INF/MANIFEST.MFplugin.xmlsrc/pom.xml
test/ 测试插件,与生产插件一一镜像 PostgreSQL 测试插件 对应 plugins/org.jkiss.dbeaver.ext.postgresql
features/ Eclipse feature 描述符 org.jkiss.dbeaver.ce.feature
product/ Eclipse product 配置与聚合构建入口 community product

从仓库结构看,plugins/ 下既有核心模块(org.jkiss.dbeaver.modelorg.jkiss.dbeaver.model.sqlorg.jkiss.dbeaver.registry 等),也有按数据库厂商划分的驱动扩展(ext.postgresqlext.mysqlext.oracleext.duckdb 等),每个厂商通常成对出现"模型插件 + UI 插件"(.ui 后缀)。

技术栈总览(与 AGENTS.md 的 Codebase 章节一致):

  • 语言:Java 21(目标平台 JavaSE-21,禁止使用 preview 特性);
  • 平台:OSGi / Eclipse Equinox;
  • UI:Eclipse RCP(SWT + JFace);
  • 数据库连接:JDBC 或自研实现(如 WMI);
  • SQL 解析:JSQLParser、ANTLR4(LSM 模块);
  • 测试:JUnit 5、Mockito、自研 OSGi 测试运行器(org.jkiss.dbeaver.osgi.test.runner)。

二、Maven + Tycho 构建体系

2.1 为什么不能单独构建一个插件

AGENTS.md 明确指出:在单个 bundle 目录里直接执行 mvn package 通常都会失败。原因在于 OSGi 目标平台解析:Tycho 编译一个 bundle 时,需要目标平台中包含它 Require-Bundle 声明的全部依赖,而这些依赖来自 Eclipse P2 仓库(见下文 2.3),单 bundle 构建时 Tycho 无法独立完成整个目标平台的收集。

2.2 全量产品构建命令

正确的做法是从聚合 POM 发起整仓构建:

# 完整产品构建(桌面版 CE + Eclipse 插件版 CE)
mvn package -f product/aggregate/pom.xml -T1C -Pproduct-dbeaver-ce,product-dbeaver-eclipse-ce

其中 -T1C 表示每个 CPU 核心一个线程的并行构建。product/aggregate/pom.xml 是关键的聚合入口,它将两个仓库挂入同一反应堆:

<modules>
  <!-- dbeaver common -->
  <module>../../../dbeaver-common</module>
  <!-- dbeaver ce -->
  <module>../..</module>
</modules>

即聚合 POM 同时纳入了本仓库(../..)和同级的 dbeaver-common 仓库。本仓库根 pom.xml<parent> 正是 com.dbeaver.common.main<relativePath>../dbeaver-common/pom.xml</relativePath>),Tycho 相关插件(target-platform-configurationtycho-maven-plugintycho-compiler-plugin)也在此统一声明,并配置了 win32/linux/macosx 六种 OS/架构组合的环境矩阵。

此外,根 pom 中定义了一个默认激活的 desktop profile(当未设置 headless-platform 属性时激活),它把 test/ 模块纳入构建——这正是"没有独立测试命令"这一约定(2.4 节)的来源。

2.3 OSGi 依赖全部来自 P2,而非 Maven

这是理解 DBeaver 构建的关键:

  • 所有 OSGi 依赖来自 Eclipse P2 仓库(不是 Maven),声明在各 layout=p2 的根 POM 中;
  • 包括标准 Eclipse P2(RCP 开发基线)+ DBeaver 自维护 P2 仓库(配置项 repo.p2.eclipse.url);
  • 自维护 P2 的源码仓库是 dbeaver-deps-ce,它的作用是把传统 Maven 依赖转换成 P2 bundle(这样 SLF4J、JGit、Ant 等普通 Java 库才能以 OSGi 形式被 Require);
  • bundle 之间的依赖不写在 pom.xml 里,而是写在 MANIFEST.MFRequire-Bundle 头中

DuckDB 驱动插件的清单 为例,可以直观看到这种声明方式:

Bundle-SymbolicName: org.jkiss.dbeaver.ext.duckdb;singleton:=true
Require-Bundle: org.jkiss.dbeaver.model,
 org.jkiss.dbeaver.model.sql,
 org.jkiss.dbeaver.ext.generic,
 org.jkiss.dbeaver.data.gis
Import-Package: org.jkiss.code,
 org.jkiss.dbeaver.model.sql.format
Bundle-RequiredExecutionEnvironment: JavaSE-21

其中 Require-Bundle 列出 bundle 级依赖,Import-Package 列出包级依赖(org.jkiss.code 注解来自 dbeaver-common 提供的包),Bundle-RequiredExecutionEnvironment: JavaSE-21 印证了"必须 Java 21"的约束。

2.4 运行单元测试

由于 OSGi 测试要求构建环境中包含全部 bundle(或已安装到本地 .m2),在单个 bundle 内跑测试通常同样会失败。官方做法是整仓 verify:

mvn verify -f product/aggregate/pom.xml -T1C -Pproduct-dbeaver-ce,product-dbeaver-eclipse-ce

这会执行桌面 DBeaver CE 和 Eclipse 插件的测试。测试由 Maven Tycho 作为标准构建流程的一部分运行,不存在单独的 test-only Maven 命令——测试在 mvn installmvn verify(配合 desktop 场景)时自动执行。

2.5 多仓库协同:project.deps 机制

AGENTS.md 规定了一套仓库间依赖管理约定:

  • DBeaver 相关仓库位于同一组织(dbeaver)下;
  • 每个仓库根目录可能有 project.deps 文件,纯文本,每行写一个本仓库所依赖的仓库短名;本仓库的 project.deps 只有一行:dbeaver-common
  • 所有 GitHub 仓库必须克隆到同一个父目录(文档称之为 DBEAVER_DEV_HOME,即本仓库的上一级目录)——这与 2.2 节聚合 POM 中 ../../../dbeaver-common 的相对路径正好呼应;
  • 若依赖仓库在磁盘上缺失,AI Agent 可以自行将其克隆到 DBEAVER_DEV_HOME

三、插件打包规则与许可头

3.1 一个合法插件的四要素

按 AGENTS.md 的 Plugin packaging rules,每个插件必须具备:

  1. META-INF/MANIFEST.MF:OSGi bundle 元数据(SymbolicName、版本、Require-Bundle、Export-Package 等);
  2. pom.xmlpackagingeclipse-plugin;测试插件为 eclipse-test-plugin
  3. plugin.xml:声明 Eclipse 扩展点与扩展;
  4. src 源码目录,路径在 build.properties 中指定(Tycho 的硬性要求)。

3.2 Apache 2.0 许可头

所有 OSS 仓库的每个 Java 文件都必须以 Apache 2.0 许可头开始,模板见 docs/license_header.txt

/*
 * DBeaver - Universal Database Manager
 * Copyright (C) 2010-${current-year} DBeaver Corp and others
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * ...
 */

注意两条规则:${current-year} 必须替换为当年年份;且修改任何既有 Java 文件时,必须同步把其中的年份更新为当前年份

四、编码规范:注解、导入、硬编码与日志

4.1 注解约定

注解 来源 用法
@NotNull / @Nullable org.jkiss.code 尽量用于所有方法参数与返回值
@Property org.jkiss.dbeaver.model.meta 加在 getter 方法上,将对象属性暴露给 UI
@Association 模型元数据 标记关联集合(子集合)
@ForTest 项目内部 标记仅为单位测试访问而存在的成员

关于 @Property 有一个明确的坑(Common Pitfalls 章节):该注解在运行时通过反射处理,只能放在 getter 方法上,不能放在字段上。从源码看,Property.java 的声明印证了这一点:

@Target(value = {ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Property
{
    String DEFAULT_LOCAL_STRING = "#"; //NON-NLS-1
    ...

ElementType.METHOD@Target 约束意味着放在字段上会直接编译失败。

4.2 导入(import)规则

  • Java 包的 import 必须按字母序排列
  • SDK import 与其他 import 之间用一个空行分隔,并放在 import 区块末尾;
  • 代码修改/重构后,不再使用的 import 必须删除

4.3 禁止硬编码

  • 不硬编码常量:使用库中声明的常量、DBeaver 代码库中既有的 *Constants 类,或按需新建;
  • 不硬编码 UI 文案:使用 NLS 的 *Messages 资源包(详见 4.5);但异常消息必须用英文书写。

4.4 日志:统一使用 org.jkiss.dbeaver.Log

项目要求使用 Log.java(位于 org.jkiss.dbeaver.model 插件中)作为唯一日志门面,禁止 System.out 或其他日志体系(除非被直接要求)。

4.5 NLS / 本地化

每个含用户可见字符串的插件都有一对 *Messages.java + *Messages.properties(以及各语言变体),代码中通过 *Messages.MY_STRING_KEY 形式引用;plugin.xml 则使用 %key 语法引用 plugin.properties。新增任何文本常量时,至少补充英文本地化。仓库中此类文件随处可见,例如 UIConnectionMessages.propertiesCubridMessages.properties 等,可对照参考其命名与键值组织方式。

五、异常处理与长时任务

5.1 DBException 是标准检查异常

  • DBException 及其子类是数据库错误的标准检查异常(checked exception)
  • 向更上层暴露时,应将 SQLException 及其他第三方库异常包装为 DBException
  • 非检查的运行时异常只在"别无选择"的罕见情况下使用。

5.2 长时任务与异步

  • 长耗时方法应将 DBRProgressMonitor monitor 作为第一个参数
  • 异步任务使用 Jobs(通常继承 AbstractJob 类)或 RuntimeUtils 等工具。

从源码看,AbstractJob.java 声明为 public abstract class AbstractJob extends Job(继承 Eclipse 的 org.eclipse.core.runtime.Job),与文档描述一致。

5.3 UI 线程安全(高频踩坑点)

所有 SWT/UI 更新必须运行在 display 线程上;跨线程时调用 UIUtils.asyncExec(Runnable)。该工具类位于 UIUtils.javaorg.jkiss.dbeaver.ui 插件)。

六、单元测试编写规范

AGENTS.md 对测试的要求:

  1. 凡模型层(非 UI)函数,尽可能都应有单元测试
  2. 测试插件放在 test/ 目录,且与生产插件镜像命名,如 test/org.jkiss.dbeaver.ext.postgresql.test/ 对应 plugins/org.jkiss.dbeaver.ext.postgresql/;仓库现有测试覆盖 PostgreSQL、MySQL、Oracle、Snowflake、ClickHouse、Greenplum、HANA、SQLite 等驱动(见 test 目录)。
  3. 测试类继承 DBeaverUnitTest(来自 org.jkiss.dbeaver.osgi.test.runner),或针对需要运行中 OSGi 容器的集成测试使用 @RunWithApplication / @RunWithProduct 注解;
  4. 测试随 Maven Tycho 构建执行(见 2.4 节),无独立测试命令。

自研 OSGi 测试运行器位于 plugins/org.jkiss.dbeaver.osgi.test.runner,从源码结构看,其提供了 OSGITestExtension(JUnit 5 扩展)、TestLauncher 测试启动器,以及 RunWithProduct.javaRunWithApplication.java 两个注解,与文档描述完全对应。

七、Git 分支与协作约定

AGENTS.md 的 Branches and Git Workflow 章节规定:

  • devel 是主开发分支,所有 PR 必须指向该分支;
  • 发布分支命名 release_VERSION,每个版本一个,严禁直接提交
  • 仅修错别字、格式或琐碎重构的 PR 通常不被接受(依据贡献者指南);
  • 命名规范:issue、commit 消息、PR 标题均遵循 dbeaver/repo#issueNumber title 格式,例如 dbeaver/dbeaver#12345 Fix NPE in PostgreSQL dialect
  • 分支命名dbeaver/repo#issueNumber-issueTitle,例如 dbeaver/dbeaver#12345-fix-npe-postgresql
  • PR 关联 issue:在 PR 描述中写 Closes org/project#issueNumber,例如 Closes dbeaver/dbeaver#12345
  • AI 贡献要求:AI 辅助的贡献应保持聚焦和小粒度,且每处改动须由人类贡献者理解并审查;若使用了 AI 工具生成代码,必须在 PR 描述中披露(例如:"This PR was generated with AI (GitHub Copilot)")。

详细的贡献流程以仓库外部的官方 Code contribution guide 为准(AGENTS.md 末尾给出的外链指向其 wiki,此处不重复)。

八、进阶文档索引

AGENTS.md 在 "Specific instruction" 一节中链接了两份深入文档,二者与本仓库根目录文件一一对应:

九、常见坑点速查表

坑点 说明 依据
UI 线程安全 SWT/UI 更新必须在 display 线程,跨线程用 UIUtils.asyncExec AGENTS.mdUIUtils.java
@Property 只能放 getter 运行时反射处理,放字段无效 Property.java
必须 Java 21 目标平台 JavaSE-21,禁用 preview 特性 MANIFEST.MFBundle-RequiredExecutionEnvironment
单 bundle 构建/测试必挂 OSGi 需要全量 bundle 参与目标平台解析,须走聚合 POM product/aggregate/pom.xmlpom.xml
依赖不走 Maven OSGi 依赖来自 P2,bundle 依赖写在 Require-Bundle 而非 pom 各插件 MANIFEST.MF
改文件忘改年份 修改 Java 文件须同步更新许可头年份 docs/license_header.txt
多仓库同目录 所有 dbeaver 仓库须克隆到同一 DBEAVER_DEV_HOME 父目录 project.depsAGENTS.md

适用前提说明:以上构建命令基于当前仓库的多仓库布局(dbeaver-common 位于同级目录),在无 dbeaver-common 的检出中执行 mvn verify -f product/aggregate/pom.xml 会因聚合模块缺失而失败;构建环境需满足 Java 21 与 Maven(Tycho 插件)要求。本文所有结论均取自仓库内文档与源码,如 AGENTS.mdAGENTS-Architecture.mdAGENTS-New-Database-Driver.md 及各插件的 MANIFEST.MF/pom.xml,行级细节以仓库实际内容为准。

登录后查看全文
热门项目推荐
相关项目推荐