Eclipse PDE: имитирует IResourceChangeEvents для создания IJavaProject между PDE и рабочим пространством разработчика?

1

(ПРИМЕЧАНИЕ - ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ НИЖЕ)

В моем подключаемом модуле я пытаюсь создать IJavaProject (используя Eclipse JDT, код в конце), который создает проект Java почти ТОЧНО, как если бы IJavaProject был создан разработчиком (или тем, кто использует плагин). Я могу создать IJavaProject из своего PDE, и он отлично работает, но мне нужно подражать IResourceChangeEvents которые возникают из создания проекта в моем PDE, чтобы соответствовать IResourceChangeEvents которые возникают из создания Java-проекта в рабочей области разработчика.

Я измеряю "IResourceChangeEvents", используя свой IResourceChangeListener (он использует посетителя, и должен быть прав - просмотрите здесь код). Когда Java Project создается в рабочей области разработчика, я IResourceChangeEvents следующие 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"

И когда я создаю IJavaProject с использованием Eclipse JDT в своем PDE (код в конце), я измеряю эти 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"

Если CR CHANGED-ROOT, CP CHANGED-PROJECT а CF CHANGED-FILE.

Любые предложения по другому способу создания IJavaProject?

Вот мой 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"
Теги:
eclipse-plugin

1 ответ

1
Лучший ответ

Попробуйте эти две вещи:

  • Используйте реализацию IWorkspaceRunnable для переноса всех изменений ресурсов в одну транзакцию. Это должно сделать изменения более похожими на создание дельта проекта.

  • Перед запуском кода убедитесь, что проект удален с диска. Похоже, вы удалили его из рабочей области, но не в файловую систему.

  • 0
    Спасибо за советы. Когда вы пакетируете изменения моего ресурса, вы предлагаете запустить его асинхронно? Поскольку я пытаюсь вернуть свой javaProject , я решил подождать, пока работа не будет полностью завершена, прежде чем использовать мой javaProject . Я рассматриваю возможность использования WorkspaceJob с runInWorkspace и создания внутреннего класса, расширяющего Job , а затем использую IJobManager для присоединения к заданию до его завершения.
  • 0
    @ Лукас Синхронно работает нормально. Это не займет много времени, хотя он работает быстрее, чем без IWorkspaceRunnable, потому что вы не запускаете сборщики каждый раз, когда добавляете ресурс - только один раз в конце.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню