首页 > 代码库 > org.eclipse.core.resources.natures org.eclipse.core.resources.builders扩展点介绍

org.eclipse.core.resources.natures org.eclipse.core.resources.builders扩展点介绍

builder和nature是Eclipse中提供的两个扩展点。一般来说我们都是先有自己特定的project类型,然后在这类project上加上自定义的builder和nature。

 

其实所谓的特定的project通常都是由特有的nature来标识的;而又一般builder是建立在某类特定的project上,所以我们可以得出:Nature决定了project和builder。

1、创建nature扩展点

   <extension
         id="nature"
         name="WorkFlow Project Nature"
         point="org.eclipse.core.resources.natures">
      <runtime>
         <run
               class="com.workflow.nature.WorkflowProjectNature">
         </run>
      </runtime>
      <builder
            id="MyDesigner.builder"><!--builder的扩展点ID为plugin的ID加上builder扩展的ID-->
      </builder>
   </extension>
2、创建builder扩展点

 <extension
         id="builder"
         name="WorkFlow Project Builder"
         point="org.eclipse.core.resources.builders">
      <builder
            hasNature="true"
            isConfigurable="false">
         <run
               class="com.workflow.builder.ProjectBuilder">
         </run>
      </builder>
   </extension>
3、nature的实现类

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;

import com.workflow.builder.ProjectBuilder;
import com.workflow.tool.ProjectUtil;
/**
 * 自定义的nature实现类
 * @author lww
 *
 */
public class WorkflowProjectNature implements IProjectNature {

	private IProject project;
	public static final String ID = "MyDesigner.nature";//nature的ID为plugin的ID加上nature扩展的ID
	/**
	 * builder安装
	 */
	@Override
	public void configure() throws CoreException {
		
		IProjectDescription description = project.getDescription();  
	    ProjectUtil.addBuilderToProject(description,  
	            new String[] { ProjectBuilder.ID }, null);  
	    project.setDescription(description, null);  
		
	}
	/**
	 * builder卸载
	 */
	@Override
	public void deconfigure() throws CoreException {

		IProjectDescription description = project.getDescription();  
		    ProjectUtil.removeBuilderFromProject(description,  
		            new String[] { ProjectBuilder.ID }, null);  
		    project.setDescription(description, null); 
	}

	@Override
	public IProject getProject() {
		
		return project;
	}
	@Override
	public void setProject(IProject project) {//在project.setDescription()的时候调用,如果那个project的description安了这个nature
		
		this.project = project;
	}

}
4、builder的实现类

import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
 *自定义 builder实现类
 *org.eclipse.core.resources.builders用于提供一种操作,
 *这种操作可以在IResource改变的时候自动去build,如同改变java文件,会自动进行build,
 *显示错误一样,我们扩展这个builder,并且在自己的项目中使用。我们要做的就是实现build的过程,
 *至于时机由eclipse控制
 * @author lww
 *
 */
public class ProjectBuilder extends IncrementalProjectBuilder {

	private IProject project;
	public static final String ID = "MyDesigner.builder";// Builder的ID为plugin的ID加上Builder扩展的ID.
	private static final String MARKER_TYPE = "MyDesigner.xmlProblem";

	private SAXParserFactory parserFactory;

	/**
	 * 根据不同的build类型,来实现不同的build策略
	 */
	@Override
	protected IProject[] build(int kind, Map<String, String> args,
			IProgressMonitor monitor) throws CoreException {
		switch (kind) {
		case FULL_BUILD:
			fullBuild(monitor);
			break;
		default:
			IResourceDelta delta = getDelta(project);
			if (delta == null) {
				fullBuild(monitor);
			} else {
				incrementalBuild(delta, monitor);
			}
			break;
		}
		return null;
	}
	/**
	 * 点击project 菜单栏中clean Action的时候执行该方法
	 */
	@Override
	protected void clean(IProgressMonitor monitor) throws CoreException {
		super.clean(monitor);
		/*
		 * remove all build files
		 */
		IFolder outputFiles = project.getFolder("Processes");
		outputFiles.refreshLocal(IResource.DEPTH_INFINITE, monitor);
		if (outputFiles.exists()) {
			outputFiles.delete(true, monitor);
		}
	}
	/**
	 * 调用一些初始信息,或者初始变量
	 */
	@Override
	protected void startupOnInitialize() {
		super.startupOnInitialize();
		this.project = getProject();
	}
	/**
	 * 添加 标识,在Markers视图中显示该错误
	 * @param file
	 * @param message
	 * @param lineNumber
	 * @param severity
	 */
	private void addMarker(final IFile file, String message, int lineNumber,
			int severity) {
		try {
			IMarker marker = file.createMarker(MARKER_TYPE);
			marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
			marker.setAttribute(IMarker.MESSAGE, message);
			marker.setAttribute(IMarker.SEVERITY, severity);
			if (lineNumber == -1) {
				lineNumber = 1;
			}
			marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
			
		} catch (CoreException e) {
		}
		
	}
	/**
	 * 检查文件后缀为.xml
	 * @param resource
	 */
	void checkXML(IResource resource) {
		if (resource instanceof IFile && resource.getName().endsWith(".xml")) {
			IFile file = (IFile) resource;
			deleteMarkers(file);
			XMLErrorHandler reporter = new XMLErrorHandler(file);
			try {
				getParser().parse(file.getContents(), reporter);
			} catch (Exception e1) {
			}
		}
	}
	/**
	 * 删除Markers
	 * @param file
	 */
	private void deleteMarkers(IFile file) {
		try {
			file.deleteMarkers(MARKER_TYPE, false, IResource.DEPTH_ZERO);
		} catch (CoreException ce) {
		}
	}
	private SAXParser getParser() throws ParserConfigurationException,
		SAXException {
		if (parserFactory == null) {
			parserFactory = SAXParserFactory.newInstance();
		}
		return parserFactory.newSAXParser();
	}
	
	protected void fullBuild(final IProgressMonitor monitor)
			throws CoreException {
		try {
			getProject().accept(new WorkFlowResourceVisitor());
		} catch (CoreException e) {
		}
	}

	protected void incrementalBuild(IResourceDelta delta,
			IProgressMonitor monitor) throws CoreException {
		// the visitor does the work.
		delta.accept(new WorkFlowDeltaVisitor());
	}

	class WorkFlowDeltaVisitor implements IResourceDeltaVisitor {

		@Override
		public boolean visit(IResourceDelta delta) throws CoreException {
			IResource resource = delta.getResource();
			switch (delta.getKind()) {
			case IResourceDelta.ADDED:
				// handle added resource
				checkXML(resource);
				break;
			case IResourceDelta.REMOVED:
				// handle removed resource
				break;
			case IResourceDelta.CHANGED:
				// handle changed resource
				checkXML(resource);
				break;
			}
			// return true to continue visiting children.
			return true;
		}
	}

	class WorkFlowResourceVisitor implements IResourceVisitor {

		@Override
		public boolean visit(IResource resource) throws CoreException {
			checkXML(resource);
			return true;
		}
	}

	class XMLErrorHandler extends DefaultHandler {
		private IFile file;

		public XMLErrorHandler(IFile file) {
			this.file = file;
		}

		private void addMarker(SAXParseException e, int severity) {
			ProjectBuilder.this.addMarker(file, e.getMessage(),
					e.getLineNumber(), severity);
		}

		public void error(SAXParseException exception) throws SAXException {
			addMarker(exception, IMarker.SEVERITY_ERROR);
		}

		public void fatalError(SAXParseException exception) throws SAXException {
			addMarker(exception, IMarker.SEVERITY_ERROR);
		}

		public void warning(SAXParseException exception) throws SAXException {
			addMarker(exception, IMarker.SEVERITY_WARNING);
		}
	}

}

5、操作类

import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
 * project的操作类(添加nature、builder)
 * @author lww
 *
 */
public class ProjectUtil {
	/**
	 * 添加Nature信息到Project中
	 * 添加Comment信息
	 */
	public static void addNature2Project(IProjectDescription description, String[] natureIds) throws CoreException {  
	    String[] prevNatures = description.getNatureIds();  
	    String[] newNatures = new String[prevNatures.length + natureIds.length];  
	    System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);  
	    for(int i = prevNatures.length;i<newNatures.length;i++){  
	        newNatures[i] = natureIds[i-prevNatures.length];  
	    }  
	    description.setNatureIds(newNatures);  
	    
	    description.setComment("It's a WorkFlow project");
	    
	}  
	/**
	 * 添加builder到project中
	 * @param description
	 * @param builderIds
	 * @param monitor
	 * @throws CoreException
	 */
	public static void addBuilderToProject(IProjectDescription description,  
	        String[] builderIds, IProgressMonitor monitor) throws CoreException {  
	    ICommand[] buildSpec = description.getBuildSpec();  
	    ICommand[] newBuilders = new ICommand[buildSpec.length  
	            + builderIds.length];  
	    System.arraycopy(buildSpec, 0, newBuilders, 0, buildSpec.length);  
	    for (int i = buildSpec.length; i < newBuilders.length; i++) {  
	        ICommand command = description.newCommand();  
	        command.setBuilderName(builderIds[i - buildSpec.length]);  
	        newBuilders[i] = command;  
	    }  
	    description.setBuildSpec(newBuilders);  
	}  
	/**
	 * 移除builder从project中
	 * @param description
	 * @param builderIds
	 * @param monitor
	 */
	public static void removeBuilderFromProject(  
	        IProjectDescription description, String[] builderIds,  
	        IProgressMonitor monitor) {  
	    ICommand[] buildSpec = description.getBuildSpec();  
	    List<ICommand> newBuilders = new ArrayList<ICommand>();  
	    for (ICommand command : buildSpec) {  
	        boolean find = false;  
	        for (String id : builderIds) {  
	            if (command.getBuilderName().equals(id)) {  
	                find = true;  
	                break;  
	            }  
	        }  
	        if (!find) {  
	            newBuilders.add(command);  
	        }  
	    }  
	    description.setBuildSpec(newBuilders.toArray(new ICommand[0]));  
	}  
}

org.eclipse.core.resources.builders用于提供一种操作,这种操作可以在IResource改变的时候自动去build,如同改变java文件,会自动进行build,显示错误一样,我们扩展这个builder,并且在自己的项目中使用。我们要做的就是实现build的过程,至于时机由eclipse控制
     上面的例子就在修改文件时,验证XML文件内容格式是否存在问题,并显示在markers视图中显示,所以还要添加扩展点org.eclipse.core.resources.markers。
6、markers扩展点

 <extension
         id="xmlProblem"
         name="com.workflow.xmlProblem"
         point="org.eclipse.core.resources.markers">
      <persistent
            value=http://www.mamicode.com/"true">>

7、创建工程

IWorkspace workspace = ResourcesPlugin.getWorkspace();  
IWorkspaceRoot root = workspace.getRoot();  
  
String projectName = "TestNPB";  
IProject project = root.getProject(projectName);  
if (!project.exists()) {  
    project.create(null);  
    project.open(null);  
}  
IProjectDescription description = project.getDescription();  
ProjectUtil.addNature2Project(description, new String[]{LiugangProjectNature.ID}, null);  
project.setDescription(description, null);  

创建的工程变为

.project文件中多了buildSpec和natures
当修改后缀名为.xml的文件后,保存,它就会去检查xml文件内容,若内容存在问题就在markers中显示错误信息


参考资料:http://liugang594.iteye.com/blog/261513

http://blog.csdn.net/soszou/article/details/8018032