diff options
4 files changed, 349 insertions, 301 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java index b5429eb3a..d22ffc413 100644 --- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java +++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java @@ -67,12 +67,13 @@ class Candidates /** * Private copy constructor used by the copy() method. + * * @param dependentMap the capability dependency map. * @param candidateMap the requirement candidate map. * @param hostFragments the fragment map. * @param wrappedHosts the wrapped hosts map. - * @param substitutableMap - **/ + * @param substitutableMap + */ private Candidates( Set<Resource> mandatoryResources, Map<Capability, Set<Requirement>> dependentMap, @@ -94,7 +95,7 @@ class Candidates /** * Constructs an empty Candidates object. - **/ + */ public Candidates(Map<Resource, Boolean> validOnDemandResources) { m_mandatoryResources = new HashSet<Resource>(); @@ -110,14 +111,15 @@ class Candidates * Populates candidates for the specified revision. How a revision is * resolved depends on its resolution type as follows: * <ul> - * <li><tt>MANDATORY</tt> - must resolve and failure to do so throws - * an exception.</li> - * <li><tt>OPTIONAL</tt> - attempt to resolve, but no exception is thrown - * if the resolve fails.</li> - * <li><tt>ON_DEMAND</tt> - only resolve on demand; this only applies to - * fragments and will only resolve a fragment if its host is already - * selected as a candidate.</li> + * <li><tt>MANDATORY</tt> - must resolve and failure to do so throws an + * exception.</li> + * <li><tt>OPTIONAL</tt> - attempt to resolve, but no exception is thrown if + * the resolve fails.</li> + * <li><tt>ON_DEMAND</tt> - only resolve on demand; this only applies to + * fragments and will only resolve a fragment if its host is already + * selected as a candidate.</li> * </ul> + * * @param rc the resolve context used for populating the candidates. * @param resource the resource whose candidates should be populated. * @param resolution indicates the resolution type. @@ -149,7 +151,6 @@ class Candidates return; } - if (resolution == MANDATORY) { m_mandatoryResources.add(resource); @@ -171,6 +172,7 @@ class Candidates /** * Populates candidates for the specified revision. + * * @param state the resolver state used for populating the candidates. * @param revision the revision whose candidates should be populated. */ @@ -220,9 +222,8 @@ class Candidates else if (cacheValue != null) { // Increment and get the cycle count. - cycleCount = (Integer) - (((Object[]) cacheValue)[0] - = new Integer(((Integer) ((Object[]) cacheValue)[0]).intValue() + 1)); + cycleCount = (Integer) (((Object[]) cacheValue)[0] = + new Integer(((Integer) ((Object[]) cacheValue)[0]).intValue() + 1)); // Get the already populated candidates. localCandidateMap = (Map) ((Object[]) cacheValue)[1]; // Get the remaining requirements. @@ -261,7 +262,7 @@ class Candidates .get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE); if (!rc.isEffective(req) || ((resolution != null) - && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC))) + && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC))) { continue; } @@ -285,9 +286,9 @@ class Candidates if (Util.isFragment(resource) && rc.getWirings().containsKey(resource)) { // This is a fragment that is already resolved and there is no unresolved hosts to attach it to. - m_populateResultCache.put(resource, Boolean.TRUE); - return; - } + m_populateResultCache.put(resource, Boolean.TRUE); + return; + } String msg = "Unable to resolve " + resource + ": missing requirement " + req; if (rethrow != null) @@ -321,26 +322,31 @@ class Candidates { add(localCandidateMap); } - if ((rc instanceof FelixResolveContext) && !Util.isFragment(resource)) { - Collection<Resource> ondemandFragments = ((FelixResolveContext) rc).getOndemandResources(resource); - for (Resource fragment : ondemandFragments) { - Boolean valid = m_validOnDemandResources.get(fragment); - if (valid == null) { - // Mark this resource as a valid on demand resource - m_validOnDemandResources.put(fragment, Boolean.TRUE); - valid = Boolean.TRUE; - } - if (valid) { - // This resource is a valid on demand resource; - // populate it now, consider it optional - populate(rc, fragment, OPTIONAL); - } - } + if ((rc instanceof FelixResolveContext) && !Util.isFragment(resource)) + { + Collection<Resource> ondemandFragments = ((FelixResolveContext) rc).getOndemandResources(resource); + for (Resource fragment : ondemandFragments) + { + Boolean valid = m_validOnDemandResources.get(fragment); + if (valid == null) + { + // Mark this resource as a valid on demand resource + m_validOnDemandResources.put(fragment, Boolean.TRUE); + valid = Boolean.TRUE; + } + if (valid) + { + // This resource is a valid on demand resource; + // populate it now, consider it optional + populate(rc, fragment, OPTIONAL); + } + } } } } - private void populateSubstitutables() { + private void populateSubstitutables() + { for (Map.Entry<Resource, Object> populated : m_populateResultCache.entrySet()) { if (populated.getValue() instanceof Boolean) @@ -366,14 +372,14 @@ class Candidates Map<String, Collection<Capability>> exportNames = new HashMap<String, Collection<Capability>>(); for (Capability packageExport : packageExports) { - String packageName = (String) packageExport.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE); - Collection<Capability> caps = exportNames.get(packageName); - if (caps == null) - { - caps = new ArrayList<Capability>(1); - exportNames.put(packageName, caps); - } - caps.add(packageExport); + String packageName = (String) packageExport.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE); + Collection<Capability> caps = exportNames.get(packageName); + if (caps == null) + { + caps = new ArrayList<Capability>(1); + exportNames.put(packageName, caps); + } + caps.add(packageExport); } // Check if any requirements substitute one of the exported packages for (Requirement req : packageImports) @@ -383,15 +389,17 @@ class Candidates { String packageName = (String) substitutes.iterator().next().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE); Collection<Capability> exportedPackages = exportNames.get(packageName); - if (exportedPackages != null) { + if (exportedPackages != null) + { // The package is exported; - // Check if the requirement only has the bundle's own export as candidates - substitutes = new ArrayList<Capability>(substitutes); + // Check if the requirement only has the bundle's own export as candidates + substitutes = new ArrayList<Capability>(substitutes); for (Capability exportedPackage : exportedPackages) { substitutes.remove(exportedPackage); } - if (!substitutes.isEmpty()) { + if (!substitutes.isEmpty()) + { for (Capability exportedPackage : exportedPackages) { m_subtitutableMap.put(exportedPackage, req); @@ -400,26 +408,30 @@ class Candidates } } } - } + } private static final int UNPROCESSED = 0; private static final int PROCESSING = 1; private static final int SUBSTITUTED = 2; private static final int EXPORTED = 3; + void checkSubstitutes(List<Candidates> importPermutations) throws ResolutionException { Map<Capability, Integer> substituteStatuses = new HashMap<Capability, Integer>(m_subtitutableMap.size()); - for (Capability substitutable : m_subtitutableMap.keySet()) { + for (Capability substitutable : m_subtitutableMap.keySet()) + { // initialize with unprocessed substituteStatuses.put(substitutable, UNPROCESSED); } // note we are iterating over the original unmodified map by design - for (Capability substitutable : m_subtitutableMap.keySet()) { + for (Capability substitutable : m_subtitutableMap.keySet()) + { isSubstituted(substitutable, substituteStatuses); } // Remove any substituted exports from candidates - for (Map.Entry<Capability, Integer> substituteStatus : substituteStatuses.entrySet()) { + for (Map.Entry<Capability, Integer> substituteStatus : substituteStatuses.entrySet()) + { if (substituteStatus.getValue() == SUBSTITUTED) { if (m_dependentMap.isEmpty()) @@ -437,10 +449,13 @@ class Candidates Set<Requirement> dependents = m_dependentMap.get(substituteStatus.getKey()); if (dependents != null) { - for (Requirement dependent : dependents) { + for (Requirement dependent : dependents) + { List<Capability> candidates = m_candidateMap.get(dependent); - if (candidates != null) { - candidates: for (Iterator<Capability> iCandidates = candidates.iterator(); iCandidates.hasNext();) + if (candidates != null) + { + candidates: + for (Iterator<Capability> iCandidates = candidates.iterator(); iCandidates.hasNext();) { Capability candidate = iCandidates.next(); Integer candidateStatus = substituteStatuses.get(candidate); @@ -448,44 +463,46 @@ class Candidates { candidateStatus = EXPORTED; } - switch (candidateStatus) { - case EXPORTED : - // non-substituted candidate hit before the substituted one; do not continue - break candidates; - case SUBSTITUTED : - default : - // Need to remove any substituted that comes before an exported candidate - iCandidates.remove(); - // continue to next candidate - break; - } + switch (candidateStatus) + { + case EXPORTED: + // non-substituted candidate hit before the substituted one; do not continue + break candidates; + case SUBSTITUTED: + default: + // Need to remove any substituted that comes before an exported candidate + iCandidates.remove(); + // continue to next candidate + break; + } } } - } + } } } } - private boolean isSubstituted(Capability substitutableCap, Map<Capability, Integer> substituteStatuses) throws ResolutionException + private boolean isSubstituted(Capability substitutableCap, Map<Capability, Integer> substituteStatuses) throws ResolutionException { Integer substituteState = substituteStatuses.get(substitutableCap); - if (substituteState == null) - { - return false; - } - - switch (substituteState.intValue()) { - case PROCESSING : - // found a cycle mark the initiator as not substituted - substituteStatuses.put(substitutableCap, EXPORTED); - return false; - case SUBSTITUTED : - return true; - case EXPORTED : - return false; - default : - break; - } + if (substituteState == null) + { + return false; + } + + switch (substituteState.intValue()) + { + case PROCESSING: + // found a cycle mark the initiator as not substituted + substituteStatuses.put(substitutableCap, EXPORTED); + return false; + case SUBSTITUTED: + return true; + case EXPORTED: + return false; + default: + break; + } Requirement substitutableReq = m_subtitutableMap.get(substitutableCap); if (substitutableReq == null) @@ -511,16 +528,16 @@ class Candidates { // The resource's exported package is substituted for this permutation. substituteStatuses.put(substitutableCap, SUBSTITUTED); - return true; + return true; } - } + } } // if we get here then the export is not substituted substituteStatuses.put(substitutableCap, EXPORTED); return false; } - public void populateDynamic( + public void populateDynamic( ResolveContext rc, Resource resource, Requirement req, List<Capability> candidates) throws ResolutionException { @@ -554,6 +571,7 @@ class Candidates * synthesizes candidates for any candidates coming from any attached * fragments, since fragment capabilities only appear once, but technically * each host represents a unique capability. + * * @param state the resolver state. * @param revision the revision being resolved. * @param candidates the candidates to process. @@ -568,7 +586,7 @@ class Candidates ResolutionException rethrow = null; Set<Capability> fragmentCands = null; for (Iterator<Capability> itCandCap = candidates.iterator(); - itCandCap.hasNext(); ) + itCandCap.hasNext();) { Capability candCap = itCandCap.next(); @@ -626,11 +644,12 @@ class Candidates { for (Capability fragCand : fragmentCands) { - String fragCandName = fragCand.getNamespace(); - if (IdentityNamespace.IDENTITY_NAMESPACE.equals(fragCandName)) { - // no need to wrap identity namespace ever - continue; - } + String fragCandName = fragCand.getNamespace(); + if (IdentityNamespace.IDENTITY_NAMESPACE.equals(fragCandName)) + { + // no need to wrap identity namespace ever + continue; + } // Only necessary for resolved fragments. Wiring wiring = rc.getWirings().get(fragCand.getResource()); if (wiring != null) @@ -644,7 +663,7 @@ class Candidates // since it may be a substitutable export. if (!fragCandName.equals(PackageNamespace.PACKAGE_NAMESPACE) || rc.getWirings().get(wire.getProvider()) - .getResourceCapabilities(null).contains(fragCand)) + .getResourceCapabilities(null).contains(fragCand)) { // Note that we can just add this as a candidate // directly, since we know it is already resolved. @@ -691,13 +710,14 @@ class Candidates /** * Adds a requirement and its matching candidates to the internal data - * structure. This method assumes it owns the data being passed in and - * does not make a copy. It takes the data and processes, such as calculating - * which requirements depend on which capabilities and recording any fragments - * it finds for future merging. + * structure. This method assumes it owns the data being passed in and does + * not make a copy. It takes the data and processes, such as calculating + * which requirements depend on which capabilities and recording any + * fragments it finds for future merging. + * * @param req the requirement to add. * @param candidates the candidates matching the requirement. - **/ + */ private void add(Requirement req, List<Capability> candidates) { if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE)) @@ -711,10 +731,11 @@ class Candidates /** * Adds requirements and candidates in bulk. The outer map is not retained - * by this method, but the inner data structures are, so they should not - * be further modified by the caller. + * by this method, but the inner data structures are, so they should not be + * further modified by the caller. + * * @param candidates the bulk requirements and candidates to add. - **/ + */ private void add(Map<Requirement, List<Capability>> candidates) { for (Entry<Requirement, List<Capability>> entry : candidates.entrySet()) @@ -724,12 +745,15 @@ class Candidates } /** - * Returns the wrapped resource associated with the given resource. If the resource - * was not wrapped, then the resource itself is returned. This is really only - * needed to determine if the root resources of the resolve have been wrapped. + * Returns the wrapped resource associated with the given resource. If the + * resource was not wrapped, then the resource itself is returned. This is + * really only needed to determine if the root resources of the resolve have + * been wrapped. + * * @param r the resource whose wrapper is desired. - * @return the wrapper resource or the resource itself if it was not wrapped. - **/ + * @return the wrapper resource or the resource itself if it was not + * wrapped. + */ public Resource getWrappedHost(Resource r) { Resource wrapped = m_allWrappedHosts.get(r); @@ -738,9 +762,10 @@ class Candidates /** * Gets the candidates associated with a given requirement. + * * @param req the requirement whose candidates are desired. * @return the matching candidates or null. - **/ + */ public List<Capability> getCandidates(Requirement req) { return m_candidateMap.get(req); @@ -756,24 +781,25 @@ class Candidates * modules and attaching their selected fragments, removing all unselected * fragment modules, and replacing all occurrences of the original fragments * in the internal data structures with the wrapped host modules instead. - * Thus, fragment capabilities and requirements are merged into the appropriate - * host and the candidates for the fragment now become candidates for the host. - * Likewise, any module depending on a fragment now depend on the host. Note - * that this process is sort of like multiplication, since one fragment that - * can attach to two hosts effectively gets multiplied across the two hosts. - * So, any modules being satisfied by the fragment will end up having the - * two hosts as potential candidates, rather than the single fragment. - * @throws ResolutionException if the removal of any unselected fragments result - * in the root module being unable to resolve. - **/ + * Thus, fragment capabilities and requirements are merged into the + * appropriate host and the candidates for the fragment now become + * candidates for the host. Likewise, any module depending on a fragment now + * depend on the host. Note that this process is sort of like + * multiplication, since one fragment that can attach to two hosts + * effectively gets multiplied across the two hosts. So, any modules being + * satisfied by the fragment will end up having the two hosts as potential + * candidates, rather than the single fragment. + * + * @throws ResolutionException if the removal of any unselected fragments + * result in the root module being unable to resolve. + */ public void prepare(ResolveContext rc) throws ResolutionException { // Maps a host capability to a map containing its potential fragments; // the fragment map maps a fragment symbolic name to a map that maps // a version to a list of fragments requirements matching that symbolic // name and version. - Map<Capability, Map<String, Map<Version, List<Requirement>>>> - hostFragments = Collections.EMPTY_MAP; + Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments = Collections.EMPTY_MAP; if (m_fragmentsPresent) { hostFragments = populateDependents(); @@ -792,17 +818,15 @@ class Candidates // * This includes setting candidates for attached fragment // requirements as well as replacing fragment capabilities // with host's attached fragment capabilities. - // Steps 1 and 2 List<WrappedResource> hostResources = new ArrayList<WrappedResource>(); List<Resource> unselectedFragments = new ArrayList<Resource>(); - for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> - hostEntry : hostFragments.entrySet()) + for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> hostEntry : hostFragments.entrySet()) { // Step 1 Capability hostCap = hostEntry.getKey(); - Map<String, Map<Version, List<Requirement>>> fragments - = hostEntry.getValue(); + Map<String, Map<Version, List<Requirement>>> fragments = + hostEntry.getValue(); List<Resource> selectedFragments = new ArrayList<Resource>(); for (Entry<String, Map<Version, List<Requirement>>> fragEntry : fragments.entrySet()) @@ -981,12 +1005,10 @@ class Candidates // the fragment map maps a fragment symbolic name to a map that maps // a version to a list of fragments requirements matching that symbolic // name and version. - private Map<Capability, - Map<String, Map<Version, List<Requirement>>>> populateDependents() + private Map<Capability, Map<String, Map<Version, List<Requirement>>>> populateDependents() { - Map<Capability, Map<String, Map<Version, List<Requirement>>>> - hostFragments = new HashMap<Capability, - Map<String, Map<Version, List<Requirement>>>>(); + Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments = + new HashMap<Capability, Map<String, Map<Version, List<Requirement>>>>(); for (Entry<Requirement, List<Capability>> entry : m_candidateMap.entrySet()) { Requirement req = entry.getKey(); @@ -1008,8 +1030,7 @@ class Candidates String resSymName = Util.getSymbolicName(req.getResource()); Version resVersion = Util.getVersion(req.getResource()); - Map<String, Map<Version, List<Requirement>>> - fragments = hostFragments.get(cap); + Map<String, Map<Version, List<Requirement>>> fragments = hostFragments.get(cap); if (fragments == null) { fragments = new HashMap<String, Map<Version, List<Requirement>>>(); @@ -1041,9 +1062,11 @@ class Candidates * as a fragment or a singleton. This process may cause other modules to * become unresolved if they depended on the module's capabilities and there * is no other candidate. + * * @param revision the module to remove. - * @throws ResolveException if removing the module caused the resolve to fail. - **/ + * @throws ResolveException if removing the module caused the resolve to + * fail. + */ private void removeResource(Resource resource, ResolutionException ex) throws ResolutionException { @@ -1066,12 +1089,14 @@ class Candidates * Removes the specified module from the internal data structures, which * involves removing its requirements and its capabilities. This may cause * other modules to become unresolved as a result. + * * @param br the module to remove. - * @param unresolvedRevisions a list to containing any additional modules that - * that became unresolved as a result of removing this module and will - * also need to be removed. - * @throws ResolveException if removing the module caused the resolve to fail. - **/ + * @param unresolvedRevisions a list to containing any additional modules + * that that became unresolved as a result of removing this module and will + * also need to be removed. + * @throws ResolveException if removing the module caused the resolve to + * fail. + */ private void remove(Resource resource, Set<Resource> unresolvedResources) throws ResolutionException { @@ -1088,8 +1113,9 @@ class Candidates /** * Removes a requirement from the internal data structures. + * * @param req the requirement to remove. - **/ + */ private void remove(Requirement req) { boolean isFragment = req.getNamespace().equals(HostNamespace.HOST_NAMESPACE); @@ -1111,12 +1137,14 @@ class Candidates /** * Removes a capability from the internal data structures. This may cause * other modules to become unresolved as a result. + * * @param c the capability to remove. - * @param unresolvedRevisions a list to containing any additional modules that - * that became unresolved as a result of removing this module and will - * also need to be removed. - * @throws ResolveException if removing the module caused the resolve to fail. - **/ + * @param unresolvedRevisions a list to containing any additional modules + * that that became unresolved as a result of removing this module and will + * also need to be removed. + * @throws ResolveException if removing the module caused the resolve to + * fail. + */ private void remove(Capability c, Set<Resource> unresolvedResources) throws ResolutionException { @@ -1147,8 +1175,9 @@ class Candidates /** * Creates a copy of the Candidates object. This is used for creating * permutations when package space conflicts are discovered. + * * @return copy of this Candidates object. - **/ + */ public Candidates copy() { Map<Capability, Set<Requirement>> dependentMap = @@ -1190,7 +1219,7 @@ class Candidates { Wiring wiring = rc.getWirings().get(resource); System.out.println(" " + resource - + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)")); + + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)")); List<Requirement> reqs = (wiring != null) ? wiring.getResourceRequirements(null) : resource.getRequirements(null); @@ -1216,4 +1245,4 @@ class Candidates } System.out.println("=== END CANDIDATE MAP ==="); } -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java index 7dbaadc24..502a7e459 100644 --- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java +++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java @@ -20,26 +20,25 @@ import java.util.Collection; import org.osgi.resource.Resource; -public interface FelixResolveContext { - - /** - * Return the resources that the resolver should attempt to resolve on - * demand for specified resource which is being resolved. Inability to - * resolve one of the on demand resources will not result in a - * resolution exception. - * - * <p> - * The resolver will ask for on demand resources for each resource that - * is getting pulled into a resolve operation. - * An example of an on demand resource is a fragment. When a host - * is being resolved the resolve context will be asked if any additional - * resources should be added to the resolve operation. The resolve context - * may decide that the potential fragments of the host should be resolved - * along with the host. - * - * @return A collection of the resources that the resolver should attempt to - * resolve for this resolve context. May be empty if there are no - * on demand resources. The returned collection may be unmodifiable. - */ - public Collection<Resource> getOndemandResources(Resource host); +public interface FelixResolveContext +{ + /** + * Return the resources that the resolver should attempt to resolve on + * demand for specified resource which is being resolved. Inability to + * resolve one of the on demand resources will not result in a resolution + * exception. + * + * <p> + * The resolver will ask for on demand resources for each resource that is + * getting pulled into a resolve operation. An example of an on demand + * resource is a fragment. When a host is being resolved the resolve context + * will be asked if any additional resources should be added to the resolve + * operation. The resolve context may decide that the potential fragments of + * the host should be resolved along with the host. + * + * @return A collection of the resources that the resolver should attempt to + * resolve for this resolve context. May be empty if there are no on demand + * resources. The returned collection may be unmodifiable. + */ + public Collection<Resource> getOndemandResources(Resource host); } diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java index b652051f7..fd3a8a751 100644 --- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java +++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java @@ -26,21 +26,21 @@ import org.osgi.service.resolver.ResolutionException; * <p> * This class mimics the standard OSGi <tt>LogService</tt> interface. An * instance of this class is used by the framework for all logging. By default - * this class logs messages to standard out. The log level can be set to - * control the amount of logging performed, where a higher number results in - * more logging. A log level of zero turns off logging completely. + * this class logs messages to standard out. The log level can be set to control + * the amount of logging performed, where a higher number results in more + * logging. A log level of zero turns off logging completely. * </p> * <p> - * The log levels match those specified in the OSGi Log Service (i.e., 1 = error, - * 2 = warning, 3 = information, and 4 = debug). The default value is 1. + * The log levels match those specified in the OSGi Log Service (i.e., 1 = + * error, 2 = warning, 3 = information, and 4 = debug). The default value is 1. * </p> * <p> - * This class also uses the System Bundle's context to track log services - * and will use the highest ranking log service, if present, as a back end - * instead of printing to standard out. The class uses reflection to invoking - * the log service's method to avoid a dependency on the log interface. + * This class also uses the System Bundle's context to track log services and + * will use the highest ranking log service, if present, as a back end instead + * of printing to standard out. The class uses reflection to invoking the log + * service's method to avoid a dependency on the log interface. * </p> -**/ + */ public class Logger { public static final int LOG_ERROR = 1; @@ -77,10 +77,10 @@ public class Logger protected void doLog(int level, String msg, Throwable throwable) { - if (level > m_logLevel) - { - return; - } + if (level > m_logLevel) + { + return; + } String s = ""; s = s + msg; if (throwable != null) @@ -120,7 +120,8 @@ public class Logger } } - public void logUsesConstraintViolation(Resource resource, ResolutionException error) { + public void logUsesConstraintViolation(Resource resource, ResolutionException error) + { // do nothing by default } } diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java index d6d3910fe..6ada758b0 100644 --- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java @@ -264,30 +264,36 @@ public class ResolverImpl implements Resolver catch (ResolutionException ex) { rethrow = ex; - if (currentFaultyResources == null) { - currentFaultyResources = new HashMap<Resource, ResolutionException>(); + if (currentFaultyResources == null) + { + currentFaultyResources = new HashMap<Resource, ResolutionException>(); } Resource faultyResource = resource; // check that the faulty requirement is not from a fragment - for (Requirement faultyReq : ex.getUnresolvedRequirements()) { - if (faultyReq instanceof WrappedRequirement) + for (Requirement faultyReq : ex.getUnresolvedRequirements()) + { + if (faultyReq instanceof WrappedRequirement) { faultyResource = ((WrappedRequirement) faultyReq) .getDeclaredRequirement().getResource(); break; - } + } } currentFaultyResources.put(faultyResource, ex); } } - if (currentFaultyResources != null) { - if (faultyResources == null) { - faultyResources = currentFaultyResources; - } else if (faultyResources.size() > currentFaultyResources.size()) { - // save the optimal faultyResources which has less - faultyResources = currentFaultyResources; - } + if (currentFaultyResources != null) + { + if (faultyResources == null) + { + faultyResources = currentFaultyResources; + } + else if (faultyResources.size() > currentFaultyResources.size()) + { + // save the optimal faultyResources which has less + faultyResources = currentFaultyResources; + } } } while ((rethrow != null) @@ -299,24 +305,29 @@ public class ResolverImpl implements Resolver // again; otherwise, rethrow the resolve exception. if (rethrow != null) { - if (faultyResources != null) { - Set<Resource> resourceKeys = faultyResources.keySet(); + if (faultyResources != null) + { + Set<Resource> resourceKeys = faultyResources.keySet(); retry = (optionalResources.removeAll(resourceKeys)); - for (Resource faultyResource : resourceKeys) { - Boolean valid = validOnDemandResources.get(faultyResource); - if (valid != null && valid.booleanValue()) { - // This was an ondemand resource. - // Invalidate it and try again. - validOnDemandResources.put(faultyResource, Boolean.FALSE); - retry = true; - } - } + for (Resource faultyResource : resourceKeys) + { + Boolean valid = validOnDemandResources.get(faultyResource); + if (valid != null && valid.booleanValue()) + { + // This was an ondemand resource. + // Invalidate it and try again. + validOnDemandResources.put(faultyResource, Boolean.FALSE); + retry = true; + } + } // log all the resolution exceptions for the uses constraint violations - for (Map.Entry<Resource, ResolutionException> usesError : faultyResources.entrySet()) { - m_logger.logUsesConstraintViolation(usesError.getKey(), usesError.getValue()); - } + for (Map.Entry<Resource, ResolutionException> usesError : faultyResources.entrySet()) + { + m_logger.logUsesConstraintViolation(usesError.getKey(), usesError.getValue()); + } } - if (!retry) { + if (!retry) + { throw rethrow; } } @@ -348,8 +359,8 @@ public class ResolverImpl implements Resolver { wireMap = populateWireMap( - rc, allCandidates.getWrappedHost(target), - resourcePkgMap, wireMap, allCandidates); + rc, allCandidates.getWrappedHost(target), + resourcePkgMap, wireMap, allCandidates); } } } @@ -376,12 +387,13 @@ public class ResolverImpl implements Resolver * are used to resolve the requirement and the resolve context is not asked * to find providers for the dynamic requirement. The host resource is * expected to not be a fragment, to already be resolved and have an - * existing wiring provided by the resolve context. <p> This operation may - * resolve additional resources in order to resolve the dynamic requirement. - * The returned map will contain entries for each resource that got resolved - * in addition to the specified host resource. The wire list for the host - * resource will only contain a single wire which is for the dynamic - * requirement. + * existing wiring provided by the resolve context. + * <p> + * This operation may resolve additional resources in order to resolve the + * dynamic requirement. The returned map will contain entries for each + * resource that got resolved in addition to the specified host resource. + * The wire list for the host resource will only contain a single wire which + * is for the dynamic requirement. * * @param rc the resolve context * @param host the hosting resource @@ -419,9 +431,6 @@ public class ResolverImpl implements Resolver } } - - - Map<Resource, Packages> resourcePkgMap = new HashMap<Resource, Packages>(); Map<Resource, Boolean> onDemandResources = new HashMap<Resource, Boolean>(); @@ -514,13 +523,16 @@ public class ResolverImpl implements Resolver ((WrappedRequirement) faultyReq) .getDeclaredRequirement().getResource(); } - Boolean valid = onDemandResources.get(faultyResource); - if (valid != null && valid.booleanValue()) { - onDemandResources.put(faultyResource, Boolean.FALSE); - retry = true; - } else { + Boolean valid = onDemandResources.get(faultyResource); + if (valid != null && valid.booleanValue()) + { + onDemandResources.put(faultyResource, Boolean.FALSE); + retry = true; + } + else + { throw rethrow; - } + } } // If there is no exception to rethrow, then this was a clean // resolve, so populate the wire map. @@ -1200,18 +1212,18 @@ public class ResolverImpl implements Resolver rethrow = (rethrow != null) ? rethrow : new ResolutionException( - "Uses constraint violation. Unable to resolve resource " - + Util.getSymbolicName(resource) - + " [" + resource - + "] because it exports package '" - + pkgName - + "' and is also exposed to it from resource " - + Util.getSymbolicName(usedBlame.m_cap.getResource()) - + " [" + usedBlame.m_cap.getResource() - + "] via the following dependency chain:\n\n" - + toStringBlame(session.getContext(), allCandidates, usedBlame), - null, - null); + "Uses constraint violation. Unable to resolve resource " + + Util.getSymbolicName(resource) + + " [" + resource + + "] because it exports package '" + + pkgName + + "' and is also exposed to it from resource " + + Util.getSymbolicName(usedBlame.m_cap.getResource()) + + " [" + usedBlame.m_cap.getResource() + + "] via the following dependency chain:\n\n" + + toStringBlame(session.getContext(), allCandidates, usedBlame), + null, + null); mutated = (mutated != null) ? mutated @@ -1280,7 +1292,7 @@ public class ResolverImpl implements Resolver for (Entry<String, List<Blame>> requirementBlames : allImportRequirePkgs.entrySet()) { String pkgName = requirementBlames.getKey(); - if (!pkgs.m_usedPkgs.containsKey(pkgName)) + if (!pkgs.m_usedPkgs.containsKey(pkgName)) { continue; } @@ -1289,9 +1301,9 @@ public class ResolverImpl implements Resolver { if (!isCompatible(session, requirementBlames.getValue(), usedBlames.m_cap, resourcePkgMap)) { - // Split packages, need to think how to get a good message for split packages (sigh) - // For now we just use the first requirement that brings in the package that conflicts - Blame requirementBlame = requirementBlames.getValue().get(0); + // Split packages, need to think how to get a good message for split packages (sigh) + // For now we just use the first requirement that brings in the package that conflicts + Blame requirementBlame = requirementBlames.getValue().get(0); for (Blame usedBlame : usedBlames.m_blames) { if (checkMultiple(session, usedBlames, usedBlame, allCandidates)) @@ -1308,23 +1320,23 @@ public class ResolverImpl implements Resolver rethrow = (rethrow != null) ? rethrow : new ResolutionException( - "Uses constraint violation. Unable to resolve resource " - + Util.getSymbolicName(resource) - + " [" + resource - + "] because it is exposed to package '" - + pkgName - + "' from resources " - + Util.getSymbolicName(requirementBlame.m_cap.getResource()) - + " [" + requirementBlame.m_cap.getResource() - + "] and " - + Util.getSymbolicName(usedBlame.m_cap.getResource()) - + " [" + usedBlame.m_cap.getResource() - + "] via two dependency chains.\n\nChain 1:\n" - + toStringBlame(session.getContext(), allCandidates, requirementBlame) - + "\n\nChain 2:\n" - + toStringBlame(session.getContext(), allCandidates, usedBlame), - null, - null); + "Uses constraint violation. Unable to resolve resource " + + Util.getSymbolicName(resource) + + " [" + resource + + "] because it is exposed to package '" + + pkgName + + "' from resources " + + Util.getSymbolicName(requirementBlame.m_cap.getResource()) + + " [" + requirementBlame.m_cap.getResource() + + "] and " + + Util.getSymbolicName(usedBlame.m_cap.getResource()) + + " [" + usedBlame.m_cap.getResource() + + "] via two dependency chains.\n\nChain 1:\n" + + toStringBlame(session.getContext(), allCandidates, requirementBlame) + + "\n\nChain 2:\n" + + toStringBlame(session.getContext(), allCandidates, usedBlame), + null, + null); mutated = (mutated != null) ? mutated @@ -1383,7 +1395,8 @@ public class ResolverImpl implements Resolver // Try to permutate the candidate for the original // import requirement; only permutate it if we haven't // done so already. - for (Blame requirementBlame : requirementBlames.getValue()) { + for (Blame requirementBlame : requirementBlames.getValue()) + { Requirement req = requirementBlame.m_reqs.get(0); if (!mutated.contains(req)) { @@ -1393,8 +1406,7 @@ public class ResolverImpl implements Resolver // try to check if that the case and only permutate it once. permutateIfNeeded(allCandidates, req, importPermutations); } - } - + } m_logger.log( Logger.LOG_DEBUG, @@ -1596,39 +1608,45 @@ public class ResolverImpl implements Resolver if ((!currentBlames.isEmpty()) && (candCap != null)) { List<Capability> currentSources; - // quick check for single source package + // quick check for single source package if (currentBlames.size() == 1) { Capability currentCap = currentBlames.get(0).m_cap; - if (currentCap.equals(candCap)) { + if (currentCap.equals(candCap)) + { return true; } - currentSources = + currentSources = getPackageSources( - session, - currentCap, - resourcePkgMap); - } else { + session, + currentCap, + resourcePkgMap); + } + else + { currentSources = new ArrayList<Capability>(currentBlames.size()); - for (Blame currentBlame : currentBlames) { - List<Capability> blameSources = - getPackageSources( - session, - currentBlame.m_cap, - resourcePkgMap); - for (Capability blameSource : blameSources) { - if (!currentSources.contains(blameSource)) { - currentSources.add(blameSource); - } - } - } + for (Blame currentBlame : currentBlames) + { + List<Capability> blameSources = + getPackageSources( + session, + currentBlame.m_cap, + resourcePkgMap); + for (Capability blameSource : blameSources) + { + if (!currentSources.contains(blameSource)) + { + currentSources.add(blameSource); + } + } + } } List<Capability> candSources = getPackageSources( - session, - candCap, - resourcePkgMap); + session, + candCap, + resourcePkgMap); return currentSources.containsAll(candSources) || candSources.containsAll(currentSources); @@ -1698,7 +1716,8 @@ public class ResolverImpl implements Resolver { sourceCap = new WrappedCapability(cap.getResource(), sourceCap); } - if (!sources.contains(sourceCap)) { + if (!sources.contains(sourceCap)) + { sources.add(sourceCap); } } @@ -1787,7 +1806,7 @@ public class ResolverImpl implements Resolver { targetCand = allCandidates.getCandidates( targetCand.getRequirements(HostNamespace.HOST_NAMESPACE).get(0)) - .iterator().next().getResource(); + .iterator().next().getResource(); targetCand = allCandidates.getWrappedHost(targetCand); } @@ -1857,11 +1876,11 @@ public class ResolverImpl implements Resolver { fragmentWires.add( new WireImpl( - getDeclaredResource(fragment), - req, - unwrappedResource, - unwrappedResource.getCapabilities( - HostNamespace.HOST_NAMESPACE).get(0))); + getDeclaredResource(fragment), + req, + unwrappedResource, + unwrappedResource.getCapabilities( + HostNamespace.HOST_NAMESPACE).get(0))); } // Otherwise, if the fragment isn't already resolved and // this is the first time we are seeing it, then create @@ -1939,10 +1958,10 @@ public class ResolverImpl implements Resolver packageWires.add( new WireImpl( - resource, - dynReq, - getDeclaredResource(dynCand.getResource()), - getDeclaredCapability(dynCand))); + resource, + dynReq, + getDeclaredResource(dynCand.getResource()), + getDeclaredCapability(dynCand))); wireMap.put(resource, packageWires); @@ -2033,9 +2052,9 @@ public class ResolverImpl implements Resolver .get(PackageNamespace.PACKAGE_NAMESPACE).toString()); Capability usedCap = getSatisfyingCapability( - rc, - allCandidates, - blame.m_reqs.get(i + 1)); + rc, + allCandidates, + blame.m_reqs.get(i + 1)); sb.append("; uses:="); sb.append(usedCap.getAttributes() .get(PackageNamespace.PACKAGE_NAMESPACE)); @@ -2070,7 +2089,7 @@ public class ResolverImpl implements Resolver if (export.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE) && !export.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE) .equals(blame.m_cap.getAttributes().get( - PackageNamespace.PACKAGE_NAMESPACE))) + PackageNamespace.PACKAGE_NAMESPACE))) { sb.append("; uses:="); sb.append(blame.m_cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)); |