Eclipse PDE:为PDE和开发人员工作区之间的IJavaProject创建模仿IResourceChangeEvents?

时间:2014-03-19 01:16:13

标签: java eclipse eclipse-plugin

(注 - 最终解决方案如下)

在我的插件中,我正在尝试创建一个IJavaProject(使用Eclipse JDT,最后的代码),几乎完全创建一个Java项目,好像IJavaProject是由开发人员创建的(或者是谁使用插件)。我可以从我的PDE创建IJavaProject,它工作正常,但我需要模仿我的PDE中项目创建所产生的IResourceChangeEvents以匹配出现的IResourceChangeEvents来自开发人员工作区中的Java项目创建。

我正在衡量' IResourceChangeEvents'使用我的IResourceChangeListener(它使用访问者,并且应该是正确的 - 查看代码here)。在开发人员工作区中创建Java项目时,我正在测量以下IResourceChangeEvents

CHANGE-ROOT (1 child)
    ADD-PROJECT (5 children)
        ADD-FILE ".classpath"
        ADD-FILE ".project"
        ADD-FOLDER ".settings" ADD-FILE ".prefs"
        ADD-FOLDER ".bin"
        ADD-FOLDER ".src"

当我在PDE中使用Eclipse JDT(最后的代码)创建IJavaProject时,我会测量这些IResourceChangeEvents

C-R 
    C-P 
        ADD-FILE ".project"
C-R 
    C-P "JavaProject"                       
C-R 
    C-P 
        CHANGE-FILE ".project"
C-R 
    C-P 
        ADD-FOLDER "bin"
C-R 
    C-P 
        C-F 
            ADD-FILE ".project"             
C-R 
    C-P 
        ADD-FILE ".classpath"
C-R 
    C-P 
        ADD-FOLDER "src"
C-R 
    C-P 
        CHANGED-FILE ".classpath"

C-RCHANGED-ROOTC-PCHANGED-PROJECTC-FCHANGED-FILE

有关创建IJavaProject的其他方式的任何建议吗?

以下是我的IJavaProject创建代码:

public static IJavaProject getJavaProject(IProject project) throws CoreException
{
    return getJavaProject(project, "src", "bin");
}


public static IJavaProject getJavaProject(IProject project, String sourceFolderPath,
                                           String binFolderPath) throws CoreException
{

    if (!project.exists())
        // This creates ADDED (.project)
        ResourceUtility.createProject(project);

    System.out.println("setting description nature id's.");
    IProjectDescription description = project.getDescription();
    description.setNatureIds(new String[] {JavaCore.NATURE_ID});
    System.out.println("setting project description.");
    // Creates CHANGED (JavaProject/.project)
    project.setDescription(description, null);
    System.out.println("Creating project.");

    // Does not do anything.
    IJavaProject javaProject = JavaCore.create(project);
    IFolder binFolder = project.getFolder(binFolderPath);
    // Creates ADDED (JavaProject/bin)
    binFolder.create(false, true, null);
    javaProject.setOutputLocation(binFolder.getFullPath(), null);
    System.out.println("Installing VM.");

    List<IClasspathEntry> entries = new ArrayList<>();
    IVMInstall vmInstall = JavaRuntime.getDefaultVMInstall();
    System.out.println("JDTUtil: vmInstall: " + vmInstall);
    LibraryLocation[] locations = JavaRuntime.getLibraryLocations(vmInstall);
    System.out.println("JDTUtil: lib locations: " + locations);
    // Creates ADDED (JavaProject/bin/.project) - ignored by RCL
    for (LibraryLocation element: locations)
    {
        entries.add(JavaCore.newLibraryEntry(element.getSystemLibraryPath(), null, null));
    }
    // add libs to project class path
    // Creates ADDED (JavaProject/.classpath)
    javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);
    //
    IFolder sourceFolder = project.getFolder(sourceFolderPath);
    // Creates ADDED (JavaProject/src)
    sourceFolder.create(false, true, null);

    IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(sourceFolder);
    IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
    IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
    System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
    newEntries[oldEntries.length] = JavaCore.newSourceEntry(root.getPath());
    // Creates CHANGED (JavaProject/.classpath)
    javaProject.setRawClasspath(newEntries, null);
    return javaProject;
}

最终解决方案

正如下面的答案中所提到的,我对资源更改事件进行了批处理,这些事件导致Eclipse以不同的方式构建IJavaProject,并且比没有批处理更有效。因此,我的IJavaProject创建现在匹配Eclipse的IJavaProject创建的内部资源树表示(WOOHOO!)。

这是我的最终解决方案:

public static IJavaProject getJavaProjectBatched(final IProject project, final String sourceFolderPath,
                                                 final String binFolderPath) throws CoreException
{
    IWorkspaceRunnable r = new IWorkspaceRunnable()
    {
         @Override public void run(@Nullable IProgressMonitor monitor) throws CoreException
        {
             if (!project.exists())
                 ResourceUtility.createProject(project);

             IProjectDescription description = project.getDescription();
             description.setNatureIds(new String[] {JavaCore.NATURE_ID});
             project.setDescription(description, null);

             IFolder binFolder = project.getFolder(binFolderPath);
             binFolder.create(false, true, null);
             final IFolder sourceFolder = project.getFolder(sourceFolderPath);
             sourceFolder.create(false, true, null);

             final IJavaProject javaProject = JavaCore.create(project);
             javaProject.setOutputLocation(binFolder.getFullPath(), null);

            IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(sourceFolder);
            IClasspathEntry[] newEntries = new IClasspathEntry[1];
            newEntries[0] = JavaCore.newSourceEntry(root.getPath());
            javaProject.setRawClasspath(newEntries, null); 
        }
    };

    project.getWorkspace().run(r, null,IWorkspace.AVOID_UPDATE, null);
    @SuppressWarnings("null") @NonNull IJavaProject javaProject = JavaCore.create(project);
    return javaProject;
}

这是新的资源树,它匹配我上面需要的资源树(不包括.settings文件夹 - 只是手工创建的工件)。

CHANGE-ROOT (1 child)
    ADD-PROJECT (4 children)
        ADD-FILE ".classpath"
        ADD-FILE ".project"
        ADD-FOLDER ".bin"
        ADD-FOLDER ".src"

1 个答案:

答案 0 :(得分:1)

尝试以下两件事:

  • 使用IWorkspaceRunnable的实现将所有资源更改批处理到单个事务中。这应该使更改看起来更像创建项目资源增量。

  • 确保在运行代码之前从磁盘中删除项目。它看起来像是从工作区中删除了它而不是文件系统。