From 304e7caf16886a0a31c497a65fbb4d626e8ec4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Ujhelyi?= Date: Sun, 15 Sep 2024 14:06:47 +0200 Subject: [PATCH 1/3] Fixes PDE access for 2024-09 #191 A new helper method was introduced in ProjectGenerationHelper that accesses the appropriate method to iodentify plugin projects, and all references to the PDE class was updated to use this method, either directly or indirectly. --- .../ui/EMFPatternLanguageEditorCallback.java | 4 +- .../emf/ui/builder/CleanSupport.java | 5 +- .../emf/ui/builder/EnsurePluginSupport.java | 4 +- .../migrator/metadata/NatureUpdaterJob.java | 4 +- .../properties/QueryProjectVersionTester.java | 5 +- ...ensionBasedGenerationFragmentProvider.java | 4 +- .../core/project/ProjectGenerationHelper.java | 252 +++++++++++------- 7 files changed, 164 insertions(+), 114 deletions(-) diff --git a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/EMFPatternLanguageEditorCallback.java b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/EMFPatternLanguageEditorCallback.java index 9050a90766..c6e65cf62e 100644 --- a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/EMFPatternLanguageEditorCallback.java +++ b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/EMFPatternLanguageEditorCallback.java @@ -14,7 +14,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.pde.internal.core.natures.PDE; +import org.eclipse.viatra.query.tooling.core.project.ProjectGenerationHelper; import org.eclipse.viatra.query.tooling.core.project.ViatraQueryNature; import org.eclipse.viatra.query.tooling.ui.migrator.JavaProjectMigrator; import org.eclipse.viatra.query.tooling.ui.migrator.metadata.NatureUpdaterJob; @@ -43,7 +43,7 @@ public void afterCreatePartControl(XtextEditor editor) { if (resource != null) { final IProject project = resource.getProject(); if (project.isAccessible() && !project.isHidden() && !project.hasNature(ViatraQueryNature.NATURE_ID)) { - String question = (PDE.hasPluginNature(project)) + String question = (ProjectGenerationHelper.isOpenPDEProject(project)) ? String.format("Do you want to convert project %s to a VIATRA Query Project?", project.getName()) : String.format( diff --git a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/CleanSupport.java b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/CleanSupport.java index c7e9ef8bef..a9a59a879a 100644 --- a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/CleanSupport.java +++ b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/CleanSupport.java @@ -22,7 +22,6 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.InternalEObject; -import org.eclipse.pde.internal.core.natures.PDE; import org.eclipse.viatra.query.patternlanguage.emf.helper.PatternLanguageHelper; import org.eclipse.viatra.query.patternlanguage.emf.ui.builder.configuration.EMFPatternLanguageBuilderPreferenceAccess; import org.eclipse.viatra.query.patternlanguage.emf.jvmmodel.EMFPatternLanguageJvmModelInferrerUtil; @@ -100,7 +99,7 @@ private void internalFullClean(IBuildContext context, IProgressMonitor monitor) // clean current model project List> removableExtensions = new ArrayList<>(); removableExtensions.addAll(GenerateQuerySpecificationExtension.getRemovableExtensionIdentifiers()); - if (builderPreferenceAccess.isExtensionGenerationEnabled(modelProject) && PDE.hasPluginNature(modelProject)) { + if (builderPreferenceAccess.isExtensionGenerationEnabled(modelProject) && ProjectGenerationHelper.isOpenPDEProject(modelProject)) { ProjectGenerationHelper.removeAllExtension(modelProject, removableExtensions); } } @@ -131,7 +130,7 @@ private void cleanFragment(IProject modelProject, IGenerationFragment fragment) for (OutputConfiguration config : fsa.getOutputConfigurations().values()) { cleanFragmentFolder(fragmentProject, config); } - if (PDE.hasPluginNature(fragmentProject) && builderPreferenceAccess.isExtensionGenerationEnabled(modelProject)) { + if (ProjectGenerationHelper.isOpenPDEProject(fragmentProject) && builderPreferenceAccess.isExtensionGenerationEnabled(modelProject)) { ProjectGenerationHelper.removeAllExtension(fragmentProject, fragment.getRemovableExtensions()); } // removing all fragment-related markers diff --git a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/EnsurePluginSupport.java b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/EnsurePluginSupport.java index a6f9993e72..e8fa99d962 100644 --- a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/EnsurePluginSupport.java +++ b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/patternlanguage/emf/ui/builder/EnsurePluginSupport.java @@ -16,7 +16,6 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.pde.internal.core.natures.PDE; import org.eclipse.viatra.query.patternlanguage.emf.ui.builder.configuration.EMFPatternLanguageBuilderPreferenceAccess; import org.eclipse.viatra.query.tooling.core.generator.ExtensionData; import org.eclipse.viatra.query.tooling.core.project.ProjectGenerationHelper; @@ -94,11 +93,10 @@ public void clean() { * @param monitor * @throws CoreException */ - @SuppressWarnings("restriction") public void ensure(IProject modelProject, IProgressMonitor monitor) { // normal code generation done, extensions, packages ready to add to the plug-ins try { - if (PDE.hasPluginNature(modelProject)) { + if (ProjectGenerationHelper.isOpenPDEProject(modelProject)) { internalEnsure(modelProject, monitor); } else { logger.info(String.format("Project %s is not a plug-in project, metadata has to be managed manually.", modelProject.getName())); diff --git a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/metadata/NatureUpdaterJob.java b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/metadata/NatureUpdaterJob.java index 913729c352..add47b3895 100644 --- a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/metadata/NatureUpdaterJob.java +++ b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/metadata/NatureUpdaterJob.java @@ -25,7 +25,6 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.pde.internal.core.natures.PDE; import org.eclipse.viatra.query.patternlanguage.emf.ui.EMFPatternLanguageUIPlugin; import org.eclipse.viatra.query.tooling.core.project.ProjectGenerationHelper; import org.eclipse.viatra.query.tooling.core.project.ViatraQueryNature; @@ -48,7 +47,6 @@ * @author Zoltan Ujhelyi * */ -@SuppressWarnings("restriction") public class NatureUpdaterJob extends Job { private final IProject project; @@ -188,7 +186,7 @@ protected IStatus run(IProgressMonitor monitor) { removeGlobalEiq(project); renamePatternDefinitionFiles(project); - if (PDE.hasPluginNature(project)) { + if (ProjectGenerationHelper.isOpenPDEProject(project)) { ProjectGenerationHelper.ensureSourceFolder(project, outputConfigurationProvider.getOutputConfigurations(), monitor); ProjectGenerationHelper.ensureSingletonDeclaration(project); diff --git a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/properties/QueryProjectVersionTester.java b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/properties/QueryProjectVersionTester.java index 9f0b799aab..d908bb8bd7 100644 --- a/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/properties/QueryProjectVersionTester.java +++ b/query/plugins/org.eclipse.viatra.query.patternlanguage.emf.ui/src/org/eclipse/viatra/query/tooling/ui/migrator/properties/QueryProjectVersionTester.java @@ -16,7 +16,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.pde.internal.core.natures.PDE; +import org.eclipse.viatra.query.tooling.core.project.ProjectGenerationHelper; import org.eclipse.viatra.query.tooling.core.project.ViatraQueryNature; import org.eclipse.viatra.query.tooling.ui.migrator.MigratorConstants; import org.eclipse.xtext.ui.XtextProjectHelper; @@ -26,7 +26,6 @@ * @author Zoltan Ujhelyi * */ -@SuppressWarnings("restriction") public class QueryProjectVersionTester extends PropertyTester { private static final String VERSION_TESTER = "outdated"; @@ -71,7 +70,7 @@ public boolean test(Object receiver, String property, Object[] args, Object expe return project.findMember(MigratorConstants.GLOBAL_EIQ_PATH) != null || hasIncorrectBuildCommandOrdering(project) || hasLog4jDependency(project); } else { - return project.hasNature(PDE.PLUGIN_NATURE); + return ProjectGenerationHelper.isOpenPDEProject(project); } } } catch (Exception e) { diff --git a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/generator/fragments/ExtensionBasedGenerationFragmentProvider.java b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/generator/fragments/ExtensionBasedGenerationFragmentProvider.java index d390476f2d..d810ad5f3e 100644 --- a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/generator/fragments/ExtensionBasedGenerationFragmentProvider.java +++ b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/generator/fragments/ExtensionBasedGenerationFragmentProvider.java @@ -18,7 +18,6 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; -import org.eclipse.pde.internal.core.natures.PDE; import org.eclipse.viatra.query.patternlanguage.emf.vql.Annotation; import org.eclipse.viatra.query.patternlanguage.emf.vql.Pattern; import org.eclipse.viatra.query.tooling.core.project.ProjectGenerationHelper; @@ -93,10 +92,9 @@ public IProject getFragmentProject(IProject modelProject, IGenerationFragment fr return workspaceRoot.getProject(projectName); } - @SuppressWarnings("restriction") private String getFragmentProjectName(IProject base, IGenerationFragment fragment) { String name = ""; - if (PDE.hasPluginNature(base)) { + if (ProjectGenerationHelper.isOpenPDEProject(base)) { name = ProjectGenerationHelper.getBundleSymbolicName(base); } else { base.getName(); diff --git a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java index 38ba2303a3..7a04dd3485 100644 --- a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java +++ b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java @@ -10,6 +10,8 @@ package org.eclipse.viatra.query.tooling.core.project; import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -41,8 +43,8 @@ import org.eclipse.pde.core.project.IPackageImportDescription; import org.eclipse.pde.core.project.IRequiredBundleDescription; import org.eclipse.pde.internal.core.PDECore; -import org.eclipse.pde.internal.core.natures.PDE; import org.eclipse.viatra.query.runtime.ViatraQueryRuntimePlugin; +import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; import org.eclipse.viatra.query.tooling.core.generator.ExtensionData; import org.eclipse.viatra.query.tooling.core.generator.ViatraQueryGeneratorPlugin; @@ -71,19 +73,26 @@ public abstract class ProjectGenerationHelper { private static final String UTF8_ENCODING = "UTF-8"; /** - * Contains the default bundle requirements for VIATRA in a format that can be loaded into {@link #ensureBundleDependencies(IProject, List)}. + * Contains the default bundle requirements for VIATRA in a format that can be loaded into + * {@link #ensureBundleDependencies(IProject, List)}. + * * @since 2.0 */ - public static final List DEFAULT_VIATRA_BUNDLE_REQUIREMENTS = Arrays.asList("org.eclipse.emf.ecore", ViatraQueryRuntimePlugin.PLUGIN_ID, - "org.eclipse.viatra.query.runtime.rete", "org.eclipse.viatra.query.runtime.localsearch", "org.eclipse.xtext.xbase.lib"); + public static final List DEFAULT_VIATRA_BUNDLE_REQUIREMENTS = Arrays.asList("org.eclipse.emf.ecore", + ViatraQueryRuntimePlugin.PLUGIN_ID, "org.eclipse.viatra.query.runtime.rete", + "org.eclipse.viatra.query.runtime.localsearch", "org.eclipse.xtext.xbase.lib"); /** - * Contains the default import package requirements for VIATRA in a format that can be loaded into {@link #ensurePackageImports(IProject, List)}. + * Contains the default import package requirements for VIATRA in a format that can be loaded into + * {@link #ensurePackageImports(IProject, List)}. + * * @since 2.0 */ - public static final List DEFAULT_VIATRA_IMPORT_PACKAGES = Arrays.asList("org.apache.log4j", "javax.annotation"); - - private ProjectGenerationHelper() {/*Utility class constructor*/} - + public static final List DEFAULT_VIATRA_IMPORT_PACKAGES = Arrays.asList("org.apache.log4j", + "javax.annotation"); + + private ProjectGenerationHelper() { + /* Utility class constructor */} + private static final class IDToPackageImportTransformer implements Function { private final IBundleProjectService service; @@ -109,25 +118,50 @@ public IRequiredBundleDescription apply(String input) { return service.newRequiredBundle(input, null, false, false); } } - + + private static boolean isPDEProject(IProject project) { + /* + * In SimRel 2024-09 the PDE#hasPluginNature call was moved to + * PluginProject#isPluginProject, but this is incompatible with 2022-06 + * TODO Rreplace this with a direct method call after minimum requirements are updated + */ + try { + Method checkMethod; + + try { + final Class pluginProjectClass = Class + .forName("org.eclipse.pde.internal.core.natures.PluginProject"); + checkMethod = pluginProjectClass.getMethod("isPluginProject", IProject.class); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { + final Class pdeClass = Class.forName("org.eclipse.pde.internal.core.natures.PDE"); + checkMethod = pdeClass.getMethod("hasPluginNature", IProject.class); + } + + return (Boolean) checkMethod.invoke(checkMethod, project); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new ViatraQueryException("Unsupported PDE version", "Erroneous installation, required PDE method cannot be called", e); + } + } + /** * Return true if the given project exists, is open and has PDE plug-in nature configured + * * @param project */ - public static boolean isOpenPDEProject(IProject project){ - return project.exists() && project.isOpen() && (PDE.hasPluginNature(project)); + public static boolean isOpenPDEProject(IProject project) { + return project.exists() && project.isOpen() && (isPDEProject(project)); } - + /** - * Checks whether the given project exists, is open and has PDE plug-in nature configured. Throws - * an {@link IllegalArgumentException} otherwise. + * Checks whether the given project exists, is open and has PDE plug-in nature configured. Throws an + * {@link IllegalArgumentException} otherwise. + * * @param project */ - public static void checkOpenPDEProject(IProject project){ - Preconditions.checkArgument(isOpenPDEProject(project), - INVALID_PROJECT_MESSAGE, project.getName()); + public static void checkOpenPDEProject(IProject project) { + Preconditions.checkArgument(isOpenPDEProject(project), INVALID_PROJECT_MESSAGE, project.getName()); } - + /** * A single source folder named src */ @@ -155,16 +189,17 @@ public static void createProject(IProjectDescription description, IProject proj, final IBundleProjectService service = context.getService(ref); IBundleProjectDescription bundleDesc = service.getDescription(proj); bundleDesc.setLocationURI(description.getLocationURI()); - IPath[] additionalBinIncludes = new IPath[] { new Path("plugin.xml")}; - ProjectGenerationHelper.fillProjectMetadata(proj, dependencies, DEFAULT_VIATRA_IMPORT_PACKAGES, service, bundleDesc, additionalBinIncludes); + IPath[] additionalBinIncludes = new IPath[] { new Path("plugin.xml") }; + ProjectGenerationHelper.fillProjectMetadata(proj, dependencies, DEFAULT_VIATRA_IMPORT_PACKAGES, service, + bundleDesc, additionalBinIncludes); bundleDesc.apply(monitor); - //Ensure UTF-8 encoding + // Ensure UTF-8 encoding proj.setDefaultCharset(UTF8_ENCODING, monitor); // Adding VIATRA Query-specific natures ProjectGenerationHelper.updateNatures(proj, ImmutableList.of(ViatraQueryNature.XTEXT_NATURE_ID, ViatraQueryNature.NATURE_ID), - ImmutableList.of(), monitor); + ImmutableList. of(), monitor); } finally { monitor.done(); if (context != null && ref != null) { @@ -176,8 +211,8 @@ public static void createProject(IProjectDescription description, IProject proj, /** * Updates the set of project natures of a selected project */ - public static void updateNatures(IProject proj, Collection naturesToAdd, - Collection naturesToRemove, IProgressMonitor monitor) throws CoreException { + public static void updateNatures(IProject proj, Collection naturesToAdd, Collection naturesToRemove, + IProgressMonitor monitor) throws CoreException { IProjectDescription desc = proj.getDescription(); Set newNatures = new LinkedHashSet<>(); newNatures.addAll(Arrays.asList(desc.getNatureIds())); @@ -225,7 +260,8 @@ public static void initializePluginProject(IProject project, final List ref = context.getServiceReference(IBundleProjectService.class); final IBundleProjectService service = context.getService(ref); IBundleProjectDescription bundleDesc = service.getDescription(project); - fillProjectMetadata(project, dependencies, Collections.emptyList(), service, bundleDesc, additionalBinIncludes); + fillProjectMetadata(project, dependencies, Collections. emptyList(), service, bundleDesc, + additionalBinIncludes); bundleDesc.apply(monitor); } finally { if (context != null && ref != null) { @@ -244,9 +280,9 @@ public static void initializePluginProject(IProject project, final List * @param service * @param bundleDesc */ - public static void fillProjectMetadata(IProject project, final List dependencies, final List packageImports, - final IBundleProjectService service, IBundleProjectDescription bundleDesc, - final IPath[] additionalBinIncludes) { + public static void fillProjectMetadata(IProject project, final List dependencies, + final List packageImports, final IBundleProjectService service, + IBundleProjectDescription bundleDesc, final IPath[] additionalBinIncludes) { bundleDesc.setBundleName(project.getName()); bundleDesc.setBundleVersion(new Version(0, 0, 1, "qualifier")); bundleDesc.setSingleton(true); @@ -255,14 +291,16 @@ public static void fillProjectMetadata(IProject project, final List depe bundleDesc.setExtensionRegistry(true); bundleDesc.setBinIncludes(additionalBinIncludes); - bundleDesc.setBundleClasspath(getUpdatedBundleClasspathEntries(new IBundleClasspathEntry[0], SINGLESOURCEFOLDER, service)); + bundleDesc.setBundleClasspath( + getUpdatedBundleClasspathEntries(new IBundleClasspathEntry[0], SINGLESOURCEFOLDER, service)); bundleDesc.setExecutionEnvironments(new String[] { ViatraQueryNature.EXECUTION_ENVIRONMENT }); // Adding dependencies - IRequiredBundleDescription[] reqBundles = Lists.transform(dependencies, - new IDToRequireBundleTransformer(service)).toArray(new IRequiredBundleDescription[dependencies.size()]); + IRequiredBundleDescription[] reqBundles = Lists + .transform(dependencies, new IDToRequireBundleTransformer(service)) + .toArray(new IRequiredBundleDescription[dependencies.size()]); bundleDesc.setRequiredBundles(reqBundles); - IPackageImportDescription[] importArray = Lists.transform(packageImports, - new IDToPackageImportTransformer(service)) + IPackageImportDescription[] importArray = Lists + .transform(packageImports, new IDToPackageImportTransformer(service)) .toArray(new IPackageImportDescription[packageImports.size()]); bundleDesc.setPackageImports(importArray); } @@ -304,6 +342,7 @@ public static boolean checkBundleDependency(IProject project, String dependency) /** * Ensures that the given plug-in project is declared a singleton. This is required for extensions. + * * @param project * @throws CoreException * @since 2.0 @@ -325,7 +364,7 @@ public static void ensureSingletonDeclaration(IProject project) throws CoreExcep } } } - + /** * Updates project manifest to ensure the selected bundle dependencies are set. Does not change existing * dependencies. @@ -334,22 +373,25 @@ public static void ensureSingletonDeclaration(IProject project) throws CoreExcep * @param dependencies * @throws CoreException */ - public static void ensureBundleDependencies(IProject project, final List dependencies) throws CoreException { - ensureBundleDependenciesAndPackageImports(project, dependencies, Collections.emptyList(), new NullProgressMonitor()); + public static void ensureBundleDependencies(IProject project, final List dependencies) + throws CoreException { + ensureBundleDependenciesAndPackageImports(project, dependencies, Collections. emptyList(), + new NullProgressMonitor()); } /** - * Updates project manifest to ensure the selected package imports are set. Does not change existing - * package imports or required bundle declarations. + * Updates project manifest to ensure the selected package imports are set. Does not change existing package imports + * or required bundle declarations. * * @param project * @param packageImports * @throws CoreException */ public static void ensurePackageImports(IProject project, final List packageImports) throws CoreException { - ensureBundleDependenciesAndPackageImports(project, Collections.emptyList(), packageImports, new NullProgressMonitor()); + ensureBundleDependenciesAndPackageImports(project, Collections. emptyList(), packageImports, + new NullProgressMonitor()); } - + /** * Updates project manifest to ensure the selected bundle dependencies are set. Does not change existing * dependencies. @@ -360,8 +402,8 @@ public static void ensurePackageImports(IProject project, final List pac * @param monitor * @throws CoreException */ - public static void ensureBundleDependenciesAndPackageImports(IProject project, final List dependencies, final List importPackages, - IProgressMonitor monitor) throws CoreException { + public static void ensureBundleDependenciesAndPackageImports(IProject project, final List dependencies, + final List importPackages, IProgressMonitor monitor) throws CoreException { checkOpenPDEProject(project); if (dependencies.isEmpty() && importPackages.isEmpty()) { return; @@ -373,7 +415,9 @@ public static void ensureBundleDependenciesAndPackageImports(IProject project, f ref = context.getServiceReference(IBundleProjectService.class); final IBundleProjectService service = context.getService(ref); IBundleProjectDescription bundleDesc = service.getDescription(project); - List nonSelfDependencies = dependencies.stream().filter(dependency -> !Objects.equals(bundleDesc.getSymbolicName(), dependency)).collect(Collectors.toList()); + List nonSelfDependencies = dependencies.stream() + .filter(dependency -> !Objects.equals(bundleDesc.getSymbolicName(), dependency)) + .collect(Collectors.toList()); if (!nonSelfDependencies.isEmpty()) { ensureBundleDependencies(service, bundleDesc, nonSelfDependencies); } @@ -392,15 +436,18 @@ public static void ensureBundleDependenciesAndPackageImports(IProject project, f * Updates the plugin dependency settings of the given project by replacing entries according to the given map. This * method preserves optional and re-export flags, and updates version settings (if was originally set) * - * @param project the project to apply changes on - * @param replacedDependencies bundle IDs to replace dependencies - * @param versions version ranges to set for the new entries + * @param project + * the project to apply changes on + * @param replacedDependencies + * bundle IDs to replace dependencies + * @param versions + * version ranges to set for the new entries * @param monitor * @throws CoreException * @since 1.5 */ - public static void replaceBundleDependencies(IProject project, - final Map replacedDependencies, final Map versions, IProgressMonitor monitor) throws CoreException{ + public static void replaceBundleDependencies(IProject project, final Map replacedDependencies, + final Map versions, IProgressMonitor monitor) throws CoreException { checkOpenPDEProject(project); BundleContext context = null; ServiceReference ref = null; @@ -420,7 +467,7 @@ public static void replaceBundleDependencies(IProject project, } } } - + /** * Updates plugin Manifest file to replace plug-in dependencies according to the given Map * @@ -428,41 +475,40 @@ public static void replaceBundleDependencies(IProject project, * @param bundleDesc * @param replacedDependencies */ - public static void replaceBundleDependencies(IBundleProjectService service, IBundleProjectDescription bundleDesc, - final Map replacedDependencies, final Map versions){ - + public static void replaceBundleDependencies(IBundleProjectService service, IBundleProjectDescription bundleDesc, + final Map replacedDependencies, final Map versions) { + IRequiredBundleDescription[] existingDependencies = bundleDesc.getRequiredBundles(); if (existingDependencies == null) { existingDependencies = new IRequiredBundleDescription[0]; } - + Set toRemove = new HashSet<>(); Set toAdd = new LinkedHashSet<>(); - - for(IRequiredBundleDescription r : existingDependencies){ + + for (IRequiredBundleDescription r : existingDependencies) { String id = r.getName(); - String replacedId = replacedDependencies.get(id); - if (replacedId != null){ + String replacedId = replacedDependencies.get(id); + if (replacedId != null) { VersionRange v = r.getVersionRange(); toRemove.add(id); - if (v != null){ + if (v != null) { v = versions.get(replacedId); } toAdd.add(service.newRequiredBundle(replacedId, v, r.isOptional(), r.isExported())); } } - + List dependencies = new LinkedList<>(); - for(IRequiredBundleDescription r : existingDependencies){ - if (!toRemove.contains(r.getName())){ + for (IRequiredBundleDescription r : existingDependencies) { + if (!toRemove.contains(r.getName())) { dependencies.add(r); } } dependencies.addAll(toAdd); bundleDesc.setRequiredBundles(dependencies.toArray(new IRequiredBundleDescription[dependencies.size()])); } - - + /** * Updates project manifest to ensure the selected bundle dependencies are set. Does not change existing * dependencies. @@ -473,12 +519,13 @@ public static void replaceBundleDependencies(IBundleProjectService service, IBun */ static void ensureBundleDependencies(IBundleProjectService service, IBundleProjectDescription bundleDesc, final List dependencyNames) { - + IRequiredBundleDescription[] existingDependencies = bundleDesc.getRequiredBundles(); if (existingDependencies == null) { - List missingDependencies = Lists.transform(dependencyNames, new IDToRequireBundleTransformer(service)); + List missingDependencies = Lists.transform(dependencyNames, + new IDToRequireBundleTransformer(service)); bundleDesc.setRequiredBundles(Iterables.toArray(missingDependencies, IRequiredBundleDescription.class)); - + } else { List missingDependencyNames = new ArrayList<>(dependencyNames); for (IRequiredBundleDescription bundle : existingDependencies) { @@ -486,16 +533,17 @@ static void ensureBundleDependencies(IBundleProjectService service, IBundleProje missingDependencyNames.remove(bundle.getName()); } } - List missingDependencies = Lists.transform(missingDependencyNames, new IDToRequireBundleTransformer(service)); + List missingDependencies = Lists.transform(missingDependencyNames, + new IDToRequireBundleTransformer(service)); // Since Kepler setRequiredBundles overwrites existing dependencies - Iterable dependenciesToSet = - Iterables.concat(missingDependencies, Arrays.asList(existingDependencies)); + Iterable dependenciesToSet = Iterables.concat(missingDependencies, + Arrays.asList(existingDependencies)); bundleDesc.setRequiredBundles(Iterables.toArray(dependenciesToSet, IRequiredBundleDescription.class)); } } - + /** * Updates project manifest to ensure the selected bundle dependencies are set. Does not change existing * dependencies. @@ -507,8 +555,9 @@ static void ensureBundleDependencies(IBundleProjectService service, IBundleProje static void ensurePackageImports(final IBundleProjectService service, IBundleProjectDescription bundleDesc, final List packageImports) { IPackageImportDescription[] importArray = bundleDesc.getPackageImports(); - List importList = importArray == null ? Lists - . newArrayList() : Arrays.asList(importArray); + List importList = importArray == null + ? Lists. newArrayList() + : Arrays.asList(importArray); List newImports = Lists.newArrayList(packageImports); for (IPackageImportDescription importDecl : importList) { final String packageName = importDecl.getName(); @@ -542,9 +591,9 @@ public static void ensurePackageExports(IProject project, final Collection exports, IProgressMonitor monitor) - throws CoreException { - Preconditions.checkArgument(project.exists() && project.isOpen() && (PDE.hasPluginNature(project)), + public static void ensurePackageExports(IProject project, final Collection exports, + IProgressMonitor monitor) throws CoreException { + Preconditions.checkArgument(project.exists() && project.isOpen() && (isPDEProject(project)), INVALID_PROJECT_MESSAGE, project.getName()); if (exports.isEmpty()) { return; @@ -577,7 +626,7 @@ public static void ensurePackageExports(IProject project, final Collection dependencies, IProgressMonitor monitor) throws CoreException { - Preconditions.checkArgument(project.exists() && project.isOpen() && (PDE.hasPluginNature(project)), + Preconditions.checkArgument(project.exists() && project.isOpen() && (isPDEProject(project)), INVALID_PROJECT_MESSAGE, project.getName()); if (dependencies.isEmpty()) { return; @@ -617,7 +666,8 @@ static void ensurePackageExports(final IBundleProjectService service, IBundlePro exportList.add(export); } } - exportList.addAll(Collections2.transform(missingExports, input -> service.newPackageExport(input, null, true, null))); + exportList.addAll(Collections2.transform(missingExports, + input -> service.newPackageExport(input, null, true, (String[]) null))); bundleDesc.setPackageExports(exportList.toArray(new IPackageExportDescription[exportList.size()])); } @@ -668,7 +718,7 @@ public static void ensureExtensions(IProject project, Iterable co */ public static void ensureExtensions(IProject project, Iterable contributedExtensions, Iterable> removedExtensions, IProgressMonitor monitor) throws CoreException { - Preconditions.checkArgument(project.exists() && project.isOpen() && (PDE.hasPluginNature(project)), + Preconditions.checkArgument(project.exists() && project.isOpen() && (isPDEProject(project)), INVALID_PROJECT_MESSAGE, project.getName()); if (StringExtensions.isNullOrEmpty(project.getName())) { @@ -680,7 +730,7 @@ public static void ensureExtensions(IProject project, Iterable co modifier.addExtensions(contributedExtensions); modifier.savePluginXml(); } - + /** * Updates project manifest to ensure the selected packages are removed. Does not change existing exports. * @@ -703,7 +753,7 @@ public static void removePackageExports(IProject project, List dependenc */ public static void removeAllExtension(IProject project, Collection> removableExtensionIdentifiers) throws CoreException { - Preconditions.checkArgument(project.exists() && project.isOpen() && (PDE.hasPluginNature(project))); + Preconditions.checkArgument(project.exists() && project.isOpen() && (isPDEProject(project))); if (StringExtensions.isNullOrEmpty(project.getName())) { return; @@ -713,18 +763,20 @@ public static void removeAllExtension(IProject project, modifier.removeExtensions(removableExtensionIdentifiers); modifier.savePluginXml(); } - + /** * Ensures that the project contains the output folder specified by its configuration as source folder. * * @param project * an existing, open plug-in project - * @param outputConfigurations output configurations defining the output folder + * @param outputConfigurations + * output configurations defining the output folder * @param monitor * @throws CoreException * @since 2.0 */ - public static void ensureSourceFolder(IProject project, Collection outputConfigurations, IProgressMonitor monitor) throws CoreException { + public static void ensureSourceFolder(IProject project, Collection outputConfigurations, + IProgressMonitor monitor) throws CoreException { if (!outputConfigurations.isEmpty()) { String sourceFolder = outputConfigurations.iterator().next().getOutputDirectory(); ProjectGenerationHelper.ensureSourceFolder(project, sourceFolder, monitor); @@ -736,12 +788,14 @@ public static void ensureSourceFolder(IProject project, Collection requiredSourceFolders, IProgressMonitor monitor) throws CoreException { - Preconditions.checkArgument(project.exists() && project.isOpen() && (PDE.hasPluginNature(project)), + public static void ensureSourceFolders(IProject project, List requiredSourceFolders, + IProgressMonitor monitor) throws CoreException { + Preconditions.checkArgument(project.exists() && project.isOpen() && (isPDEProject(project)), INVALID_PROJECT_MESSAGE, project.getName()); BundleContext context = null; ServiceReference ref = null; @@ -765,7 +821,8 @@ public static void ensureSourceFolders(IProject project, List requiredSo ref = context.getServiceReference(IBundleProjectService.class); final IBundleProjectService service = context.getService(ref); IBundleProjectDescription bundleDesc = service.getDescription(project); - bundleDesc.setBundleClasspath(getUpdatedBundleClasspathEntries(bundleDesc.getBundleClasspath(), requiredSourceFolders, service)); + bundleDesc.setBundleClasspath( + getUpdatedBundleClasspathEntries(bundleDesc.getBundleClasspath(), requiredSourceFolders, service)); bundleDesc.apply(monitor); } finally { if (context != null && ref != null) { @@ -782,10 +839,12 @@ public static void ensureSourceFolders(IProject project, List requiredSo */ private static IBundleClasspathEntry[] getUpdatedBundleClasspathEntries(final IBundleClasspathEntry[] oldClasspath, final List requiredSourceFolders, final IBundleProjectService service) { - - final Collection existingSourceEntries = (oldClasspath == null) ? new ArrayList<>() : getExistingSourceEntries(oldClasspath); - - Collection missingSourceFolders = Collections2.filter(requiredSourceFolders, entry -> !existingSourceEntries.contains(entry)); + + final Collection existingSourceEntries = (oldClasspath == null) ? new ArrayList<>() + : getExistingSourceEntries(oldClasspath); + + Collection missingSourceFolders = Collections2.filter(requiredSourceFolders, + entry -> !existingSourceEntries.contains(entry)); Collection newClasspathEntries = Collections2.transform(missingSourceFolders, input -> service.newBundleClasspathEntry(new Path(input), null, null)); @@ -793,12 +852,11 @@ private static IBundleClasspathEntry[] getUpdatedBundleClasspathEntries(final IB modifiedClasspathEntries.addAll(newClasspathEntries); return modifiedClasspathEntries.toArray(new IBundleClasspathEntry[modifiedClasspathEntries.size()]); } - + private static Collection getExistingSourceEntries(final IBundleClasspathEntry[] oldClasspath) { Collection classPathSourceList = Collections2.filter(Lists.newArrayList(oldClasspath), entry -> entry.getSourcePath() != null && !entry.getSourcePath().isEmpty()); - return Collections2.transform(classPathSourceList, - entry -> entry.getSourcePath().toString()); + return Collections2.transform(classPathSourceList, entry -> entry.getSourcePath().toString()); } public static String getBundleSymbolicName(IProject project) { From 3312df28660e792dddeb8f22b79fc22bae57e7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Ujhelyi?= Date: Tue, 17 Sep 2024 16:01:45 +0200 Subject: [PATCH 2/3] Minor fixes to maintain compatibility with SimRel 2020-09 #191 --- .../META-INF/MANIFEST.MF | 2 +- .../patternlanguage/emf/tests/projects/DependencyTest.xtend | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/META-INF/MANIFEST.MF b/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/META-INF/MANIFEST.MF index 1a805879cf..de58f20547 100644 --- a/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/META-INF/MANIFEST.MF +++ b/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/META-INF/MANIFEST.MF @@ -20,7 +20,7 @@ Require-Bundle: org.eclipse.viatra.query.patternlanguage.emf;bundle-version="[2. org.eclipse.viatra.query.testing.snapshot;bundle-version="[2.9.0,2.10.0)", org.eclipse.viatra.query.tooling.core;bundle-version="[2.9.0,2.10.0)", org.eclipse.viatra.query.runtime.localsearch;bundle-version="[2.9.0,2.10.0)", - org.eclipse.xtext.xbase.junit;bundle-version="[2.35.0,3.0.0)", + org.eclipse.xtext.xbase.testing;bundle-version="[2.35.0,3.0.0)", org.eclipse.xtext.common.types.ui;bundle-version="[2.35.0,3.0.0)", org.eclipse.jdt.core, org.eclipse.pde.core, diff --git a/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/src/org/eclipse/viatra/query/patternlanguage/emf/tests/projects/DependencyTest.xtend b/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/src/org/eclipse/viatra/query/patternlanguage/emf/tests/projects/DependencyTest.xtend index a39e6bfb5a..56634b04b7 100644 --- a/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/src/org/eclipse/viatra/query/patternlanguage/emf/tests/projects/DependencyTest.xtend +++ b/query/tests/org.eclipse.viatra.query.patternlanguage.emf.ui.tests/src/org/eclipse/viatra/query/patternlanguage/emf/tests/projects/DependencyTest.xtend @@ -54,14 +54,14 @@ class DependencyTest extends AbstractWorkbenchTest { @Test def void ensureSelfDependency() { ProjectGenerationHelper.ensureBundleDependencies(project, Collections.singletonList(testProjectName)) - assertFalse(project.dependencies.map[it.name].contains(testProjectName)) + assertFalse(project.dependencies.map[it.getName()].contains(testProjectName)) } @Test def void ensureDependency() { val projectName = "org.eclipse.emf" ProjectGenerationHelper.ensureBundleDependencies(project, Collections.singletonList(projectName)) - assertTrue(project.dependencies.map[it.name].contains(projectName)) + assertTrue(project.dependencies.map[it.getName()].contains(projectName)) } private def getDependencies(IProject project) { From 5d46adbc31b472c12d7f1ee36b12505b0dd4330d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Ujhelyi?= Date: Wed, 18 Sep 2024 13:46:16 +0200 Subject: [PATCH 3/3] Simplifies PDE plugin check #191 --- .../core/project/ProjectGenerationHelper.java | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java index 7a04dd3485..d038cefbd4 100644 --- a/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java +++ b/query/plugins/org.eclipse.viatra.query.tooling.core/src/org/eclipse/viatra/query/tooling/core/project/ProjectGenerationHelper.java @@ -10,8 +10,6 @@ package org.eclipse.viatra.query.tooling.core.project; import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -44,7 +42,6 @@ import org.eclipse.pde.core.project.IRequiredBundleDescription; import org.eclipse.pde.internal.core.PDECore; import org.eclipse.viatra.query.runtime.ViatraQueryRuntimePlugin; -import org.eclipse.viatra.query.runtime.exception.ViatraQueryException; import org.eclipse.viatra.query.runtime.matchers.util.Preconditions; import org.eclipse.viatra.query.tooling.core.generator.ExtensionData; import org.eclipse.viatra.query.tooling.core.generator.ViatraQueryGeneratorPlugin; @@ -71,6 +68,9 @@ public abstract class ProjectGenerationHelper { private static final String INVALID_PROJECT_MESSAGE = "Invalid project %s. Only existing, open plug-in projects are supported by the generator."; private static final String UTF8_ENCODING = "UTF-8"; + + // PDE does not have any non-internal API where this nature ID is defined + private static final String PDE_PLUGIN_NATURE = "org.eclipse.pde.PluginNature"; /** * Contains the default bundle requirements for VIATRA in a format that can be loaded into @@ -119,28 +119,8 @@ public IRequiredBundleDescription apply(String input) { } } - private static boolean isPDEProject(IProject project) { - /* - * In SimRel 2024-09 the PDE#hasPluginNature call was moved to - * PluginProject#isPluginProject, but this is incompatible with 2022-06 - * TODO Rreplace this with a direct method call after minimum requirements are updated - */ - try { - Method checkMethod; - - try { - final Class pluginProjectClass = Class - .forName("org.eclipse.pde.internal.core.natures.PluginProject"); - checkMethod = pluginProjectClass.getMethod("isPluginProject", IProject.class); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - final Class pdeClass = Class.forName("org.eclipse.pde.internal.core.natures.PDE"); - checkMethod = pdeClass.getMethod("hasPluginNature", IProject.class); - } - - return (Boolean) checkMethod.invoke(checkMethod, project); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new ViatraQueryException("Unsupported PDE version", "Erroneous installation, required PDE method cannot be called", e); - } + private static boolean isPDEProject(IProject project) throws CoreException { + return project.hasNature(PDE_PLUGIN_NATURE); } /** @@ -149,7 +129,14 @@ private static boolean isPDEProject(IProject project) { * @param project */ public static boolean isOpenPDEProject(IProject project) { - return project.exists() && project.isOpen() && (isPDEProject(project)); + try { + return project.exists() && project.isOpen() && isPDEProject(project); + } catch (CoreException e) { + // Should not happen (the exists and isOpen checks should catch most errors), + // but if for any reason the PDE nature cannot be identified consider the + // project incorrect + return false; + } } /**