(ПРИМЕЧАНИЕ - ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ НИЖЕ)
В моем подключаемом модуле я пытаюсь создать 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"
Попробуйте эти две вещи:
Используйте реализацию IWorkspaceRunnable для переноса всех изменений ресурсов в одну транзакцию. Это должно сделать изменения более похожими на создание дельта проекта.
Перед запуском кода убедитесь, что проект удален с диска. Похоже, вы удалили его из рабочей области, но не в файловую систему.
javaProject
, я решил подождать, пока работа не будет полностью завершена, прежде чем использовать мойjavaProject
. Я рассматриваю возможность использованияWorkspaceJob
сrunInWorkspace
и создания внутреннего класса, расширяющегоJob
, а затем используюIJobManager
для присоединения к заданию до его завершения.