Skip to content

Commit

Permalink
Quick-fix for import package resolution failure due to missing mandatory
Browse files Browse the repository at this point in the history
attributes:
  • Loading branch information
alshamams authored and laeubi committed Feb 11, 2024
1 parent 1d5bd08 commit aabd31d
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -1172,7 +1174,7 @@ private void validateImportPackage(IProgressMonitor monitor) {
}
}

HashMap<String, ExportPackageDescription> exported = getAvailableExportedPackages(desc.getContainingState());
Map<String, List<ExportPackageDescription>> exported = getAvailableExportedPackages(desc.getContainingState());

ImportPackageSpecification[] imports = desc.getImportPackages();
if (desc.hasDynamicImports()) {
Expand Down Expand Up @@ -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<ExportPackageDescription> 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();
Expand All @@ -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<String, Object> exportAttributes = export.getAttributes();
Map<String, Object> 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$
Expand All @@ -1241,24 +1274,13 @@ private void validateImportPackage(IProgressMonitor monitor) {
}
}

private HashMap<String, ExportPackageDescription> getAvailableExportedPackages(State state) {
BundleDescription[] bundles = state.getBundles();
private static final Comparator<BaseDescription> RESOLVED_FIRST = Comparator
.comparing((BaseDescription d) -> d.getSupplier().isResolved()).reversed(); // false<true

HashMap<String, ExportPackageDescription> 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<String, List<ExportPackageDescription>> 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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <ALSHAMA.M.S@ibm.com> 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;

/**
* <p>
* Represents a resolution to the problem of import package resolution failure
* due to missing mandatory attributes
* </p>
*/
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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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) };
Expand Down

0 comments on commit aabd31d

Please sign in to comment.