- 浏览: 32755 次
- 性别:
- 来自: 济南
Eclipse 为程序员提供了强大的文本搜索功能,程序员可以方便 的在工作空间中搜索到需要的 JAVA 代码或者文本。但是有时候,程序员希望在 .class 文件源码或者普通文本文件中搜索某个字符串,而这些文件包含于 Jar 文件中,此时 Eclipse 就无法满足要求。比如,用户试图寻找 UI 上显示的某 字符串的定义位置,这就需要在 Jar 文件内的普通文本文件 , 以及 .class 文 件源码中搜索。这些 Jar 文件包含于项目类路径中,这个功能在 RCP 开发中是 经常需要的,而 Eclipse 目前还未提供这个特性。本文通过使用 JDT(Java Development Toolkit)中与 Jar 相关的接口,解决了这个问题,并给出示例及 程序。
Eclipse 中搜索的原理
Eclipse 采用 Lucene 技术开发其搜索内核, 该内核通过对关键字进行索引,快速定位目标文件。例如,Eclipse 会对 JAVA 源文件中的类名、字段名、方法名等进行索引,当程序员使用 Open Type 功能 (快捷键:CTRL+SHIFT+T)进行类搜索时,便可以通过类名这个索引字段进行快 速搜索 ; 在使用 JAVA 搜索(Java Search)功能时,Eclipse 也会让用户指定 具体的索引字段(Search For),如可以选择方法名、类名、字段名、包名、构 造器名等,Eclipse 会根据选择的索引字段与用户的输入,快速搜索到源代码。
Eclipse 在提供 Jar 源代码搜索方面的限制
Eclipse 提供了文 件搜索(File Search)的功能,用来搜索指定范围 ( 项目、工作空间等 ) 内 的文本文件。这个功能并没有根据某些特殊关键字进行索引。因为对于任意字符 串的搜索,是无法找到特定关键字进行索引的。因此为了提高搜索效率, Eclipse 对于任意字符串的搜索范围仅限于用户编写的文本文件,而没有对项目 所依赖的 Jar 文件中的类的源代码进行搜索。因为 Jar 源代码的数量往往数量 庞大,搜索它们将是一个相当费时的操作。但是在很多情况下,程序员有必要进 行类源代码的搜索,通过查看需要的源代码解决一些问题,Eclipse 目前提供的 搜索功能就无法满足这样的需求。
JDT 中 Jar 文件相关的类结构图分析
下面两图展示了 JDT 中与 Jar 文件处理相关的类,从图中,可以清晰 的了解它们的层次、包含和对应关系。
图 1. JDT 中与 Jar 文件相关的 UML 类结构图
图 2. JDT 中与 Jar 文件相关的类结构对应图
上图描述了各个节点之间的层次、包含和对应关系,了解这些信息, 对文章下一部分的阅读是必要的。Java 项目,Jar 文件,Jar 文件中的包,Jar 文件中的普通文件夹,class 文件和非 class 文件分别对应于 IJavaProject, JarPackageFragmentRoot,JarPackageFragment,JarEntryDirectory, IClassFile 以及 JarEntryFile。IJavaProject 包含了多个 JarPackageFragmentRoot。而每个 JarPackageFragmentRoot 包含多个的 JarPackageFragment、JarEntryDirectory 和 JarEntryFile。类似的, JarPackageFragment 包含多个的 IClassFile 和 JarEntryFile;每个 JarEntryDirectory 包含多个的 JarEntryFile 和 JarEntryDirectory。
Jar 源代码搜索解决方案
本文将用一个例子程序,逐步介绍如何 实现 Jar 源代码的搜索,进一步了解 JDT 提供的 API。解决方案的主要逻辑为 :遍历工作空间下的所有 JAVA 项目,并且逐一获得项目所依赖的 Jar 文件列 表。然后遍历该列表获得每个 Jar 文件中的 class 文件源码和非 class 文件 的文本内容,使用正则表达式进行匹配查找。最后输出结果的类名、文件路径、 匹配的起始位置和匹配的字符串长度等信息。
结合这个逻辑以及 JDT 中 Jar 文件相关的类结构,上述解决方案中的主要技术问题包括:
ResourcesPlugin.getWorkspace().getRoot().getProjects() 可以获得 工作空间下的所有项目,类型为 IProject。那么如何将 IProject 对象转换为 JAVA 项目对应的 IJavaProject 对象?(文中步骤 1 解决该问题)
获 得 IJavaProject 对象后,如何获得它所依赖的 Jar 文件列表,也就是 JarPackageFragmentRoot 对象列表?(文中步骤 2 解决该问题)
获得 JarPackageFragmentRoot 对象后,如何获得它下面的包(JarPackageFragment ),又如何获得包下的 class 文件(IClassFile)和非 class 文本文件 (JarFileEntry)?(文中步骤 3、5 解决该问题)
如何获得 IClassFile 的源代码,又如何获得 JarFileEntry 的文本内容?(文中步骤 4 、6 解决该问题)
下面将对各个步骤逐一地进行分析,并且一一解决上 面提到的问题。
步骤 1. 转换 IProject 为 IJavaProject
Eclipse 工作空间下,可能存在许多类型的项目,有 JAVA 项目也有非 JAVA 项目,为了获得项目依赖的 Jar 文件,该项目必须是 Java 类型的项目。以下代码通过调用 JDT 提供的接口,获得 JAVA 项目列表。
清单 1. 获得工作空间下的所有 JAVA 项目
/* 获得工作 空间下的所有项目 */
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
if (projects != null)
{
for (IProject p : projects)
{
/* 尝试转换普通项目为 JAVA 项目 */
IJavaProject create = JavaCore.create(p);
/* 判断项目是否是 JAVA 项目 */
if (create != null && create.exists())
{
/* 操 作 JAVA 项目 */
…
}
}
}
步骤 2. 获得依赖的 JarPackageFragmentRoot 列表
获得 IJavaProject 对象后,需要得到它 所依赖的 Jar 文件列表。在 JDT 中,Jar 文件对应的类为 JarPackageFragmentRoot,下面一段程序用于获得 Jar 文件列表。
清单 2. 获得 JAVA 项目依赖的 Jar 文件列表的代码
IJavaProject project= …
IJavaElement[] children = project.getChildren();
if (children != null)
{
/* 遍历 project 下的 Java 元素 */
for (IJavaElement ele : children)
{
/* 判断是否 是 JarPackageFragmentRoot 对象 */
if (ele instanceof JarPackageFragmentRoot)
{
/* 操作此 jar 文件 */
…
}
}
}
大多数时候程序员想要搜索的范围并不包含 JRE 库的源代码,因此为了提高搜索效率,需要屏蔽 JRE 库源代码的搜索,下面一 段程序展示如何实现这个需求。
清单 3. 屏蔽 JRE 库的源码搜索
JarPackageFragmentRoot jarFile = … ;
IJavaProject project = … ;
/**
* 判断此 Jar 是否在 JRE 库中。如果是,将其屏蔽 , 以提高效率
*/
IClasspathEntry rawClasspathEntry = jarFile.getRawClasspathEntry ();
IClasspathContainer classpathContainer = JavaCore.getClasspathContainer(
rawClasspathEntry.getPath(), project);
/* 判断此 jar 是否属 于项目默认的 JRE 库。如果是,不检查该 jar*/
if (classpathContainer.getKind() == IClasspathContainer.K_DEFAULT_SYSTEM)
{
/* 跳过此 jar 的搜索 */
}
步骤 3. 获得 JarPackageFragmentRoot 中的 IClassFile 列表
如果想获得 .class 文 件的源码,就需要获得 .class 文件对应的 IClassFile 对象,下面的程序展示 了如何从 JarPackageFragmentRoot 对象开始遍历,获得其包含的 PackageFragment 对象,又从 PackageFragment 对象中获得 IClassFile 对象 列表。
清单 4. 获取所有类文件的代码
JarPackageFragmentRoot root = …
IJavaElement[] children = root.getChildren();
if (children != null)
{
/* 遍历 JarPackageFragmentRoot 下的 所有包元素 */
for (IJavaElement ele : children)
{
if (ele instanceof PackageFragment)
{
IJavaElement[] classes = ((PackageFragment) ele).getChildren();
/* 遍历 PackageFragment 下的所有类元素 */
for (IJavaElement cls : children)
{
if (ele instanceof IClassFile)
{
/* 获得 IClassFile 对象进行操作 */
}
}
}
}
}
需要注意的是,JDT 中 Jar 文件 中的包(package)对应的类为 JarPackageFragment,但是该类为 default 类 型,无法引用,可以先将它转换为它的父类 PackageFragment,然后进行处理。
步骤 4. 获得 IClassFile 源代码并比较
得到 IClassFile 对象 后,需要获得其源码 .IClassFile 提供了非常方便的接口: getSource。应用 该方法可以获得源码字符串。如果该方法的输出值为 null,说明这个类还未绑 定源代码。这种情况下可以通过双击 .class 文件,点击 Change Attached Source 按钮进行源代码的绑定。下面的程序展示了如何根据用户输入的正则表 达式进行比较搜索。
清单 5. 获取类文件源码并比较
IClassFile cf = … ;
Pattern searchPattern = Pattern.compile("用户输入的正则表达式");
/* 获得 IClassFile 源码 */
String source = cf.getSource ();
if (source != null)
{
Matcher matcher = searchPattern.matcher(source);
while (matcher.find())
{
/* 获得偏移量 */
int offset = matcher.start();
String group = matcher.group();
/* 获得长度 */
int length = group.length ();
}
}
步骤 5. 获得 JarPackageFragmentRoot 中的非 JAVA 资源
Jar 文件中 JAVA 资源主要 是 .java 文件和 .class 文件。Jar 文件中非 JAVA 的资源,对应的类为 IJarEntryResource,比如 Jar 中的 .properties 文件、META-INF 文件夹、 META-INF 文件夹下的 MANIFEST.MF 等,都属于非 JAVA 资源,这些非 JAVA 资 源可以存放于 JarPackageFragmentRoot 下,也可以存放于 JarPackageFragment 下。下面的程序展示如何遍历获得 JarPackageFragmentRoot 下的所有非 JAVA 资源。
清单 6. 获得非类文 件的资源
/* 注:ele 也可以是 PackageFragment, 它们都拥 有 getNonJavaResources 方法 */
JarPackageFragmentRoot ele = … ;
Object[] nonjavares = ele.getNonJavaResources();
if (nonjavares != null)
{
for (Object o : nonjavares)
{
/* JarEntryDirectory 相当于 META-INF 文件夹 */
if (o instanceof JarEntryDirectory)
{
JarEntryDirectory ff = (JarEntryDirectory)o;
IJarEntryResource[] children = ff.getChildren();
for (IJarEntryResource e : children)
{
if (e instanceof JarEntryDirectory)
{
/* 这里需要递归处 理 */
}
else if (e instanceof JarEntryFile)
{
/* 处理该文本文件 */
}
}
}
/* JarEntryFile 相当于 META-INF 文件夹下的 MANIFEST.MF 或者 .properties 文件等 */
else if (o instanceof JarEntryFile)
{
JarEntryFile ff = (JarEntryFile) o;
/* 处理该文本文件 */
}
}
}
步骤 6. 获得非 JAVA 资源的源代码并比较
在本文的代码示例中只展示从 JarEntryFile 获得源代码的方法,如果需要使用其他类型的非 JAVA 资源的获 取方法,请查看附件中的源码。
清单 7. 获得非类文件的文本内容并且 比较
/**
* 该方法用于获得 JarEntryFile 源代码并 且比较获得结果
*/
private void cooperate (JarEntryFile ff, Pattern searchPattern)
{
ByteArrayInputStream contents;
try
{
contents = (ByteArrayInputStream) ff.getContents ();
byte[] bs = new byte[contents.available ()];
contents.read(bs);
String con = new String(bs);
Matcher matcher = searchPattern.matcher(con);
while (matcher.find())
{
/* 获得结果的偏移和长度 */
int start = matcher.start();
int length = matcher.group().length();
}
}
catch (Exception e)
{
}
}
步骤 7. 输出结果
为了简单,程序会将结果打 印到控制台上,包括结果中的偏移量、长度、以及查找到源代码路径。
具体应用环境 ---RCP 中查找源码
在 RCP 二次开发中,有时候非常需要 查看已有 UI 的源码,供程序员参考使用。下面将使用前面开发的例子搜索包含 UI 上某字符串的源文件或源代码。一般来说,界面上的字符串都被存放于 .properties 文件,方便修改和多语言处理。由于 .properties 中可能出现占 位符,界面显示的是处理占位符后的结果,所以需要选取合适的字符串进行搜索 。搜索到 .properties 文件后,就根据该 .properties 文件所在的包名,和自 身的文件名,搜索引用该 properties 文件的类。如对于 com.ibm.wise.A_zh_CN.propertis 文件,搜索 com.ibm.wise.A 即可,具体原 因可以搜索 ResourceBundle 的相关资料进行查阅。下面展示这一搜索过程。
步骤 1. 根据 UI 上的字符串获得其 properties 文件所在
图 3. 要搜索的 UI 字符串
例子将试图搜索包含“This section provides general information about” 字符串的 properties 文件,如果未搜索到,可以 适当缩短字符串长度。
图 4. 输入 UI 字符串的程序界面
点击 OK 就可以进行搜索。
图 5. 属性文件搜索结果(用时 3.23 秒)
结果显示了包含该字符串的 properties 文件路径,以及字符串在该文件中 出现的起始位置和长度信息。该文件包含于 Jar 文件中。根据搜索到的路径, 打开文件查看源码。
图 6. 属性文件源代码
图中灰色背景部分就是需要查找的字符串。
步骤 2. 根据 properties 文件名获得引用该 properties 文件的类
在获得 properties 文件名之后,根据搜索到的 properties 文件名(在本文的例子中 是 gui.properties),搜索引用该属性文件的 java 类 , 输入查询的字符串为 :com.ibm.btools.blm.ui.attributesview.resource.gui。
图 7. 输入 使用属性文件的字符串程序界面
图 8. 类搜索结果(用时 2.43 秒)
通过 Open Type 功能,输入 BLMAttributesviewMessageKeys,就可 以找到此 .class 文件,打开 .class 文件就可以查看它的源代码。
其 他接口简单介绍
这里简单的介绍了 JDT 中与 Jar 相关的类的其他有用 接口,如表 1 所示。
表 1. 其他接口介绍
类接口IClassFileisClass():boolean 判断是否是 class 类型
isInterface():boolean 判断是否是 interface 类型PackageFragmentcreateCompilationUnit ():ICompilationUnit 新建 JAVA 文件
delete():void 删除此包
getClassFile():IClassFile 得到包下某个 class 文件
getClassFiles():IClassFile[] 得到包下所有 class 文件
getCompilationUnit():ICompilationUnit 得到包下某个 java 文件
getCompilationUnits():ICompilationUnit[] 得到包下所有 java 文件
rename():void 重命名JarPackageFragmentRootgetJar():ZipFile 得到 jar 文件对应的 ZipFile
getKind ():int 可以是 IPackageFragmentRoot.K_SOURCE 或者 IPackageFragmentRoot.K_BINARY,表示是源代码类型还是二进制类型
isArchive():boolean 判断是否是压缩文件
isReadOnly():boolean 判 断是否只读
结束语
在进行二次开发时,通 过查看源代码可以很好的帮助程序员了解原有系统,同时对于查找和分析代码漏 洞也有很大的帮助。该文章简单的介绍了如何使用 JDT 提供的接口进行源代码 的搜索,文章内容仅供参考,有兴趣的朋友可以参考该文章的实现,进行进一步 的优化,提高搜索效率,或者做成实用的插件发布,相信会受到很多 Java 程序 员的喜爱。
原文地址:http://www.ibm.com/developerworks/cn/opensource/os-ecl- jdtsearch/
Eclipse 中搜索的原理
Eclipse 采用 Lucene 技术开发其搜索内核, 该内核通过对关键字进行索引,快速定位目标文件。例如,Eclipse 会对 JAVA 源文件中的类名、字段名、方法名等进行索引,当程序员使用 Open Type 功能 (快捷键:CTRL+SHIFT+T)进行类搜索时,便可以通过类名这个索引字段进行快 速搜索 ; 在使用 JAVA 搜索(Java Search)功能时,Eclipse 也会让用户指定 具体的索引字段(Search For),如可以选择方法名、类名、字段名、包名、构 造器名等,Eclipse 会根据选择的索引字段与用户的输入,快速搜索到源代码。
Eclipse 在提供 Jar 源代码搜索方面的限制
Eclipse 提供了文 件搜索(File Search)的功能,用来搜索指定范围 ( 项目、工作空间等 ) 内 的文本文件。这个功能并没有根据某些特殊关键字进行索引。因为对于任意字符 串的搜索,是无法找到特定关键字进行索引的。因此为了提高搜索效率, Eclipse 对于任意字符串的搜索范围仅限于用户编写的文本文件,而没有对项目 所依赖的 Jar 文件中的类的源代码进行搜索。因为 Jar 源代码的数量往往数量 庞大,搜索它们将是一个相当费时的操作。但是在很多情况下,程序员有必要进 行类源代码的搜索,通过查看需要的源代码解决一些问题,Eclipse 目前提供的 搜索功能就无法满足这样的需求。
JDT 中 Jar 文件相关的类结构图分析
下面两图展示了 JDT 中与 Jar 文件处理相关的类,从图中,可以清晰 的了解它们的层次、包含和对应关系。
图 1. JDT 中与 Jar 文件相关的 UML 类结构图
图 2. JDT 中与 Jar 文件相关的类结构对应图
上图描述了各个节点之间的层次、包含和对应关系,了解这些信息, 对文章下一部分的阅读是必要的。Java 项目,Jar 文件,Jar 文件中的包,Jar 文件中的普通文件夹,class 文件和非 class 文件分别对应于 IJavaProject, JarPackageFragmentRoot,JarPackageFragment,JarEntryDirectory, IClassFile 以及 JarEntryFile。IJavaProject 包含了多个 JarPackageFragmentRoot。而每个 JarPackageFragmentRoot 包含多个的 JarPackageFragment、JarEntryDirectory 和 JarEntryFile。类似的, JarPackageFragment 包含多个的 IClassFile 和 JarEntryFile;每个 JarEntryDirectory 包含多个的 JarEntryFile 和 JarEntryDirectory。
Jar 源代码搜索解决方案
本文将用一个例子程序,逐步介绍如何 实现 Jar 源代码的搜索,进一步了解 JDT 提供的 API。解决方案的主要逻辑为 :遍历工作空间下的所有 JAVA 项目,并且逐一获得项目所依赖的 Jar 文件列 表。然后遍历该列表获得每个 Jar 文件中的 class 文件源码和非 class 文件 的文本内容,使用正则表达式进行匹配查找。最后输出结果的类名、文件路径、 匹配的起始位置和匹配的字符串长度等信息。
结合这个逻辑以及 JDT 中 Jar 文件相关的类结构,上述解决方案中的主要技术问题包括:
ResourcesPlugin.getWorkspace().getRoot().getProjects() 可以获得 工作空间下的所有项目,类型为 IProject。那么如何将 IProject 对象转换为 JAVA 项目对应的 IJavaProject 对象?(文中步骤 1 解决该问题)
获 得 IJavaProject 对象后,如何获得它所依赖的 Jar 文件列表,也就是 JarPackageFragmentRoot 对象列表?(文中步骤 2 解决该问题)
获得 JarPackageFragmentRoot 对象后,如何获得它下面的包(JarPackageFragment ),又如何获得包下的 class 文件(IClassFile)和非 class 文本文件 (JarFileEntry)?(文中步骤 3、5 解决该问题)
如何获得 IClassFile 的源代码,又如何获得 JarFileEntry 的文本内容?(文中步骤 4 、6 解决该问题)
下面将对各个步骤逐一地进行分析,并且一一解决上 面提到的问题。
步骤 1. 转换 IProject 为 IJavaProject
Eclipse 工作空间下,可能存在许多类型的项目,有 JAVA 项目也有非 JAVA 项目,为了获得项目依赖的 Jar 文件,该项目必须是 Java 类型的项目。以下代码通过调用 JDT 提供的接口,获得 JAVA 项目列表。
清单 1. 获得工作空间下的所有 JAVA 项目
/* 获得工作 空间下的所有项目 */
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
if (projects != null)
{
for (IProject p : projects)
{
/* 尝试转换普通项目为 JAVA 项目 */
IJavaProject create = JavaCore.create(p);
/* 判断项目是否是 JAVA 项目 */
if (create != null && create.exists())
{
/* 操 作 JAVA 项目 */
…
}
}
}
步骤 2. 获得依赖的 JarPackageFragmentRoot 列表
获得 IJavaProject 对象后,需要得到它 所依赖的 Jar 文件列表。在 JDT 中,Jar 文件对应的类为 JarPackageFragmentRoot,下面一段程序用于获得 Jar 文件列表。
清单 2. 获得 JAVA 项目依赖的 Jar 文件列表的代码
IJavaProject project= …
IJavaElement[] children = project.getChildren();
if (children != null)
{
/* 遍历 project 下的 Java 元素 */
for (IJavaElement ele : children)
{
/* 判断是否 是 JarPackageFragmentRoot 对象 */
if (ele instanceof JarPackageFragmentRoot)
{
/* 操作此 jar 文件 */
…
}
}
}
大多数时候程序员想要搜索的范围并不包含 JRE 库的源代码,因此为了提高搜索效率,需要屏蔽 JRE 库源代码的搜索,下面一 段程序展示如何实现这个需求。
清单 3. 屏蔽 JRE 库的源码搜索
JarPackageFragmentRoot jarFile = … ;
IJavaProject project = … ;
/**
* 判断此 Jar 是否在 JRE 库中。如果是,将其屏蔽 , 以提高效率
*/
IClasspathEntry rawClasspathEntry = jarFile.getRawClasspathEntry ();
IClasspathContainer classpathContainer = JavaCore.getClasspathContainer(
rawClasspathEntry.getPath(), project);
/* 判断此 jar 是否属 于项目默认的 JRE 库。如果是,不检查该 jar*/
if (classpathContainer.getKind() == IClasspathContainer.K_DEFAULT_SYSTEM)
{
/* 跳过此 jar 的搜索 */
}
步骤 3. 获得 JarPackageFragmentRoot 中的 IClassFile 列表
如果想获得 .class 文 件的源码,就需要获得 .class 文件对应的 IClassFile 对象,下面的程序展示 了如何从 JarPackageFragmentRoot 对象开始遍历,获得其包含的 PackageFragment 对象,又从 PackageFragment 对象中获得 IClassFile 对象 列表。
清单 4. 获取所有类文件的代码
JarPackageFragmentRoot root = …
IJavaElement[] children = root.getChildren();
if (children != null)
{
/* 遍历 JarPackageFragmentRoot 下的 所有包元素 */
for (IJavaElement ele : children)
{
if (ele instanceof PackageFragment)
{
IJavaElement[] classes = ((PackageFragment) ele).getChildren();
/* 遍历 PackageFragment 下的所有类元素 */
for (IJavaElement cls : children)
{
if (ele instanceof IClassFile)
{
/* 获得 IClassFile 对象进行操作 */
}
}
}
}
}
需要注意的是,JDT 中 Jar 文件 中的包(package)对应的类为 JarPackageFragment,但是该类为 default 类 型,无法引用,可以先将它转换为它的父类 PackageFragment,然后进行处理。
步骤 4. 获得 IClassFile 源代码并比较
得到 IClassFile 对象 后,需要获得其源码 .IClassFile 提供了非常方便的接口: getSource。应用 该方法可以获得源码字符串。如果该方法的输出值为 null,说明这个类还未绑 定源代码。这种情况下可以通过双击 .class 文件,点击 Change Attached Source 按钮进行源代码的绑定。下面的程序展示了如何根据用户输入的正则表 达式进行比较搜索。
清单 5. 获取类文件源码并比较
IClassFile cf = … ;
Pattern searchPattern = Pattern.compile("用户输入的正则表达式");
/* 获得 IClassFile 源码 */
String source = cf.getSource ();
if (source != null)
{
Matcher matcher = searchPattern.matcher(source);
while (matcher.find())
{
/* 获得偏移量 */
int offset = matcher.start();
String group = matcher.group();
/* 获得长度 */
int length = group.length ();
}
}
步骤 5. 获得 JarPackageFragmentRoot 中的非 JAVA 资源
Jar 文件中 JAVA 资源主要 是 .java 文件和 .class 文件。Jar 文件中非 JAVA 的资源,对应的类为 IJarEntryResource,比如 Jar 中的 .properties 文件、META-INF 文件夹、 META-INF 文件夹下的 MANIFEST.MF 等,都属于非 JAVA 资源,这些非 JAVA 资 源可以存放于 JarPackageFragmentRoot 下,也可以存放于 JarPackageFragment 下。下面的程序展示如何遍历获得 JarPackageFragmentRoot 下的所有非 JAVA 资源。
清单 6. 获得非类文 件的资源
/* 注:ele 也可以是 PackageFragment, 它们都拥 有 getNonJavaResources 方法 */
JarPackageFragmentRoot ele = … ;
Object[] nonjavares = ele.getNonJavaResources();
if (nonjavares != null)
{
for (Object o : nonjavares)
{
/* JarEntryDirectory 相当于 META-INF 文件夹 */
if (o instanceof JarEntryDirectory)
{
JarEntryDirectory ff = (JarEntryDirectory)o;
IJarEntryResource[] children = ff.getChildren();
for (IJarEntryResource e : children)
{
if (e instanceof JarEntryDirectory)
{
/* 这里需要递归处 理 */
}
else if (e instanceof JarEntryFile)
{
/* 处理该文本文件 */
}
}
}
/* JarEntryFile 相当于 META-INF 文件夹下的 MANIFEST.MF 或者 .properties 文件等 */
else if (o instanceof JarEntryFile)
{
JarEntryFile ff = (JarEntryFile) o;
/* 处理该文本文件 */
}
}
}
步骤 6. 获得非 JAVA 资源的源代码并比较
在本文的代码示例中只展示从 JarEntryFile 获得源代码的方法,如果需要使用其他类型的非 JAVA 资源的获 取方法,请查看附件中的源码。
清单 7. 获得非类文件的文本内容并且 比较
/**
* 该方法用于获得 JarEntryFile 源代码并 且比较获得结果
*/
private void cooperate (JarEntryFile ff, Pattern searchPattern)
{
ByteArrayInputStream contents;
try
{
contents = (ByteArrayInputStream) ff.getContents ();
byte[] bs = new byte[contents.available ()];
contents.read(bs);
String con = new String(bs);
Matcher matcher = searchPattern.matcher(con);
while (matcher.find())
{
/* 获得结果的偏移和长度 */
int start = matcher.start();
int length = matcher.group().length();
}
}
catch (Exception e)
{
}
}
步骤 7. 输出结果
为了简单,程序会将结果打 印到控制台上,包括结果中的偏移量、长度、以及查找到源代码路径。
具体应用环境 ---RCP 中查找源码
在 RCP 二次开发中,有时候非常需要 查看已有 UI 的源码,供程序员参考使用。下面将使用前面开发的例子搜索包含 UI 上某字符串的源文件或源代码。一般来说,界面上的字符串都被存放于 .properties 文件,方便修改和多语言处理。由于 .properties 中可能出现占 位符,界面显示的是处理占位符后的结果,所以需要选取合适的字符串进行搜索 。搜索到 .properties 文件后,就根据该 .properties 文件所在的包名,和自 身的文件名,搜索引用该 properties 文件的类。如对于 com.ibm.wise.A_zh_CN.propertis 文件,搜索 com.ibm.wise.A 即可,具体原 因可以搜索 ResourceBundle 的相关资料进行查阅。下面展示这一搜索过程。
步骤 1. 根据 UI 上的字符串获得其 properties 文件所在
图 3. 要搜索的 UI 字符串
例子将试图搜索包含“This section provides general information about” 字符串的 properties 文件,如果未搜索到,可以 适当缩短字符串长度。
图 4. 输入 UI 字符串的程序界面
点击 OK 就可以进行搜索。
图 5. 属性文件搜索结果(用时 3.23 秒)
结果显示了包含该字符串的 properties 文件路径,以及字符串在该文件中 出现的起始位置和长度信息。该文件包含于 Jar 文件中。根据搜索到的路径, 打开文件查看源码。
图 6. 属性文件源代码
图中灰色背景部分就是需要查找的字符串。
步骤 2. 根据 properties 文件名获得引用该 properties 文件的类
在获得 properties 文件名之后,根据搜索到的 properties 文件名(在本文的例子中 是 gui.properties),搜索引用该属性文件的 java 类 , 输入查询的字符串为 :com.ibm.btools.blm.ui.attributesview.resource.gui。
图 7. 输入 使用属性文件的字符串程序界面
图 8. 类搜索结果(用时 2.43 秒)
通过 Open Type 功能,输入 BLMAttributesviewMessageKeys,就可 以找到此 .class 文件,打开 .class 文件就可以查看它的源代码。
其 他接口简单介绍
这里简单的介绍了 JDT 中与 Jar 相关的类的其他有用 接口,如表 1 所示。
表 1. 其他接口介绍
类接口IClassFileisClass():boolean 判断是否是 class 类型
isInterface():boolean 判断是否是 interface 类型PackageFragmentcreateCompilationUnit ():ICompilationUnit 新建 JAVA 文件
delete():void 删除此包
getClassFile():IClassFile 得到包下某个 class 文件
getClassFiles():IClassFile[] 得到包下所有 class 文件
getCompilationUnit():ICompilationUnit 得到包下某个 java 文件
getCompilationUnits():ICompilationUnit[] 得到包下所有 java 文件
rename():void 重命名JarPackageFragmentRootgetJar():ZipFile 得到 jar 文件对应的 ZipFile
getKind ():int 可以是 IPackageFragmentRoot.K_SOURCE 或者 IPackageFragmentRoot.K_BINARY,表示是源代码类型还是二进制类型
isArchive():boolean 判断是否是压缩文件
isReadOnly():boolean 判 断是否只读
结束语
在进行二次开发时,通 过查看源代码可以很好的帮助程序员了解原有系统,同时对于查找和分析代码漏 洞也有很大的帮助。该文章简单的介绍了如何使用 JDT 提供的接口进行源代码 的搜索,文章内容仅供参考,有兴趣的朋友可以参考该文章的实现,进行进一步 的优化,提高搜索效率,或者做成实用的插件发布,相信会受到很多 Java 程序 员的喜爱。
原文地址:http://www.ibm.com/developerworks/cn/opensource/os-ecl- jdtsearch/
发表评论
-
打造eclipse product
2015-01-16 16:08 591请参考:http://www.ibm.com/develope ... -
关于插件卸载后plugin文件下扔保留插件文件的解释
2015-01-16 14:24 592But why aren't uninstalled bund ... -
RCP开发遇到SWTError: swt no more handles 问题解决
2014-11-02 21:05 816应用场景:在打开的编辑器中创建类图,每打开一次都要用到类图、字 ... -
rcp插件代码打包后出现中文乱码
2014-11-02 21:06 460使用message文件对含义中文的类进行国际化。在类上单击右键 ... -
插件开发中与spring集成遇到的问题
2014-10-31 19:43 1047场景: 1.我把spring的所有jar包到放到一个插 ... -
Eclipse撤销恢复机制分享
2014-10-31 19:41 2967来看下命令模式的高级篇。redo/undo操作的实现 1.首先 ... -
搜索Jar包中的类或包
2014-10-31 19:37 713import java.io.File; import jav ... -
tycho管理插件依赖架构
2014-10-31 19:31 1015附件中是我总结的使用tycho管理Eclipse插件项目的架构 ...
相关推荐
2. **搜索(Search)**:JDT的搜索功能可以快速定位代码中的特定元素,如类、方法、变量,甚至可以根据代码结构进行搜索。 3. **导航(Navigation)**:通过类视图、包浏览器和大纲视图,开发者可以快速跳转到代码...
- 搜索和比较:文本比较、资源搜索和Java搜索,并支持扩展机制。 - UI设计器:如Eclipse VE project。 - 编译和构建:包括Java Builder和任务框架,以及资源锁定、进度监控、任务中止等后台任务处理。 - Java重构:...
一款基于eclipse的源代码搜索插件,可以在开发过程中直接搜索网上的有几十万个文件的源码片段库。 支持eclipse3.X版本。 在eclipse的编辑器中,选择一个关键词,通过快捷键 Ctrl + Shift + L 键就可以快速的搜索源...
"Eclipse Spellchecker" 插件是基于Eclipse的JDT拼写检查功能,它提供了集成的文本校验功能,能检测代码注释、字符串、以及编辑器中的其他文本。这个插件允许开发者自定义词典,添加忽略的单词,以及对拼写错误进行...
- **JDT(Java Development Tools)**:Eclipse的基础,提供Java源码编辑、编译、调试等功能。 - **PDE(Plug-in Development Environment)**:用于开发Eclipse插件和RCP(Rich Client Platform)应用的工具集。 ...
5. **源码跳转**:集成Maven的源码库,允许开发者直接从Eclipse内部跳转到依赖库的源码,便于理解和调试。 6. **POM编辑**:提供强大的POM.xml文件编辑器,帮助用户轻松管理和编辑项目对象模型(Project Object ...
2. **Java开发工具(JDT)**:Eclipse的核心组件之一,提供了全面的Java语言支持,包括代码编辑、编译、调试和重构功能。 3. **插件系统**:Eclipse基于插件架构,允许开发者通过安装额外的插件扩展其功能,如Git、...
Eclipse作为一个开放源码的集成开发环境(IDE),支持多种编程语言,包括Java、C++、Python等。通过安装插件,用户可以添加对新语言的支持,提升代码编辑、调试、构建以及其他开发任务的效率。 首先,让我们来了解...
在Windows环境下,开发基于Hadoop的Java应用程序通常需要一个集成开发环境(IDE),Eclipse是其中常用的一个。本文将详细讲解如何使用Eclipse与Hadoop 2.2.0插件进行连接,以便于在Windows操作系统上进行Hadoop相关...
- **安装PDE相关组件**: 通过Eclipse的帮助菜单安装了PDE相关的组件,包括CVS Client、JDT、PDE、RCP等相关源码包。 #### 四、PDE环境配置详解 - **安装过程**: 在Eclipse的帮助菜单下选择"Install New Software......
2. **Eclipse的架构**:Eclipse基于插件模型构建,核心平台提供基础服务,如工作台、视图、编辑器和透视图,而具体的功能则由各种插件实现,这使得Eclipse具有高度的扩展性。 3. **Eclipse-inst-win64.exe**:这是...