From d036e52dfc395712be239bfcc0080c61d442c06d Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Wed, 10 Jul 2024 10:45:47 -0400 Subject: [PATCH 1/8] Resolver passing platforms --- .../resolver/RepositoryResolver.java | 64 +++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java index f2d6ca50aa4..ca5825e1775 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java @@ -82,6 +82,11 @@ public class RepositoryResolver { */ Set requestedFeatureNames; + /** + * The platforms passed to {@link #resolve(Collection)} which will help resolve versionless features + */ + Collection requestedPlatformNames; + /** * The list of samples the user has requested to install */ @@ -308,7 +313,7 @@ void indexSamples() { * @throws RepositoryResolutionException If the resource cannot be resolved */ public Collection> resolve(Collection toResolve) throws RepositoryResolutionException { - return resolve(toResolve, ResolutionMode.IGNORE_CONFLICTS); + return resolve(toResolve, null, ResolutionMode.IGNORE_CONFLICTS); } /** @@ -370,14 +375,65 @@ public Collection> resolve(String toResolve) throws Rep * @throws RepositoryResolutionException If the resource cannot be resolved */ public Collection> resolveAsSet(Collection toResolve) throws RepositoryResolutionException { - return resolve(toResolve, ResolutionMode.DETECT_CONFLICTS); + return resolve(toResolve, null, ResolutionMode.DETECT_CONFLICTS); + } + + /** + * Takes a list of feature names that the user wants to install and returns a minimal set of the {@link RepositoryResource}s that should be installed to allow those features to + * start together in one server. + *

+ * This method uses the same resolution logic that is used by the kernel at server startup to decide which features to start. Therefore calling this method with a list of + * feature names and installing the resources returned will guarantee that a server which has the same list of feature names in its server.xml will start. + *

+ * The caller must provide the full set of features from the server.xml, including those that are already installed, so that tolerated dependencies and auto-features can be + * resolved correctly. + *

+ * This method will fail if there's no valid set of dependencies for the required features that doesn't include conflicting versions of singleton features. + *

+ * For example, {@code resolve(Arrays.asList("javaee-7.0", "javaee-8.0"))} would work but {@code resolveAsSet(Arrays.asList("javaee-7.0", "javaee-8.0"))} would fail because + * javaee-7.0 and javaee-8.0 contain features which conflict with each other (and other versions are not tolerated). + *

+ * This method guarantees that it will return all the features required to start the requested features but will not ensure that the requested features will work with features + * which were already installed but were not requested in the call to this method. + *

+ * For example, if {@code ejbLite-3.2} is already installed and {@code resolve(Arrays.asList("cdi-2.0"))} is called, it will not return the autofeature which would be required + * for {@code cdi-2.0} and {@code ejbLite-3.2} to work together. + * + * @param toResolve A collection of the identifiers of the resources to resolve. It should be in the form:
+ * {name}/{version}
+ *

Where the {name} can be either the symbolic name, short name or lower case short name of the resource and /{version} is + * optional. The collection may contain a mixture of symbolic names and short names. Must not be null or empty.

+ * @param platforms A collection of the identifiers of the platforms used for resolving versionless features + * + * @return

A collection of ordered lists of {@link RepositoryResource}s to install. Each list represents a collection of resources that must be installed together or not + * at all. They should be installed in the iteration order of the list(s). Note that if a resource is required by multiple different resources then it will appear in + * multiple lists. For instance if you have requested to install A and B and A requires N which requires M and O whereas B requires Z that requires O then the returned + * collection will be (represented in JSON):

+ * + * [[M, O, N, A],[O, Z, B]] + * + *

This will not return null although it may return an empty collection if there isn't anything to install (i.e. it resolves to resources that are + * already installed)

+ *

Every auto-feature will have it's own list in the collection, this is to stop the failure to install either an auto feature or one of it's dependencies from + * stopping everything from installing. Therefore if you have features A and B that are required to provision auto feature C and you ask to resolve A and B then this + * method will return:

+ * + * [[A],[B],[A,B,C]] + * + * + * @throws RepositoryResolutionException If the resource cannot be resolved + */ + public Collection> resolveAsSet(Collection toResolve, Collection platforms) throws RepositoryResolutionException { + return resolve(toResolve, platforms, ResolutionMode.DETECT_CONFLICTS); } - Collection> resolve(Collection toResolve, ResolutionMode resolutionMode) throws RepositoryResolutionException { + Collection> resolve(Collection toResolve, Collection platforms, ResolutionMode resolutionMode) throws RepositoryResolutionException { initResolve(); initializeResolverRepository(installDefinition); processNames(toResolve); + //Set platform names passed for kernel resolver resolution + requestedPlatformNames = platforms; if (resolutionMode == ResolutionMode.DETECT_CONFLICTS) { // Call the kernel resolver to determine the features needed @@ -477,7 +533,7 @@ private NameAndVersion splitRequestedNameAndVersion(String nameAndVersion) { */ void resolveFeaturesAsSet() { FeatureResolver resolver = new FeatureResolverImpl(); - Result result = resolver.resolve(resolverRepository, kernelFeatures, featureNamesToResolve, Collections. emptySet(), false, Collections. emptySet()); + Result result = resolver.resolve(resolverRepository, kernelFeatures, featureNamesToResolve, Collections. emptySet(), false, requestedPlatformNames); featureConflicts.putAll(result.getConflicts()); From f6dc2789ac07a6b65d5bc1ccb3b9bca07c906980 Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Wed, 10 Jul 2024 10:54:04 -0400 Subject: [PATCH 2/8] Install now passing platforms --- .../src/com/ibm/ws/install/internal/InstallKernelMap.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/com.ibm.ws.install/src/com/ibm/ws/install/internal/InstallKernelMap.java b/dev/com.ibm.ws.install/src/com/ibm/ws/install/internal/InstallKernelMap.java index e3e94ae255d..6d28caa2fc9 100755 --- a/dev/com.ibm.ws.install/src/com/ibm/ws/install/internal/InstallKernelMap.java +++ b/dev/com.ibm.ws.install/src/com/ibm/ws/install/internal/InstallKernelMap.java @@ -963,9 +963,8 @@ public Collection singleFileResolve() { if (!isInstallServerFeature) { resolveResult = resolver.resolve((Collection) data.get(InstallConstants.FEATURES_TO_RESOLVE)); } else { - resolveResult = resolver.resolveAsSet((Collection) data.get(InstallConstants.FEATURES_TO_RESOLVE)); - // TODO - After Resolver changes, also start passing platforms - // (Collection) data.get(InstallConstants.PLATFORMS)); + resolveResult = resolver.resolveAsSet((Collection) data.get(InstallConstants.FEATURES_TO_RESOLVE), + (Collection) data.get(InstallConstants.PLATFORMS)); } if (!resolveResult.isEmpty()) { From 54d736186bb48d1605b880b1edc8194683f92a9e Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Thu, 11 Jul 2024 08:30:25 -0400 Subject: [PATCH 3/8] Implmenting ESA feature apis --- .../internal/kernel/KernelResolverEsa.java | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java index 4ba46596c12..8a9ed9294b4 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java @@ -227,20 +227,50 @@ public boolean isSupportedFeatureVersion() { } // - + @Override public List getPlatformNames() { - return null; // TODO + + return esaResource.getPlatforms() == null ? new ArrayList() : new ArrayList(esaResource.getPlatforms()); } @Override public String getPlatformName() { - return null; // TODO + return (!getPlatformNames().isEmpty() ? getPlatformNames().get(0) : null); } - + + /** + * Tell if this is a versionless feature. + * + * Currently these are: + * + *
  • public
  • + *
  • platformless
  • + *
  • have a short name that is equal to the feature name
  • + *
  • contain ".versionless." in their symbolic name.
  • + *
  • does not contain ".internal.versionless." in their symbolic name.
  • + *
+ * + * @return True or false telling if this is a versionless feature. + */ @Override public boolean isVersionless() { - return false; // TODO + if (!getVisibility().equals(Visibility.PUBLIC) || (getPlatformName() != null)) { + return false; + } + + String shortName = getIbmShortName(); + if ((shortName == null) || !shortName.equals(getFeatureName())) { + return false; + } + + if (getSymbolicName().indexOf(".versionless.") == -1) { + return false; + } else if (getSymbolicName().indexOf(".internal.versionless.") != -1) { + return false; + } + + return true; } @Override @@ -248,8 +278,23 @@ public boolean isConvenience() { return false; // TODO } + /** + * Tell if this is a compatibility feature. + * + *
  • private
  • + *
  • do not have a short name
  • + *
  • contain ".eeCompatible-" or ".mpCompatible-" in their symbolic name.
  • + *
+ * + * @return True or false telling if this is a versionless feature. + */ @Override public boolean isCompatibility() { - return false; // TODO + if (!getVisibility().equals(Visibility.PRIVATE)) { + return false; + } else if (getIbmShortName() != null) { + return false; + } + return (getPlatformName() != null); } } From 190620c51598bddb75e373bed6ad37c70f8ee9b5 Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Fri, 12 Jul 2024 16:44:26 -0400 Subject: [PATCH 4/8] Gather and pass error states from Result --- .../RepositoryResolutionException.java | 81 ++++++++++++++++--- .../resolver/RepositoryResolver.java | 63 ++++++++++++++- 2 files changed, 132 insertions(+), 12 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java index e1dd9f864f7..6ef662fc8d7 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-2.0/ - * + * * SPDX-License-Identifier: EPL-2.0 * * Contributors: @@ -17,6 +17,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.osgi.service.resolver.ResolutionException; @@ -40,14 +41,17 @@ public class RepositoryResolutionException extends RepositoryException { private final Collection missingProductInformation; private final Collection allRequirementsResourcesNotFound; private final Map> featureConflicts; + private Set resolvedPlatforms; + private Set missingPlatforms; + private boolean hasVersionlessIssue; /** * @param cause * @param topLevelFeaturesNotResolved * @param allRequirementsNotFound - * @param missingProductInformation all the product information requirements that could not be found. Can be empty but must not be null + * @param missingProductInformation all the product information requirements that could not be found. Can be empty but must not be null * @param allRequirementsResourcesNotFound The {@link MissingRequirement} objects that were not found. Must not be null. - * @param featureConflicts the details of any feature conflicts which occurred during feature resolution, as returned from {@link Result#getConflicts()} + * @param featureConflicts the details of any feature conflicts which occurred during feature resolution, as returned from {@link Result#getConflicts()} */ public RepositoryResolutionException(ResolutionException cause, Collection topLevelFeaturesNotResolved, Collection allRequirementsNotFound, Collection missingProductInformation, Collection allRequirementsResourcesNotFound, @@ -60,6 +64,30 @@ public RepositoryResolutionException(ResolutionException cause, Collection topLevelFeaturesNotResolved, Collection allRequirementsNotFound, + Collection missingProductInformation, Collection allRequirementsResourcesNotFound, + Map> featureConflicts, Set resolvedPlatforms, Set missingPlatforms) { + super(cause); + this.topLevelFeaturesNotResolved = topLevelFeaturesNotResolved; + this.allRequirementsNotFound = allRequirementsNotFound; + this.missingProductInformation = missingProductInformation; + this.allRequirementsResourcesNotFound = allRequirementsResourcesNotFound; + this.featureConflicts = featureConflicts; + this.resolvedPlatforms = resolvedPlatforms; + this.missingPlatforms = missingPlatforms; + this.hasVersionlessIssue = true; + } + /** * Returns a collection of top level feature names that were not resolved. * @@ -106,9 +134,9 @@ public ResolutionException getCause() { * on a {@link ProductRequirementInformation} is not in the form digit.digit.digit.digit then it will be ignored. * * @param productId The product ID to find the minimum missing version for or null to match to all products - * @param version The version to find the minimum missing version for by matching the first three parts so if you supply "9.0.0.0" and this item applies to version "8.5.5.3" - * and "9.0.0.1" then "9.0.0.1" will be returned. Supply null to match all versions - * @param edition The edition to find the minimum missing version for or null to match to all products + * @param version The version to find the minimum missing version for by matching the first three parts so if you supply "9.0.0.0" and this item applies to version "8.5.5.3" + * and "9.0.0.1" then "9.0.0.1" will be returned. Supply null to match all versions + * @param edition The edition to find the minimum missing version for or null to match to all products * @return The minimum missing version or null if there were no relevant matches */ public String getMinimumVersionForMissingProduct(String productId, String version, String edition) { @@ -152,7 +180,7 @@ private Collection filterVersions(Collection min * This method will iterate through the missingProductInformation and returned a filtered collection of all the {@link ProductRequirementInformation#versionRange}s. * * @param productId The product ID to find the version for or null to match to all products - * @param edition The edition to find the version for or null to match to all editions + * @param edition The edition to find the version for or null to match to all editions * * @return the version ranges which apply to the given product ID and edition */ @@ -185,9 +213,9 @@ private Collection filterVersionRanges(String productId, St * indicate a fairly odd repository setup.

* * @param productId The product ID to find the maximum missing version for or null to match to all products - * @param version The version to find the maximum missing version for by matching the first three parts so if you supply "8.5.5.2" and this item applies to version "8.5.5.3" - * and "9.0.0.1" then "8.5.5.3" will be returned. Supply null to match all versions - * @param edition The edition to find the maximum missing version for or null to match to all products + * @param version The version to find the maximum missing version for by matching the first three parts so if you supply "8.5.5.2" and this item applies to version "8.5.5.3" + * and "9.0.0.1" then "8.5.5.3" will be returned. Supply null to match all versions + * @param edition The edition to find the maximum missing version for or null to match to all products * @return The maximum missing version or null if there were no relevant matches or the maximum version is unbounded */ public String getMaximumVersionForMissingProduct(String productId, String version, String edition) { @@ -251,6 +279,18 @@ public Map> getFeatureConflicts() { @Override public String getMessage() { StringBuilder sb = new StringBuilder(); + + if (hasVersionlessIssue()) { + if (!getMissingPlatforms().isEmpty()) { + for (String missing : getMissingPlatforms()) { + sb.append("Platform: ").append(missing).append(" couldn't be found, no versionless features will be resolved").append("\n"); + } + } + if (getResolvedPlatforms().isEmpty() && getMissingPlatforms().isEmpty()) { + sb.append("Platform couldn't be determined, no versionless features will be resolved").append("\n"); + } + } + for (String missing : getTopLevelFeaturesNotResolved()) { sb.append("Top level feature not resolved: resource=").append(missing).append("\n"); } @@ -329,4 +369,25 @@ private String getResourceName(RepositoryResource resource) { } } + /** + * @return the resolvedPlatforms + */ + public Set getResolvedPlatforms() { + return resolvedPlatforms; + } + + /** + * @return the missingPlatforms + */ + public Set getMissingPlatforms() { + return missingPlatforms; + } + + /** + * @return the hasVersionlessIssue + */ + public boolean hasVersionlessIssue() { + return hasVersionlessIssue; + } + } diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java index ca5825e1775..c79fabd0377 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java @@ -118,6 +118,11 @@ public class RepositoryResolver { */ List resourcesWrongProduct; + /** + * List of platform names that were determined after resolve if versionless features requested, an empty list indicates a failed resolution if versionless features requested. + */ + Set resolvedPlatforms; + /** * List of requirements which couldn't be resolved but for which we found a solution that applied to the wrong product *

@@ -136,6 +141,15 @@ public class RepositoryResolver { * List of all the missing requirements we've found so far */ List missingRequirements; + /** + * List of all the missing platforms after resolution + */ + Set missingPlatforms; + + /** + * Indicates if an issue was found resolving versionless features and platforms + */ + boolean hasVersionlessIssue; /** *

@@ -378,6 +392,19 @@ public Collection> resolveAsSet(Collection toRe return resolve(toResolve, null, ResolutionMode.DETECT_CONFLICTS); } + protected boolean hasRequestedVersionlessFeatures(Collection featureList, KernelResolverRepository repo) { + for (String s : featureList) { + ProvisioningFeatureDefinition feature = repo.getFeature(s); + if (feature == null) + //Can't find the feature of that name - just skip for now.... + continue; + if (feature.isVersionless()) { + return true; + } + } + return false; + } + /** * Takes a list of feature names that the user wants to install and returns a minimal set of the {@link RepositoryResource}s that should be installed to allow those features to * start together in one server. @@ -472,6 +499,9 @@ void initResolve() { missingRequirements = new ArrayList<>(); resolverRepository = null; featureConflicts = new HashMap<>(); + resolvedPlatforms = new HashSet<>(); + missingPlatforms = new HashSet<>(); + hasVersionlessIssue = false; } /** @@ -536,6 +566,8 @@ void resolveFeaturesAsSet() { Result result = resolver.resolve(resolverRepository, kernelFeatures, featureNamesToResolve, Collections. emptySet(), false, requestedPlatformNames); featureConflicts.putAll(result.getConflicts()); + if (hasRequestedVersionlessFeatures(featureNamesToResolve, resolverRepository)) + recordVersionless(result); for (String name : result.getResolvedFeatures()) { ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); @@ -547,6 +579,21 @@ void resolveFeaturesAsSet() { } } + /** + * Record Versionless Messages and Issues + * + * @param result + * @param requestedFeatures + */ + private void recordVersionless(Result result) { + + resolvedPlatforms = result.getResolvedPlatforms(); + missingPlatforms = result.getMissingPlatforms(); + if (resolvedPlatforms.isEmpty() || !missingPlatforms.isEmpty()) + hasVersionlessIssue = true; + + } + /** * Resolves {@link #featureNamesToResolve} using a simple traversal of the dependency tree * @@ -956,7 +1003,7 @@ private EsaResource getResource(ProvisioningFeatureDefinition feature) { * @throws RepositoryResolutionException if any errors occurred during resolution */ private void reportErrors() throws RepositoryResolutionException { - if (resourcesWrongProduct.isEmpty() && missingTopLevelRequirements.isEmpty() && missingRequirements.isEmpty() && featureConflicts.isEmpty()) { + if (resourcesWrongProduct.isEmpty() && missingTopLevelRequirements.isEmpty() && missingRequirements.isEmpty() && featureConflicts.isEmpty() && !hasVersionlessIssue()) { // Everything went fine! return; } @@ -987,7 +1034,19 @@ private void reportErrors() throws RepositoryResolutionException { missingRequirementNames.add(req.getRequirementName()); } - throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts); + if (hasVersionlessIssue()) + throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts, + resolvedPlatforms, missingPlatforms); + else + throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts); + } + + /** + * @return + */ + protected boolean hasVersionlessIssue() { + + return hasVersionlessIssue; } static class NameAndVersion { From b25aec3ae12a8b05ee5090331df6a87d37c4208c Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Fri, 12 Jul 2024 21:33:53 -0400 Subject: [PATCH 5/8] Forwarding Result data --- .../RepositoryResolutionException.java | 37 +++++----- .../resolver/RepositoryResolver.java | 29 ++++++-- .../kernel/KernelResolverRepository.java | 67 +++++++++++++++++++ 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java index 6ef662fc8d7..440ed0ec55c 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -44,6 +45,7 @@ public class RepositoryResolutionException extends RepositoryException { private Set resolvedPlatforms; private Set missingPlatforms; private boolean hasVersionlessIssue; + private List missingBasePlatforms; /** * @param cause @@ -68,15 +70,17 @@ public RepositoryResolutionException(ResolutionException cause, Collectionnull + * @param allRequirementsResourcesNotFound The {@link MissingRequirement} objects that were not found. Must not be null. + * @param featureConflicts the details of any feature conflicts which occurred during feature resolution, as returned from {@link Result#getConflicts()} * @param resolvedPlatforms - * @param missingPlatforms + * @param missingPlatforms Unknown platform names + * @param missingBasePlatforms unresolved versionless features needing platforms defined */ public RepositoryResolutionException(ResolutionException cause, Collection topLevelFeaturesNotResolved, Collection allRequirementsNotFound, Collection missingProductInformation, Collection allRequirementsResourcesNotFound, - Map> featureConflicts, Set resolvedPlatforms, Set missingPlatforms) { + Map> featureConflicts, Set resolvedPlatforms, Set missingPlatforms, + List missingBasePlatforms) { super(cause); this.topLevelFeaturesNotResolved = topLevelFeaturesNotResolved; this.allRequirementsNotFound = allRequirementsNotFound; @@ -85,7 +89,8 @@ public RepositoryResolutionException(ResolutionException cause, Collection> getFeatureConflicts() { public String getMessage() { StringBuilder sb = new StringBuilder(); - if (hasVersionlessIssue()) { - if (!getMissingPlatforms().isEmpty()) { - for (String missing : getMissingPlatforms()) { - sb.append("Platform: ").append(missing).append(" couldn't be found, no versionless features will be resolved").append("\n"); - } - } - if (getResolvedPlatforms().isEmpty() && getMissingPlatforms().isEmpty()) { - sb.append("Platform couldn't be determined, no versionless features will be resolved").append("\n"); + if (!getMissingPlatforms().isEmpty()) { + for (String missing : getMissingPlatforms()) { + sb.append("Platform: ").append(missing).append(" couldn't be found, no versionless features will be resolved").append("\n"); } } + if (getResolvedPlatforms().isEmpty() && getMissingPlatforms().isEmpty()) { + sb.append("Platform couldn't be determined, no versionless features will be resolved").append("\n"); + } for (String missing : getTopLevelFeaturesNotResolved()) { sb.append("Top level feature not resolved: resource=").append(missing).append("\n"); @@ -384,10 +387,10 @@ public Set getMissingPlatforms() { } /** - * @return the hasVersionlessIssue + * @return the missingBasePlatforms */ - public boolean hasVersionlessIssue() { - return hasVersionlessIssue; + public List getMissingBasePlatforms() { + return missingBasePlatforms; } } diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java index c79fabd0377..56b44028e8c 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java @@ -32,6 +32,7 @@ import com.ibm.ws.kernel.feature.provisioning.ProvisioningFeatureDefinition; import com.ibm.ws.kernel.feature.resolver.FeatureResolver; import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Chain; +import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Repository; import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Result; import com.ibm.ws.kernel.productinfo.ProductInfo; import com.ibm.ws.product.utility.extension.IFixUtils; @@ -567,7 +568,7 @@ void resolveFeaturesAsSet() { featureConflicts.putAll(result.getConflicts()); if (hasRequestedVersionlessFeatures(featureNamesToResolve, resolverRepository)) - recordVersionless(result); + recordVersionless(result, resolverRepository); for (String name : result.getResolvedFeatures()) { ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); @@ -583,9 +584,10 @@ void resolveFeaturesAsSet() { * Record Versionless Messages and Issues * * @param result + * @param resolverRepo * @param requestedFeatures */ - private void recordVersionless(Result result) { + private void recordVersionless(Result result, Repository resolverRepo) { resolvedPlatforms = result.getResolvedPlatforms(); missingPlatforms = result.getMissingPlatforms(); @@ -1008,6 +1010,22 @@ private void reportErrors() throws RepositoryResolutionException { return; } + List missingBasePlatforms = new ArrayList(); + + // Versionless feature issues + if (!missingTopLevelRequirements.isEmpty()) { + for (String name : missingTopLevelRequirements) { + ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); + if (feature != null && feature.isVersionless()) { + ProvisioningFeatureDefinition firstChild = resolverRepository.findAllPossibleVersions(feature).get(0); + String plat = firstChild.getPlatformName(); + if (plat != null && plat.indexOf("-") != -1) { + missingBasePlatforms.add(resolverRepository.getFeatureBaseName(plat)); + } + } + } + } + Set missingProductInformation = new HashSet<>(); for (ApplicableToProduct esa : resourcesWrongProduct) { @@ -1034,11 +1052,8 @@ private void reportErrors() throws RepositoryResolutionException { missingRequirementNames.add(req.getRequirementName()); } - if (hasVersionlessIssue()) - throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts, - resolvedPlatforms, missingPlatforms); - else - throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts); + throw new RepositoryResolutionException(null, missingTopLevelRequirements, missingRequirementNames, missingProductInformation, missingRequirements, featureConflicts, + resolvedPlatforms, missingPlatforms, missingBasePlatforms); } /** diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java index 911d9d42b8b..fe3fc5c78fa 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java @@ -24,7 +24,9 @@ import org.osgi.framework.Version; import com.ibm.ws.kernel.feature.Visibility; +import com.ibm.ws.kernel.feature.provisioning.FeatureResource; import com.ibm.ws.kernel.feature.provisioning.ProvisioningFeatureDefinition; +import com.ibm.ws.kernel.feature.provisioning.SubsystemContentType; import com.ibm.ws.kernel.feature.resolver.FeatureResolver; import com.ibm.ws.repository.common.enums.FilterableAttribute; import com.ibm.ws.repository.common.enums.ResourceType; @@ -244,6 +246,71 @@ public ProvisioningFeatureDefinition getFeature(String featureName) { return feature; } + /** + * Answer the list of public versioned features derived from the passed versionless feature or empty List if doesn't exist. + * + * @return List + */ + public List findAllPossibleVersions(ProvisioningFeatureDefinition versionlessFeature) { + List result = new ArrayList<>(); + for (FeatureResource dependency : versionlessFeature.getConstituents(SubsystemContentType.FEATURE_TYPE)) { + result.add(getVersionedFeature(dependency.getSymbolicName())); + + String baseName = getFeatureBaseName(dependency.getSymbolicName()); + List tolerates = dependency.getTolerates(); + if (tolerates != null) { + for (String toleratedVersion : tolerates) { + String featureName = baseName + toleratedVersion; + result.add(getVersionedFeature(featureName)); + } + } + } + return result; + } + + /** + * + * Answer the public versioned feature based on the internal versionless linking feature + * + * @param versionlessLinkingFeatureName + * @return ProvisioningFeatureDefinition + */ + private ProvisioningFeatureDefinition getVersionedFeature(String versionlessLinkingFeatureName) { + ProvisioningFeatureDefinition result = null; + ProvisioningFeatureDefinition feature = getFeature(versionlessLinkingFeatureName); + if (feature != null) { + //This is the versionless linking feature pointing to a public versioned feature + for (FeatureResource versionedFeature : feature.getConstituents(SubsystemContentType.FEATURE_TYPE)) { + //Find the right public feature (should only be one) - set the result + ProvisioningFeatureDefinition versionedFeatureDef = getFeature(versionedFeature.getSymbolicName()); + if (versionedFeatureDef.getVisibility() != Visibility.PUBLIC) { + continue; + } + result = versionedFeatureDef; + } + } + return result; + } + + /** + * Removes the version from the end of a feature symbolic name + *

+ * The version is presumed to start after the last dash character in the name. + *

+ * E.g. {@code getFeatureBaseName("com.example.featureA-1.0")} returns {@code "com.example.featureA-"} + * + * @param nameAndVersion the feature symbolic name + * @return the feature symbolic name with any version stripped + */ + public String getFeatureBaseName(String nameAndVersion) { + int dashPosition = nameAndVersion.lastIndexOf('-'); + if (dashPosition != -1) { + return nameAndVersion.substring(0, dashPosition + 1); + } else { + return nameAndVersion; + } + } + /** * Get a feature by name, but without going and checking the remote repository if we don't know about it * From eb96f630c06308f83a54d32e990774a0a9da7b0b Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Mon, 15 Jul 2024 12:21:44 -0400 Subject: [PATCH 6/8] Add fixes from suggestions, and cleanup comments --- .../resolver/RepositoryResolver.java | 18 ++++++++---------- .../internal/kernel/KernelResolverEsa.java | 2 +- .../kernel/KernelResolverRepository.java | 9 +++++---- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java index 56b44028e8c..f0ccc794935 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java @@ -1012,16 +1012,14 @@ private void reportErrors() throws RepositoryResolutionException { List missingBasePlatforms = new ArrayList(); - // Versionless feature issues - if (!missingTopLevelRequirements.isEmpty()) { - for (String name : missingTopLevelRequirements) { - ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); - if (feature != null && feature.isVersionless()) { - ProvisioningFeatureDefinition firstChild = resolverRepository.findAllPossibleVersions(feature).get(0); - String plat = firstChild.getPlatformName(); - if (plat != null && plat.indexOf("-") != -1) { - missingBasePlatforms.add(resolverRepository.getFeatureBaseName(plat)); - } + // Versionless feature issues will appear in missingTopLevelRequirements, and this will gather the associated platform unable to target. + for (String name : missingTopLevelRequirements) { + ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); + if (feature != null && feature.isVersionless()) { + ProvisioningFeatureDefinition firstChild = resolverRepository.findAllPossibleVersions(feature).get(0); + String plat = firstChild.getPlatformName(); + if (plat != null) {//This will add just the platform name without version + missingBasePlatforms.add(resolverRepository.getFeatureBaseName(plat)); } } } diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java index 8a9ed9294b4..857b965f55e 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java @@ -283,7 +283,7 @@ public boolean isConvenience() { * *

  • private
  • *
  • do not have a short name
  • - *
  • contain ".eeCompatible-" or ".mpCompatible-" in their symbolic name.
  • + *
  • has a platform value
  • *
* * @return True or false telling if this is a versionless feature. diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java index fe3fc5c78fa..47cd993efc0 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java @@ -21,8 +21,6 @@ import java.util.Map; import java.util.Map.Entry; -import org.osgi.framework.Version; - import com.ibm.ws.kernel.feature.Visibility; import com.ibm.ws.kernel.feature.provisioning.FeatureResource; import com.ibm.ws.kernel.feature.provisioning.ProvisioningFeatureDefinition; @@ -38,6 +36,8 @@ import com.ibm.ws.repository.resources.RepositoryResource; import com.ibm.ws.repository.resources.internal.RepositoryResourceImpl; +import junit.runner.Version; + /** * Implementation of {@link FeatureResolver.Repository} which is backed by a collection of {@link EsaResource}s. */ @@ -283,10 +283,11 @@ private ProvisioningFeatureDefinition getVersionedFeature(String versionlessLink for (FeatureResource versionedFeature : feature.getConstituents(SubsystemContentType.FEATURE_TYPE)) { //Find the right public feature (should only be one) - set the result ProvisioningFeatureDefinition versionedFeatureDef = getFeature(versionedFeature.getSymbolicName()); - if (versionedFeatureDef.getVisibility() != Visibility.PUBLIC) { - continue; + if (versionedFeatureDef.getVisibility() == Visibility.PUBLIC) { + return versionedFeatureDef; } result = versionedFeatureDef; + break; } } return result; From c8e60d8fa72848df11478d9b60f84225f38d6c75 Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Mon, 15 Jul 2024 20:43:40 -0400 Subject: [PATCH 7/8] restructure,check for null --- .../kernel/KernelResolverRepository.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java index 47cd993efc0..f56f2a0c90d 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java @@ -21,6 +21,8 @@ import java.util.Map; import java.util.Map.Entry; +import org.osgi.framework.Version; + import com.ibm.ws.kernel.feature.Visibility; import com.ibm.ws.kernel.feature.provisioning.FeatureResource; import com.ibm.ws.kernel.feature.provisioning.ProvisioningFeatureDefinition; @@ -36,8 +38,6 @@ import com.ibm.ws.repository.resources.RepositoryResource; import com.ibm.ws.repository.resources.internal.RepositoryResourceImpl; -import junit.runner.Version; - /** * Implementation of {@link FeatureResolver.Repository} which is backed by a collection of {@link EsaResource}s. */ @@ -252,16 +252,21 @@ public ProvisioningFeatureDefinition getFeature(String featureName) { * @return List */ public List findAllPossibleVersions(ProvisioningFeatureDefinition versionlessFeature) { + ProvisioningFeatureDefinition publicFeature = null; List result = new ArrayList<>(); for (FeatureResource dependency : versionlessFeature.getConstituents(SubsystemContentType.FEATURE_TYPE)) { - result.add(getVersionedFeature(dependency.getSymbolicName())); - + publicFeature = getVersionedFeature(dependency.getSymbolicName()); + if (publicFeature != null) + result.add(publicFeature); + String baseName = getFeatureBaseName(dependency.getSymbolicName()); List tolerates = dependency.getTolerates(); if (tolerates != null) { for (String toleratedVersion : tolerates) { String featureName = baseName + toleratedVersion; - result.add(getVersionedFeature(featureName)); + publicFeature = getVersionedFeature(featureName); + if (publicFeature != null) + result.add(publicFeature); } } } @@ -286,11 +291,9 @@ private ProvisioningFeatureDefinition getVersionedFeature(String versionlessLink if (versionedFeatureDef.getVisibility() == Visibility.PUBLIC) { return versionedFeatureDef; } - result = versionedFeatureDef; - break; } } - return result; + return null; } /** From 9576b50171cab3af65b9b30471a3072dade7ffa9 Mon Sep 17 00:00:00 2001 From: Chuck Bridgham Date: Tue, 16 Jul 2024 11:50:04 -0400 Subject: [PATCH 8/8] Fixup syntax and javadoc based on comments --- .../RepositoryResolutionException.java | 6 +- .../resolver/RepositoryResolver.java | 66 ++++++++----------- .../internal/kernel/KernelResolverEsa.java | 9 ++- .../kernel/KernelResolverRepository.java | 6 +- 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java index 440ed0ec55c..a1d37a2b289 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolutionException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2019 IBM Corporation and others. + * Copyright (c) 2014, 2024 IBM Corporation and others. * All rights reserved. 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 @@ -44,7 +44,6 @@ public class RepositoryResolutionException extends RepositoryException { private final Map> featureConflicts; private Set resolvedPlatforms; private Set missingPlatforms; - private boolean hasVersionlessIssue; private List missingBasePlatforms; /** @@ -373,6 +372,7 @@ private String getResourceName(RepositoryResource resource) { } /** + * This states the target platforms that were used during the resolution * @return the resolvedPlatforms */ public Set getResolvedPlatforms() { @@ -380,6 +380,7 @@ public Set getResolvedPlatforms() { } /** + * This describes missspelled or unknown platform names, official names are collected by the feature metadata * @return the missingPlatforms */ public Set getMissingPlatforms() { @@ -387,6 +388,7 @@ public Set getMissingPlatforms() { } /** + * This describes base platforms like "jakartaee" that are not derived, either by passed platform values, or by other included versioned features * @return the missingBasePlatforms */ public List getMissingBasePlatforms() { diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java index f0ccc794935..8d823ad7b5a 100755 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/RepositoryResolver.java @@ -32,7 +32,6 @@ import com.ibm.ws.kernel.feature.provisioning.ProvisioningFeatureDefinition; import com.ibm.ws.kernel.feature.resolver.FeatureResolver; import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Chain; -import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Repository; import com.ibm.ws.kernel.feature.resolver.FeatureResolver.Result; import com.ibm.ws.kernel.productinfo.ProductInfo; import com.ibm.ws.product.utility.extension.IFixUtils; @@ -146,11 +145,10 @@ public class RepositoryResolver { * List of all the missing platforms after resolution */ Set missingPlatforms; - /** - * Indicates if an issue was found resolving versionless features and platforms + * returns if versionless features are part of the resolution - used to skip extra processing */ - boolean hasVersionlessIssue; + boolean includesVersionless; /** *

@@ -367,6 +365,8 @@ public Collection> resolve(String toResolve) throws Rep * For example, if {@code ejbLite-3.2} is already installed and {@code resolve(Arrays.asList("cdi-2.0"))} is called, it will not return the autofeature which would be required * for {@code cdi-2.0} and {@code ejbLite-3.2} to work together. * + * @deprecated - calling this method should be replaced by passing the platform list, required to support versionless features. + * * @param toResolve A collection of the identifiers of the resources to resolve. It should be in the form:
* {name}/{version}
*

Where the {name} can be either the symbolic name, short name or lower case short name of the resource and /{version} is @@ -389,6 +389,7 @@ public Collection> resolve(String toResolve) throws Rep * * @throws RepositoryResolutionException If the resource cannot be resolved */ + @Deprecated public Collection> resolveAsSet(Collection toResolve) throws RepositoryResolutionException { return resolve(toResolve, null, ResolutionMode.DETECT_CONFLICTS); } @@ -502,7 +503,7 @@ void initResolve() { featureConflicts = new HashMap<>(); resolvedPlatforms = new HashSet<>(); missingPlatforms = new HashSet<>(); - hasVersionlessIssue = false; + includesVersionless = false; } /** @@ -567,8 +568,11 @@ void resolveFeaturesAsSet() { Result result = resolver.resolve(resolverRepository, kernelFeatures, featureNamesToResolve, Collections. emptySet(), false, requestedPlatformNames); featureConflicts.putAll(result.getConflicts()); - if (hasRequestedVersionlessFeatures(featureNamesToResolve, resolverRepository)) - recordVersionless(result, resolverRepository); + if (hasRequestedVersionlessFeatures(featureNamesToResolve, resolverRepository)) { + includesVersionless = true; + resolvedPlatforms = result.getResolvedPlatforms(); + missingPlatforms = result.getMissingPlatforms(); + } for (String name : result.getResolvedFeatures()) { ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); @@ -580,22 +584,6 @@ void resolveFeaturesAsSet() { } } - /** - * Record Versionless Messages and Issues - * - * @param result - * @param resolverRepo - * @param requestedFeatures - */ - private void recordVersionless(Result result, Repository resolverRepo) { - - resolvedPlatforms = result.getResolvedPlatforms(); - missingPlatforms = result.getMissingPlatforms(); - if (resolvedPlatforms.isEmpty() || !missingPlatforms.isEmpty()) - hasVersionlessIssue = true; - - } - /** * Resolves {@link #featureNamesToResolve} using a simple traversal of the dependency tree * @@ -1005,21 +993,27 @@ private EsaResource getResource(ProvisioningFeatureDefinition feature) { * @throws RepositoryResolutionException if any errors occurred during resolution */ private void reportErrors() throws RepositoryResolutionException { - if (resourcesWrongProduct.isEmpty() && missingTopLevelRequirements.isEmpty() && missingRequirements.isEmpty() && featureConflicts.isEmpty() && !hasVersionlessIssue()) { + if (resourcesWrongProduct.isEmpty() && missingTopLevelRequirements.isEmpty() && missingRequirements.isEmpty() && featureConflicts.isEmpty() + && (!includesVersionless || ((!resolvedPlatforms.isEmpty()) && (missingPlatforms.isEmpty())))) { // Everything went fine! return; } List missingBasePlatforms = new ArrayList(); - // Versionless feature issues will appear in missingTopLevelRequirements, and this will gather the associated platform unable to target. - for (String name : missingTopLevelRequirements) { - ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); - if (feature != null && feature.isVersionless()) { - ProvisioningFeatureDefinition firstChild = resolverRepository.findAllPossibleVersions(feature).get(0); - String plat = firstChild.getPlatformName(); - if (plat != null) {//This will add just the platform name without version - missingBasePlatforms.add(resolverRepository.getFeatureBaseName(plat)); + // Versionless features can't be resolved if a corresponding platform is not derived, making the choice ambiguous, and the feature won't be included in the resolved list. - will gather the associated platform unable to target. + if (includesVersionless) { + for (String name : missingTopLevelRequirements) { + ProvisioningFeatureDefinition feature = resolverRepository.getFeature(name); + if (feature != null && feature.isVersionless()) { + List featureChildren = resolverRepository.findAllPossibleVersions(feature); + if (!featureChildren.isEmpty()) { + ProvisioningFeatureDefinition firstChild = featureChildren.get(0); + String plat = firstChild.getPlatformName(); + if (plat != null) {//This will add just the platform name without version + missingBasePlatforms.add(resolverRepository.getFeatureBaseName(plat)); + } + } } } } @@ -1054,14 +1048,6 @@ private void reportErrors() throws RepositoryResolutionException { resolvedPlatforms, missingPlatforms, missingBasePlatforms); } - /** - * @return - */ - protected boolean hasVersionlessIssue() { - - return hasVersionlessIssue; - } - static class NameAndVersion { public NameAndVersion(String name, String version) { diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java index 857b965f55e..f1cd8c9c496 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverEsa.java @@ -264,13 +264,12 @@ public boolean isVersionless() { return false; } - if (getSymbolicName().indexOf(".versionless.") == -1) { - return false; - } else if (getSymbolicName().indexOf(".internal.versionless.") != -1) { + if (getSymbolicName().contains(".versionless.") + && !getSymbolicName().contains(".internal.")) { + return true; + } else { return false; } - - return true; } @Override diff --git a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java index f56f2a0c90d..422c245bdd3 100644 --- a/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java +++ b/dev/com.ibm.ws.repository.resolver/src/com/ibm/ws/repository/resolver/internal/kernel/KernelResolverRepository.java @@ -258,7 +258,7 @@ public List findAllPossibleVersions(ProvisioningF publicFeature = getVersionedFeature(dependency.getSymbolicName()); if (publicFeature != null) result.add(publicFeature); - + String baseName = getFeatureBaseName(dependency.getSymbolicName()); List tolerates = dependency.getTolerates(); if (tolerates != null) { @@ -275,13 +275,13 @@ public List findAllPossibleVersions(ProvisioningF /** * - * Answer the public versioned feature based on the internal versionless linking feature + * Answer the public versioned feature based on the internal versionless linking feature, or null if can't be found * * @param versionlessLinkingFeatureName * @return ProvisioningFeatureDefinition */ private ProvisioningFeatureDefinition getVersionedFeature(String versionlessLinkingFeatureName) { - ProvisioningFeatureDefinition result = null; + ProvisioningFeatureDefinition feature = getFeature(versionlessLinkingFeatureName); if (feature != null) { //This is the versionless linking feature pointing to a public versioned feature