Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2007-02-22 00:02:30 +0000
committerThomas Watson2007-02-22 00:02:30 +0000
commit8f125ae86a197d773e2853bee02ce3a5bd9ba7a7 (patch)
treef06f89bec241efefecab90f31c1d81f2d47ec6af /bundles/org.eclipse.osgi/resolver
parent4e207e02dd929a5e0bebfd706c2b77f8b3a90bdb (diff)
downloadrt.equinox.framework-8f125ae86a197d773e2853bee02ce3a5bd9ba7a7.tar.gz
rt.equinox.framework-8f125ae86a197d773e2853bee02ce3a5bd9ba7a7.tar.xz
rt.equinox.framework-8f125ae86a197d773e2853bee02ce3a5bd9ba7a7.zip
Bug 173436 Issues with adopting the uses directiveafter_bug173436
Diffstat (limited to 'bundles/org.eclipse.osgi/resolver')
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/BundleConstraint.java43
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/GroupingChecker.java606
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java30
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java96
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverExport.java37
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java570
-rw-r--r--bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImport.java31
7 files changed, 711 insertions, 702 deletions
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/BundleConstraint.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/BundleConstraint.java
index d74b601d1..0f933f41a 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/BundleConstraint.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/BundleConstraint.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,16 +10,12 @@
*******************************************************************************/
package org.eclipse.osgi.internal.module;
-import java.util.ArrayList;
import org.eclipse.osgi.service.resolver.*;
/*
* A companion to BundleSpecification from the state for use while resolving
*/
public class BundleConstraint extends ResolverConstraint {
- // a list of matching bundles; multiple matches are only supported for fragment host constraints
- private ArrayList matchingBundles;
-
BundleConstraint(ResolverBundle bundle, VersionConstraint bundleConstraint) {
super(bundle, bundleConstraint);
}
@@ -29,41 +25,4 @@ public class BundleConstraint extends ResolverConstraint {
return false;
return ((BundleSpecification) constraint).isOptional();
}
-
- ResolverBundle getMatchingBundle() {
- return (ResolverBundle) (matchingBundles != null && matchingBundles.size() > 0 ? matchingBundles.get(0) : null);
- }
-
- ResolverBundle[] getMatchingBundles() {
- if (matchingBundles == null || matchingBundles.size() == 0)
- return null;
- return (ResolverBundle[]) matchingBundles.toArray(new ResolverBundle[matchingBundles.size()]);
- }
-
- void addMatchingBundle(ResolverBundle rb) {
- if (matchingBundles == null)
- matchingBundles = new ArrayList(1); // rare to have more than one
- if (!matchingBundles.contains(rb))
- matchingBundles.add(rb);
- }
-
- void removeMatchingBundle(ResolverBundle rb) {
- if (matchingBundles == null)
- return;
- matchingBundles.remove(rb);
- }
-
- void removeAllMatchingBundles() {
- matchingBundles = null;
- }
-
- void setMatchingBundle(ResolverBundle rb) {
- removeAllMatchingBundles();
- if (rb != null)
- addMatchingBundle(rb);
- }
-
- boolean foundMatchingBundles() {
- return matchingBundles == null ? false : matchingBundles.size() > 0;
- }
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/GroupingChecker.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/GroupingChecker.java
index 02be81def..027ca2bad 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/GroupingChecker.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/GroupingChecker.java
@@ -1,387 +1,339 @@
/*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
+ * Copyright (c) 2004, 2007 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
package org.eclipse.osgi.internal.module;
import java.util.*;
import org.eclipse.osgi.service.resolver.BundleSpecification;
-import org.osgi.framework.Constants;
/*
* The GroupingChecker checks the 'uses' directive on exported packages for consistency
*/
public class GroupingChecker {
- // Maps bundles to their exports; keyed by
- // ResolverBundle -> exports HashMap
- // the exports HashMap is keyed by
- // ResolverExport -> Object[] {'uses' constraint ArrayList, transitive constraint cache}
- HashMap bundles = new HashMap();
- private boolean checkCycles = false;
+ final PackageRoots nullPackageRoots = new PackageRoots(null, null);
+ // a mapping of bundles to their package roots; keyed by
+ // ResolverBundle -> HashMap of packages; keyed by
+ // package name -> PackageRoots[]
+ private HashMap bundles = new HashMap();
- // Gets all constraints for an exported package.
- // this will perform transitive closure on the uses constraints.
- // this method also will cache the transitive results if the bundle is resolved
- private ResolverExport[] getConstraints(ResolverExport constrained) {
- // check the cache first
- Object[] cachedResults = getCachedConstraints(constrained);
- if (cachedResults != null && cachedResults[1] != null) {
- if (!constrained.getExporter().isResolved()) {
- // need to make sure none of the current constraints are dropped
- ResolverExport[] constraints = (ResolverExport[]) cachedResults[1];
- boolean dropped = false;
- for (int i = 0; !dropped && i < constraints.length; i++)
- dropped = constraints[i].isDropped();
- if (!dropped)
- return constraints;
- // otherwise recompute the transitive constraints below
- } else {
- // we have aready cached the results for this return the cached results
- return (ResolverExport[]) cachedResults[1];
- }
+ /*
+ * This method fully populates a bundles package roots for the purpose of resolving
+ * a dynamic import. Package roots must be fully populated because we need all the
+ * roots to do proper uses constraint verification on a dynamic import supplier.
+ */
+ public void populateRoots(ResolverBundle bundle) {
+ bundles.remove(bundle);
+ // process all requires
+ BundleConstraint[] requires = bundle.getRequires();
+ for (int j = 0; j < requires.length; j++) {
+ ResolverBundle selectedSupplier = (ResolverBundle) requires[j].getSelectedSupplier();
+ if (selectedSupplier != null)
+ isConsistentInternal(bundle, selectedSupplier, new ArrayList(1), true);
}
- ArrayList resultlist = getConstraintsList(constrained);
- ResolverExport[] results = (ResolverExport[]) resultlist.toArray(new ResolverExport[resultlist.size()]);
- if (!checkCycles || constrained.getExporter().isResolved()) {
- // if the bundle is resolved or we are not checking cycles then we can add the results to the cached results
- if (cachedResults == null)
- cachedResults = createConstraintsCache(constrained); // should have been created by getConstraintsList
- cachedResults[1] = results;
+ // process all imports
+ ResolverImport[] imports = bundle.getImportPackages();
+ for (int j = 0; j < imports.length; j++) {
+ ResolverExport selectedSupplier = (ResolverExport) imports[j].getSelectedSupplier();
+ if (selectedSupplier != null)
+ isConsistentInternal(bundle, selectedSupplier, true);
}
- return results;
- }
-
- private Object[] getCachedConstraints(ResolverExport constrained) {
- // get the cached constraints for this export
- HashMap exports = (HashMap) bundles.get(constrained.getExporter());
- return exports == null ? null : (Object[]) exports.get(constrained);
- }
-
- // Gets all constraints for an exported package
- // same as getConstraints only the raw ArrayList is returned and
- // the cache is not consulted.
- private ArrayList getConstraintsList(ResolverExport constrained) {
- ArrayList results = new ArrayList();
- getTransitiveConstraints(constrained, results);
- return results;
}
- // adds the transitive 'uses' constraints for the specified constrained ResolverExport
- // to the results ArrayList.
- private void getTransitiveConstraints(ResolverExport constrained, ArrayList results) {
- if (constrained.isDropped())
- return;
- // first get any constraints that may come from required bundle exports
- ResolverExport[] constrainedRoots = constrained.getRoots();
- for (int i = 0; i < constrainedRoots.length; i++)
- // only search for transitive constraints on other exports (i.e. from required bundles)
- if (constrainedRoots[i] != constrained)
- getTransitiveConstraints(constrainedRoots[i], results);
- // now get the constraints that are specified by this export
- Object[] cachedConstraints = getCachedConstraints(constrained);
- ArrayList constraints = (ArrayList) (cachedConstraints != null ? cachedConstraints[0] : null);
- if (constraints == null)
- return;
- for (Iterator iter = constraints.iterator(); iter.hasNext();) {
- Object constraint = iter.next();
- ResolverExport[] moreConstraints = null;
- if (constraint instanceof ResolverExport) {
- // the constraint is to another export from this bundle
- ResolverExport export = (ResolverExport) constraint;
- // get the roots from this export; incase it is split from a required bundle
- moreConstraints = export.getRoots();
- } else if (constraint instanceof ResolverImport) {
- // the constraint is to an imported package
- ResolverImport imp = (ResolverImport) constraint;
- // if the import is resolved then we need to add the constraints of the roots from the export
- if (imp.getMatchingExport() != null)
- moreConstraints = imp.getMatchingExport().getRoots();
- } else if (constraint instanceof UsesRequiredExport) {
- // the constraint is on a package from a required bundle; get the roots from the required bundles
- moreConstraints = ((UsesRequiredExport) constraint).getRoots();
- }
- if (moreConstraints != null)
- // now add each root as a constraint
- for (int i = 0; i < moreConstraints.length; i++)
- if (!results.contains(moreConstraints[i])) {
- results.add(moreConstraints[i]);
- if (moreConstraints[i] != constraint)
- // add the constraints for each root
- getTransitiveConstraints(moreConstraints[i], results);
- }
- }
+ /*
+ * Verifies the uses constraint consistency for the requiringBundle with the possible matching bundle.
+ * If an inconsistency is found the export inconsistency is returned; otherwise null is returned
+ */
+ public ResolverExport isConsistent(ResolverBundle requiringBundle, ResolverBundle matchingBundle) {
+ ResolverExport inConsistentExport = isConsistentInternal(requiringBundle, matchingBundle, new ArrayList(1), false);
+ if (inConsistentExport != null)
+ return inConsistentExport;
+ return null;
}
- // creates the Object[] used to cache constraint definitions and transitive
- // closure results.
- private Object[] createConstraintsCache(ResolverExport constrained) {
- HashMap exports = (HashMap) bundles.get(constrained.getExporter());
- if (exports == null) {
- exports = new HashMap();
- bundles.put(constrained.getExporter(), exports);
+ private ResolverExport isConsistentInternal(ResolverBundle requiringBundle, ResolverBundle matchingBundle, ArrayList visited, boolean dynamicImport) {
+ // needed to prevent endless cycles
+ if (visited.contains(matchingBundle))
+ return null;
+ visited.add(matchingBundle);
+ // check that the packages exported by the matching bundle are consistent
+ ResolverExport[] matchingExports = matchingBundle.getExportPackages();
+ for (int i = 0; i < matchingExports.length; i++) {
+ if (matchingExports[i].isDropped())
+ continue;
+ if (!isConsistentInternal(requiringBundle, matchingExports[i], dynamicImport))
+ return matchingExports[i];
}
- Object[] constraints = (Object[]) exports.get(constrained);
- if (constraints == null) {
- constraints = new Object[2];
- exports.put(constrained, constraints);
+ // check that the packages from reexported bundles are consistent
+ BundleConstraint[] supplierRequires = matchingBundle.getRequires();
+ for (int j = 0; j < supplierRequires.length; j++) {
+ ResolverBundle reexported = (ResolverBundle) supplierRequires[j].getSelectedSupplier();
+ if (reexported == null || !((BundleSpecification) supplierRequires[j].getVersionConstraint()).isExported())
+ continue;
+ ResolverExport inConsistentExport = isConsistentInternal(requiringBundle, reexported, visited, dynamicImport);
+ if (inConsistentExport != null)
+ return inConsistentExport;
}
- return constraints;
- }
-
- // creates an empty list to hold constraints for the specified export
- // if a list already exists then a new list is NOT created.
- private ArrayList createConstraints(ResolverExport constrained) {
- Object[] constraints = createConstraintsCache(constrained);
- if (constraints[0] == null)
- constraints[0] = new ArrayList();
- return (ArrayList) constraints[0];
- }
-
- // adds a 'uses' constraint to a ResolverExport. A new 'uses' constraint list
- // is created if one does not exist.
- private void addConstraint(ResolverExport constrained, Object constraint) {
- ArrayList list = createConstraints(constrained);
- if (!list.contains(constraint))
- list.add(constraint);
- }
-
- private void addConstraint(ArrayList export, Object constraint) {
- for (Iterator iExport = export.iterator(); iExport.hasNext();)
- addConstraint((ResolverExport) iExport.next(), constraint);
+ return null;
}
- // removes all constraints specified by this bundles exports
- void removeAllExportConstraints(ResolverBundle bundle) {
- bundles.remove(bundle);
+ /*
+ * Verifies the uses constraint consistency for the importingBundle with the possible matching export.
+ * If an inconsistency is found the export returned; otherwise null is returned
+ */
+ public ResolverExport isConsistent(ResolverBundle importingBundle, ResolverExport matchingExport) {
+ if (!isConsistentInternal(importingBundle, matchingExport, false))
+ return matchingExport;
+ return null;
}
- // checks the 'uses' consistency of the required BundleConstraint with other required
- // BundleConstraints of the specified ResolverBundle
- ResolverBundle isConsistent(BundleConstraint req, ResolverBundle bundle) {
- BundleConstraint[] requires = req.getBundle().getRequires();
- ArrayList visited = new ArrayList(requires.length);
- for (int i = 0; i < requires.length; i++) {
- ResolverBundle match = requires[i].getMatchingBundle();
- if (match == bundle || match == null)
- continue; // the constraint has not been resolved or is to ourselves
- // check the consistency of each exported package from the new required match
- ResolverExport[] exports = match.getSelectedExports();
- for (int j = 0; j < exports.length; j++)
- if (checkReqExpConflict(exports[j], getConstraints(exports[j]), bundle, visited) != null)
- return match;
- }
+ /*
+ * Verifies the uses constraint consistency for the importingBundle with the possible dynamioc matching export.
+ * If an inconsistency is found the export returned; otherwise null is returned.
+ * Dynamic imports must perform extra checks to ensure that existing wires to package roots are
+ * consistent with the possible matching dynamic export.
+ */
+ public ResolverExport isDynamicConsistent(ResolverBundle importingBundle, ResolverExport matchingExport) {
+ if (!isConsistentInternal(importingBundle, matchingExport, true))
+ return matchingExport;
return null;
}
- // checks the 'uses consistency of the imported ResolverImport with specified
- // ResolverExport. This will also check 'uses' consistency with other imported packages
- // and other required bundles of the importing bundle.
- ResolverExport isConsistent(ResolverImport imp, ResolverExport exp) {
- ResolverExport[] expConstraints = getConstraints(exp);
- // Check imports are consistent
- ResolverImport[] imports = imp.getBundle().getImportPackages();
- for (int i = 0; i < imports.length; i++) {
- // Check new wiring constraints against constraints from previous wirings
- ResolverExport conflict = checkImpExpConflict(imp, imports[i].getMatchingExport(), exp, expConstraints);
- if (conflict != null)
- return conflict;
- }
- // Check new wiring against required exports
- BundleConstraint[] requires = imp.getBundle().getRequires();
- ArrayList visited = new ArrayList(requires.length); // visited list prevents recursive cycles
- for (int i = 0; i < requires.length; i++) {
- ResolverExport conflict = checkReqExpConflict(exp, expConstraints, requires[i].getMatchingBundle(), visited);
- if (conflict != null)
- return conflict;
- }
- // No clash, so return null
- return null;
+ private boolean isConsistentInternal(ResolverBundle importingBundle, ResolverExport matchingExport, boolean dyanamicImport) {
+ PackageRoots exportingRoots = getPackageRoots(matchingExport.getExporter(), matchingExport.getName(), null);
+ // check that the exports uses packages are consistent with existing package roots
+ if (!exportingRoots.isConsistentClassSpace(importingBundle, null))
+ return false;
+ if (!dyanamicImport)
+ return true;
+ // for dynamic imports we must check that each existing root is consistent with the possible matching export
+ PackageRoots importingRoots = getPackageRoots(importingBundle, matchingExport.getName(), null);
+ HashMap importingPackages = (HashMap) bundles.get(importingBundle);
+ if (importingPackages != null)
+ for (Iterator allImportingPackages = importingPackages.values().iterator(); allImportingPackages.hasNext();) {
+ PackageRoots roots = (PackageRoots) allImportingPackages.next();
+ if (roots != importingRoots && !roots.isConsistentClassSpace(exportingRoots, null))
+ return false;
+ }
+ return true;
}
- // checks the 'uses' constraints ResolverImport's matching export with the constraints
- // of the candidate ResolverExport. If a conflict exists then the conflict is returned.
- private ResolverExport checkImpExpConflict(ResolverImport imp, ResolverExport existing, ResolverExport candidate, ResolverExport[] candConstraints) {
- if (existing == null)
- return null; // for an import that has not been resolved
- // check the constraints of the existing wire against the candidate only
- // if the existing wire is not the candidate
- if (existing != candidate) {
- ResolverExport[] impConstraints = getConstraints(existing);
- for (int j = 0; j < impConstraints.length; j++)
- if (isConflict(candidate, impConstraints[j]))
- return existing;
+ /*
+ * returns package roots for a specific package name for a specific bundle
+ */
+ PackageRoots getPackageRoots(ResolverBundle bundle, String packageName, ArrayList visited) {
+ HashMap packages = (HashMap) bundles.get(bundle);
+ if (packages == null) {
+ packages = new HashMap(5);
+ bundles.put(bundle, packages);
}
- // Check existing wirings against constraints from candidate wiring
- for (int i = 0; i < candConstraints.length; i++) {
- // check if we export this package
- if (imp.getBundle() != candConstraints[i].getExporter()) {
- // there is no need to do this check if the candidate constaint is from ourselves
- ResolverExport[] importerExp = imp.getBundle().getExports(candConstraints[i].getName());
- if (importerExp.length > 0) {
- ResolverImport alsoImported = imp.getBundle().getImport(candConstraints[i].getName());
- // only do the extra check if we do not import the package or if we do and the import is resolved
- if (alsoImported == null || alsoImported.getMatchingExport() != null)
- for (int j = 0; j < importerExp.length; j++)
- if (!importerExp[j].isDropped() && !isOnRoot(importerExp[j].getRoots(), candConstraints[i]))
- // if we export the package and it is not the same one then we have a clash
- return existing;
- }
- }
- // check the existing resolved import against the candidate constraint
- if (isConflict(existing, candConstraints[i]))
- return existing;
+ PackageRoots packageRoots = (PackageRoots) packages.get(packageName);
+ if (packageRoots == null) {
+ packageRoots = createPackageRoots(bundle, packageName, visited == null ? new ArrayList(1) : visited);
+ packages.put(packageName, packageRoots);
}
- return null;
+ return packageRoots != null ? packageRoots : nullPackageRoots;
}
- // checks the 'uses' constraints ResolverExport with the constraints of the ResolverExports
- // from the specified ResolverBundle. If a conflict exists then the conflict is returned.
- private ResolverExport checkReqExpConflict(ResolverExport exp, ResolverExport expConstraints[], ResolverBundle bundle, ArrayList visited) {
- if (bundle == null)
+ private PackageRoots createPackageRoots(ResolverBundle bundle, String packageName, ArrayList visited) {
+ if (visited.contains(bundle))
return null;
- if (visited.contains(bundle)) // return if we visited this bundle; prevent endless loops
- return null;
- visited.add(bundle); // mark as visited
- // check the consistency of all the selected exports
- ResolverExport[] exports = bundle.getSelectedExports();
- for (int i = 0; i < exports.length; i++) {
- // first check the constraints of the 'exp' with the exported packages of the 'bundle'
- for (int j = 0; j < expConstraints.length; j++)
- if (isConflict(exports[i], expConstraints[j]))
- return exp;
- // next check the constraints of each exported package of the 'bundle' with the 'exp'
- ResolverExport[] constraints = getConstraints(exports[i]);
- for (int j = 0; j < constraints.length; j++)
- if (isConflict(exp, constraints[j]))
- return exp;
+ visited.add(bundle); // prevent endless cycles
+ // check imports
+ ResolverImport imported = bundle.getImport(packageName);
+ if (imported != null && imported.getSelectedSupplier() != null) {
+ // make sure we are not resolved to our own import
+ ResolverExport selectedExport = (ResolverExport) imported.getSelectedSupplier();
+ if (selectedExport.getExporter() != bundle) {
+ // found resolved import; get the roots from the resolved exporter;
+ // this is all the roots if the package is imported
+ return getPackageRoots(selectedExport.getExporter(), packageName, visited);
+ }
}
- // check the consistency of all the required bundles which we reexport
+ // check if the bundle exports the package
+ ResolverExport export = bundle.getExport(packageName);
+ ArrayList roots = new ArrayList(0);
+ // check roots from required bundles
BundleConstraint[] requires = bundle.getRequires();
- for (int i = 0; i < requires.length; i++)
- if (((BundleSpecification) requires[i].getVersionConstraint()).isExported()) {
- ResolverExport conflict = checkReqExpConflict(exp, expConstraints, requires[i].getMatchingBundle(), visited);
- if (conflict != null)
- return exp;
+ for (int i = 0; i < requires.length; i++) {
+ ResolverBundle supplier = (ResolverBundle) requires[i].getSelectedSupplier();
+ if (supplier == null)
+ continue; // no supplier, probably optional
+ if (supplier.getExport(packageName) != null) {
+ // the required bundle exports the package; get the package roots from it
+ PackageRoots requiredRoots = getPackageRoots(supplier, packageName, visited);
+ if (requiredRoots != null)
+ roots.add(requiredRoots);
+ } else {
+ // the bundle does not export the package; but it may reexport another bundle that does
+ BundleConstraint[] supplierRequires = supplier.getRequires();
+ for (int j = 0; j < supplierRequires.length; j++) {
+ ResolverBundle reexported = (ResolverBundle) supplierRequires[j].getSelectedSupplier();
+ if (reexported == null || !((BundleSpecification) supplierRequires[j].getVersionConstraint()).isExported())
+ continue;
+ if (reexported.getExport(packageName) != null) {
+ // the reexported bundle exports the package; get the package roots from it
+ PackageRoots reExportedRoots = getPackageRoots(reexported, packageName, visited);
+ if (reexported != null)
+ roots.add(reExportedRoots);
+ }
+ }
}
- return null;
+ }
+ if (export != null || roots.size() > 1) {
+ // in this case we cannot share the package roots object; must create one specific for this bundle
+ PackageRoots result = new PackageRoots(packageName, bundle);
+ // first merge all the roots from required bundles
+ for (Iterator iRoots = roots.iterator(); iRoots.hasNext();)
+ result.merge((PackageRoots) iRoots.next());
+ if (export != null)
+ // always add this bundles export to the end if it exports the package
+ result.addRoot(export);
+ return result;
+ }
+ return (PackageRoots) (roots.size() == 0 ? nullPackageRoots : roots.get(0));
}
- // returns true if the candidateRoot is NOT a root of the candidate ResolverExport
- private boolean isConflict(ResolverExport candidate, ResolverExport candidateRoot) {
- return candidateRoot.getExporter().isResolvable() && candidateRoot.getName().equals(candidate.getName()) && !isOnRoot(candidate.getRoots(), candidateRoot);
+ public void clear() {
+ bundles.clear();
}
- // checks that the specified ResolverExport is contained in the list of roots
- private boolean isOnRoot(ResolverExport[] roots, ResolverExport re) {
- for (int i = 0; i < roots.length; i++)
- // check the exporter; this handles multple exports of the same package name from a bundle
- if (roots[i].getExporter() == re.getExporter())
- return true;
- if (roots.length == 1 && !roots[0].getExportPackageDescription().isRoot())
- return true; // this is for a reexporter that does not have the import satisfied yet
- return false;
+ public void remove(ResolverBundle rb) {
+ bundles.remove(rb);
}
- // Add initial 'uses' constraints for a list of bundles
- void addInitialGroupingConstraints(ResolverBundle initBundle) {
- if (bundles.containsKey(initBundle))
- return; // already processed
- // for each export; add it uses constraints
- ResolverExport[] exports = initBundle.getExportPackages();
- for (int j = 0; j < exports.length; j++) {
- ArrayList export = new ArrayList();
- export.add(exports[j]);
- addInitialGroupingConstraints(export, null);
- }
- if (bundles.get(initBundle) == null)
- bundles.put(initBundle, null); // mark this bundle as processed
- }
+ private class PackageRoots {
+ private String name;
+ private ResolverBundle bundle;
+ private ResolverExport[] roots;
- // Add constraints from other exports (due to 'uses' being transitive)
- private void addInitialGroupingConstraints(ArrayList exports, ResolverExport constraint) {
- // pop the intitial export off as the current export we are checking
- ResolverExport cur = (ResolverExport) exports.get(0);
- if (cur == constraint)
- return;
- if (constraint == null) {
- if (getCachedConstraints(cur) != null)
- // we have already processed the current export; just return
- return;
- constraint = cur;
+ PackageRoots(String name, ResolverBundle bundle) {
+ this.name = name;
+ this.bundle = bundle;
}
- String[] uses = (String[]) constraint.getExportPackageDescription().getDirective(Constants.USES_DIRECTIVE);
- if (uses == null)
- return;
- boolean constraintAdded = false;
- if (!exports.contains(constraint) && getCachedConstraints(constraint) == null) {
- // the constraints have not been evaluated for this export add it to the list to process
- exports.add(constraint);
- constraintAdded = true;
+
+ public boolean hasRoots() {
+ return roots != null && roots.length > 0;
}
- ResolverBundle exporter = cur.getExporter();
- for (int i = 0; i < uses.length; i++) {
- ResolverExport[] constraintExports = exporter.getExports(uses[i]);
- for (int j = 0; j < constraintExports.length; j++) {
- // Check if the constraint has already been added so we don't recurse infinitely
- if (!createConstraints(cur).contains(constraintExports[j])) {
- addConstraint(exports, constraintExports[j]);
- addInitialGroupingConstraints(exports, constraintExports[j]);
- }
+
+ public void addRoot(ResolverExport export) {
+ if (roots == null) {
+ roots = new ResolverExport[] {export};
+ return;
+ }
+ // need to do an extra check to make sure we are not adding the same package name
+ // from multiple versions of the same bundle
+ String exportBSN = export.getExporter().getName();
+ if (exportBSN != null) {
+ // first one wins
+ for (int i = 0; i < roots.length; i++)
+ if (exportBSN.equals(roots[i].getExporter().getName()))
+ return;
+ }
+ if (!contains(export, roots)) {
+ ResolverExport[] newRoots = new ResolverExport[roots.length + 1];
+ System.arraycopy(roots, 0, newRoots, 0, roots.length);
+ newRoots[roots.length] = export;
+ roots = newRoots;
}
- ResolverImport constraintImport = exporter.getImport(uses[i]);
- if (constraintImport != null && !constraintImport.isDynamic())
- addConstraint(exports, constraintImport);
- if (constraintExports.length == 0 && (constraintImport == null || constraintImport.isDynamic()))
- addConstraint(exports, new UsesRequiredExport(constraint, uses[i]));
}
- if (constraintAdded)
- // we have finished processing all the uses for the constraint; remove it from the list to process
- exports.remove(constraint);
- }
- // Used to hold a 'uses' constraint on a package that is accessed through a required bundle
- private class UsesRequiredExport {
- // the exported package which 'uses' a package from a required bundle
- private ResolverExport export;
- // the name of the package which is 'used'
- private String usesName;
+ private boolean contains(ResolverExport export, ResolverExport[] exports) {
+ for (int i = 0; i < exports.length; i++)
+ if (exports[i] == export)
+ return true;
+ return false;
+ }
- UsesRequiredExport(ResolverExport export, String usesName) {
- this.export = export;
- this.usesName = usesName;
+ public void merge(PackageRoots packageRoots) {
+ if (packageRoots == null || packageRoots.roots == null)
+ return;
+ int size = packageRoots.roots.length;
+ for (int i = 0; i < size; i++)
+ addRoot(packageRoots.roots[i]);
}
- public ResolverExport[] getRoots() {
- ArrayList results = new ArrayList(1); // rare to have more than 1
- BundleConstraint[] requires = export.getExporter().getRequires();
- for (int i = 0; i < requires.length; i++) {
- if (requires[i].getMatchingBundle() == null)
+ public boolean isConsistentClassSpace(ResolverBundle importingBundle, ArrayList visited) {
+ if (roots == null)
+ return true;
+ int size = roots.length;
+ for (int i = 0; i < size; i++) {
+ ResolverExport root = roots[i];
+ String[] uses = root.getUsesDirective();
+ if (uses == null)
continue;
- ResolverExport requiredExport = requires[i].getMatchingBundle().getExport(usesName);
- if (requiredExport != null && !requiredExport.isDropped()) {
- ResolverExport[] roots = requiredExport.getRoots();
- for (int j = 0; j < roots.length; j++)
- if (!results.contains(requiredExport))
- results.add(roots[j]);
+ if (visited == null)
+ visited = new ArrayList(1);
+ if (visited.contains(this))
+ return true;
+ visited.add(this);
+ for (int j = 0; j < uses.length; j++) {
+ if (uses[j].equals(root.getName()))
+ continue;
+ PackageRoots thisUsedRoots = getPackageRoots(root.getExporter(), uses[j], null);
+ PackageRoots importingUsedRoots = getPackageRoots(importingBundle, uses[j], null);
+ if (thisUsedRoots == importingUsedRoots)
+ return true;
+ if (thisUsedRoots != nullPackageRoots && importingUsedRoots != nullPackageRoots)
+ if (!(subSet(thisUsedRoots.roots, importingUsedRoots.roots) || subSet(importingUsedRoots.roots, thisUsedRoots.roots)))
+ return false;
+ // need to check the usedRoots consistency for transitive closure
+ if (!thisUsedRoots.isConsistentClassSpace(importingBundle, visited))
+ return false;
}
}
- return (ResolverExport[]) results.toArray(new ResolverExport[results.size()]);
+ return true;
}
- public boolean equals(Object o) {
- if (!(o instanceof UsesRequiredExport))
- return false;
- return ((UsesRequiredExport) o).export.getExporter() == export.getExporter() && usesName.equals(((UsesRequiredExport) o).usesName);
+ public boolean isConsistentClassSpace(PackageRoots exportingRoots, ArrayList visited) {
+ if (roots == null)
+ return true;
+ int size = roots.length;
+ for (int i = 0; i < size; i++) {
+ ResolverExport root = roots[i];
+ String[] uses = root.getUsesDirective();
+ if (uses == null)
+ continue;
+ if (visited == null)
+ visited = new ArrayList(1);
+ if (visited.contains(this))
+ return true;
+ visited.add(this);
+ for (int j = 0; j < uses.length; j++) {
+ if (uses[j].equals(root.getName()) || !uses[j].equals(exportingRoots.name))
+ continue;
+ PackageRoots thisUsedRoots = getPackageRoots(root.getExporter(), uses[j], null);
+ PackageRoots exportingUsedRoots = getPackageRoots(exportingRoots.bundle, uses[j], null);
+ if (thisUsedRoots == exportingRoots)
+ return true;
+ if (thisUsedRoots != nullPackageRoots && exportingUsedRoots != nullPackageRoots)
+ if (!(subSet(thisUsedRoots.roots, exportingUsedRoots.roots) || subSet(exportingUsedRoots.roots, thisUsedRoots.roots)))
+ return false;
+ // need to check the usedRoots consistency for transitive closure
+ if (!thisUsedRoots.isConsistentClassSpace(exportingRoots, visited))
+ return false;
+ }
+ }
+ return true;
}
- }
- public void setCheckCycles(boolean checkCycles) {
- this.checkCycles = checkCycles;
+ // TODO this is a behavioral change; before we only required 1 supplier to match; now roots must be subsets
+ private boolean subSet(ResolverExport[] superSet, ResolverExport[] subSet) {
+ for (int i = 0; i < subSet.length; i++) {
+ boolean found = false;
+ for (int j = 0; j < superSet.length; j++)
+ if (subSet[i] == superSet[j]) {
+ found = true;
+ break;
+ }
+ if (!found)
+ return false;
+ }
+ return true;
+ }
}
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java
index 2d805d787..6a7caa076 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -116,19 +116,17 @@ public class ResolverBundle extends VersionSupplier {
return (ResolverExport[]) results.toArray(new ResolverExport[results.size()]);
}
- void clearWires(boolean clearUnresolvable) {
+ void clearWires() {
ResolverImport[] allImports = getImportPackages();
- for (int i = 0; i < allImports.length; i++) {
- allImports[i].setMatchingExport(null);
- if (clearUnresolvable)
- allImports[i].clearUnresolvableWirings();
- }
+ for (int i = 0; i < allImports.length; i++)
+ allImports[i].clearPossibleSuppliers();
if (host != null)
- host.removeAllMatchingBundles();
+ host.clearPossibleSuppliers();
+
BundleConstraint[] allRequires = getRequires();
for (int i = 0; i < allRequires.length; i++)
- allRequires[i].setMatchingBundle(null);
+ allRequires[i].clearPossibleSuppliers();
GenericConstraint[] allGenericRequires = getGenericRequires();
for (int i = 0; i < allGenericRequires.length; i++)
@@ -309,7 +307,7 @@ public class ResolverBundle extends VersionSupplier {
return new ResolverExport[0]; // cannot attach to fragments;
if (!getBundle().attachFragments() || (isResolved() && !getBundle().dynamicFragments()))
return new ResolverExport[0]; // host is restricting attachment
- if (fragment.getHost().getMatchingBundles() != null && !((HostSpecification) fragment.getHost().getVersionConstraint()).isMultiHost())
+ if (fragment.getHost().getNumPossibleSuppliers() > 0 && !((HostSpecification) fragment.getHost().getVersionConstraint()).isMultiHost())
return new ResolverExport[0]; // fragment is restricting attachment
ImportPackageSpecification[] newImports = fragment.getBundle().getImportPackages();
@@ -327,7 +325,7 @@ public class ResolverBundle extends VersionSupplier {
if (fragments.contains(fragment))
return new ResolverExport[0];
fragments.add(fragment);
- fragment.getHost().addMatchingBundle(this);
+ fragment.getHost().addPossibleSupplier(this);
if (newImports.length > 0) {
ArrayList hostImports = new ArrayList(newImports.length);
@@ -373,7 +371,7 @@ public class ResolverBundle extends VersionSupplier {
boolean result = false;
for (int i = 0; i < newImports.length; i++) {
ResolverImport hostImport = getImport(newImports[i].getName());
- ResolverExport resolvedExport = hostImport == null ? null : hostImport.getMatchingExport();
+ ResolverExport resolvedExport = (ResolverExport) (hostImport == null ? null : hostImport.getSelectedSupplier());
if ((resolvedExport == null && isResolved()) || (resolvedExport != null && !newImports[i].isSatisfiedBy(resolvedExport.getExportPackageDescription()))) {
result = true;
resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newImports[i].toString(), newImports[i]);
@@ -381,7 +379,7 @@ public class ResolverBundle extends VersionSupplier {
}
for (int i = 0; i < newRequires.length; i++) {
BundleConstraint hostRequire = getRequire(newRequires[i].getName());
- ResolverBundle resolvedRequire = hostRequire == null ? null : hostRequire.getMatchingBundle();
+ ResolverBundle resolvedRequire = (ResolverBundle) (hostRequire == null ? null : hostRequire.getSelectedSupplier());
if ((resolvedRequire == null && isResolved()) || (resolvedRequire != null && !newRequires[i].isSatisfiedBy(resolvedRequire.getBundle()))) {
result = true;
resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newRequires[i].toString(), newRequires[i]);
@@ -411,7 +409,7 @@ public class ResolverBundle extends VersionSupplier {
return new ResolverExport[0];
fragment.setNewFragmentExports(false);
- fragment.getHost().removeMatchingBundle(this);
+ fragment.getHost().removePossibleSupplier(this);
ArrayList fragImports = (ArrayList) fragmentImports.remove(fragment.bundleID);
ArrayList fragRequires = (ArrayList) fragmentRequires.remove(fragment.bundleID);
ArrayList removedExports = (ArrayList) fragmentExports.remove(fragment.bundleID);
@@ -436,7 +434,7 @@ public class ResolverBundle extends VersionSupplier {
for (Iterator iOldImports = fragImports.iterator(); iOldImports.hasNext();) {
ResolverImport oldImport = (ResolverImport) iOldImports.next();
if (newImport.getName().equals(oldImport.getName()))
- newImport.setMatchingExport(oldImport.getMatchingExport());
+ newImport.setPossibleSuppliers(oldImport.getPossibleSuppliers());
}
}
ArrayList newRequires = (ArrayList) fragmentRequires.get(remainingFrags[i].bundleID);
@@ -446,7 +444,7 @@ public class ResolverBundle extends VersionSupplier {
for (Iterator iOldRequires = fragRequires.iterator(); iOldRequires.hasNext();) {
BundleConstraint oldRequire = (BundleConstraint) iOldRequires.next();
if (newRequire.getName().equals(oldRequire.getName()))
- newRequire.setMatchingBundle(oldRequire.getMatchingBundle());
+ newRequire.setPossibleSuppliers(oldRequire.getPossibleSuppliers());
}
}
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java
index 6edb7ca9f..7f3040e26 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java
@@ -1,13 +1,11 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+ * Copyright (c) 2005, 2007 IBM Corporation and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
package org.eclipse.osgi.internal.module;
import org.eclipse.osgi.service.resolver.BundleDescription;
@@ -17,8 +15,10 @@ import org.eclipse.osgi.service.resolver.VersionConstraint;
* A companion to VersionConstraint from the state used while resolving
*/
public abstract class ResolverConstraint {
- ResolverBundle bundle;
- VersionConstraint constraint;
+ final protected ResolverBundle bundle;
+ final protected VersionConstraint constraint;
+ private VersionSupplier[] possibleSuppliers;
+ private int selectedSupplierIndex = 0;
ResolverConstraint(ResolverBundle bundle, VersionConstraint constraint) {
this.bundle = bundle;
@@ -63,4 +63,80 @@ public abstract class ResolverConstraint {
// returns whether this constraint is optional
abstract boolean isOptional();
+
+ public void setPossibleSuppliers(VersionSupplier[] possibleSuppliers) {
+ this.possibleSuppliers = possibleSuppliers;
+ }
+
+ void addPossibleSupplier(VersionSupplier supplier) {
+ if (supplier == null)
+ return;
+ // we hope multiple suppliers are rare so do simple array expansion here.
+ if (possibleSuppliers == null) {
+ possibleSuppliers = new VersionSupplier[] {supplier};
+ return;
+ }
+ VersionSupplier[] newSuppliers = new VersionSupplier[possibleSuppliers.length + 1];
+ System.arraycopy(possibleSuppliers, 0, newSuppliers, 0, possibleSuppliers.length);
+ newSuppliers[possibleSuppliers.length] = supplier;
+ possibleSuppliers = newSuppliers;
+ }
+
+ public void removePossibleSupplier(VersionSupplier supplier) {
+ if (possibleSuppliers == null || supplier == null)
+ return;
+ int index = -1;
+ for (int i = 0; i < possibleSuppliers.length; i++) {
+ if (possibleSuppliers[i] == supplier) {
+ index = i;
+ break;
+ }
+ }
+ if (index >= 0) {
+ if (possibleSuppliers.length == 1) {
+ possibleSuppliers = null;
+ return;
+ }
+ VersionSupplier[] newSuppliers = new VersionSupplier[possibleSuppliers.length - 1];
+ System.arraycopy(possibleSuppliers, 0, newSuppliers, 0, index);
+ if (index < possibleSuppliers.length - 1)
+ System.arraycopy(possibleSuppliers, index + 1, newSuppliers, index, possibleSuppliers.length - index - 1);
+ }
+ }
+
+ int getNumPossibleSuppliers() {
+ if (possibleSuppliers == null)
+ return 0;
+ return possibleSuppliers.length;
+ }
+
+ boolean selectNextSupplier() {
+ if (possibleSuppliers == null || selectedSupplierIndex >= possibleSuppliers.length)
+ return false;
+ selectedSupplierIndex += 1;
+ return selectedSupplierIndex < possibleSuppliers.length;
+ }
+
+ VersionSupplier getSelectedSupplier() {
+ if (possibleSuppliers == null || selectedSupplierIndex >= possibleSuppliers.length)
+ return null;
+ return possibleSuppliers[selectedSupplierIndex];
+ }
+
+ void setSelectedSupplier(int selectedSupplier) {
+ this.selectedSupplierIndex = selectedSupplier;
+ }
+
+ int getSelectedSupplierIndex() {
+ return this.selectedSupplierIndex;
+ }
+
+ VersionSupplier[] getPossibleSuppliers() {
+ return possibleSuppliers;
+ }
+
+ void clearPossibleSuppliers() {
+ possibleSuppliers = null;
+ selectedSupplierIndex = 0;
+ }
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverExport.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverExport.java
index 0c329b164..49ad45483 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverExport.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverExport.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,9 +10,9 @@
*******************************************************************************/
package org.eclipse.osgi.internal.module;
-import java.util.ArrayList;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
+import org.osgi.framework.Constants;
/*
* A companion to ExportPackageDescription from the state used while resolving.
@@ -37,36 +37,7 @@ public class ResolverExport extends VersionSupplier {
return resolverBundle;
}
- /*
- * returns a list of roots for this export. The returned list will include and exports
- * which the exporting bundle may get access to from imported packages or required bundles.
- */
- ResolverExport[] getRoots() {
- ArrayList results = new ArrayList(1); // usually only one root
- addRoots(results);
- return (ResolverExport[]) results.toArray(new ResolverExport[results.size()]);
- }
-
- /*
- * Adds roots for this export to the specified roots list.
- */
- private void addRoots(ArrayList roots) {
- if (roots.contains(this))
- return;
- ResolverImport ri = getExporter().getImport(getName());
- if (ri != null && ri.getMatchingExport() != null && ri.getMatchingExport() != this) {
- ri.getMatchingExport().addRoots(roots);
- return;
- }
- // always add to the front of the list
- roots.add(0, this);
- BundleConstraint[] requires = getExporter().getRequires();
- for (int i = 0; i < requires.length; i++) {
- if (requires[i].getMatchingBundle() == null)
- continue;
- ResolverExport requiredExport = requires[i].getBundle().getExport(getName());
- if (requiredExport != null && !requiredExport.isDropped())
- requiredExport.addRoots(roots);
- }
+ String[] getUsesDirective() {
+ return (String[]) getExportPackageDescription().getDirective(Constants.USES_DIRECTIVE);
}
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
index b5a827d8e..32c82f4f1 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java
@@ -1,13 +1,11 @@
/*******************************************************************************
- * Copyright (c) 2004, 2007 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
+ * Copyright (c) 2004, 2007 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
*
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
package org.eclipse.osgi.internal.module;
import java.util.*;
@@ -100,12 +98,6 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
}
rewireBundles(); // Reconstruct wirings
- ResolverBundle[] initBundles = (ResolverBundle[]) bundleMapping.values().toArray(new ResolverBundle[bundleMapping.size()]);
- for (int i = 0; i < initBundles.length; i++)
- // only initialize grouping constraint for resolved bundles;
- // we add the constraints for unresolved bundles before we start a resolve opertation
- if (initBundles[i].isResolved())
- groupingChecker.addInitialGroupingConstraints(initBundles[i]);
setDebugOptions();
initialized = true;
}
@@ -179,10 +171,10 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
private void rewireRequire(BundleConstraint req, ArrayList visited) {
- if (req.getMatchingBundle() != null)
+ if (req.getSelectedSupplier() != null)
return;
ResolverBundle matchingBundle = (ResolverBundle) bundleMapping.get(req.getVersionConstraint().getSupplier());
- req.setMatchingBundle(matchingBundle);
+ req.addPossibleSupplier(matchingBundle);
if (matchingBundle == null && !req.isOptional()) {
System.err.println("Could not find matching bundle for " + req.getVersionConstraint()); //$NON-NLS-1$
// TODO log error!!
@@ -193,7 +185,7 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
private void rewireImport(ResolverImport imp, ArrayList visited) {
- if (imp.isDynamic() || imp.getMatchingExport() != null)
+ if (imp.isDynamic() || imp.getSelectedSupplier() != null)
return;
// Re-wire 'imp'
ResolverExport matchingExport = null;
@@ -202,12 +194,12 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
Object[] matches = resolverExports.get(imp.getName());
for (int j = 0; j < matches.length; j++) {
ResolverExport export = (ResolverExport) matches[j];
- if (export.getExporter() == exporter && imp.isSatisfiedBy(export)) {
+ if (export.getExporter() == exporter && importSupplier == export.getExportPackageDescription()) {
matchingExport = export;
break;
}
}
- imp.setMatchingExport(matchingExport);
+ imp.addPossibleSupplier(matchingExport);
// Check if we wired to a reprovided package (in which case the ResolverExport doesn't exist)
if (matchingExport == null && exporter != null) {
ResolverExport reprovidedExport = new ResolverExport(exporter, importSupplier);
@@ -215,15 +207,15 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
exporter.addExport(reprovidedExport);
resolverExports.put(reprovidedExport.getName(), reprovidedExport);
}
- imp.setMatchingExport(reprovidedExport);
+ imp.addPossibleSupplier(reprovidedExport);
}
// If we still have a null wire and it's not optional, then we have an error
- if (imp.getMatchingExport() == null && !imp.isOptional()) {
+ if (imp.getSelectedSupplier() == null && !imp.isOptional()) {
System.err.println("Could not find matching export for " + imp.getVersionConstraint()); //$NON-NLS-1$
// TODO log error!!
}
- if (imp.getMatchingExport() != null) {
- rewireBundle(imp.getMatchingExport().getExporter(), visited);
+ if (imp.getSelectedSupplier() != null) {
+ rewireBundle(((ResolverExport) imp.getSelectedSupplier()).getExporter(), visited);
}
}
@@ -408,23 +400,24 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
}
+ // TODO this does not do proper uses constraint verification.
private void resolveOptionalConstraints(ResolverBundle bundle) {
BundleConstraint[] requires = bundle.getRequires();
ArrayList cycle = new ArrayList();
boolean resolvedOptional = false;
for (int i = 0; i < requires.length; i++)
- if (requires[i].isOptional() && requires[i].getMatchingBundle() == null) {
+ if (requires[i].isOptional() && requires[i].getSelectedSupplier() == null) {
cycle.clear();
resolveRequire(requires[i], cycle);
- if (requires[i].getMatchingBundle() != null)
+ if (requires[i].getSelectedSupplier() != null)
resolvedOptional = true;
}
ResolverImport[] imports = bundle.getImportPackages();
for (int i = 0; i < imports.length; i++)
- if (imports[i].isOptional() && imports[i].getMatchingExport() == null) {
+ if (imports[i].isOptional() && imports[i].getSelectedSupplier() == null) {
cycle.clear();
- resolveImport(imports[i], true, cycle);
- if (imports[i].getMatchingExport() != null)
+ resolveImport(imports[i], cycle);
+ if (imports[i].getSelectedSupplier() != null)
resolvedOptional = true;
}
if (resolvedOptional) {
@@ -451,19 +444,21 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// we still want to call isResolvable here to populate any possible ResolverErrors for the bundle
bundles[i].setResolvable(isResolvable(bundles[i].getBundle(), platformProperties, rejectedSingletons) || developmentMode);
bundles[i].clearRefs();
- groupingChecker.removeAllExportConstraints(bundles[i]);
}
+ resolveBundles0(bundles, platformProperties, rejectedSingletons);
+ if (DEBUG_WIRING)
+ printWirings();
+ // set the resolved status of the bundles in the State
+ stateResolveBundles(bundles);
+ }
+ private void resolveBundles0(ResolverBundle[] bundles, Dictionary[] platformProperties, ArrayList rejectedSingletons) {
// First attach all fragments to the matching hosts
for (int i = 0; i < bundles.length; i++)
attachFragment(bundles[i], rejectedSingletons);
- // add initial grouping constraints after fragments have been attached
- for (int i = 0; i < bundles.length; i++)
- groupingChecker.addInitialGroupingConstraints(bundles[i]);
// Lists of cyclic dependencies recording during resolving
ArrayList cycle = new ArrayList(1); // start small
- ArrayList resolvedBundles = new ArrayList(bundles.length);
// Attempt to resolve all unresolved bundles
for (int i = 0; i < bundles.length; i++) {
if (DEBUG)
@@ -473,21 +468,170 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// Check for any bundles involved in a cycle.
// if any bundles in the cycle are not resolved then we need to resolve the resolvable ones
checkCycle(cycle);
- if (bundles[i].isResolvable())
- resolvedBundles.add(bundles[i]);
}
-
// Resolve all fragments that are still attached to at least one host.
if (unresolvedBundles.size() > 0) {
ResolverBundle[] unresolved = (ResolverBundle[]) unresolvedBundles.toArray(new ResolverBundle[unresolvedBundles.size()]);
for (int i = 0; i < unresolved.length; i++)
resolveFragment(unresolved[i]);
}
+ checkUsesConstraints(bundles, platformProperties, rejectedSingletons);
+ }
- if (DEBUG_WIRING)
- printWirings();
- // set the resolved status of the bundles in the State
- stateResolveBundles(bundles);
+ private void checkUsesConstraints(ResolverBundle[] bundles, Dictionary[] platformProperties, ArrayList rejectedSingletons) {
+ ResolverConstraint[] multipleSuppliers = getMultipleSuppliers(bundles);
+ ArrayList conflictingConstraints = findBestCombination(bundles, multipleSuppliers);
+ Set conflictedBundles = null;
+ if (conflictingConstraints != null) {
+ for (Iterator conflicts = conflictingConstraints.iterator(); conflicts.hasNext();) {
+ ResolverConstraint conflict = (ResolverConstraint) conflicts.next();
+ if (conflict.isOptional()) {
+ conflict.clearPossibleSuppliers();
+ continue;
+ }
+ conflictedBundles = new HashSet(conflictingConstraints.size());
+ ResolverBundle conflictedBundle;
+ if (conflict.isFromFragment())
+ conflictedBundle = (ResolverBundle) bundleMapping.get(conflict.getVersionConstraint().getBundle());
+ else
+ conflictedBundle = conflict.getBundle();
+ if (conflictedBundle != null) {
+ conflictedBundles.add(conflictedBundle);
+ int type = conflict instanceof ResolverImport ? ResolverError.IMPORT_PACKAGE_USES_CONFLICT : ResolverError.REQUIRE_BUNDLE_USES_CONFLICT;
+ state.addResolverError(conflictedBundle.getBundle(), type, conflict.getVersionConstraint().toString(), conflict.getVersionConstraint());
+ conflictedBundle.setResolvable(false);
+ conflictedBundle.clearRefs();
+ setBundleUnresolved(conflictedBundle, false, developmentMode);
+ }
+ }
+ if (conflictedBundles != null && conflictedBundles.size() > 0) {
+ ArrayList remainingUnresolved = new ArrayList();
+ for (int i = 0; i < bundles.length; i++) {
+ if (!conflictedBundles.contains(bundles[i])) {
+ setBundleUnresolved(bundles[i], false, developmentMode);
+ remainingUnresolved.add(bundles[i]);
+ }
+ }
+ resolveBundles0((ResolverBundle[]) remainingUnresolved.toArray(new ResolverBundle[remainingUnresolved.size()]), platformProperties, rejectedSingletons);
+ }
+ }
+ }
+
+ private ArrayList findBestCombination(ResolverBundle[] bundles, ResolverConstraint[] multipleSuppliers) {
+ int[] bestCombination = new int[multipleSuppliers.length];
+ ArrayList conflictingBundles = null;
+ if (multipleSuppliers.length > 0) {
+ conflictingBundles = findBestCombination(bundles, multipleSuppliers, bestCombination);
+ for (int i = 0; i < bestCombination.length; i++)
+ multipleSuppliers[i].setSelectedSupplier(bestCombination[i]);
+ } else {
+ conflictingBundles = getConflicts(bundles);
+ }
+ // do not need to keep uses data in memory
+ groupingChecker.clear();
+ return conflictingBundles;
+ }
+
+ private void getCombination(ResolverConstraint[] multipleSuppliers, int[] combination) {
+ for (int i = 0; i < combination.length; i++)
+ combination[i] = multipleSuppliers[i].getSelectedSupplierIndex();
+ }
+
+ private ArrayList findBestCombination(ResolverBundle[] bundles, ResolverConstraint[] multipleSuppliers, int[] bestCombination) {
+ // first tryout all zeros
+ ArrayList bestConflicts = getConflicts(bundles);
+ if (bestConflicts == null)
+ return null; // the first selected have no conflicts; return without iterating over all combinations
+ // now iterate over every possible combination until either zero conflicts are found
+ // or we have run out of combinations
+ // if all combinations are tried then return the combination with the lowest number of conflicts
+ int bestConflictCount = getConflictCount(bestConflicts);
+ while (bestConflictCount != 0 && getNextCombination(multipleSuppliers)) {
+ ArrayList conflicts = getConflicts(bundles);
+ int conflictCount = getConflictCount(conflicts);
+ if (conflictCount < bestConflictCount) {
+ bestConflictCount = conflictCount;
+ bestConflicts = conflicts;
+ getCombination(multipleSuppliers, bestCombination);
+ }
+ }
+ return bestConflicts;
+ }
+
+ private boolean getNextCombination(ResolverConstraint[] multipleSuppliers) {
+ if (multipleSuppliers[0].selectNextSupplier())
+ return true; // the current slot has a next supplier
+ multipleSuppliers[0].setSelectedSupplier(0); // reset first slot
+ int current = 1;
+ while (current < multipleSuppliers.length) {
+ if (multipleSuppliers[current].selectNextSupplier())
+ return true;
+ multipleSuppliers[current].setSelectedSupplier(0); // reset the current slot
+ current++; // move to the next slot
+ }
+ return false;
+ }
+
+ // only count non-optional conflicts
+ private int getConflictCount(ArrayList conflicts) {
+ if (conflicts == null || conflicts.size() == 0)
+ return 0;
+ int result = 0;
+ for (Iterator iConflicts = conflicts.iterator(); iConflicts.hasNext();)
+ if (!((ResolverConstraint) iConflicts.next()).isOptional())
+ result += 1;
+ return result;
+ }
+
+ private ArrayList getConflicts(ResolverBundle[] bundles) {
+ groupingChecker.clear();
+ ArrayList conflicts = null;
+ bundlesLoop: for (int i = 0; i < bundles.length; i++) {
+ BundleConstraint[] requires = bundles[i].getRequires();
+ for (int j = 0; j < requires.length; j++) {
+ ResolverBundle selectedSupplier = (ResolverBundle) requires[j].getSelectedSupplier();
+ ResolverExport conflict = selectedSupplier == null ? null : groupingChecker.isConsistent(bundles[i], selectedSupplier);
+ if (conflict != null) {
+ if (conflicts == null)
+ conflicts = new ArrayList(1);
+ conflicts.add(requires[j]);
+ // continue on for optonal conflicts because we don't count them
+ if (!requires[j].isOptional())
+ continue bundlesLoop;
+ }
+ }
+ ResolverImport[] imports = bundles[i].getImportPackages();
+ for (int j = 0; j < imports.length; j++) {
+ ResolverExport selectedSupplier = (ResolverExport) imports[j].getSelectedSupplier();
+ ResolverExport conflict = selectedSupplier == null ? null : groupingChecker.isConsistent(bundles[i], selectedSupplier);
+ if (conflict != null) {
+ if (conflicts == null)
+ conflicts = new ArrayList(1);
+ conflicts.add(imports[j]);
+ // continue on for optional conflicts because we don't count them
+ if (!imports[j].isOptional())
+ continue bundlesLoop;
+ }
+ }
+ }
+ return conflicts;
+ }
+
+ // get a list of resolver constraints that have multiple suppliers
+ private ResolverConstraint[] getMultipleSuppliers(ResolverBundle[] bundles) {
+ ArrayList multipleSuppliers = new ArrayList(1);
+ for (int i = 0; i < bundles.length; i++) {
+ BundleConstraint[] requires = bundles[i].getRequires();
+ for (int j = 0; j < requires.length; j++)
+ if (requires[j].getNumPossibleSuppliers() > 1)
+ multipleSuppliers.add(requires[j]);
+ ResolverImport[] imports = bundles[i].getImportPackages();
+ for (int j = 0; j < imports.length; j++) {
+ if (imports[j].getNumPossibleSuppliers() > 1)
+ multipleSuppliers.add(imports[j]);
+ }
+ }
+ return (ResolverConstraint[]) multipleSuppliers.toArray(new ResolverConstraint[multipleSuppliers.size()]);
}
private void checkCycle(ArrayList cycle) {
@@ -496,37 +640,37 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
return;
for (int i = cycleSize - 1; i >= 0; i--) {
ResolverBundle cycleBundle = (ResolverBundle) cycle.get(i);
- // clear grouping (uses) constraints so we can do proper constaint checking now that the cycle is resolved
- groupingChecker.removeAllExportConstraints(cycleBundle);
- groupingChecker.addInitialGroupingConstraints(cycleBundle);
if (!cycleBundle.isResolvable())
cycle.remove(i); // remove this from the list of bundles that need reresolved
- }
- boolean reresolveCycle = cycle.size() != cycleSize || !isCycleConsistent(cycle); //we removed an unresolvable bundle; must reresolve remaining cycle
- for (int i = 0; i < cycle.size(); i++) {
- ResolverBundle rb = (ResolverBundle) cycle.get(0);
// Check that we haven't wired to any dropped exports
- ResolverImport[] imports = rb.getImportPackages();
- for (int j = 0; j < imports.length; j++)
+ ResolverImport[] imports = cycleBundle.getImportPackages();
+ for (int j = 0; j < imports.length; j++) {
// check for dropped exports
- if (imports[j].getMatchingExport() != null && imports[j].getMatchingExport().isDropped()) {
- imports[j].addUnresolvableWiring(imports[j].getMatchingExport().getExporter());
- reresolveCycle = true;
+ while (imports[j].getSelectedSupplier() != null) {
+ ResolverExport importSupplier = (ResolverExport) imports[j].getSelectedSupplier();
+ if (importSupplier.isDropped())
+ imports[j].selectNextSupplier();
+ else
+ break;
}
+ if (!imports[j].isDynamic() && !imports[j].isOptional() && imports[j].getSelectedSupplier() == null) {
+ cycleBundle.setResolvable(false);
+ cycleBundle.clearRefs();
+ state.addResolverError(imports[j].getVersionConstraint().getBundle(), ResolverError.MISSING_IMPORT_PACKAGE, imports[j].getVersionConstraint().toString(), imports[j].getVersionConstraint());
+ cycle.remove(i);
+ }
+ }
}
+ boolean reresolveCycle = cycle.size() != cycleSize; //we removed an unresolvable bundle; must reresolve remaining cycle
if (reresolveCycle) {
for (int i = 0; i < cycle.size(); i++) {
ResolverBundle cycleBundle = (ResolverBundle) cycle.get(i);
- groupingChecker.removeAllExportConstraints(cycleBundle);
- groupingChecker.addInitialGroupingConstraints(cycleBundle);
- cycleBundle.clearWires(false);
+ cycleBundle.clearWires();
cycleBundle.clearRefs();
}
- groupingChecker.setCheckCycles(true); // need to do the expensive cycle checks now
ArrayList innerCycle = new ArrayList(cycle.size());
for (int i = 0; i < cycle.size(); i++)
resolveBundle((ResolverBundle) cycle.get(i), innerCycle);
- groupingChecker.setCheckCycles(false); // disable the expensive cycle checks
checkCycle(innerCycle);
} else {
for (int i = 0; i < cycle.size(); i++) {
@@ -537,23 +681,6 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
}
- // checks all the uses constraints of a cycle to make sure they
- // are consistent now that the cycle has been resolved.
- private boolean isCycleConsistent(ArrayList cycle) {
- for (Iterator iter = cycle.iterator(); iter.hasNext();) {
- ResolverBundle bundle = (ResolverBundle) iter.next();
- BundleConstraint[] requires = bundle.getRequires();
- for (int i = 0; i < requires.length; i++)
- if (requires[i].getMatchingBundle() != null && groupingChecker.isConsistent(requires[i], requires[i].getMatchingBundle()) != null)
- return false;
- ResolverImport[] imports = bundle.getImportPackages();
- for (int i = 0; i < imports.length; i++)
- if (imports[i].getMatchingExport() != null && groupingChecker.isConsistent(imports[i], imports[i].getMatchingExport()) != null)
- return false;
- }
- return true;
- }
-
private boolean selectSingletons(ResolverBundle[] bundles, ArrayList rejectedSingletons) {
if (developmentMode)
return false; // do no want to unresolve singletons in development mode
@@ -592,11 +719,9 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
private void resolveFragment(ResolverBundle fragment) {
if (!fragment.isFragment())
return;
- if (fragment.getHost().foundMatchingBundles()) {
- stateResolveFragConstraints(fragment);
+ if (fragment.getHost().getNumPossibleSuppliers() > 0)
if (!developmentMode || state.getResolverErrors(fragment.getBundle()).length == 0)
setBundleResolved(fragment);
- }
}
// This method will attempt to resolve the supplied bundle and any bundles that it is dependent on
@@ -615,7 +740,7 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
return true;
} else if (bundle.getState() == ResolverBundle.UNRESOLVED) {
// 'bundle' is UNRESOLVED so move to RESOLVING
- bundle.clearWires(true);
+ bundle.clearWires();
setBundleResolving(bundle);
}
@@ -670,7 +795,7 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
ResolverImport[] imports = bundle.getImportPackages();
for (int i = 0; i < imports.length; i++) {
// Only resolve non-dynamic imports here
- if (!imports[i].isDynamic() && !resolveImport(imports[i], true, cycle)) {
+ if (!imports[i].isDynamic() && !resolveImport(imports[i], cycle)) {
if (DEBUG || DEBUG_IMPORTS)
ResolverImpl.log("** IMPORT " + imports[i].getName() + "[" + imports[i].getBundleDescription() + "] failed to resolve"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// If the import has failed to resolve and it is from a fragment, then remove the fragment from the host
@@ -711,8 +836,6 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
if (bundle.getState() == ResolverBundle.UNRESOLVED)
bundle.setResolvable(false); // Set it to unresolvable so we don't attempt to resolve it again in this round
- // tell the state what we resolved the constraints to
- stateResolveConstraints(bundle);
return bundle.getState() != ResolverBundle.UNRESOLVED;
}
@@ -758,21 +881,22 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
result = true; // Wired to ourselves
continue;
}
- ResolverBundle[] capabilityHosts = capability.isFromFragment() ? capability.getResolverBundle().getHost().getMatchingBundles() : new ResolverBundle[] {capability.getResolverBundle()};
+ VersionSupplier[] capabilityHosts = capability.isFromFragment() ? capability.getResolverBundle().getHost().getPossibleSuppliers() : new ResolverBundle[] {capability.getResolverBundle()};
boolean foundResolvedMatch = false;
for (int j = 0; capabilityHosts != null && j < capabilityHosts.length; j++) {
- if (capabilityHosts[j] == constraint.getBundle()) {
+ ResolverBundle capabilitySupplier = (ResolverBundle) capabilityHosts[j];
+ if (capabilitySupplier == constraint.getBundle()) {
// the capability is from a fragment attached to this host do not recursively resolve the host again
foundResolvedMatch = true;
continue;
}
// if in dev mode then allow a constraint to resolve to an unresolved bundle
- if (capabilityHosts[j].getState() == ResolverBundle.RESOLVED || (resolveBundle(capabilityHosts[j], cycle) || developmentMode)) {
- foundResolvedMatch |= !capability.isFromFragment() ? true : capability.getResolverBundle().getHost().getMatchingBundles() != null;
+ if (capabilitySupplier.getState() == ResolverBundle.RESOLVED || (resolveBundle(capabilitySupplier, cycle) || developmentMode)) {
+ foundResolvedMatch |= !capability.isFromFragment() ? true : capability.getResolverBundle().getHost().getPossibleSuppliers() != null;
// Check cyclic dependencies
- if (capabilityHosts[j].getState() == ResolverBundle.RESOLVING)
- if (!cycle.contains(capabilityHosts[j]))
- cycle.add(capabilityHosts[j]);
+ if (capabilitySupplier.getState() == ResolverBundle.RESOLVING)
+ if (!cycle.contains(capabilitySupplier))
+ cycle.add(capabilitySupplier);
}
}
if (!foundResolvedMatch) {
@@ -791,14 +915,13 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
private boolean resolveRequire(BundleConstraint req, ArrayList cycle) {
if (DEBUG_REQUIRES)
ResolverImpl.log("Trying to resolve: " + req.getBundle() + ", " + req.getVersionConstraint()); //$NON-NLS-1$ //$NON-NLS-2$
- if (req.getMatchingBundle() != null) {
+ if (req.getSelectedSupplier() != null) {
// Check for unrecorded cyclic dependency
- if (req.getMatchingBundle().getState() == ResolverBundle.RESOLVING)
- if (!cycle.contains(req.getBundle())) {
- cycle.add(req.getBundle());
- if (DEBUG_CYCLES)
- ResolverImpl.log("require-bundle cycle: " + req.getBundle() + " -> " + req.getMatchingBundle()); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ if (!cycle.contains(req.getBundle())) {
+ cycle.add(req.getBundle());
+ if (DEBUG_CYCLES)
+ ResolverImpl.log("require-bundle cycle: " + req.getBundle() + " -> " + req.getSelectedSupplier()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
if (DEBUG_REQUIRES)
ResolverImpl.log(" - already wired"); //$NON-NLS-1$
return true; // Already wired (due to grouping dependencies) so just return
@@ -812,29 +935,28 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// Check if export matches
if (req.isSatisfiedBy(bundle)) {
bundle.addRef(req.getBundle());
- if (result)
- continue;
- req.setMatchingBundle(bundle); // Wire to the bundle
- if (req.getBundle() == bundle) {
- result = true; // Wired to ourselves
- continue;
- }
- // if in dev mode then allow a constraint to resolve to an unresolved bundle
- if (bundle.getState() != ResolverBundle.RESOLVED && !resolveBundle(bundle, cycle) && !developmentMode) {
- req.setMatchingBundle(null);
- continue; // Bundle hasn't resolved
+ // first add the possible supplier; this is done before resolving the supplier bundle to prevent endless cycle loops.
+ req.addPossibleSupplier(bundle);
+ if (req.getBundle() != bundle) {
+ // if in dev mode then allow a constraint to resolve to an unresolved bundle
+ if (bundle.getState() != ResolverBundle.RESOLVED && !resolveBundle(bundle, cycle) && !developmentMode) {
+ req.removePossibleSupplier(bundle);
+ continue; // Bundle hasn't resolved
+ }
}
// Check cyclic dependencies
- if (bundle.getState() == ResolverBundle.RESOLVING)
- // If the bundle is RESOLVING, we have a cyclic dependency
- if (!cycle.contains(req.getBundle())) {
- cycle.add(req.getBundle());
- if (DEBUG_CYCLES)
- ResolverImpl.log("require-bundle cycle: " + req.getBundle() + " -> " + req.getMatchingBundle()); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ if (req.getBundle() != bundle) {
+ if (bundle.getState() == ResolverBundle.RESOLVING)
+ // If the bundle is RESOLVING, we have a cyclic dependency
+ if (!cycle.contains(req.getBundle())) {
+ cycle.add(req.getBundle());
+ if (DEBUG_CYCLES)
+ ResolverImpl.log("require-bundle cycle: " + req.getBundle() + " -> " + req.getSelectedSupplier()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
if (DEBUG_REQUIRES)
ResolverImpl.log("Found match: " + bundle.getBundle() + ". Wiring"); //$NON-NLS-1$ //$NON-NLS-2$
- result = checkRequiresConstraints(req, req.getMatchingBundle());
+ result = true;
}
}
if (result || req.isOptional())
@@ -843,27 +965,17 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
return false;
}
- private boolean checkRequiresConstraints(BundleConstraint req, ResolverBundle bundle) {
- if (groupingChecker.isConsistent(req, bundle) != null) {
- req.setMatchingBundle(null);
- state.addResolverError(req.getBundleDescription(), ResolverError.REQUIRE_BUNDLE_USES_CONFLICT, bundle.getBundle().toString(), req.getVersionConstraint());
- return req.isOptional();
- }
- return true;
- }
-
// Resolve the supplied import. Returns true if the import can be resolved, false otherwise
- private boolean resolveImport(ResolverImport imp, boolean checkReexportsFromRequires, ArrayList cycle) {
+ private boolean resolveImport(ResolverImport imp, ArrayList cycle) {
if (DEBUG_IMPORTS)
ResolverImpl.log("Trying to resolve: " + imp.getBundle() + ", " + imp.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- if (imp.getMatchingExport() != null) {
+ if (imp.getSelectedSupplier() != null) {
// Check for unrecorded cyclic dependency
- if (imp.getMatchingExport().getExporter().getState() == ResolverBundle.RESOLVING)
- if (!cycle.contains(imp.getBundle())) {
- cycle.add(imp.getBundle());
- if (DEBUG_CYCLES)
- ResolverImpl.log("import-package cycle: " + imp.getBundle() + " -> " + imp.getMatchingExport() + " from " + imp.getMatchingExport().getBundle()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
+ if (!cycle.contains(imp.getBundle())) {
+ cycle.add(imp.getBundle());
+ if (DEBUG_CYCLES)
+ ResolverImpl.log("import-package cycle: " + imp.getBundle() + " -> " + imp.getSelectedSupplier() + " from " + imp.getSelectedSupplier().getBundle()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
if (DEBUG_IMPORTS)
ResolverImpl.log(" - already wired"); //$NON-NLS-1$
return true; // Already wired (due to grouping dependencies) so just return
@@ -875,16 +987,15 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
if (DEBUG_IMPORTS)
ResolverImpl.log("CHECKING: " + export.getExporter().getBundle() + ", " + export.getName()); //$NON-NLS-1$ //$NON-NLS-2$
// Check if export matches
- if (imp.isSatisfiedBy(export) && imp.isNotAnUnresolvableWiring(export)) {
+ if (imp.isSatisfiedBy(export)) {
int originalState = export.getExporter().getState();
if (imp.isDynamic() && originalState != ResolverBundle.RESOLVED)
continue; // Must not attempt to resolve an exporter when dynamic
if (imp.getBundle() == export.getExporter() && !export.getExportPackageDescription().isRoot())
continue; // Can't wire to our own re-export
export.getExporter().addRef(imp.getBundle());
- if (result)
- continue;
- imp.setMatchingExport(export); // Wire the import to the export
+ // first add the possible supplier; this is done before resolving the supplier bundle to prevent endless cycle loops.
+ imp.addPossibleSupplier(export);
ResolverExport[] importerExps = null;
if (imp.getBundle() != export.getExporter()) {
// Save the exports of this package from the importer in case we need to add them back
@@ -897,54 +1008,40 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
// if in dev mode then allow a constraint to resolve to an unresolved bundle
if ((originalState != ResolverBundle.RESOLVED && !resolveBundle(export.getExporter(), cycle) && !developmentMode) || export.isDropped()) {
- if (imp.getMatchingExport() != null && imp.getMatchingExport() != export) // has been resolved to some other export recursively
- return true;
+ // remove the possible supplier
+ imp.removePossibleSupplier(export);
// add back the exports of this package from the importer
for (int j = 0; j < importerExps.length; j++)
resolverExports.put(importerExps[j].getName(), importerExps[j]);
- imp.setMatchingExport(null);
continue; // Bundle hasn't resolved || export has not been selected and is unavailable
}
- }
- // If the importer has become unresolvable then stop here
- if (!imp.getBundle().isResolvable())
- return false;
- // Check grouping dependencies
- if (checkImportConstraints(imp, imp.getMatchingExport(), cycle, importerExps) && imp.getMatchingExport() != null) {
- // Record any cyclic dependencies
- if (export != imp.getMatchingExport())
- export = imp.getMatchingExport();
- if (imp.getBundle() != export.getExporter())
- if (export.getExporter().getState() == ResolverBundle.RESOLVING) {
- // If the exporter is RESOLVING, we have a cyclic dependency
- if (!cycle.contains(imp.getBundle())) {
- cycle.add(imp.getBundle());
- if (DEBUG_CYCLES)
- ResolverImpl.log("import-package cycle: " + imp.getBundle() + " -> " + imp.getMatchingExport() + " from " + imp.getMatchingExport().getBundle()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
+ } else if (export.isDropped())
+ continue; // we already found a possible import that satisifies us; our export is dropped
+
+ // Record any cyclic dependencies
+ if (imp.getBundle() != export.getExporter())
+ if (export.getExporter().getState() == ResolverBundle.RESOLVING) {
+ // If the exporter is RESOLVING, we have a cyclic dependency
+ if (!cycle.contains(imp.getBundle())) {
+ cycle.add(imp.getBundle());
+ if (DEBUG_CYCLES)
+ ResolverImpl.log("import-package cycle: " + imp.getBundle() + " -> " + imp.getSelectedSupplier() + " from " + imp.getSelectedSupplier().getBundle()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
- if (DEBUG_IMPORTS)
- ResolverImpl.log("Found match: " + export.getExporter() + ". Wiring " + imp.getBundle() + ":" + imp.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- result = true;
- } else if (!imp.getBundle().isResolvable()) {
- // If grouping has caused recursive calls to resolveImport, and the grouping has failed
- // then we need to catch that here, so we don't continue trying to wire here
- return false;
- }
- if (!result && imp.getMatchingExport() != null && imp.getMatchingExport() != export)
- return true; // Grouping has changed the wiring, so return here
+ }
+ if (DEBUG_IMPORTS)
+ ResolverImpl.log("Found match: " + export.getExporter() + ". Wiring " + imp.getBundle() + ":" + imp.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ result = true;
}
}
+
if (result)
return true;
- if (checkReexportsFromRequires && resolveImportReprovide(imp, cycle))
- return true; // A reprovide satisfies imp
+ if (resolveImportReprovide(imp, cycle))
+ return true;
if (imp.isOptional())
return true; // If the import is optional then just return true
-
return false;
}
-
// Check if the import can be resolved to a re-exported package (has no export object to match to)
private boolean resolveImportReprovide(ResolverImport imp, ArrayList cycle) {
String bsn = ((ImportPackageSpecification) imp.getVersionConstraint()).getBundleSymbolicName();
@@ -972,9 +1069,9 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
if (!((BundleSpecification) requires[i].getVersionConstraint()).isExported())
continue; // Skip require if it doesn't re-export the packages
// Check exports to see if we've found the root
- if (requires[i].getMatchingBundle() == null)
+ if (requires[i].getSelectedSupplier() == null)
continue;
- ResolverExport[] exports = requires[i].getMatchingBundle().getExports(imp.getName());
+ ResolverExport[] exports = ((ResolverBundle) requires[i].getSelectedSupplier()).getExports(imp.getName());
for (int j = 0; j < exports.length; j++) {
Map directives = exports[j].getExportPackageDescription().getDirectives();
directives.remove(Constants.USES_DIRECTIVE);
@@ -987,56 +1084,17 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
reexporter.addExport(re);
resolverExports.put(re.getName(), re);
// Resolve import
- if (resolveImport(imp, false, cycle))
- return true;
+ imp.addPossibleSupplier(re);
+ return true;
}
}
// Check requires of matching bundle (recurse down the chain)
- if (resolveImportReprovide0(imp, reexporter, requires[i].getMatchingBundle(), cycle, visited))
+ if (resolveImportReprovide0(imp, reexporter, (ResolverBundle) requires[i].getSelectedSupplier(), cycle, visited))
return true;
}
return false;
}
- // This method checks and resolves (if possible) grouping dependencies
- // Returns true, if the dependencies can be resolved, false otherwise
- private boolean checkImportConstraints(ResolverImport imp, ResolverExport exp, ArrayList cycle, ResolverExport[] importerExps) {
- if (DEBUG_GROUPING)
- ResolverImpl.log(" Checking grouping for " + imp.getBundle() + ":" + imp.getName() + " -> " + exp.getExporter() + ":" + exp.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- ResolverBundle importer = imp.getBundle();
- ResolverExport clash = groupingChecker.isConsistent(imp, exp);
- if (clash == null)
- return true;
- if (DEBUG_GROUPING)
- ResolverImpl.log(" * grouping clash with " + clash.getExporter() + ":" + clash.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- // Try to rewire imp
- imp.addUnresolvableWiring(exp.getExporter());
- imp.setMatchingExport(null);
- if (resolveImport(imp, false, cycle))
- return true;
- if (imp.isDynamic())
- return false;
- // Rewiring of imp has failed so try to rewire clashing import
- imp.clearUnresolvableWirings();
- imp.setMatchingExport(exp);
- ResolverImport[] imports = importer.getImportPackages();
- for (int i = 0; i < imports.length; i++) {
- if (imports[i].getMatchingExport() != null && imports[i].getMatchingExport().getName().equals(clash.getName())) {
- imports[i].addUnresolvableWiring(imports[i].getMatchingExport().getExporter());
- imports[i].setMatchingExport(null); // clear the conflicting wire
- // If the clashing import package was also exported then
- // we need to put the export back into resolverExports
- if (importerExps != null)
- resolverExports.put(importerExps);
- }
- }
- // Try to re-resolve the bundle
- if (resolveBundle(importer, cycle))
- return true;
- state.addResolverError(imp.getVersionConstraint().getBundle(), ResolverError.IMPORT_PACKAGE_USES_CONFLICT, imp.getVersionConstraint().toString(), imp.getVersionConstraint());
- return false;
- }
-
// Move a bundle to UNRESOLVED
private void setBundleUnresolved(ResolverBundle bundle, boolean removed, boolean isDevMode) {
if (bundle.getState() == ResolverBundle.UNRESOLVED)
@@ -1074,21 +1132,22 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// Resolves the bundles in the State
private void stateResolveBundles(ResolverBundle[] resolvedBundles) {
- for (int i = 0; i < resolvedBundles.length; i++)
+ for (int i = 0; i < resolvedBundles.length; i++) {
if (!resolvedBundles[i].getBundle().isResolved())
stateResolveBundle(resolvedBundles[i]);
+ }
}
private void stateResolveConstraints(ResolverBundle rb) {
ResolverImport[] imports = rb.getImportPackages();
for (int i = 0; i < imports.length; i++) {
- ResolverExport export = imports[i].getMatchingExport();
+ ResolverExport export = (ResolverExport) imports[i].getSelectedSupplier();
BaseDescription supplier = export == null ? null : export.getExportPackageDescription();
state.resolveConstraint(imports[i].getVersionConstraint(), supplier);
}
BundleConstraint[] requires = rb.getRequires();
for (int i = 0; i < requires.length; i++) {
- ResolverBundle bundle = requires[i].getMatchingBundle();
+ ResolverBundle bundle = (ResolverBundle) requires[i].getSelectedSupplier();
BaseDescription supplier = bundle == null ? null : bundle.getBundle();
state.resolveConstraint(requires[i].getVersionConstraint(), supplier);
}
@@ -1104,18 +1163,18 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
}
private void stateResolveFragConstraints(ResolverBundle rb) {
- ResolverBundle host = rb.getHost().getMatchingBundle();
+ ResolverBundle host = (ResolverBundle) rb.getHost().getSelectedSupplier();
ImportPackageSpecification[] imports = rb.getBundle().getImportPackages();
for (int i = 0; i < imports.length; i++) {
ResolverImport hostImport = host.getImport(imports[i].getName());
- ResolverExport export = hostImport == null ? null : hostImport.getMatchingExport();
+ ResolverExport export = (ResolverExport) (hostImport == null ? null : hostImport.getSelectedSupplier());
BaseDescription supplier = export == null ? null : export.getExportPackageDescription();
state.resolveConstraint(imports[i], supplier);
}
BundleSpecification[] requires = rb.getBundle().getRequiredBundles();
for (int i = 0; i < requires.length; i++) {
BundleConstraint hostRequire = host.getRequire(requires[i].getName());
- ResolverBundle bundle = hostRequire == null ? null : hostRequire.getMatchingBundle();
+ ResolverBundle bundle = (ResolverBundle) (hostRequire == null ? null : hostRequire.getSelectedSupplier());
BaseDescription supplier = bundle == null ? null : bundle.getBundle();
state.resolveConstraint(requires[i], supplier);
}
@@ -1125,6 +1184,10 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// if in dev mode then we want to tell the state about the constraints we were able to resolve
if (!rb.isResolved() && !developmentMode)
return;
+ if (rb.isFragment())
+ stateResolveFragConstraints(rb);
+ else
+ stateResolveConstraints(rb);
// Gather selected exports
ResolverExport[] exports = rb.getSelectedExports();
ArrayList selectedExports = new ArrayList(exports.length);
@@ -1136,31 +1199,29 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// Gather exports that have been wired to
ResolverImport[] imports = rb.getImportPackages();
ArrayList exportsWiredTo = new ArrayList(imports.length);
- for (int i = 0; i < imports.length; i++) {
- if (imports[i].getMatchingExport() != null) {
- exportsWiredTo.add(imports[i].getMatchingExport().getExportPackageDescription());
- }
- }
+ for (int i = 0; i < imports.length; i++)
+ if (imports[i].getSelectedSupplier() != null)
+ exportsWiredTo.add(imports[i].getSelectedSupplier().getBaseDescription());
ExportPackageDescription[] exportsWiredToArray = (ExportPackageDescription[]) exportsWiredTo.toArray(new ExportPackageDescription[exportsWiredTo.size()]);
// Gather bundles that have been wired to
BundleConstraint[] requires = rb.getRequires();
ArrayList bundlesWiredTo = new ArrayList(requires.length);
for (int i = 0; i < requires.length; i++)
- if (requires[i].getMatchingBundle() != null)
- bundlesWiredTo.add(requires[i].getMatchingBundle().getBundle());
+ if (requires[i].getSelectedSupplier() != null)
+ bundlesWiredTo.add(requires[i].getSelectedSupplier().getBaseDescription());
BundleDescription[] bundlesWiredToArray = (BundleDescription[]) bundlesWiredTo.toArray(new BundleDescription[bundlesWiredTo.size()]);
BundleDescription[] hostBundles = null;
if (rb.isFragment()) {
- ResolverBundle[] matchingBundles = rb.getHost().getMatchingBundles();
+ VersionSupplier[] matchingBundles = rb.getHost().getPossibleSuppliers();
if (matchingBundles != null && matchingBundles.length > 0) {
hostBundles = new BundleDescription[matchingBundles.length];
for (int i = 0; i < matchingBundles.length; i++) {
hostBundles[i] = matchingBundles[i].getBundle();
if (rb.isNewFragmentExports() && hostBundles[i].isResolved()) {
// update the host's set of selected exports
- ResolverExport[] hostExports = matchingBundles[i].getSelectedExports();
+ ResolverExport[] hostExports = ((ResolverBundle) matchingBundles[i]).getSelectedExports();
ExportPackageDescription[] hostExportsArray = new ExportPackageDescription[hostExports.length];
for (int j = 0; j < hostExports.length; j++)
hostExportsArray[j] = hostExports[j].getExportPackageDescription();
@@ -1203,16 +1264,30 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
// Resolve the import
if (requestedPackage.equals(resolverImports[j].getName())) {
found = true;
- if (resolveImport(resolverImports[j], true, new ArrayList())) {
- // If the import resolved then return it's matching export
+ // populate the grouping checker with current imports
+ groupingChecker.populateRoots(resolverImports[j].getBundle());
+ if (resolveImport(resolverImports[j], new ArrayList())) {
+ found = false;
+ while (!found && resolverImports[j].getSelectedSupplier() != null) {
+ if (groupingChecker.isDynamicConsistent(resolverImports[j].getBundle(), (ResolverExport) resolverImports[j].getSelectedSupplier()) != null)
+ resolverImports[j].selectNextSupplier(); // not consistent; try the next
+ else
+ found = true; // found a valid wire
+ }
resolverImports[j].setName(null);
+ if (!found) {
+ // not found or there was a conflict; reset the suppliers and return null
+ resolverImports[j].setPossibleSuppliers(null);
+ return null;
+ }
+ // If the import resolved then return it's matching export
if (DEBUG_IMPORTS)
- ResolverImpl.log("Resolved dynamic import: " + rb + ":" + resolverImports[j].getName() + " -> " + resolverImports[j].getMatchingExport().getExporter() + ":" + requestedPackage); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- ExportPackageDescription matchingExport = resolverImports[j].getMatchingExport().getExportPackageDescription();
+ ResolverImpl.log("Resolved dynamic import: " + rb + ":" + resolverImports[j].getName() + " -> " + ((ResolverExport) resolverImports[j].getSelectedSupplier()).getExporter() + ":" + requestedPackage); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ ExportPackageDescription matchingExport = ((ResolverExport) resolverImports[j].getSelectedSupplier()).getExportPackageDescription();
// If it is a wildcard import then clear the wire, so other
// exported packages can be found for it
if (importName.endsWith("*")) //$NON-NLS-1$
- resolverImports[j].setMatchingExport(null);
+ resolverImports[j].setPossibleSuppliers(null);
return matchingExport;
}
}
@@ -1225,8 +1300,15 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
directives.put(Constants.RESOLUTION_DIRECTIVE, ImportPackageSpecification.RESOLUTION_DYNAMIC);
ImportPackageSpecification packageSpec = state.getFactory().createImportPackageSpecification(requestedPackage, null, null, null, directives, null, importingBundle);
ResolverImport newImport = new ResolverImport(rb, packageSpec);
- if (resolveImport(newImport, true, new ArrayList()))
- return newImport.getMatchingExport().getExportPackageDescription();
+ if (resolveImport(newImport, new ArrayList())) {
+ while (newImport.getSelectedSupplier() != null) {
+ if (groupingChecker.isDynamicConsistent(rb, (ResolverExport) newImport.getSelectedSupplier()) != null)
+ newImport.selectNextSupplier();
+ else
+ break;
+ }
+ return ((ResolverExport) newImport.getSelectedSupplier()).getExportPackageDescription();
+ }
}
if (DEBUG || DEBUG_IMPORTS)
ResolverImpl.log("Failed to resolve dynamic import: " + requestedPackage); //$NON-NLS-1$
@@ -1266,7 +1348,7 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
if (!pending) {
bundleMapping.remove(bundle);
- groupingChecker.removeAllExportConstraints(rb);
+ groupingChecker.remove(rb);
}
if (!pending || !bundle.isResolved()) {
resolverExports.remove(rb.getExportPackages());
@@ -1289,7 +1371,7 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
resolverBundles.remove(re);
resolverGenerics.remove(re.getGenericCapabilities());
bundleMapping.remove(removedBundles[i]);
- groupingChecker.removeAllExportConstraints(re);
+ groupingChecker.remove(re);
// the bundle is removed
if (removedBundles[i] == bundle.getBundle())
removed = true;
@@ -1365,17 +1447,17 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
ResolverImpl.log(" (r) no requires"); //$NON-NLS-1$
} else {
for (int i = 0; i < requireBundles.length; i++) {
- if (requireBundles[i].getMatchingBundle() == null) {
+ if (requireBundles[i].getSelectedSupplier() == null) {
ResolverImpl.log(" (r) " + rb.getBundle() + " -> NULL!!!"); //$NON-NLS-1$ //$NON-NLS-2$
} else {
- ResolverImpl.log(" (r) " + rb.getBundle() + " -> " + requireBundles[i].getMatchingBundle()); //$NON-NLS-1$ //$NON-NLS-2$
+ ResolverImpl.log(" (r) " + rb.getBundle() + " -> " + requireBundles[i].getSelectedSupplier()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
// Hosts
BundleConstraint hostSpec = rb.getHost();
if (hostSpec != null) {
- ResolverBundle[] hosts = hostSpec.getMatchingBundles();
+ VersionSupplier[] hosts = hostSpec.getPossibleSuppliers();
if (hosts != null)
for (int i = 0; i < hosts.length; i++) {
ResolverImpl.log(" (h) " + rb.getBundle() + " -> " + hosts[i].getBundle()); //$NON-NLS-1$ //$NON-NLS-2$
@@ -1388,15 +1470,15 @@ public class ResolverImpl implements org.eclipse.osgi.service.resolver.Resolver
continue;
}
for (int i = 0; i < imports.length; i++) {
- if (imports[i].isDynamic() && imports[i].getMatchingExport() == null) {
+ if (imports[i].isDynamic() && imports[i].getSelectedSupplier() == null) {
ResolverImpl.log(" (w) " + imports[i].getBundle() + ":" + imports[i].getName() + " -> DYNAMIC"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- } else if (imports[i].isOptional() && imports[i].getMatchingExport() == null) {
+ } else if (imports[i].isOptional() && imports[i].getSelectedSupplier() == null) {
ResolverImpl.log(" (w) " + imports[i].getBundle() + ":" + imports[i].getName() + " -> OPTIONAL (could not be wired)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- } else if (imports[i].getMatchingExport() == null) {
+ } else if (imports[i].getSelectedSupplier() == null) {
ResolverImpl.log(" (w) " + imports[i].getBundle() + ":" + imports[i].getName() + " -> NULL!!!"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
ResolverImpl.log(" (w) " + imports[i].getBundle() + ":" + imports[i].getName() + " -> " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- imports[i].getMatchingExport().getExporter() + ":" + imports[i].getMatchingExport().getName()); //$NON-NLS-1$
+ ((ResolverExport) imports[i].getSelectedSupplier()).getExporter() + ":" + imports[i].getSelectedSupplier().getName()); //$NON-NLS-1$
}
}
}
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImport.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImport.java
index 1e9919f78..848841ba6 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImport.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImport.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.osgi.internal.module;
-import java.util.ArrayList;
import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
import org.osgi.framework.Constants;
@@ -18,9 +17,6 @@ import org.osgi.framework.Constants;
* A companion to ImportPackageSpecification from the state used while resolving
*/
public class ResolverImport extends ResolverConstraint {
- private ResolverExport matchingExport;
- // Wires we know will cause the module to become unresolvable (due to grouping dependencies)
- private ArrayList unresolvableWirings = new ArrayList();
// only used for dynamic imports
private String name;
@@ -36,31 +32,6 @@ public class ResolverImport extends ResolverConstraint {
return ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(((ImportPackageSpecification) constraint).getDirective(Constants.RESOLUTION_DIRECTIVE));
}
- ResolverExport getMatchingExport() {
- return matchingExport;
- }
-
- void setMatchingExport(ResolverExport matchingExport) {
- this.matchingExport = matchingExport;
- }
-
- // Records an unresolvable wiring for this import (grouping dependencies)
- void addUnresolvableWiring(ResolverBundle exporter) {
- unresolvableWirings.add(exporter);
- }
-
- // Clear the list of all the unresovable wirings. This is called when we move
- // the module to UNRESOLVED so we can start from scratch if we ever try again
- void clearUnresolvableWirings() {
- unresolvableWirings = new ArrayList();
- }
-
- // Returns true if the supplied export has not been recorded as
- // an unresolvable wiring for this import
- boolean isNotAnUnresolvableWiring(ResolverExport exp) {
- return !unresolvableWirings.contains(exp.getExporter());
- }
-
public String getName() {
if (name != null)
return name; // return the required package set for a dynamic import

Back to the top