Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath

时间:2023-02-07 09:04:09

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.一致的信息。

资源插件提供IProjectIFolder, and IFile实现用户对这些资源类型的访问,IResource中则定义了扩展的通用操作接口,还可以使用org.eclipse.core.runtime中的接口IPath来表示工作区的资源或文件系统的访问路径。

对资源的访问与对java.io.File的访问类似,当调用对应API时,返回一个句柄,不需要在访问前确保资源是否存在。具体的,通过如下代码实现访问:

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  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);  
 

 

在对项目进行操作前,必须执行打开操作。打开项目操作将从文件系统中读取项目结构并读入内存,创建对应的项目资源树,这是一个显式的操作。

获取项目实例的再下一层,就是对项目中的文件和文件夹进行访问:

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. //获取文件夹实例  
  2.   
  3. IFolder imagesFolder = myWebProject.getFolder("images");  
  4.   
  5. if (imagesFolder.exists()) {  
  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.     newLogo.create(fileStream, falsenull);  
  16.   
  17.     // create closes the file stream, so no worries.    
  18.   
  19. }  
 

 

上面的过程,首先获取images文件夹的句柄,在判断其存在后,在其中创建新文件newLogo

 

资源与文件系统的关联

通过接口IResource.getLocationURI来获得资源的绝对文件系统路径。反过来,通过IWorkspaceRootfindFilesForLocationURI或者findContainersForLocationURI来实现文件系统路径到工作区路径的mapping

 

资源属性

用于保存资源相关的特殊信息,包含会话级和持久级。会话级当项目关闭后失效,用于在内存中方便以名值对形式保存属性,持久级则在文件系统中保留资源属性,有长度限制(不大于2kb,对用于对象的持久化似乎有难度),需要注意命名时不要出现冲突。

 

项目级参数

可以为运行时参数Runtime preferences定义项目级范围(Project-Scope,用于在项目范围内对参数进行保存和操作:

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  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();  
 

 

资源挂接

工作区中的资源可以来自文件系统的不同位置,通过资源挂接来实现。实例代码:

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1.    IWorkspace workspace = ResourcesPlugin.getWorkspace();  
  2.   
  3.    IPathVariableManager pathMan = workspace.getPathVariableManager();  
  4.   
  5.    String name = "TEMP";  
  6.   
  7.    IPath value = new Path("c:\temp");  
  8.   
  9.    //定义path变量,实现资源挂接  
  10.   
  11. if (pathMan.validateName(name).isOK() && pathMan.validateValue(value).isOK()) {  
  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.    IProject project = workspace.getProject("Project");//assume this exists  
  22.   
  23.    IFolder link = project.getFolder("Link");  
  24.   
  25.    IPath location = new Path("TEMP/folder");  
  26.   
  27.    //在资源操作前需要加入验证动作  
  28.   
  29. if (workspace.validateLinkLocation(location).isOK()) {  
  30.   
  31.       link.createLink(location, IResource.NONE, null);  
  32.   
  33.    } else {  
  34.   
  35.       //invalid location, throw an exception or warn user  
  36.   
  37.    }  
  38.   
  39.    //运行结果  
  40.  link.getFullPath() ==> "/Project/Link"  
  41.    link.getLocation() ==> "c:tempfolder"  
  42.   
  43.    link.getRawLocation() ==> "TEMP/folder"  
  44.   
  45.    link.isLinked() ==> "true"  
  46.   
  47.     
  48.   
  49.    IFile child = link.getFile("abc.txt");  
  50.   
  51.    child.create(...);  
  52.   
  53.    child.getFullPath() ==> "/Project/Link/abc.txt"  
  54.   
  55.    child.getLocation() ==> "c:tempfolderabc.txt"  
  56.   
  57.    child.getRawLocation() ==> "c:tempfolderabc.txt"  
  58.   
  59.    child.isLinked() ==> "false"  
 

 


Eclipse资源管理(二)

IProject中的Builder与Nature

1.创建一个新的工程

如下是创建一个新的工程的代码,但是此时工程就是一个文件夹,没有任何特性

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. public void createProject(String projectName) throws CoreException{  
  2.         IWorkspace workspace = ResourcesPlugin.getWorkspace();  
  3.         IWorkspaceRoot root = workspace.getRoot();  
  4.           
  5.         IProject project = root.getProject(projectName);  
  6.         if(!project.exists()){  
  7.             project.create(null);  
  8.             project.open(null);  
  9.         }  
  10.           
  11.         ProjectUtil.addNature2Project(project, new String[]{LengProjectNature.ID}, null);  
  12.     }  
 

 

 

2.为project扩展相应的nature

nature是工程特性的一种标识,eclipse中有如此多种类的project,系统是如何识别他们的。IProject对象本身没有什么特别的标识,所以区分各种不同的project,主要是nature来进行区分。例如,如果两种不同的project对象,如果有同样的一种nature特性,如果我们只需要考虑这种nature特性的时候,这两种project其实是可以等同的。可以借鉴equals方法来进行理解。

 

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. <extension  
  2.          id="com.leng.test.project.nature.LengProjectNature"  
  3.          name="Leng Project Nature"  
  4.          point="org.eclipse.core.resources.natures">  
  5.       <runtime>  
  6.          <run  
  7.                class="com.leng.test.project.nature.LengProjectNature">  
  8.          </run>  
  9.       </runtime>  
  10.       <builder  
  11.             id="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类

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. public class LengProjectNature implements IProjectNature {  
  2.       
  3.     private IProject project;    
  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 CoreException {  
  12.         ProjectUtil.addBuilderToProject(project,    
  13.                 new String[] { LengIncrementalProjectBuilder.ID }, null);    
  14.     }  
  15.   
  16.     @Override  
  17.     public void deconfigure() throws CoreException {  
  18.         ProjectUtil.removeBuilderFromProject(project,    
  19.                 new String[] { LengIncrementalProjectBuilder.ID }, null);    
  20.     }  
  21.   
  22.     @Override  
  23.     public IProject getProject() {  
  24.         return project;  
  25.     }  
  26.   
  27.     /** 
  28.      * setProject()和configure()的调用顺序是先调setProject()后调configure(). 
  29.      */  
  30.     @Override  
  31.     public void setProject(IProject project) {  
  32.         this.project = project;  
  33.     }  
  34.   
  35. }  
 

 

3.nature的img扩展:

 

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. <extension  
  2.          point="org.eclipse.ui.ide.projectNatureImages">  
  3.       <image  
  4.             icon="com.leng.test.project.image1"  
  5.             id="com.leng.test.project.image1"  
  6.             natureId="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中

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. <extension  
  2.          id="com.leng.test.project.nature.LengIncrementalProjectBuilder"  
  3.          point="org.eclipse.core.resources.builders">  
  4.       <builder  
  5.             callOnEmptyDelta="false"  
  6.             hasNature="true"  
  7.             isConfigurable="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。

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. public class LengIncrementalProjectBuilder extends IncrementalProjectBuilder {  
  2.   
  3.     public static final String ID = "com.leng.test.project.nature.LengIncrementalProjectBuilder";  
  4.       
  5.     public LengIncrementalProjectBuilder() {  
  6.     }  
  7.   
  8.     @Override  
  9.     protected IProject[] build(int kind, Map args, IProgressMonitor monitor)  
  10.             throws CoreException {  
  11.         getCommand();  
  12.         getDelta(getProject());  
  13.           
  14.         switch (kind) {    
  15.         case FULL_BUILD:    
  16. //          processFullBuild(monitor);    
  17.             break;    
  18.         case CLEAN_BUILD:  
  19.             break;  
  20.         default:    
  21.             IResourceDelta delta = getDelta(getProject());     
  22.             break;    
  23.         }    
  24.         return null;  
  25.     }  
  26.   
  27.       
  28.     @Override  
  29.     protected void startupOnInitialize() {  
  30.         super.startupOnInitialize();  
  31.     }  
  32.   
  33.     /** 
  34.      * 清除一些保留且无用的东西 
  35.      */  
  36.     @Override  
  37.     protected void clean(IProgressMonitor monitor) throws CoreException {  
  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 —— 表示文件的位置,比如出现错误的位置。

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. <extension  
  2.          id="my.marker"  
  3.          name="My Marker"  
  4.          point="org.eclipse.core.resources.markers">  
  5.       <persistent  
  6.             value="true">  
  7.       </persistent>  
  8.       <super  
  9.             type="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视图中显示

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. public static void addMarker(IResource resource, String message,  
  2.             int lineNumber, int severity, int priority) throws CoreException {  
  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

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. ResourcesPlugin.getWorkspace().getRoot().deleteMarkers(  
  2.            MARKER_ID, false, IResource.DEPTH_INFINITE); (在工程上添加marker)  
  3. ifile.deleteMarkers( MARKER_ID, false, IResource.DEPTH_INFINITE); (在file上添加marker)  
 



Eclipse资源管理(四)

eclipse资源监听

 

1.资源监听必须实现IResourceChangeListener接口

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. IWorkspace workspace = ResourcesPlugin.getWorkspace();  
  2.    IResourceChangeListener listener = new IResourceChangeListener() {  
  3.       public void resourceChanged(IResourceChangeEvent event) {  
  4.          System.out.println("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.创建资源的样本

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. IWorkspace workspace = ResourcesPlugin.getWorkspace();  
  2.    final IProject project = workspace.getRoot().getProject("My Project");  
  3.    IWorkspaceRunnable operation = new IWorkspaceRunnable() {  
  4.       public void run(IProgressMonitor monitor) throws CoreException {  
  5.          int fileCount = 10;  
  6.          project.create(null);  
  7.          project.open(null);  
  8.          for (int i = 0; i < fileCount; i++) {  
  9.             IFile file = project.getFile("File" + i);  
  10.             file.create(null, IResource.NONE, null);  
  11.          }  
  12.       }  
  13.    };  
  14.    workspace.run(operation, null);  
 

 

 

3.一个简单的完整的资源监听实现类

 

Java代码  Eclipse资源管理IResource,IWorkspace,IProject, IFolder,IPath
  1. public class DocIndexUpdater implements IResourceChangeListener {  
  2.       private TableViewer table; //assume this gets initialized somewhere  
  3.       private static final IPath DOC_PATH = new Path("MyProject/doc");  
  4.       public void resourceChanged(IResourceChangeEvent event) {  
  5.          //we are only interested in POST_CHANGE events  
  6.          if (event.getType() != IResourceChangeEvent.POST_CHANGE)  
  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 ArrayList();  
  14.          IResourceDeltaVisitor visitor = new IResourceDeltaVisitor() {  
  15.             public boolean visit(IResourceDelta delta) {  
  16.                //only interested in changed resources (not added or removed)  
  17.                if (delta.getKind() != IResourceDelta.CHANGED)  
  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 (resource.getType() == IResource.FILE &&   
  25.                 "txt".equalsIgnoreCase(resource.getFileExtension())) {  
  26.                   changed.add(resource);  
  27.                }  
  28.                return true;  
  29.             }  
  30.          };  
  31.          try {  
  32.             docDelta.accept(visitor);  
  33.          } catch (CoreException e) {  
  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 (!display.isDisposed()) {  
  42.             display.asyncExec(new Runnable() {  
  43.                public void run() {  
  44.                   //make sure the table still exists  
  45.                   if (table.getControl().isDisposed())  
  46.                      return;  
  47.                   table.update(changed.toArray(), null);  
  48.                }  
  49.             });  
  50.          }  
  51.       }  
  52.    }