diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java index d34bbc7d19..ceb8197565 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/IUBundleContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2021 IBM Corporation and others. + * Copyright (c) 2009, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,6 +15,7 @@ * Manumitting Technologies Inc - bug 437726: wrong error messages opening target definition * Alexander Fedorov (ArSysOp) - Bug 542425, Bug 574629 * Christoph Läubrich - Bug 568865 - [target] add advanced editing capabilities for custom target platforms + * - support wildcard in IU *******************************************************************************/ package org.eclipse.pde.internal.core.target; @@ -33,7 +34,10 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.IntStream; +import java.util.stream.Stream; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; @@ -76,6 +80,10 @@ */ public class IUBundleContainer extends AbstractBundleContainer { + private static final String QUESTION_MARK = "?"; //$NON-NLS-1$ + + private static final String ASTERIX = "*"; //$NON-NLS-1$ + /** * Constant describing the type of bundle container */ @@ -262,14 +270,22 @@ protected TargetBundle[] resolveBundles(ITargetDefinition definition, IProgressM IInstallableUnit[] cacheIUs(ITargetDefinition target) throws CoreException { IProfile profile = fSynchronizer.getProfile(); ArrayList result = new ArrayList<>(); - MultiStatus status = new MultiStatus(PDECore.PLUGIN_ID, 0, Messages.IUBundleContainer_ProblemsLoadingRepositories, null); + MultiStatus status = new MultiStatus(PDECore.PLUGIN_ID, 0, + Messages.IUBundleContainer_ProblemsLoadingRepositories, null); for (int i = 0; i < fIds.length; i++) { - IQuery query = QueryUtil.createIUQuery(fIds[i], fVersions[i]); - IQueryResult queryResult = profile.query(query, null); - if (queryResult.isEmpty()) { - status.add(Status.error(NLS.bind(Messages.IUBundleContainer_1, fIds[i] + " " + fVersions[i]))); //$NON-NLS-1$ + String id = fIds[i]; + Version version = fVersions[i]; + Pattern pattern = createIdPattern(id, status); + if (pattern == null) { + IQuery query = QueryUtil.createIUQuery(id, version); + IQueryResult queryResult = profile.query(query, null); + if (queryResult.isEmpty()) { + status.add(Status.error(NLS.bind(Messages.IUBundleContainer_1, id + " " + version))); //$NON-NLS-1$ + } else { + result.add(queryResult.iterator().next()); + } } else { - result.add(queryResult.iterator().next()); + queryWithPattern(profile, result, version, pattern); } } if (!status.isOK()) { @@ -744,12 +760,20 @@ IInstallableUnit[] getRootIUs(ITargetDefinition definition, IProgressMonitor mon List result = new ArrayList<>(); for (int j = 0; j < fIds.length; j++) { // For versions such as 0.0.0, the IU query may return multiple IUs, so we check which is the latest version - IQuery query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery(fIds[j], fVersions[j])); - IQueryResult queryResult = repos.query(query, null); - if (queryResult.isEmpty()) { - status.add(Status.error(NLS.bind(Messages.IUBundleContainer_1, fIds[j] + " " + fVersions[j])));//$NON-NLS-1$ + String id = fIds[j]; + Version version = fVersions[j]; + Pattern pattern = createIdPattern(id, status); + IQueryResult queryResult; + if (pattern == null) { + IQuery query = QueryUtil.createLatestQuery(QueryUtil.createIUQuery(id, version)); + queryResult = repos.query(query, null); + if (queryResult.isEmpty()) { + status.add(Status.error(NLS.bind(Messages.IUBundleContainer_1, id + " " + version)));//$NON-NLS-1$ + } else { + result.add(queryResult.iterator().next()); + } } else { - result.add(queryResult.iterator().next()); + queryWithPattern(repos, result, version, pattern); } } if (!status.isOK()) { @@ -759,6 +783,37 @@ IInstallableUnit[] getRootIUs(ITargetDefinition definition, IProgressMonitor mon return result.toArray(new IInstallableUnit[0]); } + private static void queryWithPattern(IQueryable repos, List result, + Version version, + Pattern pattern) { + Stream allMatchingPattern = repos.query(QueryUtil.ALL_UNITS, null).stream() + .filter(iu -> pattern.matcher(iu.getId()).matches()); + if (version == null || Version.emptyVersion.equals(version)) { + allMatchingPattern + .collect(Collectors.groupingBy(IInstallableUnit::getId)).values().stream().flatMap( + list -> list.stream().sorted(Comparator.comparing(IInstallableUnit::getVersion).reversed())) + .forEach(result::add); + } else { + allMatchingPattern.filter(iu -> version.compareTo(iu.getVersion()) == 0).forEach(result::add); + } + } + + private static Pattern createIdPattern(String id, MultiStatus status) { + if (id.contains(ASTERIX) || id.contains(QUESTION_MARK)) { + try { + String pattern = id; + pattern = pattern.replace(".", "\\."); //$NON-NLS-1$//$NON-NLS-2$ + pattern = pattern.replace("-", "\\-"); //$NON-NLS-1$ //$NON-NLS-2$ + pattern = pattern.replace('?', '.'); + pattern = pattern.replace("*", ".*"); //$NON-NLS-1$ //$NON-NLS-2$ + return Pattern.compile(String.format("^%s$", pattern), Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ + } catch (IllegalArgumentException iae) { + status.add(Status.error(Messages.IUBundleContainer_12, iae)); + } + } + return null; + } + @Override public T getAdapter(Class adapter) { if (adapter.isInstance(fSynchronizer)) { diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.java index 61227d89d7..b76888497f 100755 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.java @@ -30,6 +30,7 @@ public class Messages extends NLS { public static String IUBundleContainer_1; public static String IUBundleContainer_10; public static String IUBundleContainer_11; + public static String IUBundleContainer_12; public static String IUBundleContainer_2; public static String IUBundleContainer_3; public static String IUBundleContainer_4; diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.properties b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.properties index 0ca65c26be..2c4eac22c5 100755 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.properties +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/target/Messages.properties @@ -25,8 +25,9 @@ IUBundleContainer_0=Provisioning target IUBundleContainer_1=Unable to locate installable unit {0} IUBundleContainer_10=Provisioning Agent Location service not found IUBundleContainer_11=Global Provisioning Agent service not found +IUBundleContainer_12=Can not compile pattern: {0} because of {1} IUBundleContainer_2=Metadata repository service not found -IUBundleContainer_3=Artifact respository service not found +IUBundleContainer_3=Artifact repository service not found IUBundleContainer_4=Provisioning engine not found IUBundleContainer_5=Provisioning planner not found IUBundleContainer_6=Target provisioning skipped install plan