Eclipse资源管理(一)
基本概念
Eclipse开发平台提供资源插件(org.eclipse.core.resources),插件提供对项目(Project)、文件(File)、文件夹(Folder)的相关管理和操作。
工作区(workspace)是用户数据文件在平台中的组织和保存区,工作区中的文件通过资源的概念进行组织。工作台(Workbench)可以理解为用户浏览和操作工作区的一个工具。资源插件提供创建、导航、操作工作区中资源的API。工作台利用这些API提供对应功能给用户,这些API也允许用户进行扩展。
资源有三种类型:项目(Project)、文件(File)、文件夹(Folder)。项目中包含若干个文件和文件夹,作为一个表示特殊区域的资源单元和容器,项目之间不可嵌套。工作区中有若干个项目。文件和文件夹的概念和OS中的概念类似。
工作区中的资源以资源树的形式进行组织,文件和文件夹都是项目的后代结点。定义了一个工作区根作为一类特殊的资源存在,作为资源树的根节点。
资源的访问
在开发平台中,工作区由IWorkspace的实例进行表示,IWorkspace提供对工作区中的资源访问接口。具体的,通过如下语句获取工作区实例:
IWorkspace workspace = ResourcesPlugin.getWorkspace();
在文件系统中,工作区与一般的文件夹结构一致。但包含有两类隐藏文件(夹),.metadata存放于工作区根位置,是一个文件夹,文件夹中保存包含有工作区结构的信息文件,在开发平台中必须通过特殊的插件API进行访问;.project则存在于项目节点位置,是一文件,文件中保存着与IProjectDescription.一致的信息。
资源插件提供IProject, IFolder, and IFile实现用户对这些资源类型的访问,IResource中则定义了扩展的通用操作接口,还可以使用org.eclipse.core.runtime中的接口IPath来表示工作区的资源或文件系统的访问路径。
对资源的访问与对java.io.File的访问类似,当调用对应API时,返回一个句柄,不需要在访问前确保资源是否存在。具体的,通过如下代码实现访问:
1. //获取工作区根
2.
3. IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
4.
5. //从工作区根获得项目实例
6.
7. IProject myWebProject = myWorkspaceRoot.getProject("MyWeb");
8.
9. // open if necessary
10.
11. if (myWebProject.exists() && !myWebProject.isOpen()) myWebProject.open(null);
在对项目进行操作前,必须执行打开操作。打开项目操作将从文件系统中读取项目结构并读入内存,创建对应的项目资源树,这是一个显式的操作。
获取项目实例的再下一层,就是对项目中的文件和文件夹进行访问:
1. //获取文件夹实例
2.
3. IFolder imagesFolder = myWebProject.getFolder("images");
4.
5. if
6.
7. // create a new file
8.
9. IFile newLogo = imagesFolder.getFile("newLogo.png");
10.
11. //文件系统的创建过程
12.
13. FileInputStream fileStream = new FileInputStream("c:/MyOtherData/newLogo.png");
14.
15. false, null);
16.
17. // create closes the file stream, so no worries.
18.
19. }
上面的过程,首先获取images文件夹的句柄,在判断其存在后,在其中创建新文件newLogo。
资源与文件系统的关联
通过接口IResource.getLocationURI来获得资源的绝对文件系统路径。反过来,通过IWorkspaceRoot的findFilesForLocationURI或者findContainersForLocationURI来实现文件系统路径到工作区路径的mapping。
资源属性
用于保存资源相关的特殊信息,包含会话级和持久级。会话级当项目关闭后失效,用于在内存中方便以名值对形式保存属性,持久级则在文件系统中保留资源属性,有长度限制(不大于2kb,对用于对象的持久化似乎有难度),需要注意命名时不要出现冲突。
项目级参数
可以为运行时参数Runtime preferences定义项目级范围(Project-Scope),用于在项目范围内对参数进行保存和操作:
1. //获取ContextIScopeContext projectScope = new ProjectScope(MyProject);//获取对应项目的参数节点Preferences projectNode = projectScope.node("com.example.myplugin");if (projectNode != null) {value = node.getBoolean("MyPreference", "true");//do something with the value.}
2. //参数回写
3.
4. projectNode.flush();
资源挂接
工作区中的资源可以来自文件系统的不同位置,通过资源挂接来实现。实例代码:
1. IWorkspace workspace = ResourcesPlugin.getWorkspace();
2.
3. IPathVariableManager pathMan = workspace.getPathVariableManager();
4.
5. "TEMP";
6.
7. new Path("c:\temp");
8.
9. //定义path变量,实现资源挂接
10.
11. if
12.
13. pathMan.setValue(name, value);
14.
15. else
16.
17. //invalid name or value, throw an exception or warn user
18.
19. }
20.
21. "Project");//assume this exists
22.
23. "Link");
24.
25. new Path("TEMP/folder");
26.
27. //在资源操作前需要加入验证动作
28.
29. if
30.
31. null);
32.
33. else
34.
35. //invalid location, throw an exception or warn user
36.
37. }
38.
39. //运行结果
40. "/Project/Link"
41. "c:tempfolder"
42.
43. "TEMP/folder"
44.
45. "true"
46.
47.
48.
49. "abc.txt");
50.
51. child.create(...);
52.
53. "/Project/Link/abc.txt"
54.
55. "c:tempfolderabc.txt"
56.
57. "c:tempfolderabc.txt"
58.
59. "false"
Eclipse资源管理(二)
IProject中的Builder与Nature
1.创建一个新的工程
如下是创建一个新的工程的代码,但是此时工程就是一个文件夹,没有任何特性
1. public void createProject(String projectName) throws
2. IWorkspace workspace = ResourcesPlugin.getWorkspace();
3. IWorkspaceRoot root = workspace.getRoot();
4.
5. IProject project = root.getProject(projectName);
6. if(!project.exists()){
7. null);
8. null);
9. }
10.
11. new String[]{LengProjectNature.ID}, null);
12. }
2.为project扩展相应的nature
nature是工程特性的一种标识,eclipse中有如此多种类的project,系统是如何识别他们的。IProject对象本身没有什么特别的标识,所以区分各种不同的project,主要是nature来进行区分。例如,如果两种不同的project对象,如果有同样的一种nature特性,如果我们只需要考虑这种nature特性的时候,这两种project其实是可以等同的。可以借鉴equals方法来进行理解。
1. <extension
2. "com.leng.test.project.nature.LengProjectNature"
3. "Leng Project Nature"
4. "org.eclipse.core.resources.natures">
5. <runtime>
6. <run
7. class="com.leng.test.project.nature.LengProjectNature">
8. </run>
9. </runtime>
10. <builder
11. "com.leng.test.project.nature.LengIncrementalProjectBuilder">
12. </builder>
13. </extension>
1)一个nature里面可以包含多个builder,并且用builder的id进行识别
注意:com.leng.test.project.nature.LengIncrementalProjectBuilder是builder所在的插件的id+.+builderId
2)实现一个IProjectNature类
1. public class LengProjectNature implements
2.
3. private
4.
5. /**
6. * nature的ID为plugin的ID加上nature扩展的ID
7. */
8. public static final String ID = "com.leng.test.project.com.leng.test.project.nature.LengProjectNature";
9.
10. @Override
11. public void configure() throws
12. ProjectUtil.addBuilderToProject(project,
13. new String[] { LengIncrementalProjectBuilder.ID }, null);
14. }
15.
16. @Override
17. public void deconfigure() throws
18. ProjectUtil.removeBuilderFromProject(project,
19. new String[] { LengIncrementalProjectBuilder.ID }, null);
20. }
21.
22. @Override
23. public
24. return
25. }
26.
27. /**
28. * setProject()和configure()的调用顺序是先调setProject()后调configure().
29. */
30. @Override
31. public void
32. this.project = project;
33. }
34.
35. }
3.nature的img扩展:
1. <extension
2. "org.eclipse.ui.ide.projectNatureImages">
3. <image
4. "com.leng.test.project.image1"
5. "com.leng.test.project.image1"
6. "com.leng.test.project.image1">
7. </image>
8. </extension>
依赖插件org.eclipse.ui.ide,此扩展点为特点的nature项目提供特点的图像标记,如java工程中的文件中“J”。
4.为nature扩展相应的builder
刚才说到nature是用来标识project的特性的,但是特性不能当饭吃。new一个工程里面那么多东西,而且算不是new,是其他改变工程里面资源的操作。如果说nature只是标识,那么builder就是实实在在的构建了。
当然,构建器本身是独立的,出来跟nature绑定使用,还可以直接添加到project中
1. <extension
2. "com.leng.test.project.nature.LengIncrementalProjectBuilder"
3. "org.eclipse.core.resources.builders">
4. <builder
5. "false"
6. "true"
7. "true">
8. <run
9. class="com.leng.test.project.nature.LengIncrementalProjectBuilder">
10. </run>
11. </builder>
12. </extension>
hasNature:该构建器是否跟nature关联,默认为false,如果为true则必须nature存在才会触发构建
isConfigurable:设定构建器是否可以通过特定的构建触发器运行,如果为true,则可以通过ICommand.setBuilding
callOnEmptyDelta:当增量构建的增量为null时,如果设置此属性为true则始终构建,不会关构建内容是否为null。
1. public class LengIncrementalProjectBuilder extends
2.
3. public static final String ID = "com.leng.test.project.nature.LengIncrementalProjectBuilder";
4.
5. public
6. }
7.
8. @Override
9. protected IProject[] build(int
10. throws
11. getCommand();
12. getDelta(getProject());
13.
14. switch
15. case
16. // processFullBuild(monitor);
17. break;
18. case
19. break;
20. default:
21. IResourceDelta delta = getDelta(getProject());
22. break;
23. }
24. return null;
25. }
26.
27.
28. @Override
29. protected void
30. super.startupOnInitialize();
31. }
32.
33. /**
34. * 清除一些保留且无用的东西
35. */
36. @Override
37. protected void clean(IProgressMonitor monitor) throws
38. super.clean(monitor);
39. }
40. }
kind:构建类型,FULL_BUILD(全量构建),INCREMENTAL_BUILD(增量构建),
AUTO_BUILD(自动构建,也是增量的),CLEAN_BUILD(在调用build方法前调用clean方法)
getDelta:获取指定工程里面增量改变的资源内容
派生资源:派生资源就是完全由build构建出来的资源,由某一种源派生出来。
5.构建器的触发
构建器的触发有两种方式:一种是自动触发,系统资源改变时,由eclipse自动增量构建。另一种是手动构建,IWorkspace和IProject里面都有构建方法,只要获取到相关对象就可以进行构建。
Eclipse资源管理(三)
关于marker的使用
描述:在eclipse中marker是用来代码级别的各种状态信息的一个框架,使用marker可以轻松的浏览和定位文件中的错误或其他的一些信息。
1.定义marker,在eclipse中已经定义了一些marker,但是在我们使用的时候,也有可能需要定义自己marker。
如下是eclipse中已经存在的marker:
org.eclipse.core.resources.marker —— 记号层次结构的根。
org.eclipse.core.resources.problemmarker —— 表示问题或错误消息,出现在问题列表中。
org.eclipse.core.resources.taskmarker —— 表示待办事项,出现在任务列表中。
org.eclipse.core.resources.bookmark —— 表示文件,比如搜索结果。
org.eclipse.core.resources.textmarker —— 表示文件的位置,比如出现错误的位置。
1. <extension
2. "my.marker"
3. "My Marker"
4. "org.eclipse.core.resources.markers">
5. <persistent
6. "true">
7. </persistent>
8. super
9. "org.eclipse.core.resources.problemmarker">
10. super>
11. </extension>
super:通过super进行继承已有的marker的能力。
persistent:为true的时候,marker信息被持久,下次打开的时候记录依然会出现
定义一个marker只是原则上这个这种marker类型存在了,但是还需要进行真正的使用
2.创建marker
1)marker是为了描述资源的,所以也应该是在IResource中进行增加marker
2)针对某一个文件,每一次重新加载marker的时候,先把旧的marker清理掉
3)marker里面有很多属性可以进行设置,都是通过setAttribute方式进行设置的。而具体有哪些属性可以参考IMarker,自己也可以创建自己的属性。
4)由于继承了problemmarker,所以marker会在problem视图中显示
1. public static void
2. int lineNumber, int severity, int priority) throws
3. if (resource != null) {
4. IMarker marker = resource.createMarker(PROBLEMS_MARKER_ID);
5. if (message != null)
6. marker.setAttribute(IMarker.MESSAGE, message);
7. if (lineNumber >= 0)
8. marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
9. marker.setAttribute(IMarker.SEVERITY, severity);
10. marker.setAttribute(IMarker.PRIORITY, priority);
11. }
12. }
3.删除marker
1. ResourcesPlugin.getWorkspace().getRoot().deleteMarkers(
2. false, IResource.DEPTH_INFINITE); (在工程上添加marker)
3. ifile.deleteMarkers( MARKER_ID, false, IResource.DEPTH_INFINITE); (在file上添加marker)
Eclipse资源管理(四)
eclipse资源监听
IResourceChangeListener接口
1. IWorkspace workspace = ResourcesPlugin.getWorkspace();
2. new
3. public void
4. "Something changed!");
5. }
6. };
7. workspace.addResourceChangeListener(listener);
8.
9. //... some time later one ...
10. workspace.removeResourceChangeListener(listener);
IWorkspace.addResourceChangeListener(Listener)IWorkspace.removeResourceChangeListener(Listener)
2.创建资源的样本
1. IWorkspace workspace = ResourcesPlugin.getWorkspace();
2. final IProject project = workspace.getRoot().getProject("My Project");
3. new
4. public void run(IProgressMonitor monitor) throws
5. int fileCount = 10;
6. null);
7. null);
8. for (int i = 0; i < fileCount; i++) {
9. "File"
10. null, IResource.NONE, null);
11. }
12. }
13. };
14. null);
3.一个简单的完整的资源监听实现类
1. public class DocIndexUpdater implements
2. private TableViewer table; //assume this gets initialized somewhere
3. private static final IPath DOC_PATH = new Path("MyProject/doc");
4. public void
5. //we are only interested in POST_CHANGE events
6. if
7. return;
8. IResourceDelta rootDelta = event.getDelta();
9. //get the delta, if any, for the documentation directory
10. IResourceDelta docDelta = rootDelta.findMember(DOC_PATH);
11. if (docDelta == null)
12. return;
13. final ArrayList changed = new
14. new
15. public boolean
16. //only interested in changed resources (not added or removed)
17. if
18. return true;
19. //only interested in content changes
20. if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
21. return true;
22. IResource resource = delta.getResource();
23. //only interested in files with the "txt" extension
24. if
25. "txt".equalsIgnoreCase(resource.getFileExtension())) {
26. changed.add(resource);
27. }
28. return true;
29. }
30. };
31. try
32. docDelta.accept(visitor);
33. catch
34. //open error dialog with syncExec or print to plugin log file
35. }
36. //nothing more to do if there were no changed text files
37. if (changed.size() == 0)
38. return;
39. //post this update to the table
40. Display display = table.getControl().getDisplay();
41. if
42. new
43. public void
44. //make sure the table still exists
45. if
46. return;
47. null);
48. }
49. });
50. }
51. }
52. }