aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ross2013-12-02 16:49:17 (EST)
committerJohn Ross2013-12-05 16:10:51 (EST)
commite63ebd96d5eecb32c44ef6d2d315e04074cf771c (patch)
treed911c071e330b9d7db8bfbe1ec0852247897bc27
parent34dd34042093037aa0e72bcfc4a2cb1a9e316f36 (diff)
downloadrt.equinox.framework-e63ebd96d5eecb32c44ef6d2d315e04074cf771c.zip
rt.equinox.framework-e63ebd96d5eecb32c44ef6d2d315e04074cf771c.tar.gz
rt.equinox.framework-e63ebd96d5eecb32c44ef6d2d315e04074cf771c.tar.bz2
[Bug 420067] Add support for org.eclipse.osgi/resolver/providers resolver trace option.
Specifying org.eclipse.osgi/resolver/providers = true within the .options file will enable trace output describing what's happening between the resolve context and resolver when finding providers. A list of the current output follows. (1) The requirement for which providers are being found. (2) Capabilities filtered because their effective directive was not equal to "resolve". (3) Capabilities filtered by resolver hooks via the filterMatches method. (4) Capabilities filtered because their resource was no resolved. (5) Capabilities filtered because the requirer did not have permission. (6) Capabilities filtered because the provider did not have permission. (7) Capabilities filtered because they were disabled. (8) Capabilities filtered because they were substituted. (9) The list of capabilities being returned to the resolver after filtering. I tried to format the output so that it's easily readable using line separators and tabs. The risk, of course, is that while it might look good in the console output, it could look horrible when System.out is routed to some third-party logging mechanism.
-rw-r--r--bundles/org.eclipse.osgi/.options20
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java145
2 files changed, 146 insertions, 19 deletions
diff --git a/bundles/org.eclipse.osgi/.options b/bundles/org.eclipse.osgi/.options
index a9d64e5..6e8fded 100644
--- a/bundles/org.eclipse.osgi/.options
+++ b/bundles/org.eclipse.osgi/.options
@@ -38,20 +38,12 @@ org.eclipse.osgi/eclipseadaptor/debug/platformadmin/resolver=false
org.eclipse.osgi/eclipseadaptor/converter/debug = false
### OSGi resolver options
-# Turns on debugging for the resolver
-org.eclipse.osgi/resolver/debug = false
-# Prints out wiring information after the resolver has completed the resolve process
-org.eclipse.osgi/resolver/wiring = false
-# Prints out Import-Package information
-org.eclipse.osgi/resolver/imports = false
-# Prints out Require-Bundle information
-org.eclipse.osgi/resolver/requires = false
-# Prints out debug information form the "uses" clause
-org.eclipse.osgi/resolver/uses = false
-# Prints out cycle information
-org.eclipse.osgi/resolver/cycles = false
-# Prints out Eclipse-GenericRequire information
-org.eclipse.osgi/resolver/generics = false
+# General debug option for the resolver. Enabling this option is equivalent to
+# enabling all other resolver debug options.
+org.eclipse.osgi/resolver = false
+# Displays information about matching capabilities returned to the resolver and
+# why any were filtered out.
+org.eclipse.osgi/resolver/providers = true
#### Profile settings
org.eclipse.osgi/profile/startup = false
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 e3e9bd1..09456b0 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
@@ -16,10 +16,13 @@ import org.apache.felix.resolver.*;
import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement;
import org.eclipse.osgi.container.namespaces.EquinoxFragmentNamespace;
import org.eclipse.osgi.internal.container.InternalUtils;
+import org.eclipse.osgi.internal.debug.Debug;
+import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.report.resolution.*;
import org.eclipse.osgi.report.resolution.ResolutionReport.Entry;
import org.eclipse.osgi.report.resolution.ResolutionReport.Entry.Type;
+import org.eclipse.osgi.service.debug.DebugOptions;
import org.osgi.framework.BundleException;
import org.osgi.framework.Version;
import org.osgi.framework.hooks.resolver.ResolverHook;
@@ -33,6 +36,24 @@ import org.osgi.service.resolver.*;
* in a module {@link ModuleContainer container}.
*/
final class ModuleResolver {
+ static final String SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+ static final char TAB = '\t';
+
+ private static final String OPTION_RESOLVER = EquinoxContainer.NAME + "/resolver"; //$NON-NLS-1$
+ private static final String OPTION_PROVIDERS = OPTION_RESOLVER + "/providers"; //$NON-NLS-1$
+
+ static boolean DEBUG_RESOLVER = false;
+ static boolean DEBUG_PROVIDERS = false;
+
+ private void setDebugOptions() {
+ DebugOptions options = adaptor.getDebugOptions();
+ // may be null if debugging is not enabled
+ if (options == null)
+ return;
+ DEBUG_RESOLVER = options.getBooleanOption(OPTION_RESOLVER, false);
+ DEBUG_PROVIDERS = options.getBooleanOption(OPTION_PROVIDERS, false);
+ }
+
private static final Collection<String> NON_PAYLOAD_CAPABILITIES = Arrays.asList(IdentityNamespace.IDENTITY_NAMESPACE);
static final Collection<String> NON_PAYLOAD_REQUIREMENTS = Arrays.asList(HostNamespace.HOST_NAMESPACE, ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
@@ -51,6 +72,7 @@ final class ModuleResolver {
*/
ModuleResolver(ModuleContainerAdaptor adaptor) {
this.adaptor = adaptor;
+ setDebugOptions();
}
/**
@@ -241,9 +263,21 @@ final class ModuleResolver {
static void removeNonEffectiveCapabilities(ListIterator<ModuleCapability> iCapabilities) {
rewind(iCapabilities);
while (iCapabilities.hasNext()) {
- Object effective = iCapabilities.next().getDirectives().get(Namespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
- if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective))
+ Capability capability = iCapabilities.next();
+ Object effective = capability.getDirectives().get(Namespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
+ if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) {
iCapabilities.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was not effective") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource()) //
+ .toString());
+ }
+ }
}
}
@@ -495,8 +529,32 @@ final class ModuleResolver {
@Override
public List<Capability> findProviders(Requirement requirement) {
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Finding capabilities for requirement") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(requirement) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(requirement.getResource()) //
+ .toString());
+ }
List<ModuleCapability> candidates = moduleDatabase.findCapabilities(requirement);
List<Capability> result = filterProviders(requirement, candidates);
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ StringBuilder builder = new StringBuilder("RESOLVER: Capabilities being returned to the resolver"); //$NON-NLS-1$
+ int i = 0;
+ for (Capability capability : result) {
+ builder.append(SEPARATOR).append(TAB) //
+ .append("[").append(++i).append("] ") //$NON-NLS-1$ //$NON-NLS-2$
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource());
+ }
+ Debug.println(builder.toString());
+ }
return result;
}
@@ -510,7 +568,29 @@ final class ModuleResolver {
removeNonEffectiveCapabilities(iCandidates);
removeSubstituted(iCandidates);
filterPermissions((BundleRequirement) requirement, iCandidates);
+
+ List<ModuleCapability> filteredMatches = null;
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ filteredMatches = new ArrayList<ModuleCapability>(candidates);
+ }
hook.filterMatches((BundleRequirement) requirement, InternalUtils.asListBundleCapability(candidates));
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ filteredMatches.removeAll(candidates);
+ if (!filteredMatches.isEmpty()) {
+ StringBuilder builder = new StringBuilder("RESOLVER: Capabilities filtered by ResolverHook.filterMatches"); //$NON-NLS-1$
+ int i = 0;
+ for (Capability capability : filteredMatches) {
+ builder.append(SEPARATOR).append(TAB) //
+ .append("[").append(++i).append("] ") //$NON-NLS-1$ //$NON-NLS-2$
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource());
+ }
+ Debug.println(builder.toString());
+ }
+ }
// filter resolved hosts after calling hooks to allow hooks to see the host capability
filterResolvedHosts(requirement, candidates, filterResolvedHosts);
@@ -538,8 +618,19 @@ final class ModuleResolver {
private void filterFailedToResolve(List<ModuleCapability> candidates) {
for (Iterator<ModuleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
- if (failedToResolve.contains(iCandidates.next().getRevision())) {
+ ModuleCapability capability = iCandidates.next();
+ if (failedToResolve.contains(capability.getRevision())) {
iCandidates.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because its resource was not resolved") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource()) //
+ .toString());
+ }
}
}
}
@@ -575,8 +666,30 @@ final class ModuleResolver {
}
Permission requirePermission = InternalUtils.getRequirePermission(candidate);
Permission providePermission = InternalUtils.getProvidePermission(candidate);
- if (!requirement.getRevision().getBundle().hasPermission(requirePermission) || !candidate.getRevision().getBundle().hasPermission(providePermission)) {
+ if (!requirement.getRevision().getBundle().hasPermission(requirePermission)) {
iCandidates.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because requirer did not have permission") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(candidate) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(candidate.getResource()) //
+ .toString());
+ }
+ } else if (!candidate.getRevision().getBundle().hasPermission(providePermission)) {
+ iCandidates.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because provider did not have permission") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(candidate) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(candidate.getResource()) //
+ .toString());
+ }
}
}
}
@@ -584,8 +697,20 @@ final class ModuleResolver {
private void filterDisabled(ListIterator<ModuleCapability> iCandidates) {
rewind(iCandidates);
while (iCandidates.hasNext()) {
- if (disabled.contains(iCandidates.next().getResource()))
+ Capability capability = iCandidates.next();
+ if (disabled.contains(capability.getResource())) {
iCandidates.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was disabled") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource()) //
+ .toString());
+ }
+ }
}
}
@@ -596,6 +721,16 @@ final class ModuleResolver {
ModuleWiring wiring = wirings.get(capability.getRevision());
if (wiring != null && wiring.isSubtituted(capability)) {
iCapabilities.remove();
+ if (DEBUG_RESOLVER || DEBUG_PROVIDERS) {
+ Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was substituted") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB) //
+ .append(capability) //
+ .append(SEPARATOR).append(TAB).append(TAB) //
+ .append("of resource") //$NON-NLS-1$
+ .append(SEPARATOR).append(TAB).append(TAB).append(TAB) //
+ .append(capability.getResource()) //
+ .toString());
+ }
}
}
}