diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java index 02add784310..57a3e0857ec 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java @@ -1981,20 +1981,20 @@ public void testUses4() throws BundleException, IOException { */ @Test public void testUses5Importer() throws BundleException, IOException { - doTestUses5("uses.k.importer.MF"); + doTestUses5("uses.k.importer.MF", 3); } @Test public void testUses5ReqCap() throws BundleException, IOException { - doTestUses5("uses.k.reqCap.MF"); + doTestUses5("uses.k.reqCap.MF", 3); } @Test public void testUses5Requirer() throws BundleException, IOException { - doTestUses5("uses.k.requirer.MF"); + doTestUses5("uses.k.requirer.MF", 3); } - public void doTestUses5(String kManifest) throws BundleException, IOException { + public void doTestUses5(String kManifest, int max) throws BundleException, IOException { DummyContainerAdaptor adaptor = createDummyAdaptor(); ModuleContainer container = adaptor.getContainer(); @@ -2006,12 +2006,13 @@ public void doTestUses5(String kManifest) throws BundleException, IOException { Module uses_m_conflict1 = installDummyModule("uses.m.conflict1.MF", "m.conflict1", container); Module uses_m_conflict2 = installDummyModule("uses.m.conflict2.MF", "m.conflict2", container); - container.resolve(null, false); + ResolutionReport report = container.resolve(null, false); assertEquals("k should resolve.", State.RESOLVED, uses_k.getState()); assertEquals("l should resolve.", State.RESOLVED, uses_l.getState()); assertEquals("m.conflict1 should resolve.", State.RESOLVED, uses_m_conflict1.getState()); assertEquals("m.conflict2 should resolve.", State.RESOLVED, uses_m_conflict2.getState()); + assertNotMoreThanPermutationCreated(report, max); } @Test @@ -3929,14 +3930,28 @@ public void testSubstitutionWithMoreThan2Providers() throws BundleException, IOE "osgi.ee; osgi.ee=JavaSE; version:List=\"1.3, 1.4, 1.5, 1.6, 1.7\"", // container); ResolutionReport report = container.resolve(Arrays.asList(systemBundle), true); - assertNull("Failed to resolve test.", report.getResolutionException()); + assertSucessfulWith(report, 1); List modules = new ArrayList<>(); for (String manifest : HTTPCOMPS_AND_EATHER) { modules.add(installDummyModule(manifest, manifest, container)); } report = container.resolve(modules, true); + assertSucessfulWith(report, 115); + } + + protected void assertSucessfulWith(ResolutionReport report, int maxTotalPermutations) { assertNull("Failed to resolve test.", report.getResolutionException()); + assertNotMoreThanPermutationCreated(report, maxTotalPermutations); + } + + protected void assertNotMoreThanPermutationCreated(ResolutionReport report, int maxTotal) { + int totalPermutations = report.getTotalPermutations(); + if (totalPermutations > maxTotal) { + fail("Maximum of " + maxTotal + " permutations expected but was " + totalPermutations + " (" + + report.getProcessedPermutations() + " processed)."); + } + return; } @Test diff --git a/bundles/org.eclipse.osgi/.settings/.api_filters b/bundles/org.eclipse.osgi/.settings/.api_filters new file mode 100644 index 00000000000..047d8370886 --- /dev/null +++ b/bundles/org.eclipse.osgi/.settings/.api_filters @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF index f78b0b106f8..5c4ecd9f507 100644 --- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF @@ -36,7 +36,7 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru org.eclipse.osgi.internal.signedcontent;x-internal:=true, org.eclipse.osgi.internal.url;x-internal:=true, org.eclipse.osgi.launch;version="1.1";uses:="org.osgi.framework,org.osgi.framework.launch,org.osgi.framework.connect", - org.eclipse.osgi.report.resolution;version="1.0";uses:="org.osgi.service.resolver,org.osgi.resource", + org.eclipse.osgi.report.resolution;version="1.1.0";uses:="org.osgi.service.resolver,org.osgi.resource", org.eclipse.osgi.service.datalocation;version="1.4.0", org.eclipse.osgi.service.debug;version="1.2", org.eclipse.osgi.service.environment;version="1.4", @@ -107,7 +107,7 @@ Bundle-Activator: org.eclipse.osgi.internal.framework.SystemBundleActivator Bundle-Description: %systemBundle Bundle-Copyright: %copyright Bundle-Vendor: %eclipse.org -Bundle-Version: 3.19.100.qualifier +Bundle-Version: 3.20.0.qualifier Bundle-Localization: systembundle Bundle-DocUrl: http://www.eclipse.org Eclipse-ExtensibleAPI: true diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java index 4f260770dec..d93eb6d3a06 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; - import org.eclipse.osgi.container.Module.StartOptions; import org.eclipse.osgi.container.Module.State; import org.eclipse.osgi.container.Module.StopOptions; @@ -651,7 +650,8 @@ public ResolutionReport resolve(Collection triggers, boolean triggersMan private ResolutionReport resolve(Collection triggers, boolean triggersMandatory, boolean restartTriggers) { if (isRefreshingSystemModule()) { return new ModuleResolutionReport(null, Collections.emptyMap(), - new ResolutionException("Unable to resolve while shutting down the framework.")); //$NON-NLS-1$ + new ResolutionException("Unable to resolve while shutting down the framework."), -1, -1, -1, -1, //$NON-NLS-1$ + -1); } ResolutionReport report = null; try (ResolutionLock.Permits resolutionPermits = _resolutionLock.acquire(1)) { @@ -664,7 +664,7 @@ private ResolutionReport resolve(Collection triggers, boolean triggersMa if (be.getType() == BundleException.REJECTED_BY_HOOK || be.getType() == BundleException.STATECHANGE_ERROR) { return new ModuleResolutionReport(null, Collections.emptyMap(), - new ResolutionException(be)); + new ResolutionException(be), -1, -1, -1, -1, -1); } } throw e; @@ -672,7 +672,8 @@ private ResolutionReport resolve(Collection triggers, boolean triggersMa } while (report == null); } catch (ResolutionLockException e) { return new ModuleResolutionReport(null, Collections.emptyMap(), - new ResolutionException("Timeout acquiring lock for resolution", e, Collections.emptyList())); //$NON-NLS-1$ + new ResolutionException("Timeout acquiring lock for resolution", e, Collections.emptyList()), -1, //$NON-NLS-1$ + -1, -1, -1, -1); } return report; } @@ -1341,7 +1342,7 @@ public ResolutionReport refresh(Collection initial) { if (!isRefreshingSystemModule()) { return resolve(refreshTriggers, false, true); } - return new ModuleResolutionReport(null, null, null); + return new ModuleResolutionReport(null, null, null, -1, -1, -1, -1, -1); } /** diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolutionReport.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolutionReport.java index a55766421b9..975e4a51c3b 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolutionReport.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolutionReport.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.eclipse.osgi.container.ModuleResolver.ResolveProcess.ResolveLogger; import org.eclipse.osgi.internal.messages.Msg; import org.eclipse.osgi.report.resolution.ResolutionReport; import org.osgi.framework.wiring.BundleRevision; @@ -49,9 +50,12 @@ public void addEntry(Resource resource, Entry.Type type, Object data) { entries.add(new EntryImpl(type, data)); } - public ModuleResolutionReport build(Map> resolutionResult, ResolutionException cause) { - return new ModuleResolutionReport(resolutionResult, resourceToEntries, cause); + public ModuleResolutionReport build(Map> resolutionResult, ResolutionException cause, + ResolveLogger logger) { + return new ModuleResolutionReport(resolutionResult, resourceToEntries, cause, logger.totalPerm, + logger.processedPerm, logger.usesPerm, logger.subPerm, logger.importPerm); } + } static class EntryImpl implements Entry { @@ -77,9 +81,19 @@ public Type getType() { private final Map> entries; private final ResolutionException resolutionException; private final Map> resolutionResult; + private int totalPerm; + private int processedPerm; + private int usesPerm; + private int subPerm; + private int importPerm; ModuleResolutionReport(Map> resolutionResult, Map> entries, - ResolutionException cause) { + ResolutionException cause, int totalPerm, int processedPerm, int usesPerm, int subPerm, int importPerm) { + this.totalPerm = totalPerm; + this.processedPerm = processedPerm; + this.usesPerm = usesPerm; + this.subPerm = subPerm; + this.importPerm = importPerm; this.entries = entries == null ? Collections.emptyMap() : Collections.unmodifiableMap(new HashMap<>(entries)); this.resolutionResult = resolutionResult == null ? Collections.emptyMap() : Collections.unmodifiableMap(resolutionResult); @@ -176,4 +190,29 @@ private static void printResolutionEntry(StringBuilder result, String prepend, R public String getResolutionReportMessage(Resource resource) { return getResolutionReport0(null, (ModuleRevision) resource, getEntries(), null); } + + @Override + public int getTotalPermutations() { + return totalPerm; + } + + @Override + public int getProcessedPermutations() { + return processedPerm; + } + + @Override + public int getUsesPermutations() { + return usesPerm; + } + + @Override + public int getImportPermutations() { + return importPerm; + } + + @Override + public int getSubstitutionPermutations() { + return subPerm; + } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java index 64f918e9833..6efc6216841 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java @@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.apache.felix.resolver.Logger; +import org.apache.felix.resolver.PermutationType; import org.apache.felix.resolver.ResolutionError; import org.apache.felix.resolver.ResolverImpl; import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement; @@ -89,11 +90,13 @@ final class ModuleResolver { private static final String OPTION_USES = OPTION_RESOLVER + "/uses"; //$NON-NLS-1$ private static final String OPTION_WIRING = OPTION_RESOLVER + "/wiring"; //$NON-NLS-1$ private static final String OPTION_REPORT = OPTION_RESOLVER + "/report"; //$NON-NLS-1$ + private static final String OPTION_PERMUTATION = OPTION_RESOLVER + "/permutation"; //$NON-NLS-1$ boolean DEBUG_ROOTS = false; boolean DEBUG_PROVIDERS = false; boolean DEBUG_HOOKS = false; boolean DEBUG_USES = false; + boolean DEBUG_PERMUTATIONS = false; boolean DEBUG_WIRING = false; boolean DEBUG_REPORT = false; @@ -115,6 +118,7 @@ void setDebugOptions() { DEBUG_USES = debugAll || options.getBooleanOption(OPTION_USES, false); DEBUG_WIRING = debugAll || options.getBooleanOption(OPTION_WIRING, false); DEBUG_REPORT = debugAll || options.getBooleanOption(OPTION_REPORT, false); + DEBUG_PERMUTATIONS = debugAll || options.getBooleanOption(OPTION_PERMUTATION, false); } static final Collection NON_PAYLOAD_CAPABILITIES = Arrays.asList(IdentityNamespace.IDENTITY_NAMESPACE); @@ -470,6 +474,11 @@ class ResolveProcess extends ResolveContext implements Comparator, E class ResolveLogger extends Logger { private Map errors = null; + public int totalPerm; + public int processedPerm; + public int usesPerm; + public int importPerm; + public int subPerm; public ResolveLogger() { super(DEBUG_USES ? Logger.LOG_DEBUG : 0); @@ -510,6 +519,28 @@ protected void doLog(int level, String msg, Throwable throwable) { + (throwable != null ? (TAB + TAB + throwable.getMessage()) : "")); //$NON-NLS-1$ } + @Override + public void logPermutationAdded(PermutationType type) { + totalPerm++; + switch (type) { + case USES: + usesPerm++; + break; + case IMPORT: + importPerm++; + break; + case SUBSTITUTE: + subPerm++; + } + } + + PermutationType[] permutationTypes = PermutationType.values(); + + @Override + public void logProcessPermutation(PermutationType type) { + processedPerm++; + } + } private final ModuleResolutionReport.Builder reportBuilder = new ModuleResolutionReport.Builder(); @@ -918,7 +949,7 @@ ModuleResolutionReport resolve() { BundleException be = (BundleException) e.getCause(); if (be.getType() == BundleException.REJECTED_BY_HOOK) { return new ModuleResolutionReport(null, Collections.emptyMap(), - new ResolutionException(be)); + new ResolutionException(be), -1, -1, -1, -1, -1); } } throw e; @@ -962,7 +993,7 @@ ModuleResolutionReport resolve() { if (DEBUG_WIRING) { printWirings(result); } - report = reportBuilder.build(result, re); + report = reportBuilder.build(result, re, logger); if (DEBUG_REPORT) { if (report.getResolutionException() != null) { Debug.printStackTrace(report.getResolutionException()); diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java index 8750706f0a8..0b59f6dac0b 100644 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java @@ -22,7 +22,6 @@ import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.felix.resolver.ResolverImpl.PermutationType; import org.apache.felix.resolver.ResolverImpl.ResolveSession; import org.apache.felix.resolver.reason.ReasonException; import org.apache.felix.resolver.util.*; diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Logger.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Logger.java index 7789ffba10a..b82c0d9e424 100644 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Logger.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Logger.java @@ -131,4 +131,29 @@ public void logUsesConstraintViolation(Resource resource, ResolutionError error) { // do nothing by default } + + /** + * Called whenever a new permutation is added by the resolver. + * + * @param type the type of the permutation + * @param remaining a function that can be used to query the now current number + * of permutation types + */ + public void logPermutationAdded(PermutationType type) + { + // do nothing by default + } + + /** + * Called whenever a permutation is removed and about to be processed by the + * resolver. + * + * @param type the type of permutation that will be processed + * @param remaining a function that can be used to query the now current number + * of permutation types + */ + public void logProcessPermutation(PermutationType type) + { + // do nothing by default + } } diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/PermutationType.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/PermutationType.java new file mode 100644 index 00000000000..43d583ba75b --- /dev/null +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/PermutationType.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.resolver; +public enum PermutationType { + USES, + IMPORT, + SUBSTITUTE +} \ No newline at end of file diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java index 6c9b278db3c..77963fbe4d8 100644 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java @@ -23,7 +23,7 @@ import java.util.Map.Entry; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; - +import java.util.function.ToIntFunction; import org.apache.felix.resolver.reason.ReasonException; import org.apache.felix.resolver.util.ArrayMap; import org.apache.felix.resolver.util.CandidateSelector; @@ -45,12 +45,6 @@ public class ResolverImpl implements Resolver private final Executor m_executor; - enum PermutationType { - USES, - IMPORT, - SUBSTITUTE - } - // Note this class is not thread safe. // Only use in the context of a single thread. static class ResolveSession implements Runnable @@ -91,10 +85,13 @@ static class ResolveSession implements Runnable private final ConcurrentMap> m_usesCache = new ConcurrentHashMap>(); private ResolutionError m_currentError; volatile private CancellationException m_isCancelled = null; + private final Logger logger; - static ResolveSession createSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, Requirement dynamicReq, List dynamicCandidates) + static ResolveSession createSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, + Requirement dynamicReq, List dynamicCandidates, Logger logger) { - ResolveSession session = new ResolveSession(resolveContext, executor, dynamicHost, dynamicReq, dynamicCandidates); + ResolveSession session = new ResolveSession(resolveContext, executor, dynamicHost, dynamicReq, + dynamicCandidates, logger); // call onCancel first session.getContext().onCancel(session); // now gather the mandatory and optional resources @@ -102,13 +99,15 @@ static ResolveSession createSession(ResolveContext resolveContext, Executor exec return session; } - private ResolveSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, Requirement dynamicReq, List dynamicCandidates) + private ResolveSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, + Requirement dynamicReq, List dynamicCandidates, Logger logger) { m_resolveContext = resolveContext; m_executor = executor; m_dynamicHost = dynamicHost; m_dynamicReq = dynamicReq; m_dynamicCandidates = dynamicCandidates; + this.logger = logger; if (m_dynamicHost != null) { m_mandatoryResources = Collections.singletonList(dynamicHost); m_optionalResources = Collections.emptyList(); @@ -186,33 +185,39 @@ void addPermutation(PermutationType type, Candidates permutation) { m_substPermutations.add(m_substituteIndex++, permutation); break; default : - throw new IllegalArgumentException("Unknown permitation type: " + type); + throw new IllegalArgumentException("Unknown permutation type: " + type); } } catch (IndexOutOfBoundsException e) { // just a safeguard, this really should never happen typeToAddTo.add(permutation); } + logger.logPermutationAdded(type); } } Candidates getNextPermutation() { Candidates next = null; + PermutationType type; do { if (!m_usesPermutations.isEmpty()) { next = m_usesPermutations.remove(0); + type = PermutationType.USES; } else if (!m_importPermutations.isEmpty()) { next = m_importPermutations.remove(0); + type = PermutationType.IMPORT; } else if (!m_substPermutations.isEmpty()) { next = m_substPermutations.remove(0); + type = PermutationType.SUBSTITUTE; } else { return null; } + logger.logProcessPermutation(type); } while(!m_processedDeltas.add(next.getDelta())); // Null out each time a new permutation is attempted. @@ -222,6 +227,7 @@ else if (!m_substPermutations.isEmpty()) // clear mutateIndexes also so we insert new permutations // based of this permutation as a higher priority clearMutateIndexes(); + return next; } @@ -416,7 +422,7 @@ public Void run() { public Map> resolve(ResolveContext rc, Executor executor) throws ResolutionException { - ResolveSession session = ResolveSession.createSession(rc, executor, null, null, null); + ResolveSession session = ResolveSession.createSession(rc, executor, null, null, null, m_logger); return doResolve(session); } @@ -667,7 +673,8 @@ public Map> resolveDynamic(ResolveContext context, "Matching candidate does not provide a package name."); } } - ResolveSession session = ResolveSession.createSession(context, new DumbExecutor(), host, dynamicRequirement, matches); + ResolveSession session = ResolveSession.createSession(context, new DumbExecutor(), host, dynamicRequirement, + matches, m_logger); return doResolve(session); } diff --git a/bundles/org.eclipse.osgi/pom.xml b/bundles/org.eclipse.osgi/pom.xml index cfdf6729465..6aea6b7ca77 100644 --- a/bundles/org.eclipse.osgi/pom.xml +++ b/bundles/org.eclipse.osgi/pom.xml @@ -19,7 +19,7 @@ org.eclipse.osgi org.eclipse.osgi - 3.19.100-SNAPSHOT + 3.20.0-SNAPSHOT eclipse-plugin @@ -31,7 +31,6 @@ org.eclipse.tycho tycho-compiler-plugin - ${tycho.version} -nowarn:[${project.basedir}/osgi/src${path.separator}${project.basedir}/felix/src${path.separator}${project.basedir}/felix/src_test] diff --git a/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF index 129f85cb422..0a60e767518 100644 --- a/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.osgi/supplement/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.equinox.supplement -Bundle-Version: 1.10.800.qualifier +Bundle-Version: 1.10.900.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: org.eclipse.equinox.log;version="1.1", diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/report/resolution/ResolutionReport.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/report/resolution/ResolutionReport.java index fdf783c6383..999269fcd46 100644 --- a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/report/resolution/ResolutionReport.java +++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/report/resolution/ResolutionReport.java @@ -15,6 +15,8 @@ import java.util.List; import java.util.Map; +import org.eclipse.pde.api.tools.annotations.NoImplement; +import org.osgi.annotation.versioning.ProviderType; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.resource.Resource; import org.osgi.service.resolver.ResolutionException; @@ -96,6 +98,8 @@ * * @since 3.10 */ +@ProviderType +@NoImplement public interface ResolutionReport { public interface Entry { enum Type { @@ -193,4 +197,38 @@ public interface Listener { * @return a resolution report message. */ String getResolutionReportMessage(Resource resource); + + /** + * @return the number of permutations created to solve the problem or -1 if + * unknown + * @since 3.20 + */ + int getTotalPermutations(); + + /** + * @return the number of processed permutations -1 if unknown + * @since 3.20 + */ + int getProcessedPermutations(); + + /** + * @return the number of permutations cause by a use-constraint violation -1 if + * unknown + * @since 3.20 + */ + int getUsesPermutations(); + + /** + * @return the number of permutations cause by a package substitution or -1 if + * unknown + * @since 3.20 + */ + int getSubstitutionPermutations(); + + /** + * @return the number of permutations cause by a different package provider + * selected or -1 if unknown + * @since 3.20 + */ + int getImportPermutations(); }