diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java index d9a04792ca4..74f80f4f17b 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECoreMessages.java @@ -26,6 +26,8 @@ public class PDECoreMessages extends NLS { public static String BuildErrorReporter_cannotFindJar; + public static String BundleErrorReporter_MissingMandatoryDirective; + public static String BundleErrorReporter_ConflictingAutoModule; public static String BundleErrorReporter_badFilter; @@ -247,6 +249,10 @@ public class PDECoreMessages extends NLS { public static String ManifestConsistencyChecker_buildPropertiesSubtask; + public static String AddMandatoryAttrResolution_label; + + public static String AddMandatoryAttrResolution_description; + public static String BuildErrorReporter_missingEntry; public static String BuildErrorReporter_missingFolder; public static String BuildErrorReporter_emptyEntry; diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java index a10bff21621..10748691a5c 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BundleErrorReporter.java @@ -22,9 +22,9 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.Deque; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.List; @@ -34,6 +34,7 @@ import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -56,6 +57,7 @@ import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.environments.IExecutionEnvironment; import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager; +import org.eclipse.osgi.service.resolver.BaseDescription; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.service.resolver.BundleSpecification; import org.eclipse.osgi.service.resolver.ExportPackageDescription; @@ -1172,7 +1174,7 @@ private void validateImportPackage(IProgressMonitor monitor) { } } - HashMap exported = getAvailableExportedPackages(desc.getContainingState()); + Map> exported = getAvailableExportedPackages(desc.getContainingState()); ImportPackageSpecification[] imports = desc.getImportPackages(); if (desc.hasDynamicImports()) { @@ -1210,8 +1212,10 @@ private void validateImportPackage(IProgressMonitor monitor) { boolean optional = isOptional(element); int severity = getRequireBundleSeverity(element, optional); - ExportPackageDescription export = exported.get(name); - if (export != null) { + List exports = exported.getOrDefault(name, List.of()); + if (!exports.isEmpty()) { + exports.sort(RESOLVED_FIRST); + for (ExportPackageDescription export : exports) { if (export.getSupplier().isResolved()) { Version version = export.getVersion(); org.eclipse.osgi.service.resolver.VersionRange range = importSpec.getVersionRange(); @@ -1220,18 +1224,47 @@ private void validateImportPackage(IProgressMonitor monitor) { addMarkerAttribute(marker,PDEMarkerFactory.compilerKey,CompilerFlags.P_UNRESOLVED_IMPORTS); return; } + String[] mandatoryAttributes = (String[]) export.getDirective(Constants.RESOLUTION_MANDATORY); + if (mandatoryAttributes != null) { + Map exportAttributes = export.getAttributes(); + Map importAttributes = importSpec.getAttributes(); + for (String mandatory : mandatoryAttributes) { + Object exportValue = exportAttributes != null ? exportAttributes.get(mandatory) : null; + Object importValue = importAttributes != null ? importAttributes.get(mandatory) : null; + + if (importValue == null || !importValue.equals(exportValue)) { + VirtualMarker marker = report( + NLS.bind(PDECoreMessages.BundleErrorReporter_MissingMandatoryDirective, + new String[] { name, mandatory, export.getExporter().getName() }), + getPackageLine(header, element), severity, + PDEMarkerFactory.M_NO_MANDATORY_ATTR_IMPORT_PACKAGE, + PDEMarkerFactory.CAT_FATAL); + addMarkerAttribute(marker, PDEMarkerFactory.compilerKey, + CompilerFlags.P_UNRESOLVED_IMPORTS); + + if (marker != null) { + marker.setAttribute("packageName", name); //$NON-NLS-1$ + marker.setAttribute("mandatoryAttrName", mandatory); //$NON-NLS-1$ + marker.setAttribute("mandatoryAttrValue", exportValue); //$NON-NLS-1$ + } + } + } + } } else { VirtualMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_unresolvedExporter,new String[] { export.getSupplier().getSymbolicName(), name }),getPackageLine(header, element), severity, PDEMarkerFactory.CAT_OTHER); addMarkerAttribute(marker,PDEMarkerFactory.compilerKey, CompilerFlags.P_UNRESOLVED_IMPORTS); return; } } + return; + } VirtualMarker marker = report(NLS.bind(PDECoreMessages.BundleErrorReporter_PackageNotExported, name), getPackageLine(header, element), severity, PDEMarkerFactory.M_IMPORT_PKG_NOT_AVAILABLE, PDEMarkerFactory.CAT_FATAL); addMarkerAttribute(marker, PDEMarkerFactory.compilerKey, CompilerFlags.P_UNRESOLVED_IMPORTS); if (marker != null) { + // marker.setAttribute(PDEMarkerFactory.M_NO_MANDATORY_ATTR_IMPORT_PACKAGE); marker.setAttribute("packageName", name); //$NON-NLS-1$ if (optional) { marker.setAttribute("optional", true); //$NON-NLS-1$ @@ -1241,24 +1274,13 @@ private void validateImportPackage(IProgressMonitor monitor) { } } - private HashMap getAvailableExportedPackages(State state) { - BundleDescription[] bundles = state.getBundles(); + private static final Comparator RESOLVED_FIRST = Comparator + .comparing((BaseDescription d) -> d.getSupplier().isResolved()).reversed(); // false exported = new HashMap<>(); - for (BundleDescription bundle : bundles) { - ExportPackageDescription[] exports = bundle.getExportPackages(); - for (ExportPackageDescription export : exports) { - String name = export.getName(); - if (exported.containsKey(name)) { - if (export.getSupplier().isResolved()) { - exported.put(name, export); - } - } else { - exported.put(name, export); - } - } - } - return exported; + private Map> getAvailableExportedPackages(State state) { + BundleDescription[] bundles = state.getBundles(); + return Arrays.stream(bundles).map(b -> b.getExportPackages()).flatMap(Arrays::stream) + .collect(Collectors.groupingBy(BaseDescription::getName, Collectors.toCollection(ArrayList::new))); } protected void validateExportPackage(IProgressMonitor monitor) { diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java index 6616b25b4f1..355b55cd811 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/PDEMarkerFactory.java @@ -76,7 +76,8 @@ public class PDEMarkerFactory { public static final int M_EXEC_ENV_TOO_LOW = 0x1029; // other problem public static final int M_CONFLICTING_AUTOMATIC_MODULE = 0x1030; // other // problem - + public static final int M_NO_MANDATORY_ATTR_IMPORT_PACKAGE = 0x1031; // fatal + // problem // build properties fixes public static final int B_APPEND_SLASH_FOLDER_ENTRY = 0x2001; public static final int B_REMOVE_SLASH_FILE_ENTRY = 0x2002; diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties index 44eb4c4905c..fd939892e92 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/pderesources.properties @@ -126,6 +126,9 @@ BuildErrorReporter_CompilercomplianceLevel=Compiler compliance level Builders_Manifest_key_not_found = Key ''{0}'' is not found in localization properties file: {1} Builders_Manifest_useless_file = A plug-in manifest must contain at least one extension or extension point BuildErrorReporter_missingEntry = ''{0}'' build entry is missing +AddMandatoryAttrResolution_label=Adds mandatory attribute ''{0}'' with value ''{1}'' +AddMandatoryAttrResolution_description=Add mandatory attribute value +BundleErrorReporter_MissingMandatoryDirective=The imported package ''{0}'' is missing the mandatory attribute ''{1}'' with a exported value from ''{2}'' bundle Builders_Convert_missingAttribute = ''{0}'' attribute is missing Builders_Convert_illegalValue = Illegal value for ''{0}'' attribute diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddMandatoryAttributeImportPackageResolution.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddMandatoryAttributeImportPackageResolution.java new file mode 100644 index 00000000000..1cb325bc304 --- /dev/null +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/AddMandatoryAttributeImportPackageResolution.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2023 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *Qui + * Contributors: + * IBM Corporation - initial API and implementation + * Alshama M S Initial implementation + *******************************************************************************/ + +package org.eclipse.pde.internal.ui.correction; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.osgi.util.NLS; +import org.eclipse.pde.internal.core.PDECoreMessages; +import org.eclipse.pde.internal.core.text.bundle.Bundle; +import org.eclipse.pde.internal.core.text.bundle.BundleModel; +import org.eclipse.pde.internal.core.text.bundle.ImportPackageHeader; +import org.eclipse.pde.internal.core.text.bundle.ImportPackageObject; +import org.eclipse.pde.internal.ui.PDEPlugin; +import org.osgi.framework.Constants; + +/** + *

+ * Represents a resolution to the problem of import package resolution failure + * due to missing mandatory attributes + *

+ */ +public class AddMandatoryAttributeImportPackageResolution extends AbstractManifestMarkerResolution { + /** + * Creates a new resolution + */ + public AddMandatoryAttributeImportPackageResolution(IMarker marker) { + super(AbstractPDEMarkerResolution.CREATE_TYPE, marker); + } + + /** + * Resolves the problem by adding mandatory attribute + */ + @Override + protected void createChange(BundleModel model) { + try { + String packagename = (String) marker.getAttribute("packageName"); //$NON-NLS-1$ + Bundle bundle = (Bundle) model.getBundle(); + ImportPackageHeader header = (ImportPackageHeader) bundle.getManifestHeader(Constants.IMPORT_PACKAGE); + if (header != null) { + ImportPackageObject obj = header.getPackage(packagename); + obj.setAttribute(getAttributeName(), getAttributeValue()); + header.update(true); + } + } catch (CoreException e) { + PDEPlugin.log(e); + } + } + + private String getAttributeValue() throws CoreException { + return (String) marker.getAttribute("mandatoryAttrValue"); //$NON-NLS-1$ + } + + private String getAttributeName() throws CoreException { + return (String) marker.getAttribute("mandatoryAttrName"); //$NON-NLS-1$ + } + + @Override + public String getDescription() { + try { + return NLS.bind(PDECoreMessages.AddMandatoryAttrResolution_label, getAttributeName(), getAttributeValue()); + } catch (CoreException e) { + PDEPlugin.log(e); + return NLS.bind(PDECoreMessages.AddMandatoryAttrResolution_label, "", ""); //$NON-NLS-1$//$NON-NLS-2$ + } + } + + @Override + public String getLabel() { + return PDECoreMessages.AddMandatoryAttrResolution_description; + } + +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java index 5241444319d..20223bdd405 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/correction/ResolutionGenerator.java @@ -137,6 +137,8 @@ public IMarkerResolution[] getNonConfigSevResolutions(IMarker marker) { return new IMarkerResolution[] {new NoLineTerminationResolution(AbstractPDEMarkerResolution.REMOVE_TYPE, marker)}; case PDEMarkerFactory.M_R4_SYNTAX_IN_R3_BUNDLE : return new IMarkerResolution[] {new AddBundleManifestVersionResolution(marker)}; + case PDEMarkerFactory.M_NO_MANDATORY_ATTR_IMPORT_PACKAGE: + return new IMarkerResolution[] { new AddMandatoryAttributeImportPackageResolution(marker) }; case PDEMarkerFactory.M_SERVICECOMPONENT_MISSING_LAZY: return new IMarkerResolution[] { new AddActivationPolicyResolution(AbstractPDEMarkerResolution.CREATE_TYPE, marker) };