- 浏览: 149122 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
EclipseEye:
fair_jm 写道不错 蛮详细的 谢谢分享
SWT/JFace专题 --- SWT中Display和多线程 -
fair_jm:
不错 蛮详细的 谢谢分享
SWT/JFace专题 --- SWT中Display和多线程
2 工作空间API
本节将重点介绍工作空间API和编程模式的关键部分。在您对资源进行操作时,这部分内容会非常有用。
工作空间API的全面描述位于org.eclipse.core.resources包的Javadoc中,您可以在Eclipse帮助系统中的Platform Plug-in Developer Guide一节中找到。
2.1 工作空间和工作空间根目录
当启动Eclipse时,您访问的是单个工作空间。为了在插件代码中访问工作空间,需要获取当前工作空间的引用。为此,可以通过访问org.eclipse.core.resources插件的插件类,来获取如下的工作空间。
IWorkspace myWorkspace =
org.eclipse.core.resources.ResourcesPlugin.getWorkspace();
一旦获得了工作空间的引用,您就可以添加资源更改侦听器,添加保存参与者以及导航至IWorkspaceRoot。
myWorkspace.getRoot();
下面列出了IWorkspace API中的一些值得注意的方法:
● getDescription返回工作空间的描述。这些描述可以用来获取或者更改与工作空间相关的设置,例如工作空间中的项目按照何种顺序构建,资源发生更改时构建过程是否自动执行。其中许多设置与Preferences对话框的Workbench页面中的选项相对应。
● validateName(name,type)返回一个IStatus对象,该方法将验证传入的名称对于指定的资源类别是否合法。
● addResourceChangeListener(…)用于向工作空间添加通用或者特定变化事件的侦听器。
● addSaveParticipant(…)注册一个保存参与者类,该类负责对由传入参数中所指定的插件的工作空间保存事件进行处理。
名称验证过程由validateName方法提供,它执行必要的测试以验证名称对于指定的资源类型是否合法。只有当资源真正被创建时,才会进行名称的验证过程,而创建一个资源句柄时,并不会进行名称验证。如果您想在实际创建资源之前,验证名称是否合法,请使用validateName方法。
通常您可以简单地获取工作空间引用,然后使用getRoot方法得到工作空间根目录;从根目录开始,您可以移动到资源模型的其他区域,例如查找特定的项目、添加/修改资源以及在资源树中查找与工具相关的内容。
工作空间根目录是项目的容器,因此,也是所有资源的容器。工作空间根目录实现了IContainer接口。项目和文件夹也实现了该接口。尽管如此,工作空间根目录只能包含项目。而项目和文件夹可以包含文件夹和文件。工作空间根目录并没有在Navigator视图中显示出来,但您可以通过项目获取其父结点(getParent),得到工作空间根目录。显然,对于getParent方法,工作空间根目录将返回null。
您可能会指出默认的工作空间目录名应该是workspaceroot。虽然存在一个与工作空间对应的接口(IWorkspace),但是这个接口并没有扩展IResource接口。不要被IWorkspace和IWorkspaceRoot两个接口在结构上的差别和它们所扮演的角色弄糊涂。只需记住一切资源都存在于工作空间中,而您的代码应该总是借助于工作空间API来创建、访问和修改资源。如果您直接向文件系统写文件,然后再通过工作空间刷新来保持工作空间与文件系统的同步,这样会大大削弱了工作空间API的能力。不仅如此,在未同步期间,任何资源变化侦听器或者构建器将无法收到通知,直到文件系统与工作空间同步为止,而且您将无法选择在资源更改的同时,把变化记录在本地的历史记录中。当工作空间文件发生更改时,内置于工作空间API的本地历史记录必须进行相应的更新;而直接对文件系统进行的修改不会被本地历史记录所捕获。
注意:
在胖客户端平台应用程序中,工作空间目录仍然存在。在不考虑-data调用选项所指定的工作空间目录名称的情况下,工作空间目录扮演两种角色。一种是作为.metadata目录的父目录,另一种是作为项目的默认位置。只有当配置中包含了org.eclipse.core.resources插件,并且由Workbench正确地启动,工作空间才可以包含项目。这一步对于基于org.eclipse.ui.ide.workbench应用程序的IDE配置来说是自动完成的。
2.2 资源容器
一旦获得工作空间根目录,就可以很容易地访问工作空间内的其他资源。每种资源类型均提供了各种访问资源的方法,包括操纵资源树、获取资源的句柄(无论资源是否存在),以及查找特定的资源实例。
对于那些包含子资源的资源来说,IContainer接口是一个通用的编程接口。这里的容器包括工作空间根目录、项目和文件夹。表1-1列出了资源模型接口及其方法。这些方法可以用来导航资源,一直到资源树中某个文件的内容。
表1-1 资源模型导航
表1-1中的许多方法都返回资源的句柄;如果在工作空间中找不到请求的资源,则返回null。您应该仅通过工作空间API来访问资源。然而,当您编写自定义的资源程序时,需要认识到以下事实:尽管工作空间建立在文件系统之上,但文件系统并不一定与工作空间一致。
2.3 工作空间资源句柄
工作空间容器提供了各式各样的getter方法来通过名称请求资源。它们都是句柄方法,这些方法将返回工作空间资源的句柄。但是,它们并不能保证在工作空间中一定存在该资源。您可以请求句柄来获取一个可能存在的资源,或者也可以以此作为创建新资源的第一步。
findXxxx方法可以查明资源是否实际存在于工作空间中;当工作空间无法感知到该资源时,将返回null。但这仍然没有告诉您该资源是否存在于文件系统中而尚未被工作空间感知。
您需要了解资源的两个层面:工作空间和文件系统。您可以获取工作空间资源的句柄,并且测试这些资源是否真正存在于工作空间中,但是文件系统状态却是独立的。文件系统中存在的资源可能在工作空间中并不存在;而工作空间中的资源也可能不在文件系统中。为了避免冲突,您可以询问资源是否与文件系统同步,或者自己检查文件系统的状态。许多工作空间API方法也会向您询问如何处理同步问题——您可以选择终止同步或让同步过程继续下去。
通过使用isSynchronized方法,您既可以查询一个资源的同步信息,也可以查询该资源的成员以及该资源的所有子资源的同步信息。下面的示例代码演示了如何查询一个文件夹及其成员是否已经同步。
bool inSync=
folder.isSynchronized(IResource.DEPTH_ONE);
其他有关深度的选项是DEPTH_ZERO和DEPTH_INFINITE,这些选项在调用isSynchronized和refreshLocal等方法中会用到。
2.4 项目
创建一个项目需要进行以下操作:首先需要从工作空间根目录中获取该项目的句柄;然后创建一个项目描述,该项目描述中包含路径的描述以确定项目在文件系统中的位置;最后创建并打开该项目。下面这个例子所展示的程序,实现了在目录d:\workspacehome\new_Project下创建一个名为new_Project的项目。
private void createProject() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject newProjectHandle = root.getProject("new_Project");
// Get a project descriptor.
IPath targetPath = new Path("d:/workspacehome/"
+ newProjectHandle.getName());
final IProjectDescription description =
workspace.newProjectDescription(newProjectHandle.getName());
description.setLocation(targetPath);
try {
newProjectHandle.create(descriptior), null);
newProjectHandle.open(null);
} catch (CoreException e) {
// Deal with exception.
}
如果项目描述中的路径值为null,则项目会被创建在默认的位置(工作空间目录)。通常情况下,项目都是通过New Resource向导来创建的。在配套光盘上的资源编程解决方案中,包含了一个New Project向导,通过它可以创建带有指定性质的项目。
下面所列的是IProject接口中有关项目操作的关键方法。
● isOpen方法:当项目处于打开状态时,返回true;即使项目处于关闭状态,所有项目仍存在于工作空间中,所以您需要检查项目所处的状态。
● getDescription方法:返回项目的IProjectDescription对象。
● getNature(…)方法:返回指定的项目性质,当项目中没有添加该项目性质时,返回null。
● hasNature(…)方法:判断由性质扩展id指定的项目性质是否已经添加到该项目中。
● isNatureEnabled(…)方法:当由性质扩展标识符指定的项目性质被激活时,返回true。可能存在与性质定义相冲突的地方,从而强制终止性质。
以上方法中,某些方法是非常方便的,而大部分方法的处理过程中都涉及到项目描述。
工作空间也支持创建一个与项目相关的状态目录。不同于插件的状态目录,项目状态目录直接与项目相关,也直接与需要该项目状态目录支持的插件相关。您可以调用getWorkingLocation方法获取指定插件的项目状态目录的路径值。下面的代码展示了该方法的一次调用,并且返回了相应的路径值。
IPath path =
project.getWorkingLocation("plugin.id");
E:/workspace/.metadata/.plugins/
org.ec1ipse.core.resources/.projects/q.r.s/plugin.id
2.5 项目描述
项目在文件系统中以文件夹的形式存在,它在资源模型中具有Eclipse特有的行为,这些行为展示了项目的功能。项目借助于项目描述来管理这些信息。通过项目描述,一个项目可以与一个或更多性质以及构建器相关联,并且可以维持指向其他项目的引用(参见图1-4)。
图1-4 项目描述:对性质、构建器和项目引用进行管理
项目描述的用途在于记录项目的重要信息。在Eclipse中,与项目描述有关的API由IProjectDescription接口定义,而项目描述本身在工作空间中则是一个文件。对于每个项目,都存在一个项目描述文件.project,它由资源插件负责管理。下面的例子展示了一个插件开发项目的.project文件的内容。
<?xm1 version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.ibm.too1.resources</name>
<comment> </comment>
<projects> </projects>
<bui1dSpec>
<bui1dCommand>
<name>org.eclipse.jdt.core.javabui1der</name>
<arguments> </arguments>
</bui1dCommand>
<bui1dCommand>
<name>org.ec1ipse.pde.ManifestBuilder</name>
<arguments> </arguments>
</bui1dCommand>
<buildCommand>
<name>org.ec1ipse.pde.SchemaBui1der</name>
<arguments> </arguments>
</bui1dCommand>
</bui1dSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.ec1ipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
将关于项目的信息保存为项目文件夹下的一个文件,我们可以把它存储在一个资源库中。但如果该类信息作为资源属性存储,它将保存在当前工作空间的.metadata文件夹中,从而无法保存在资源库中。如果您的工具要求关于项目的信息在团队成员内部共享,应该考虑将它保存为一个文件,并存储在资源库中,或者使用用户设置API。
您可以在项目描述中添加性质和构建器,使之与项目关联起来。使用下面的方法,可以获得项目的性质列表。
String[] natures = project.getDescription().getNatureIds();
每个项目都需要定义它的构建命令,而且每个命令都知道构建器的名称。您可以获取所有的构建命令(description.getBuildSpec),然后可以从每个命令中获取构建器的名称(command.getBuilderName)。
注意:
尽管项目的构建器和性质存储在一个文件中,但您最好不要直接编辑该文件,修改这些信息。因为,直接向该文件添加一个性质,并不会触发Eclipse对该性质进行配置。所以,性质和构建器只能作为工具功能的一部分进行添加或删除。
您可以通过两种方式引用其他项目:使用用户界面中的项目属性页,或者使用IProjectDescription API。使用用户界面,您可以创建简单的项目引用,而IProjectDescription API则不仅允许创建同样简单的项目引用,而且可以存储一个动态计算的项目引用集。
只有简单的项目引用才会保存在.project文件中。下面是一个存储了项目引用的.project文件,这里只显示项目引用部分的内容。
<projects>
<project>com.ibm.tool.core</project>
<project>com.ibm.tool.common</project>
</projects>
从项目出发,通过使用如下的API调用,您既可以获得它所引用的项目,也可以获得引用了它的项目。
project.getReferencedProjects();
project.getReferencingProjects();
引用当前项目的项目不会存储在.project文件中,但是可以通过访问工作空间资源模型来确定哪些项目引用了当前项目。
IProjectDescription API也支持创建和访问动态引用的项目集。这些项目是在运行时定义的,这些定义并没有保存在.project文件中,而是保存在工作空间的元数据中。不同于简单的项目引用,动态引用不显示在用户界面中,惟一的相关记录保存在工作空间的元数据中。既然这些引用对于用户是不可见的,而且无法直接修改,您就可以把动态项目引用称为“粘滞引用”。由于这些引用不会发送到资源库中,所以当项目检出时,它们也需要重新计算。
下面的代码片段展示了如何利用IProjectDescription接口定义和获取一个动态引用的项目集。
// Calculate project array and define as dynamic
// project references.
IProject[] projects =
CalculateToolSpecificProjectSet();
Project.getDescription().setDynamicReferences (projects);
您可以根据需要来使用这些不同的项目引用方法。诸如JDT和PDE这样的工具,均根据各自的意图使用了这些方法。虽然它们所创建的项目引用作为工作空间的一部分进行管理和/或保存在.project文件中,但在Eclipse平台的其他地方,并不会使用这些项目引用。
2.6 资源
IResource接口是资源模型的顶层接口。除工作空间之外的所有核心资源对象均实现了IResource接口。工作空间并不属于该扩展层次中,但是它却包含在资源模型的逻辑表示中(如图1-1所示)。IResource接口提供对于所有资源均可用的基本功能。使用该层的API,您可以完成如下一些操作:
● 复制、移动或者删除资源(copy、move或delete)。
● 确定资源在工作空间中的位置(getParent、getProject或getFullPath)。
● 判断资源是否存在于工作空间中(exists或isAccessible)。
● 读取资源相关的属性,例如派生属性、只读属性或诸如同步之类的状态属性(表明该资源以及给定深度的后代资源是否与文件系统同步)。
注意:
与创建资源有关的API是与资源类型相关的;这些功能并没有作为通用的IResource API的一部分。
也可以从文件系统中刷新资源。这种刷新方法已经在本章前述部分的“资源模型与文件系统的交互”一节中介绍过了。而这里的IResource.refreshLocal方法可以传递一个深度参数,以指明刷新的对象仅仅是该资源,还是该资源及其成员,或者是该资源及其所有后代资源。在创建资源之前,执行一次刷新操作,可以使您的程序更为简洁,但将刷新强加于用户并不一定合适。因为他们可能在项目中保存文件和文件夹,而这些文件和文件夹不一定包含在工作空间中。外部启动的编辑器也可以在项目资源树中创建临时文件。如果您的程序突然将这些资源加入到工作空间中,可能会造成用户管理工作空间内容的混乱。
有些资源可以标识为派生资源。派生资源是由工具而非用户创建的,它们可以在工具对另一个资源进行处理的过程中被重新创建。对于派生资源,工具可以选择实现特殊的处理过程,例如不将该资源发送到资源档案库中,或者在清除操作中删除所有的派生资源。比如,Java的.class文件是在Java源文件编译的过程中产生的,所以可以标记为派生资源。
如果资源被标记为只读的话,则表示不允许通过工作空间API更改这些资源(但标记为只读的文件夹仍可以向其中添加文件)。编辑器应该不允许修改标记为只读的文件,或者至少当您试图修改只读文件时,应该弹出警告。这时,系统会抛出一个异常。如果文件系统中资源的只读属性被修改了,那么isReadOnly方法会立即返回新的属性,而无需等待工作空间刷新。
2.7 路径
在工作空间API中,路径通常作为方法的参数和返回值使用。路径指的是由标准的分隔符(/)分隔开的一个字符串,该字符串可以以分隔符开头和/或分隔符结尾。驱动器标识符前缀是可有可无的,例如D:或Cork/Data:都是合法的。路径值可以是相对路径,或者是指向资源的绝对位置的引用。
表1-2对不同类型的路径值进行了比较,这里以一个名为a.proj的项目为例,列举了您可以从像aFold这样的文件夹中获取的路径值。
表1-2 路径值
注意:
getLocation与getRawLocation方法的差别是非常微妙的。如Javadoc中所描述的那样:
如果资源是一个已存在的项目,返回的路径将等于项目描述中的位置路径。如果资源是在一个已经打开的项目中的链接资源,返回的路径将等于链接资源创建时的位置路径。其他情况下,getRawLocation与getLocation方法的返回值相同。
惟一值得注意的不同之处是,对于默认位置下(在工作空间目录中)的项目,getRawLocation方法将返回null。
在获取引用或创建资源句柄时,您可以使用路径来定义资源的位置,例如使用getFile(IPath path)或getFolder(IPath path)方法;在复制或移动资源时,您可以将路径作为参数传递;当您查询变量的值,比如资源、工作空间根目录和平台的位置时,路径可以作为返回值。
尽管工作空间API包括IPath接口,但您应该使用Path类的构造方法创建一个新的路径。
IPath myPath = new Path("my/Path/");
IPath myPatLocation = new Path("D:\", "my/Path/");
Path类的构造函数可以接收一个String类型的路径值作为参数,也可以接收两个String类型的值,第一个表示驱动器,第二个表示路径。如果该String类型的路径值的每段(通过分隔符隔开)是有效的,则该路径是有效的。而对于路径中的每段字符,如果它是非空的而且不包含冒号(:),并且不以空格开头或结尾,则该段字符是有效的。如果路径值中包括一个反斜杠(\),它将会被自动转换为正斜杠(/)。
IPath接口所提供的方法,允许您对路径值进行操作。您可以查阅相关的Javadoc或源代码以获取可用方法的更多详细信息。
2.8 文件夹和文件
创建文件夹和创建文件使用的是相同的编程模式:首先,获取资源的句柄,然后判断该资源是否存在,如果不存在,则可以创建该资源。通常,您可以从文件夹或项目中获得一个文件夹或文件的句柄。如果请求的是一个已经存在资源,那么您已经获得一个可以直接使用的资源。如果请求的资源并不存在,那么需要创建该资源。但有一个前提必须满足:该资源的父资源必须是可访问的。
下面的代码根据名称获取项目的一个文件夹,如果该文件夹不存在,则试图创建该文件夹。
private void createFolderInProject(
IProject project, String folderName) {
IFolder newFolder = project.getFolder(folderName);
if (!newFolder.exists()) {
try {
newFolder.create(true, true, null);
} catch (CoreException e) {
// Deal with exception.
}
}
}
在获取句柄、创建文件夹的过程中,文件系统有可能已经具有一个同名的文件夹,或者所给的文件夹名不合法。
当文件系统中包含未被工作空间所感知的资源时,您所设计的创建策略,需要捕获或避免创建错误。对于这一点,Workbench New Folder向导使用了一种混和策略:在处理创建请求之前,先检查文件夹名是否合法,如果文件夹已经存在于文件系统中,则创建失败。
文件的创建及其内容的设定可以通过工作空间API来实现。IFile API支持使用输入流来获取、设定和添加文件的内容,相应的方法如下所示:
● getContents方法:获取文件内容的输入流。
● setContents方法:通过传入一个输入流参数,或者IFileState参数来设定文件的内容。
● appendContents方法:向当前文件的内容追加一个输入流。
下面的代码展示了如何在传入参数所指定的文件夹下创建一个文件。如果文件已经存在,它的内容将被替换。其中的getInitialContents方法用来提供新文件的内容或者替换现有文件的内容。
private void createFi1eInFo1der2(IFo1der folder) {
IFile newFile = folder.getFi1e("new_Fi1e.txt");
try {
if (newFile.exists())
newFile.setContents(
getInitialContents(),
true, false, null);
else {
java.io.Fi1e systemFile =
newFile.getLocation().toFile();
if (systemFile.exists() {
// Skip create -- in file system.
// Could refreshLocal on parent at this point.
} else {
newFile.create(getInitialContents(), false, null);
}
}
} catch (CoreException ce) {
// Failed.
}
}
// Return input stream used to create initial file contents.
private InputStream getInitialContents() {
StringBuffer sb = new StringBuffer();
sb.append("My New File Contents");
return new ByteArrayInputStream(sb.toString().getBytes());
}
这段代码所使用的保证文件可以被创建的方法,已经超出了工作空间API的能力。它通过检查文件系统来判断文件是否已经存在。如果文件已经存在于文件系统中,但不在工作空间中,则跳过该文件的创建和内容设定过程。
2.9 链接资源
资源不一定总是物理存在于项目的文件系统树中。在项目的根目录下,您可以创建链接资源。链接资源指的是一个指向文件夹或文件的引用,而这些文件夹或文件并不物理存在于项目中。链接资源既可以通过New Folder或New File向导创建,也可以利用工作空间API创建。
下面的程序将会在项目中创建一个链接文件夹和一个链接文件。
IPath path = new Path("E:/SharedResources/This");
IFolder folder = project.getFo1der("aFo1der");
if (!folder.exists())
try {
folder.createLink(path,IResource.NONE,nul1);
} catch (CoreException e) {
e.printStackTrace();
}
path = new Path("E:/SharedResources/That.txt");
IFile file = project.getFi1e("aFi1e.txt");
if (!file.exists())
try {
fi1e.createLink(path,IResource.ALLOW_MISSING_LOCAL,nul1);
} catch (CoreException e) {
e.printStackTrace();
}
createLink方法包含一个ALLOW_MISSING_LOCAL参数,该参数表明当欲链接的目标文件不存在时,仍允许创建该链接文件。这一选项同样适用于文件夹。
如果您正在操作链接资源,也许需要考虑一些特殊的处理选项。如果请求一个复制或移动操作,您可以使用IResource.SHALLOW参数指明,复制的是链接,而非所链接的资源。同样,您也可以通过isLinked方法询问资源是否是一个链接资源。
如果一个文件夹或文件在工作空间中被其他资源链接,您可以通过IWorkspaceRoot来查找这些链接的位置。您只需要将一个绝对路径(e:\folderName或e:\folder\fileName.txt)作为findContainersForLocation方法或findFilesForLocation方法的IPath参数传入。将一个文件夹的IPath参数传入findContainersForLocation方法中,可以返回一个容器数组,其中每个容器中均链接了该文件夹。而将一个文件的IPath参数传入findContainersForLocation方法中,也可以返回一个容器数组,其中每个容器中均链接了该文件。这些方法对于非链接的资源也有效,但是返回的结果意义不大;这与getParent方法的情形是一样的。
2.10 访问资源树中的资源
当您需要查找一个项目、文件夹甚至整个工作空间中的所有资源时,您可以使用工作空间API中的IResourceVisitor或IResourceProxyVisitor接口。通过这些接口,您可以对资源树上的某个节点进行操作,而且可以访问该节点的所有子节点。
为了操作资源树中给定节点的所有元素,您可以定义一个实现IResourceVisitor或IResourceProxyVisitor接口的类。这两个接口均只定义了一个方法,即visit方法。在您处理资源树中每个元素以及子元素时,需要调用该visit方法。
这两个接口之间的差别并不复杂:IResourceVisitor只需给定一个要处理的IResource资源实例,而IResourceProxyVisitor则要给定一个真实的IResourceProxy实例。该IResourceProxy实例允许您对诸如名称、类型之类的属性进行检查,但其开销要远小于创建一个真实的IResource实例。这样,可以大大减少处理资源树的开销。IResourceProxy的属性可以帮助您决定是继续访问下一个代理对象,还是需要一个真实的IResource实例。如果需要真实的资源,只需调用IResourceProxy.requestResource方法即可。
您可以向IResource.accept方法传入感兴趣的资源节点的IResourceVisitor或IResourceProxyVisitor实例,来处理资源树。accept方法存在多种签名,除了访问者参数,其他参数可以用来指导如何处理访问者。
下面的程序展示了IResourceVisitor接口的一种简单实现。IResourceProxyVisitor接口的实现几乎完全一样,惟一的区别在于传入给visit方法的参数类型不同。
private void visitResourceTree(IResource resource) {
IResourceVisitor visitor = new IResourceVisitor() {
public boolean visit(IResource res) {
// Process the resource.
// ... Your logic here ...
// By returning true, you are saying you want
// to process the children.
return true;
};
};
try {
resource.accept(visitor);
} catch (CoreException e) {
// Problem during visit processing.
}
}
当您希望处理工作空间中的所有或者部分内容时,您可以实现IResourceVisitor或IResourceProxyVisitor接口。访问者的基本功能就是允许您沿着工作空间资源树“行走”。它所返回的boolean值将指导访问者架构继续访问当前资源的子节点。
注意:
工作空间API还包含一个IResourceDeltaVisitor接口。该接口支持处理作为IResourceDelta的一部分所提供的资源树。
--------------------
说明:
参考资料来源--《Eclipse 权威开发指南(第2版)》
这是一本译著,原名《The Java Developer’s Guide to Eclipse》 2nd Edition, 这本还是比较全面和深入的讲解了Eclipse开发中的各个部分的感念和原理的,不适合入门,做过一段时间的开发后阅读比较好。
本节将重点介绍工作空间API和编程模式的关键部分。在您对资源进行操作时,这部分内容会非常有用。
工作空间API的全面描述位于org.eclipse.core.resources包的Javadoc中,您可以在Eclipse帮助系统中的Platform Plug-in Developer Guide一节中找到。
2.1 工作空间和工作空间根目录
当启动Eclipse时,您访问的是单个工作空间。为了在插件代码中访问工作空间,需要获取当前工作空间的引用。为此,可以通过访问org.eclipse.core.resources插件的插件类,来获取如下的工作空间。
IWorkspace myWorkspace =
org.eclipse.core.resources.ResourcesPlugin.getWorkspace();
一旦获得了工作空间的引用,您就可以添加资源更改侦听器,添加保存参与者以及导航至IWorkspaceRoot。
myWorkspace.getRoot();
下面列出了IWorkspace API中的一些值得注意的方法:
● getDescription返回工作空间的描述。这些描述可以用来获取或者更改与工作空间相关的设置,例如工作空间中的项目按照何种顺序构建,资源发生更改时构建过程是否自动执行。其中许多设置与Preferences对话框的Workbench页面中的选项相对应。
● validateName(name,type)返回一个IStatus对象,该方法将验证传入的名称对于指定的资源类别是否合法。
● addResourceChangeListener(…)用于向工作空间添加通用或者特定变化事件的侦听器。
● addSaveParticipant(…)注册一个保存参与者类,该类负责对由传入参数中所指定的插件的工作空间保存事件进行处理。
名称验证过程由validateName方法提供,它执行必要的测试以验证名称对于指定的资源类型是否合法。只有当资源真正被创建时,才会进行名称的验证过程,而创建一个资源句柄时,并不会进行名称验证。如果您想在实际创建资源之前,验证名称是否合法,请使用validateName方法。
通常您可以简单地获取工作空间引用,然后使用getRoot方法得到工作空间根目录;从根目录开始,您可以移动到资源模型的其他区域,例如查找特定的项目、添加/修改资源以及在资源树中查找与工具相关的内容。
工作空间根目录是项目的容器,因此,也是所有资源的容器。工作空间根目录实现了IContainer接口。项目和文件夹也实现了该接口。尽管如此,工作空间根目录只能包含项目。而项目和文件夹可以包含文件夹和文件。工作空间根目录并没有在Navigator视图中显示出来,但您可以通过项目获取其父结点(getParent),得到工作空间根目录。显然,对于getParent方法,工作空间根目录将返回null。
您可能会指出默认的工作空间目录名应该是workspaceroot。虽然存在一个与工作空间对应的接口(IWorkspace),但是这个接口并没有扩展IResource接口。不要被IWorkspace和IWorkspaceRoot两个接口在结构上的差别和它们所扮演的角色弄糊涂。只需记住一切资源都存在于工作空间中,而您的代码应该总是借助于工作空间API来创建、访问和修改资源。如果您直接向文件系统写文件,然后再通过工作空间刷新来保持工作空间与文件系统的同步,这样会大大削弱了工作空间API的能力。不仅如此,在未同步期间,任何资源变化侦听器或者构建器将无法收到通知,直到文件系统与工作空间同步为止,而且您将无法选择在资源更改的同时,把变化记录在本地的历史记录中。当工作空间文件发生更改时,内置于工作空间API的本地历史记录必须进行相应的更新;而直接对文件系统进行的修改不会被本地历史记录所捕获。
注意:
在胖客户端平台应用程序中,工作空间目录仍然存在。在不考虑-data调用选项所指定的工作空间目录名称的情况下,工作空间目录扮演两种角色。一种是作为.metadata目录的父目录,另一种是作为项目的默认位置。只有当配置中包含了org.eclipse.core.resources插件,并且由Workbench正确地启动,工作空间才可以包含项目。这一步对于基于org.eclipse.ui.ide.workbench应用程序的IDE配置来说是自动完成的。
2.2 资源容器
一旦获得工作空间根目录,就可以很容易地访问工作空间内的其他资源。每种资源类型均提供了各种访问资源的方法,包括操纵资源树、获取资源的句柄(无论资源是否存在),以及查找特定的资源实例。
对于那些包含子资源的资源来说,IContainer接口是一个通用的编程接口。这里的容器包括工作空间根目录、项目和文件夹。表1-1列出了资源模型接口及其方法。这些方法可以用来导航资源,一直到资源树中某个文件的内容。
表1-1 资源模型导航
出 发 点 | 方 法 | 方 法 描 述 |
IWorkspaceRoot | getProjects() | 获取工作空间中所有项目组成的数组,无论项目在工作空间中处于打开还是关闭状态 |
getProject(“project_name”) | 获取指定项目的句柄,该项目可能不存在 | |
IProject | getReferencedProjects() | 获取该项目所引用的所有项目组成的数组,引用是通过项目描述设定的 |
getReferencingProjects() | 获取处于打开状态并且引用了当前项目的项目组成的数组 | |
getFolder(“fold_name”) | 返回指定文件夹的句柄,该文件夹可能不存在 | |
getFile(“file_name”) | 返回指定文件的句柄,该文件可能不存在 | |
IFolder | getFile(“file_name”) | 返回指定文件的句柄,该文件可能不存在 |
IFile | getContents() | 获取包含当前文件内容的输入流。该方法存在多种签名 |
setContents(InputStream,…) | 使用传入的输入流设置文件的内容。该方法存在多种签名 | |
IResource | getParent() | 获取当前资源的父资源,对于工作空间根目录,将返回null |
getProject() | 返回管理该资源的项目 | |
getWorkspace() | 返回工作空间 | |
findMarkers() | 返回该资源的指定类型的所有标记,如果需要,也可以返回资源的子资源的标记 | |
IContainer | members() | 返回容器内所有资源组成的数组,但不包含这些资源的子资源。对于工作空间根目录,返回的数组只包含项目 |
getFolder(“folder_name”) | 返回指定文件夹的句柄。该文件夹可能不存在 | |
getFile(“file_name”) | 返回指定文件的句柄。该文件可能不存在 | |
findMember(“member_name”) | ||
findMember(“IPath”) | 返回指定的成员,成员不存在时返回null |
2.3 工作空间资源句柄
工作空间容器提供了各式各样的getter方法来通过名称请求资源。它们都是句柄方法,这些方法将返回工作空间资源的句柄。但是,它们并不能保证在工作空间中一定存在该资源。您可以请求句柄来获取一个可能存在的资源,或者也可以以此作为创建新资源的第一步。
findXxxx方法可以查明资源是否实际存在于工作空间中;当工作空间无法感知到该资源时,将返回null。但这仍然没有告诉您该资源是否存在于文件系统中而尚未被工作空间感知。
您需要了解资源的两个层面:工作空间和文件系统。您可以获取工作空间资源的句柄,并且测试这些资源是否真正存在于工作空间中,但是文件系统状态却是独立的。文件系统中存在的资源可能在工作空间中并不存在;而工作空间中的资源也可能不在文件系统中。为了避免冲突,您可以询问资源是否与文件系统同步,或者自己检查文件系统的状态。许多工作空间API方法也会向您询问如何处理同步问题——您可以选择终止同步或让同步过程继续下去。
通过使用isSynchronized方法,您既可以查询一个资源的同步信息,也可以查询该资源的成员以及该资源的所有子资源的同步信息。下面的示例代码演示了如何查询一个文件夹及其成员是否已经同步。
bool inSync=
folder.isSynchronized(IResource.DEPTH_ONE);
其他有关深度的选项是DEPTH_ZERO和DEPTH_INFINITE,这些选项在调用isSynchronized和refreshLocal等方法中会用到。
2.4 项目
创建一个项目需要进行以下操作:首先需要从工作空间根目录中获取该项目的句柄;然后创建一个项目描述,该项目描述中包含路径的描述以确定项目在文件系统中的位置;最后创建并打开该项目。下面这个例子所展示的程序,实现了在目录d:\workspacehome\new_Project下创建一个名为new_Project的项目。
private void createProject() {
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
IProject newProjectHandle = root.getProject("new_Project");
// Get a project descriptor.
IPath targetPath = new Path("d:/workspacehome/"
+ newProjectHandle.getName());
final IProjectDescription description =
workspace.newProjectDescription(newProjectHandle.getName());
description.setLocation(targetPath);
try {
newProjectHandle.create(descriptior), null);
newProjectHandle.open(null);
} catch (CoreException e) {
// Deal with exception.
}
如果项目描述中的路径值为null,则项目会被创建在默认的位置(工作空间目录)。通常情况下,项目都是通过New Resource向导来创建的。在配套光盘上的资源编程解决方案中,包含了一个New Project向导,通过它可以创建带有指定性质的项目。
下面所列的是IProject接口中有关项目操作的关键方法。
● isOpen方法:当项目处于打开状态时,返回true;即使项目处于关闭状态,所有项目仍存在于工作空间中,所以您需要检查项目所处的状态。
● getDescription方法:返回项目的IProjectDescription对象。
● getNature(…)方法:返回指定的项目性质,当项目中没有添加该项目性质时,返回null。
● hasNature(…)方法:判断由性质扩展id指定的项目性质是否已经添加到该项目中。
● isNatureEnabled(…)方法:当由性质扩展标识符指定的项目性质被激活时,返回true。可能存在与性质定义相冲突的地方,从而强制终止性质。
以上方法中,某些方法是非常方便的,而大部分方法的处理过程中都涉及到项目描述。
工作空间也支持创建一个与项目相关的状态目录。不同于插件的状态目录,项目状态目录直接与项目相关,也直接与需要该项目状态目录支持的插件相关。您可以调用getWorkingLocation方法获取指定插件的项目状态目录的路径值。下面的代码展示了该方法的一次调用,并且返回了相应的路径值。
IPath path =
project.getWorkingLocation("plugin.id");
E:/workspace/.metadata/.plugins/
org.ec1ipse.core.resources/.projects/q.r.s/plugin.id
2.5 项目描述
项目在文件系统中以文件夹的形式存在,它在资源模型中具有Eclipse特有的行为,这些行为展示了项目的功能。项目借助于项目描述来管理这些信息。通过项目描述,一个项目可以与一个或更多性质以及构建器相关联,并且可以维持指向其他项目的引用(参见图1-4)。
图1-4 项目描述:对性质、构建器和项目引用进行管理
项目描述的用途在于记录项目的重要信息。在Eclipse中,与项目描述有关的API由IProjectDescription接口定义,而项目描述本身在工作空间中则是一个文件。对于每个项目,都存在一个项目描述文件.project,它由资源插件负责管理。下面的例子展示了一个插件开发项目的.project文件的内容。
<?xm1 version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.ibm.too1.resources</name>
<comment> </comment>
<projects> </projects>
<bui1dSpec>
<bui1dCommand>
<name>org.eclipse.jdt.core.javabui1der</name>
<arguments> </arguments>
</bui1dCommand>
<bui1dCommand>
<name>org.ec1ipse.pde.ManifestBuilder</name>
<arguments> </arguments>
</bui1dCommand>
<buildCommand>
<name>org.ec1ipse.pde.SchemaBui1der</name>
<arguments> </arguments>
</bui1dCommand>
</bui1dSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.ec1ipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
将关于项目的信息保存为项目文件夹下的一个文件,我们可以把它存储在一个资源库中。但如果该类信息作为资源属性存储,它将保存在当前工作空间的.metadata文件夹中,从而无法保存在资源库中。如果您的工具要求关于项目的信息在团队成员内部共享,应该考虑将它保存为一个文件,并存储在资源库中,或者使用用户设置API。
您可以在项目描述中添加性质和构建器,使之与项目关联起来。使用下面的方法,可以获得项目的性质列表。
String[] natures = project.getDescription().getNatureIds();
每个项目都需要定义它的构建命令,而且每个命令都知道构建器的名称。您可以获取所有的构建命令(description.getBuildSpec),然后可以从每个命令中获取构建器的名称(command.getBuilderName)。
注意:
尽管项目的构建器和性质存储在一个文件中,但您最好不要直接编辑该文件,修改这些信息。因为,直接向该文件添加一个性质,并不会触发Eclipse对该性质进行配置。所以,性质和构建器只能作为工具功能的一部分进行添加或删除。
您可以通过两种方式引用其他项目:使用用户界面中的项目属性页,或者使用IProjectDescription API。使用用户界面,您可以创建简单的项目引用,而IProjectDescription API则不仅允许创建同样简单的项目引用,而且可以存储一个动态计算的项目引用集。
只有简单的项目引用才会保存在.project文件中。下面是一个存储了项目引用的.project文件,这里只显示项目引用部分的内容。
<projects>
<project>com.ibm.tool.core</project>
<project>com.ibm.tool.common</project>
</projects>
从项目出发,通过使用如下的API调用,您既可以获得它所引用的项目,也可以获得引用了它的项目。
project.getReferencedProjects();
project.getReferencingProjects();
引用当前项目的项目不会存储在.project文件中,但是可以通过访问工作空间资源模型来确定哪些项目引用了当前项目。
IProjectDescription API也支持创建和访问动态引用的项目集。这些项目是在运行时定义的,这些定义并没有保存在.project文件中,而是保存在工作空间的元数据中。不同于简单的项目引用,动态引用不显示在用户界面中,惟一的相关记录保存在工作空间的元数据中。既然这些引用对于用户是不可见的,而且无法直接修改,您就可以把动态项目引用称为“粘滞引用”。由于这些引用不会发送到资源库中,所以当项目检出时,它们也需要重新计算。
下面的代码片段展示了如何利用IProjectDescription接口定义和获取一个动态引用的项目集。
// Calculate project array and define as dynamic
// project references.
IProject[] projects =
CalculateToolSpecificProjectSet();
Project.getDescription().setDynamicReferences (projects);
您可以根据需要来使用这些不同的项目引用方法。诸如JDT和PDE这样的工具,均根据各自的意图使用了这些方法。虽然它们所创建的项目引用作为工作空间的一部分进行管理和/或保存在.project文件中,但在Eclipse平台的其他地方,并不会使用这些项目引用。
2.6 资源
IResource接口是资源模型的顶层接口。除工作空间之外的所有核心资源对象均实现了IResource接口。工作空间并不属于该扩展层次中,但是它却包含在资源模型的逻辑表示中(如图1-1所示)。IResource接口提供对于所有资源均可用的基本功能。使用该层的API,您可以完成如下一些操作:
● 复制、移动或者删除资源(copy、move或delete)。
● 确定资源在工作空间中的位置(getParent、getProject或getFullPath)。
● 判断资源是否存在于工作空间中(exists或isAccessible)。
● 读取资源相关的属性,例如派生属性、只读属性或诸如同步之类的状态属性(表明该资源以及给定深度的后代资源是否与文件系统同步)。
注意:
与创建资源有关的API是与资源类型相关的;这些功能并没有作为通用的IResource API的一部分。
也可以从文件系统中刷新资源。这种刷新方法已经在本章前述部分的“资源模型与文件系统的交互”一节中介绍过了。而这里的IResource.refreshLocal方法可以传递一个深度参数,以指明刷新的对象仅仅是该资源,还是该资源及其成员,或者是该资源及其所有后代资源。在创建资源之前,执行一次刷新操作,可以使您的程序更为简洁,但将刷新强加于用户并不一定合适。因为他们可能在项目中保存文件和文件夹,而这些文件和文件夹不一定包含在工作空间中。外部启动的编辑器也可以在项目资源树中创建临时文件。如果您的程序突然将这些资源加入到工作空间中,可能会造成用户管理工作空间内容的混乱。
有些资源可以标识为派生资源。派生资源是由工具而非用户创建的,它们可以在工具对另一个资源进行处理的过程中被重新创建。对于派生资源,工具可以选择实现特殊的处理过程,例如不将该资源发送到资源档案库中,或者在清除操作中删除所有的派生资源。比如,Java的.class文件是在Java源文件编译的过程中产生的,所以可以标记为派生资源。
如果资源被标记为只读的话,则表示不允许通过工作空间API更改这些资源(但标记为只读的文件夹仍可以向其中添加文件)。编辑器应该不允许修改标记为只读的文件,或者至少当您试图修改只读文件时,应该弹出警告。这时,系统会抛出一个异常。如果文件系统中资源的只读属性被修改了,那么isReadOnly方法会立即返回新的属性,而无需等待工作空间刷新。
2.7 路径
在工作空间API中,路径通常作为方法的参数和返回值使用。路径指的是由标准的分隔符(/)分隔开的一个字符串,该字符串可以以分隔符开头和/或分隔符结尾。驱动器标识符前缀是可有可无的,例如D:或Cork/Data:都是合法的。路径值可以是相对路径,或者是指向资源的绝对位置的引用。
表1-2对不同类型的路径值进行了比较,这里以一个名为a.proj的项目为例,列举了您可以从像aFold这样的文件夹中获取的路径值。
表1-2 路径值
路 径 类 型 | 方 法 | 值 |
相对于工作空间位置 | IResource.getFullPath() | /a.proj/aFold |
相对于项目 | IResource.getProjectRelativePath() | aFold |
文件系统中的物理位置 | IResource.getLocation() | e:/eclipse/workspace/a.proj/aFold |
文件系统中的原始物理位置 | IResource.getRawLocation() | e:/eclipse/workspace/a.proj/aFold |
注意:
getLocation与getRawLocation方法的差别是非常微妙的。如Javadoc中所描述的那样:
如果资源是一个已存在的项目,返回的路径将等于项目描述中的位置路径。如果资源是在一个已经打开的项目中的链接资源,返回的路径将等于链接资源创建时的位置路径。其他情况下,getRawLocation与getLocation方法的返回值相同。
惟一值得注意的不同之处是,对于默认位置下(在工作空间目录中)的项目,getRawLocation方法将返回null。
在获取引用或创建资源句柄时,您可以使用路径来定义资源的位置,例如使用getFile(IPath path)或getFolder(IPath path)方法;在复制或移动资源时,您可以将路径作为参数传递;当您查询变量的值,比如资源、工作空间根目录和平台的位置时,路径可以作为返回值。
尽管工作空间API包括IPath接口,但您应该使用Path类的构造方法创建一个新的路径。
IPath myPath = new Path("my/Path/");
IPath myPatLocation = new Path("D:\", "my/Path/");
Path类的构造函数可以接收一个String类型的路径值作为参数,也可以接收两个String类型的值,第一个表示驱动器,第二个表示路径。如果该String类型的路径值的每段(通过分隔符隔开)是有效的,则该路径是有效的。而对于路径中的每段字符,如果它是非空的而且不包含冒号(:),并且不以空格开头或结尾,则该段字符是有效的。如果路径值中包括一个反斜杠(\),它将会被自动转换为正斜杠(/)。
IPath接口所提供的方法,允许您对路径值进行操作。您可以查阅相关的Javadoc或源代码以获取可用方法的更多详细信息。
2.8 文件夹和文件
创建文件夹和创建文件使用的是相同的编程模式:首先,获取资源的句柄,然后判断该资源是否存在,如果不存在,则可以创建该资源。通常,您可以从文件夹或项目中获得一个文件夹或文件的句柄。如果请求的是一个已经存在资源,那么您已经获得一个可以直接使用的资源。如果请求的资源并不存在,那么需要创建该资源。但有一个前提必须满足:该资源的父资源必须是可访问的。
下面的代码根据名称获取项目的一个文件夹,如果该文件夹不存在,则试图创建该文件夹。
private void createFolderInProject(
IProject project, String folderName) {
IFolder newFolder = project.getFolder(folderName);
if (!newFolder.exists()) {
try {
newFolder.create(true, true, null);
} catch (CoreException e) {
// Deal with exception.
}
}
}
在获取句柄、创建文件夹的过程中,文件系统有可能已经具有一个同名的文件夹,或者所给的文件夹名不合法。
当文件系统中包含未被工作空间所感知的资源时,您所设计的创建策略,需要捕获或避免创建错误。对于这一点,Workbench New Folder向导使用了一种混和策略:在处理创建请求之前,先检查文件夹名是否合法,如果文件夹已经存在于文件系统中,则创建失败。
文件的创建及其内容的设定可以通过工作空间API来实现。IFile API支持使用输入流来获取、设定和添加文件的内容,相应的方法如下所示:
● getContents方法:获取文件内容的输入流。
● setContents方法:通过传入一个输入流参数,或者IFileState参数来设定文件的内容。
● appendContents方法:向当前文件的内容追加一个输入流。
下面的代码展示了如何在传入参数所指定的文件夹下创建一个文件。如果文件已经存在,它的内容将被替换。其中的getInitialContents方法用来提供新文件的内容或者替换现有文件的内容。
private void createFi1eInFo1der2(IFo1der folder) {
IFile newFile = folder.getFi1e("new_Fi1e.txt");
try {
if (newFile.exists())
newFile.setContents(
getInitialContents(),
true, false, null);
else {
java.io.Fi1e systemFile =
newFile.getLocation().toFile();
if (systemFile.exists() {
// Skip create -- in file system.
// Could refreshLocal on parent at this point.
} else {
newFile.create(getInitialContents(), false, null);
}
}
} catch (CoreException ce) {
// Failed.
}
}
// Return input stream used to create initial file contents.
private InputStream getInitialContents() {
StringBuffer sb = new StringBuffer();
sb.append("My New File Contents");
return new ByteArrayInputStream(sb.toString().getBytes());
}
这段代码所使用的保证文件可以被创建的方法,已经超出了工作空间API的能力。它通过检查文件系统来判断文件是否已经存在。如果文件已经存在于文件系统中,但不在工作空间中,则跳过该文件的创建和内容设定过程。
2.9 链接资源
资源不一定总是物理存在于项目的文件系统树中。在项目的根目录下,您可以创建链接资源。链接资源指的是一个指向文件夹或文件的引用,而这些文件夹或文件并不物理存在于项目中。链接资源既可以通过New Folder或New File向导创建,也可以利用工作空间API创建。
下面的程序将会在项目中创建一个链接文件夹和一个链接文件。
IPath path = new Path("E:/SharedResources/This");
IFolder folder = project.getFo1der("aFo1der");
if (!folder.exists())
try {
folder.createLink(path,IResource.NONE,nul1);
} catch (CoreException e) {
e.printStackTrace();
}
path = new Path("E:/SharedResources/That.txt");
IFile file = project.getFi1e("aFi1e.txt");
if (!file.exists())
try {
fi1e.createLink(path,IResource.ALLOW_MISSING_LOCAL,nul1);
} catch (CoreException e) {
e.printStackTrace();
}
createLink方法包含一个ALLOW_MISSING_LOCAL参数,该参数表明当欲链接的目标文件不存在时,仍允许创建该链接文件。这一选项同样适用于文件夹。
如果您正在操作链接资源,也许需要考虑一些特殊的处理选项。如果请求一个复制或移动操作,您可以使用IResource.SHALLOW参数指明,复制的是链接,而非所链接的资源。同样,您也可以通过isLinked方法询问资源是否是一个链接资源。
如果一个文件夹或文件在工作空间中被其他资源链接,您可以通过IWorkspaceRoot来查找这些链接的位置。您只需要将一个绝对路径(e:\folderName或e:\folder\fileName.txt)作为findContainersForLocation方法或findFilesForLocation方法的IPath参数传入。将一个文件夹的IPath参数传入findContainersForLocation方法中,可以返回一个容器数组,其中每个容器中均链接了该文件夹。而将一个文件的IPath参数传入findContainersForLocation方法中,也可以返回一个容器数组,其中每个容器中均链接了该文件。这些方法对于非链接的资源也有效,但是返回的结果意义不大;这与getParent方法的情形是一样的。
2.10 访问资源树中的资源
当您需要查找一个项目、文件夹甚至整个工作空间中的所有资源时,您可以使用工作空间API中的IResourceVisitor或IResourceProxyVisitor接口。通过这些接口,您可以对资源树上的某个节点进行操作,而且可以访问该节点的所有子节点。
为了操作资源树中给定节点的所有元素,您可以定义一个实现IResourceVisitor或IResourceProxyVisitor接口的类。这两个接口均只定义了一个方法,即visit方法。在您处理资源树中每个元素以及子元素时,需要调用该visit方法。
这两个接口之间的差别并不复杂:IResourceVisitor只需给定一个要处理的IResource资源实例,而IResourceProxyVisitor则要给定一个真实的IResourceProxy实例。该IResourceProxy实例允许您对诸如名称、类型之类的属性进行检查,但其开销要远小于创建一个真实的IResource实例。这样,可以大大减少处理资源树的开销。IResourceProxy的属性可以帮助您决定是继续访问下一个代理对象,还是需要一个真实的IResource实例。如果需要真实的资源,只需调用IResourceProxy.requestResource方法即可。
您可以向IResource.accept方法传入感兴趣的资源节点的IResourceVisitor或IResourceProxyVisitor实例,来处理资源树。accept方法存在多种签名,除了访问者参数,其他参数可以用来指导如何处理访问者。
下面的程序展示了IResourceVisitor接口的一种简单实现。IResourceProxyVisitor接口的实现几乎完全一样,惟一的区别在于传入给visit方法的参数类型不同。
private void visitResourceTree(IResource resource) {
IResourceVisitor visitor = new IResourceVisitor() {
public boolean visit(IResource res) {
// Process the resource.
// ... Your logic here ...
// By returning true, you are saying you want
// to process the children.
return true;
};
};
try {
resource.accept(visitor);
} catch (CoreException e) {
// Problem during visit processing.
}
}
当您希望处理工作空间中的所有或者部分内容时,您可以实现IResourceVisitor或IResourceProxyVisitor接口。访问者的基本功能就是允许您沿着工作空间资源树“行走”。它所返回的boolean值将指导访问者架构继续访问当前资源的子节点。
注意:
工作空间API还包含一个IResourceDeltaVisitor接口。该接口支持处理作为IResourceDelta的一部分所提供的资源树。
--------------------
说明:
参考资料来源--《Eclipse 权威开发指南(第2版)》
这是一本译著,原名《The Java Developer’s Guide to Eclipse》 2nd Edition, 这本还是比较全面和深入的讲解了Eclipse开发中的各个部分的感念和原理的,不适合入门,做过一段时间的开发后阅读比较好。
发表评论
-
再说SWT中的滚动面板ScrolledComposite实现
2013-06-19 15:43 2328记得以前写过一篇关于滚动面板的文章 SWT中 Scrolle ... -
OSGi参考资料
2013-04-18 01:11 681基于 OSGi 的面向服务的组件编程 探索 OSGi 框架的组 ... -
CDT(编辑、调试)参考资料
2013-04-17 02:15 1112CDT编辑器 --------- 构建基于 CDT 的编辑器, ... -
Workspace Resource框架专题(3)处理工作空间资源更改事件
2013-04-17 01:44 13793 处理工作空间资源更改事件 工作空间API允许工具对它 ... -
Workspace Resource框架专题(1)Resource的概念
2013-04-17 01:12 13891 Resource的概念 如 ... -
如何恢复断点及Marker
2013-03-05 00:41 0如何恢复断点及Marker -
深入Workbench框架
2013-03-01 02:10 1720深入Workbench框架(结合UIPersistent) 1 ... -
Eclipse插件开发中的Action
2013-02-24 23:10 2004插入点用来定义菜单出 ... -
Eclipse开发中编辑器(Editors)和视图(View)总结
2013-02-24 22:58 29081.视图(Views) 视图( ... -
SWT/JFace专题 --- 对话框向导(Dialogs Wizards)
2013-02-24 22:42 2229对话框向导(Dialogs Wizar ... -
SWT/JFace专题 --- JFace
2013-02-24 22:37 1634JFace JFace是基于SWT的一套图形工具包,它没有为 ... -
SWT/JFace专题 --- SWT中Display和多线程
2013-02-24 15:25 3235Display 1.Display 的创建 一个SWT程序 ... -
SWT/JFace专题 --- SWT API 结构
2013-02-23 18:31 1077SWT API 结构 1.布局类(l ... -
Eclipse启动过程(源码级剖析)
2013-02-20 03:24 3418双击eclipse安装目录下的eclipse.exe运行后,会 ... -
SWT/JFace专题 --- SWT结构浅析
2013-02-23 17:02 1023SWT技术是一套基于Java的 ... -
Eclipse平台体系结构
2013-02-21 23:56 18911.Eclipse平台体系结构 1 ... -
RCP平台架构
2013-02-23 14:11 1480RCP 富客户端通常是指具有独立用户界面的客户端程序。富客户 ... -
Ant构建脚本相关
2013-02-18 01:26 0Ant构建脚本相关 -
CDT源码架构研究
2013-02-18 01:24 0CDT源码架构研究 -
SWT/JFace专题 --- SWT/JFace概述
2013-02-23 16:59 864SWT(Standerd Widget Toolkit,标准图 ...
相关推荐
2. 对于未显示的文件夹,右键点击项目,选择`Properties` -> `Resource` -> `Linked Resources`,将`COCOS2DX`替换为Cocos2d-x的实际路径,例如`F:\cocos2d-x-2.2.3\cocos2d-x-2.2.3`。 3. 修改`Build Command`为NDK...
它提供了处理RDF(Resource Description Framework)、RDFS(RDF Schema)和OWL(Web Ontology Language)数据的工具和API,是Java开发人员在处理知识图谱和本体工程时的重要选择。"jena-workspace"看起来像是一个...
2. 加载CAA提供的模块:通过CAA Workspace -> Locate Prerequisite Workspaces,添加CATIA安装目录下的B18目录,加载完成后如果没有错误提示,表示加载成功。 3. 创建模块:File -> Add CAA V5 Project -> New ...
2. StdAfx.cpp:这是预编译头文件的源代码,通常用于包含常用库和宏定义,以减少编译时间。 3. Rasdetectcodeguru.dsp 和 Rasdetectcodeguru.dsw:这两个是Visual Studio的老式项目文件,用于存储项目设置、编译...
在Windows SDK中,开发者可以直接使用C或C++语言来编写系统级别的应用程序,而不依赖于特定的编程框架,如Microsoft Visual C++的MFC或.NET Framework。这使得程序更轻量级,同时对系统资源的控制更加精细。 描述中...
<Resource name="jdbc/test2" auth="Container" factory="org.objectweb.jndi.DataSourceFactory" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/...
- `MenuXPApp.dsp`和`MenuXPApp.dsw`:这是两个Visual Studio的工程文件,`.dsp`文件是基于MSBuild的项目文件,而`.dsw`文件则是旧版的Workspace文件,它们包含了项目的配置信息,如编译器设置、依赖库等,用于在...
学习这个源码可以帮助理解MFC框架如何与Windows API协同工作来实现图形界面和数据可视化。同时,它也提供了实践C++面向对象编程、事件驱动编程以及Windows程序设计的实例。对于想要提升MFC和Windows应用开发技能的...
5. **MFC应用框架**:这个项目使用了MFC库,它是C++对Windows API的封装,提供了面向对象的编程模型,简化了Windows程序的开发。 以上就是这个压缩包中的文件所涉及的Visual C++和USB设备检测的知识点。通过理解...
1. **MFC框架**:VC++的MFC库提供了一套面向对象的API,使得开发者可以快速构建Windows应用程序。在这个计算器项目中,MFC被用来创建对话框,处理用户输入,以及实现图形用户界面。 2. **对话框设计**:计算器的...
- **封装 Windows API**: MFC 对复杂的 Windows API 进行了抽象和封装,使得开发人员可以更高效地编写代码。 - **类层次结构清晰**: MFC 提供了一套丰富的类层次结构,便于开发人员理解和使用。 - **文档/视图架构**...
MFC框架是Visual C++的一个重要组成部分,它为开发者提供了丰富的类库和API接口,极大地简化了Windows应用程序的开发过程。MFC框架主要由以下几个方面组成: - **基础类**:如CObject、CPoint等,它们是MFC的基础。...
2. **串口API**:在Windows环境下,通常是使用WinAPI的`CreateFile`、`DCB`结构体、`SetCommState`、`ReadFile`和`WriteFile`等函数来操作串口。 3. **MFC串口通信**:了解MFC框架下如何创建串口对象,使用`CSerial`...
为了更好地理解和开发Eclipse插件,你需要熟悉Eclipse的生命周期、扩展点机制、SWT/JFace(用于创建用户界面)以及PDE提供的各种工具和API。同时,学习如何使用Eclipse的插件架构来实现自定义的IDE特性,如新的编辑...
2. **数据库API**:为了访问SQL数据库,通常会使用ODBC(Open Database Connectivity)或ADO(ActiveX Data Objects)。ODBC是微软提供的数据库接口,允许程序通过统一的方式与多种数据库系统交互。ADO是更高级的...
3. **WinMain.dsw**:这是一个Visual Studio workspace文件,包含了项目的配置信息,如源文件、编译设置等。开发者可以使用这个文件在Visual Studio环境中打开并继续开发项目。 4. **resource.h**:资源头文件,...
Eclipse是一个开放源码的软件开发平台,它包含了一个核心框架,允许开发者创建、集成和运行应用程序。Eclipse最初由IBM开发,后来成为了一个社区驱动的项目。该IDE支持多种编程语言,如Java、C++、Python等,并通过...