Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Candidates.java Wed Jun 15 18:57:20 2011 @@ -31,10 +31,8 @@ import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.felix.framework.BundleRevisionImpl; -import org.apache.felix.framework.BundleWiringImpl; import org.apache.felix.framework.resolver.Resolver.ResolverState; import org.apache.felix.framework.util.Util; -import org.apache.felix.framework.wiring.BundleCapabilityImpl; import org.apache.felix.framework.wiring.BundleRequirementImpl; import org.osgi.framework.Constants; import org.osgi.framework.Version; @@ -44,10 +42,8 @@ import org.osgi.framework.wiring.BundleR class Candidates { - private final BundleRevision m_root; - - // Set of all candidate bundle revisions. - private final Set<BundleRevision> m_candidateRevisions; + // Set of all involved bundle revisions. + private final Set<BundleRevision> m_involvedRevisions; // Maps a capability to requirements that match it. private final Map<BundleCapability, Set<BundleRequirement>> m_dependentMap; // Maps a requirement to the capability it matches. @@ -69,23 +65,20 @@ class Candidates /** * Private copy constructor used by the copy() method. - * @param root the root module for the resolve. * @param dependentMap the capability dependency map. * @param candidateMap the requirement candidate map. * @param hostFragments the fragment map. * @param wrappedHosts the wrapped hosts map. **/ private Candidates( - BundleRevision root, - Set<BundleRevision> candidateRevisions, + Set<BundleRevision> involvedRevisions, Map<BundleCapability, Set<BundleRequirement>> dependentMap, Map<BundleRequirement, SortedSet<BundleCapability>> candidateMap, Map<BundleCapability, Map<String, Map<Version, List<BundleRequirement>>>> hostFragments, Map<BundleRevision, HostBundleRevision> wrappedHosts, Map<BundleRevision, Object> populateResultCache, boolean fragmentsPresent) { - m_root = root; - m_candidateRevisions = candidateRevisions; + m_involvedRevisions = involvedRevisions; m_dependentMap = dependentMap; m_candidateMap = candidateMap; m_hostFragments = hostFragments; @@ -95,49 +88,17 @@ class Candidates } /** - * Constructs a new populated Candidates object for the specified root module. - * @param state the resolver state used for populating the candidates. - * @param root the root module for the resolve. - **/ - public Candidates(ResolverState state, BundleRevision root) - { - m_root = root; - m_candidateRevisions = new HashSet<BundleRevision>(); - m_dependentMap = new HashMap<BundleCapability, Set<BundleRequirement>>(); - m_candidateMap = new HashMap<BundleRequirement, SortedSet<BundleCapability>>(); - m_hostFragments = - new HashMap<BundleCapability, Map<String, Map<Version, List<BundleRequirement>>>>(); - m_allWrappedHosts = new HashMap<BundleRevision, HostBundleRevision>(); - m_populateResultCache = new HashMap<BundleRevision, Object>(); - - populate(state, m_root); - } - - /** - * Constructs a new populated Candidates object with the specified root module and - * starting requirement and matching candidates. This constructor is used - * when the root module is performing a dynamic import for the given - * requirement and the given potential candidates. - * @param state the resolver state used for populating the candidates. - * @param root the module with a dynamic import to resolve. - * @param req the requirement being resolved. - * @param candidates the potential candidates matching the requirement. + * Constructs an empty Candidates object. **/ - public Candidates(ResolverState state, BundleRevision root, - BundleRequirement req, SortedSet<BundleCapability> candidates) + public Candidates() { - m_root = root; - m_candidateRevisions = new HashSet<BundleRevision>(); + m_involvedRevisions = new HashSet<BundleRevision>(); m_dependentMap = new HashMap<BundleCapability, Set<BundleRequirement>>(); m_candidateMap = new HashMap<BundleRequirement, SortedSet<BundleCapability>>(); m_hostFragments = new HashMap<BundleCapability, Map<String, Map<Version, List<BundleRequirement>>>>(); m_allWrappedHosts = new HashMap<BundleRevision, HostBundleRevision>(); m_populateResultCache = new HashMap<BundleRevision, Object>(); - - add(req, candidates); - - populateDynamic(state, m_root); } /** @@ -314,6 +275,9 @@ class Candidates } else if (cycleCount.intValue() == 0) { + // Record invoved revision. + m_involvedRevisions.add(revision); + // Record that the revision was successfully populated. m_populateResultCache.put(revision, Boolean.TRUE); @@ -325,26 +289,31 @@ class Candidates } } - public final void populateOptional(ResolverState state, BundleRevision revision) - { - // We will always attempt to populate optional fragments, since this - // is necessary for greedy resolving of fragment. Howevere, we'll only - // attempt to populate optional non-fragment revisions if they aren't - // already resolved. +// TODO: OSGi R4.3 - Related to resolve() method clean up, can this just +// become the normal case? Currently, it just swallows the resolve +// exception, which would have to change. + public final boolean populate( + ResolverState state, BundleRevision revision, boolean isGreedyAttach) + { + // We will always attempt to populate fragments, since this is necessary + // for greedy attaching of fragment. However, we'll only attempt to + // populate optional non-fragment revisions if they aren't already + // resolved. boolean isFragment = Util.isFragment(revision); if (!isFragment && (revision.getWiring() != null)) { - return; + return false; } try { - // If the optional revision is a fragment, then we only want to populate - // the fragment if it has a candidate host in the set of already populated - // revisions. We do this to avoid unnecessary work in prepare(). If the - // fragment has a host, we'll prepopulate the result cache here to avoid - // having to do the host lookup again in populate(). - if (isFragment) + // If the optional revision is a fragment and this is a greedy attach, + // then only populate the fragment if it has a candidate host in the + // set of already populated revisions. We do this to avoid resolving + // unneeded fragments and hosts. If the fragment has a host, we'll + // prepopulate the result cache here to avoid having to do the host + // lookup again in populate(). + if (isGreedyAttach && isFragment) { // Get the current result cache value, to make sure the revision // hasn't already been populated. @@ -385,7 +354,7 @@ class Candidates // return since this fragment isn't needed. if (hosts.isEmpty()) { - return; + return false; } // If there are populates host candidates, then finish up @@ -423,26 +392,37 @@ class Candidates } catch (ResolveException ex) { - // Ignore since the revision is optional. + return false; } + + return true; } - private boolean isPopulated(BundleRevision revision) + public boolean isPopulated(BundleRevision revision) { Object value = m_populateResultCache.get(revision); return ((value != null) && (value instanceof Boolean)); } - private void populateDynamic(ResolverState state, BundleRevision revision) + public ResolveException getResolveException(BundleRevision revision) { - // There should be one entry in the candidate map, which are the - // the candidates for the matching dynamic requirement. Get the - // matching candidates and populate their candidates if necessary. + Object value = m_populateResultCache.get(revision); + return ((value != null) && (value instanceof ResolveException)) + ? (ResolveException) value : null; + } + + public void populateDynamic( + ResolverState state, BundleRevision revision, + BundleRequirement req, SortedSet<BundleCapability> candidates) + { + // Add the dynamic imports candidates. +// TODO: OSGi R4.3 - Can we just calculate the candidates inside here too? +// I think we don't because of performance reasons since we have to +// look them up already. If so, maybe it is not worth doing it here. + add(req, candidates); + + // Populate the candidates for the dynamic import. ResolveException rethrow = null; - Entry<BundleRequirement, SortedSet<BundleCapability>> entry = - m_candidateMap.entrySet().iterator().next(); - BundleRequirement dynReq = entry.getKey(); - SortedSet<BundleCapability> candidates = entry.getValue(); for (Iterator<BundleCapability> itCandCap = candidates.iterator(); itCandCap.hasNext(); ) { @@ -468,10 +448,12 @@ class Candidates { if (rethrow == null) { - rethrow = new ResolveException("Dynamic import failed.", revision, dynReq); + rethrow = new ResolveException("Dynamic import failed.", revision, req); } throw rethrow; } + + m_populateResultCache.put(revision, Boolean.TRUE); } /** @@ -492,16 +474,6 @@ class Candidates // Record the candidates. m_candidateMap.put(req, candidates); - - // Make a list of all candidate revisions for determining singetons. - // Add the requirement as a dependent on the candidates. Keep track - // of fragments for hosts. - for (BundleCapability cap : candidates) - { - // Remember the revision for all capabilities so we can - // determine which ones are singletons. - m_candidateRevisions.add(cap.getRevision()); - } } /** @@ -569,7 +541,7 @@ class Candidates final Map<String, BundleRevision> singletons = new HashMap<String, BundleRevision>(); - for (Iterator<BundleRevision> it = m_candidateRevisions.iterator(); it.hasNext(); ) + for (Iterator<BundleRevision> it = m_involvedRevisions.iterator(); it.hasNext(); ) { BundleRevision br = it.next(); if (isSingleton(br)) @@ -597,18 +569,25 @@ class Candidates // if it wasn't selected. if (singleton != null) { - removeRevision(singleton); + removeRevision( + singleton, + new ResolveException( + "Conflict with another singleton.", singleton, null)); } } else { - removeRevision(br); + removeRevision(br, + new ResolveException( + "Conflict with another singleton.", br, null)); } } } // If the root is a singleton, then prefer it over any other singleton. - if (isSingleton(m_root)) +// TODO: OSGi R4.3/SINGLETON - How do we prefer the root as a singleton? +/* + if ((m_root != null) && isSingleton(m_root)) { BundleRevision singleton = singletons.get(m_root.getSymbolicName()); singletons.put(m_root.getSymbolicName(), m_root); @@ -627,6 +606,7 @@ class Candidates removeRevision(singleton); } } +*/ // Make sure selected singletons do not conflict with existing // singletons passed into this method. @@ -637,7 +617,9 @@ class Candidates if ((singleton != null) && (singleton != existing)) { singletons.remove(singleton.getSymbolicName()); - removeRevision(singleton); + removeRevision(singleton, + new ResolveException( + "Conflict with another singleton.", singleton, null)); } } @@ -712,7 +694,9 @@ class Candidates // Step 3 for (BundleRevision br : unselectedFragments) { - removeRevision(br); + removeRevision(br, + new ResolveException( + "Fragment was not selected for attachment.", br, null)); } // Step 4 @@ -722,15 +706,20 @@ class Candidates // from the merged host. for (BundleCapability c : hostRevision.getDeclaredCapabilities(null)) { - Set<BundleRequirement> dependents = - m_dependentMap.get(((HostedCapability) c).getDeclaredCapability()); - if (dependents != null) - { - for (BundleRequirement r : dependents) + // Don't replace the host capability, since the fragment will + // really be attached to the original host, not the wrapper. + if (!c.getNamespace().equals(BundleRevision.HOST_NAMESPACE)) + { + Set<BundleRequirement> dependents = + m_dependentMap.get(((HostedCapability) c).getDeclaredCapability()); + if (dependents != null) { - Set<BundleCapability> cands = m_candidateMap.get(r); - cands.remove(((HostedCapability) c).getDeclaredCapability()); - cands.add(c); + for (BundleRequirement r : dependents) + { + Set<BundleCapability> cands = m_candidateMap.get(r); + cands.remove(((HostedCapability) c).getDeclaredCapability()); + cands.add(c); + } } } } @@ -806,17 +795,14 @@ class Candidates * @param revision the module to remove. * @throws ResolveException if removing the module caused the resolve to fail. **/ - private void removeRevision(BundleRevision revision) throws ResolveException + private void removeRevision(BundleRevision revision, ResolveException ex) { - if (m_root.equals(revision)) - { -// TODO: SINGLETON RESOLVER - Improve this message. - String msg = "Unable to resolve " + m_root; - ResolveException ex = new ResolveException(msg, m_root, null); - throw ex; - } + // Add removal reason to result cache. + m_populateResultCache.put(revision, ex); + // Remove from dependents. Set<BundleRevision> unresolvedRevisions = new HashSet<BundleRevision>(); remove(revision, unresolvedRevisions); + // Remove dependents that failed as a result of removing revision. while (!unresolvedRevisions.isEmpty()) { Iterator<BundleRevision> it = unresolvedRevisions.iterator(); @@ -928,13 +914,10 @@ class Candidates m_candidateMap.remove(r); if (!((BundleRequirementImpl) r).isOptional()) { - if (m_root.equals(r.getRevision())) - { - String msg = "Unable to resolve " + m_root - + ": missing requirement " + r; - ResolveException ex = new ResolveException(msg, m_root, r); - throw ex; - } + String msg = "Unable to resolve " + r.getRevision() + + ": missing requirement " + r; + m_populateResultCache.put( + r.getRevision(), new ResolveException(msg, r.getRevision(), r)); unresolvedRevisions.add(r.getRevision()); } } @@ -968,7 +951,7 @@ class Candidates } return new Candidates( - m_root, m_candidateRevisions, dependentMap, candidateMap, + m_involvedRevisions, dependentMap, candidateMap, m_hostFragments, m_allWrappedHosts, m_populateResultCache, m_fragmentsPresent); }
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/HostedCapability.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/HostedCapability.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/HostedCapability.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/HostedCapability.java Wed Jun 15 18:57:20 2011 @@ -113,7 +113,9 @@ public class HostedCapability extends Bu if (getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) { return "[" + m_host + "] " - + getNamespace() + "; " + getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR); + + getNamespace() + + "; " + + getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); } return "[" + m_host + "] " + getNamespace() + "; " + getAttributes(); } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Resolver.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Resolver.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Resolver.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/Resolver.java Wed Jun 15 18:57:20 2011 @@ -31,6 +31,8 @@ public interface Resolver Map<BundleRevision, List<ResolverWire>> resolve( ResolverState state, BundleRevision revision, Set<BundleRevision> optional); Map<BundleRevision, List<ResolverWire>> resolve( + ResolverState state, Set<BundleRevision> revisions, Set<BundleRevision> optional); + Map<BundleRevision, List<ResolverWire>> resolve( ResolverState state, BundleRevision revision, String pkgName, Set<BundleRevision> fragments); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java Wed Jun 15 18:57:20 2011 @@ -71,17 +71,25 @@ public class ResolverImpl implements Res try { - // Populate all candidates. - Candidates allCandidates = new Candidates(state, revision); + // Populate revision's candidates. + Candidates allCandidates = new Candidates(); + allCandidates.populate(state, revision); // Try to populate optional fragments. for (BundleRevision br : optional) { - allCandidates.populateOptional(state, br); + allCandidates.populate(state, br, true); } // Merge any fragments into hosts. allCandidates.prepare(getResolvedSingletons(state)); + // Make sure revision is still valid, since it could + // fail due to fragment and/or singleton selection. +// TODO: OSGi R4.3 - Could this be merged back into Candidates? + if (!allCandidates.isPopulated(revision)) + { + throw allCandidates.getResolveException(revision); + } // Record the initial candidate permutation. m_usesPermutations.add(allCandidates); @@ -183,6 +191,182 @@ public class ResolverImpl implements Res } public Map<BundleRevision, List<ResolverWire>> resolve( + ResolverState state, Set<BundleRevision> revisions, Set<BundleRevision> optional) + { + Map<BundleRevision, List<ResolverWire>> wireMap = new HashMap<BundleRevision, List<ResolverWire>>(); + Map<BundleRevision, Packages> revisionPkgMap = new HashMap<BundleRevision, Packages>(); + + boolean retry; + do + { + retry = false; + + try + { + // Create object to hold all candidates. + Candidates allCandidates = new Candidates(); + + // Populate revisions. + for (Iterator<BundleRevision> it = revisions.iterator(); it.hasNext(); ) + { + BundleRevision br = it.next(); +// TODO: OSGi R4.3 - This is not correct for fragments, since they may have wires already +// but we still need to resolve them. + if ((br.getWiring() != null) || !allCandidates.populate(state, br, false)) + { + it.remove(); + } + } + + // Try to populate optional fragments. + for (BundleRevision br : optional) + { + allCandidates.populate(state, br, true); + } + + // Merge any fragments into hosts. + allCandidates.prepare(getResolvedSingletons(state)); + + // Prune failed revisions. +// TODO: OSGi R4.3 - Again, can we merge this stuff into Candidates? +// for (Iterator<BundleRevision> it = revisions.iterator(); it.hasNext(); ) +// { +// if (!allCandidates.isPopulated(it.next())) +// { +// it.remove(); +// } +// } + + // Record the initial candidate permutation. + m_usesPermutations.add(allCandidates); + + ResolveException rethrow = null; + + // If the requested revision is a fragment, then + // ultimately we will verify the host., so store + // any host requirements + Map<BundleRevision, List<BundleRequirement>> hostReqs = + new HashMap<BundleRevision, List<BundleRequirement>>(); + for (BundleRevision br : revisions) + { + hostReqs.put( + br, br.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE)); + } + + do + { + rethrow = null; + + revisionPkgMap.clear(); + m_packageSourcesCache.clear(); + + allCandidates = (m_usesPermutations.size() > 0) + ? m_usesPermutations.remove(0) + : m_importPermutations.remove(0); +//allCandidates.dump(); + + for (BundleRevision br : revisions) + { + BundleRevision target = br; + + // If we are resolving a fragment, then we + // actually want to verify its host. + List<BundleRequirement> hostReq = hostReqs.get(br); + if (!hostReq.isEmpty()) + { + target = allCandidates.getCandidates(hostReq.get(0)) + .iterator().next().getRevision(); + } + + calculatePackageSpaces( + allCandidates.getWrappedHost(target), allCandidates, revisionPkgMap, + new HashMap(), new HashSet()); +//System.out.println("+++ PACKAGE SPACES START +++"); +//dumpRevisionPkgMap(revisionPkgMap); +//System.out.println("+++ PACKAGE SPACES END +++"); + + try + { + checkPackageSpaceConsistency( + false, allCandidates.getWrappedHost(target), + allCandidates, revisionPkgMap, new HashMap()); + } + catch (ResolveException ex) + { + rethrow = ex; + } + } + } + while ((rethrow != null) + && ((m_usesPermutations.size() > 0) || (m_importPermutations.size() > 0))); + + // If there is a resolve exception, then determine if an + // optionally resolved revision is to blame (typically a fragment). + // If so, then remove the optionally resolved resolved and try + // again; otherwise, rethrow the resolve exception. + if (rethrow != null) + { + BundleRevision faultyRevision = + getActualBundleRevision(rethrow.getRevision()); + if (rethrow.getRequirement() instanceof HostedRequirement) + { + faultyRevision = + ((HostedRequirement) rethrow.getRequirement()) + .getDeclaredRequirement().getRevision(); + } + if (revisions.remove(faultyRevision)) + { + retry = true; + } + else if (optional.remove(faultyRevision)) + { + retry = true; + } + else + { + throw rethrow; + } + } + // If there is no exception to rethrow, then this was a clean + // resolve, so populate the wire map. + else + { + for (BundleRevision br : revisions) + { + BundleRevision target = br; + + // If we are resolving a fragment, then we + // actually want to populate its host's wires. + List<BundleRequirement> hostReq = hostReqs.get(br); + if (!hostReq.isEmpty()) + { + target = allCandidates.getCandidates(hostReq.get(0)) + .iterator().next().getRevision(); + } + + if (allCandidates.isPopulated(target)) + { + wireMap = + populateWireMap( + allCandidates.getWrappedHost(target), + revisionPkgMap, wireMap, allCandidates); + } + } + } + } + finally + { + // Always clear the state. + m_usesPermutations.clear(); + m_importPermutations.clear(); + } + } + while (retry); + + return wireMap; + } + + public Map<BundleRevision, List<ResolverWire>> resolve( ResolverState state, BundleRevision revision, String pkgName, Set<BundleRevision> optional) { @@ -212,11 +396,18 @@ public class ResolverImpl implements Res // Try to populate optional fragments. for (BundleRevision br : optional) { - allCandidates.populateOptional(state, br); + allCandidates.populate(state, br, true); } // Merge any fragments into hosts. allCandidates.prepare(getResolvedSingletons(state)); + // Make sure revision is still valid, since it could + // fail due to fragment and/or singleton selection. +// TODO: OSGi R4.3 - Could this be merged back into Candidates? + if (!allCandidates.isPopulated(revision)) + { + throw allCandidates.getResolveException(revision); + } // Record the initial candidate permutation. m_usesPermutations.add(allCandidates); @@ -349,7 +540,7 @@ public class ResolverImpl implements Res for (BundleCapability cap : revision.getWiring().getCapabilities(null)) { if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) - && cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).equals(pkgName)) + && cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(pkgName)) { return null; } @@ -366,7 +557,7 @@ public class ResolverImpl implements Res // there is a matching one for the package from which we want to // load a class. Map<String, Object> attrs = new HashMap(1); - attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName); + attrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName); BundleRequirementImpl req = new BundleRequirementImpl( revision, BundleRevision.PACKAGE_NAMESPACE, @@ -417,7 +608,8 @@ public class ResolverImpl implements Res if (candidates.size() > 0) { - allCandidates = new Candidates(state, revision, dynReq, candidates); + allCandidates = new Candidates(); + allCandidates.populateDynamic(state, revision, dynReq, candidates); } return allCandidates; @@ -682,7 +874,7 @@ public class ResolverImpl implements Res // for imported or required packages, appropriately. String pkgName = (String) - candCap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR); + candCap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); List blameReqs = new ArrayList(); blameReqs.add(currentReq); @@ -1147,7 +1339,7 @@ public class ResolverImpl implements Res if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) { exports.put( - (String) cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR), + (String) cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), cap); } } @@ -1165,7 +1357,7 @@ public class ResolverImpl implements Res BundleRevision.PACKAGE_NAMESPACE)) { String pkgName = (String) wire.getCapability() - .getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR); + .getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); exports.remove(pkgName); } } @@ -1181,7 +1373,7 @@ public class ResolverImpl implements Res if ((cands != null) && !cands.isEmpty()) { String pkgName = (String) cands.iterator().next() - .getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR); + .getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); exports.remove(pkgName); } } @@ -1267,7 +1459,7 @@ public class ResolverImpl implements Res // Get the package name associated with the capability. String pkgName = cap.getAttributes() - .get(BundleCapabilityImpl.PACKAGE_ATTR).toString(); + .get(BundleRevision.PACKAGE_NAMESPACE).toString(); // Since a revision can export the same package more than once, get // all package capabilities for the specified package name. @@ -1277,7 +1469,7 @@ public class ResolverImpl implements Res for (int capIdx = 0; capIdx < caps.size(); capIdx++) { if (caps.get(capIdx).getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) - && caps.get(capIdx).getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).equals(pkgName)) + && caps.get(capIdx).getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(pkgName)) { sources.add(caps.get(capIdx)); } @@ -1423,7 +1615,7 @@ public class ResolverImpl implements Res { // Ignore revisions that import themselves. if (!revision.equals(blame.m_cap.getRevision()) - && blame.m_cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR) + && blame.m_cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE) .equals(pkgName)) { if (blame.m_cap.getRevision().getWiring() == null) @@ -1434,7 +1626,7 @@ public class ResolverImpl implements Res Packages candPkgs = revisionPkgMap.get(blame.m_cap.getRevision()); Map<String, Object> attrs = new HashMap(1); - attrs.put(BundleCapabilityImpl.PACKAGE_ATTR, pkgName); + attrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName); packageWires.add( new ResolverWireImpl( revision, @@ -1530,9 +1722,9 @@ public class ResolverImpl implements Res (BundleRequirementImpl) blame.m_reqs.get(i)); if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) { - sb.append(BundleCapabilityImpl.PACKAGE_ATTR); + sb.append(BundleRevision.PACKAGE_NAMESPACE); sb.append("="); - sb.append(cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).toString()); + sb.append(cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()); BundleCapability usedCap; if ((i + 2) < blame.m_reqs.size()) { @@ -1547,7 +1739,7 @@ public class ResolverImpl implements Res (BundleRequirementImpl) blame.m_reqs.get(i + 1)); } sb.append("; uses:="); - sb.append(usedCap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR)); + sb.append(usedCap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE)); } else { @@ -1560,18 +1752,18 @@ public class ResolverImpl implements Res BundleCapability export = Util.getSatisfyingCapability( blame.m_cap.getRevision(), (BundleRequirementImpl) blame.m_reqs.get(i)); - sb.append(BundleCapabilityImpl.PACKAGE_ATTR); + sb.append(BundleRevision.PACKAGE_NAMESPACE); sb.append("="); - sb.append(export.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).toString()); - if (!export.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR) - .equals(blame.m_cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR))) + sb.append(export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()); + if (!export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE) + .equals(blame.m_cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE))) { sb.append("; uses:="); - sb.append(blame.m_cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR)); + sb.append(blame.m_cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE)); sb.append("\n export: "); - sb.append(BundleCapabilityImpl.PACKAGE_ATTR); + sb.append(BundleRevision.PACKAGE_NAMESPACE); sb.append("="); - sb.append(blame.m_cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR).toString()); + sb.append(blame.m_cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()); } sb.append("\n "); sb.append(blame.m_cap.getRevision().getSymbolicName()); @@ -1617,7 +1809,7 @@ public class ResolverImpl implements Res public String toString() { return m_cap.getRevision() - + "." + m_cap.getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR) + + "." + m_cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE) + (((m_reqs == null) || m_reqs.isEmpty()) ? " NO BLAME" : " BLAMED ON " + m_reqs); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/ShrinkableCollection.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/ShrinkableCollection.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/ShrinkableCollection.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/ShrinkableCollection.java Wed Jun 15 18:57:20 2011 @@ -24,21 +24,21 @@ import java.util.Iterator; /** This collection wraps any other collection but prohibits calls to add * elements to the collection. */ -public class ShrinkableCollection implements Collection +public class ShrinkableCollection<T> implements Collection<T> { - private final Collection m_delegate; + private final Collection<T> m_delegate; - public ShrinkableCollection(Collection delegate) + public ShrinkableCollection(Collection<T> delegate) { m_delegate = delegate; } - public boolean add(Object o) + public boolean add(T o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) + public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); } @@ -53,16 +53,18 @@ public class ShrinkableCollection implem return m_delegate.contains(o); } - public boolean containsAll(Collection c) + public boolean containsAll(Collection<?> c) { return m_delegate.containsAll(c); } + @Override public boolean equals(Object o) { return m_delegate.equals(o); } + @Override public int hashCode() { return m_delegate.hashCode(); @@ -83,12 +85,12 @@ public class ShrinkableCollection implem return m_delegate.remove(o); } - public boolean removeAll(Collection c) + public boolean removeAll(Collection<?> c) { return m_delegate.removeAll(c); } - public boolean retainAll(Collection c) + public boolean retainAll(Collection<?> c) { return m_delegate.retainAll(c); } @@ -103,7 +105,7 @@ public class ShrinkableCollection implem return m_delegate.toArray(); } - public Object[] toArray(Object[] a) + public <A> A[] toArray(A[] a) { return m_delegate.toArray(a); } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/Util.java Wed Jun 15 18:57:20 2011 @@ -358,7 +358,7 @@ public class Util if (w.getCapability().getNamespace() .equals(BundleRevision.PACKAGE_NAMESPACE) && w.getCapability().getAttributes() - .get(BundleCapabilityImpl.PACKAGE_ATTR).equals(name)) + .get(BundleRevision.PACKAGE_NAMESPACE).equals(name)) { return w; } Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java Wed Jun 15 18:57:20 2011 @@ -95,11 +95,11 @@ public class ManifestParser // Parse bundle symbolic name. // - BundleCapabilityImpl requireCap = parseBundleSymbolicName(owner, m_headerMap); - if (requireCap != null) + BundleCapabilityImpl bundleCap = parseBundleSymbolicName(owner, m_headerMap); + if (bundleCap != null) { m_bundleSymbolicName = (String) - requireCap.getAttributes().get(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE); + bundleCap.getAttributes().get(BundleRevision.BUNDLE_NAMESPACE); // Add a bundle capability and a host capability to all // non-fragment bundles. A host capability is the same @@ -109,12 +109,15 @@ public class ManifestParser // dependencies. if (headerMap.get(Constants.FRAGMENT_HOST) == null) { - capList.add(requireCap); + capList.add(bundleCap); + Map<String, Object> hostAttrs = + new HashMap<String, Object>(bundleCap.getAttributes()); + Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE); + hostAttrs.put(BundleRevision.HOST_NAMESPACE, value); capList.add(new BundleCapabilityImpl( owner, BundleRevision.HOST_NAMESPACE, Collections.EMPTY_MAP, -// TODO: OSGi R4.3 - Wraps map as unmodifiable twice. - requireCap.getAttributes())); + hostAttrs)); } // Add a singleton capability if the bundle is a singleton. @@ -123,13 +126,16 @@ public class ManifestParser // attach this information to the bundle or host capabilities // because fragments don't have those capabilities, but fragments // can be singletons too. - if (isSingleton(requireCap)) + if (isSingleton(bundleCap)) { + Map<String, Object> singletonAttrs = + new HashMap<String, Object>(bundleCap.getAttributes()); + Object value = singletonAttrs.remove(BundleRevision.BUNDLE_NAMESPACE); + singletonAttrs.put(BundleCapabilityImpl.SINGLETON_NAMESPACE, value); capList.add(new BundleCapabilityImpl( owner, BundleCapabilityImpl.SINGLETON_NAMESPACE, Collections.EMPTY_MAP, -// TODO: OSGi R4.3 - Wraps map as unmodifiable twice. - requireCap.getAttributes())); + singletonAttrs)); } } @@ -418,7 +424,7 @@ public class ManifestParser // notion where namespace is also the name of the key attribute. Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1); newAttrs.put( - BundleCapabilityImpl.PACKAGE_ATTR, + BundleRevision.PACKAGE_NAMESPACE, path); newAttrs.putAll(attrs); @@ -812,7 +818,7 @@ public class ManifestParser Map<String, Object> attrs = clause.m_attrs; Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1); newAttrs.put( - BundleCapabilityImpl.PACKAGE_ATTR, + BundleRevision.PACKAGE_NAMESPACE, pkgName); newAttrs.putAll(attrs); @@ -1124,7 +1130,7 @@ public class ManifestParser for (int i = 0; i < exports.size(); i++) { if (map.get(exports.get(i).getAttributes() - .get(BundleCapabilityImpl.PACKAGE_ATTR)) == null) + .get(BundleRevision.PACKAGE_NAMESPACE)) == null) { // Convert Version to VersionRange. Map<String, Object> attrs = new HashMap<String, Object>(); @@ -1138,7 +1144,7 @@ public class ManifestParser List<String> paths = new ArrayList(); paths.add((String) - exports.get(i).getAttributes().get(BundleCapabilityImpl.PACKAGE_ATTR)); + exports.get(i).getAttributes().get(BundleRevision.PACKAGE_NAMESPACE)); clauseList.add( new ParsedHeaderClause( paths, Collections.EMPTY_MAP, attrs, Collections.EMPTY_MAP)); @@ -1252,7 +1258,7 @@ public class ManifestParser // Create a require capability and return it. String symName = (String) clauses.get(0).m_paths.get(0); Map<String, Object> attrs = new HashMap<String, Object>(2); - attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, symName); + attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName); attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion); return new BundleCapabilityImpl( owner, @@ -1317,7 +1323,7 @@ public class ManifestParser Map<String, Object> attrs = clauses.get(0).m_attrs; Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1); newAttrs.put( - Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, + BundleRevision.HOST_NAMESPACE, clauses.get(0).m_paths.get(0)); newAttrs.putAll(attrs); @@ -1403,7 +1409,7 @@ public class ManifestParser // Prepend the symbolic name to the array of attributes. Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1); newAttrs.put( - Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, + BundleRevision.BUNDLE_NAMESPACE, path); newAttrs.putAll(attrs); Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/wiring/BundleCapabilityImpl.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/wiring/BundleCapabilityImpl.java?rev=1136150&r1=1136149&r2=1136150&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/wiring/BundleCapabilityImpl.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/wiring/BundleCapabilityImpl.java Wed Jun 15 18:57:20 2011 @@ -36,7 +36,6 @@ public class BundleCapabilityImpl implem { public static final String SINGLETON_NAMESPACE = "singleton"; - public static final String PACKAGE_ATTR = "package"; public static final String VERSION_ATTR = "version"; private final BundleRevision m_revision; @@ -199,7 +198,7 @@ public class BundleCapabilityImpl implem if (m_namespace.equals(BundleRevision.PACKAGE_NAMESPACE)) { return "[" + m_revision + "] " - + m_namespace + "; " + m_attrs.get(PACKAGE_ATTR); + + m_namespace + "; " + m_attrs.get(BundleRevision.PACKAGE_NAMESPACE); } return "[" + m_revision + "] " + m_namespace + "; " + m_attrs; }
