blob: a9aef9c5ee3f58e43667dda422c43524422c5249 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.module;
import java.util.ArrayList;
import java.util.HashMap;
public class GroupingChecker {
HashMap constraints = new HashMap();
void addConstraint(ResolverExport constrained, ResolverExport constraint) {
ArrayList list = (ArrayList) constraints.get(constrained);
if (list == null) {
list = new ArrayList();
constraints.put(constrained, list);
}
if (!list.contains(constraint))
list.add(constraint);
}
private void addConstraints(ResolverExport constrained, ArrayList newConstraints) {
ArrayList list = (ArrayList) constraints.get(constrained);
if (list == null) {
constraints.put(constrained, newConstraints);
} else {
for (int i = 0; i < newConstraints.size(); i++) {
ResolverExport exp = (ResolverExport) newConstraints.get(i);
if (!list.contains(exp))
list.add(newConstraints.get(i));
}
}
}
void removeConstraint(ResolverExport constrained, ResolverExport constraint) {
ArrayList list = (ArrayList) constraints.get(constrained);
if (list == null)
return;
list.remove(constraint);
}
void removeAllConstraints(ResolverExport constrained) {
constraints.put(constrained, null);
}
ResolverExport isConsistent(ResolverImport imp, ResolverExport exp) {
// Check imports are consistent
ResolverImport[] imports = imp.getBundle().getImportPackages();
BundleConstraint[] requires = imp.getBundle().getRequires();
for (int i = 0; i < imports.length; i++) {
// Check new wiring against constraints from previous wirings
ResolverExport wire = imports[i].getMatchingExport();
if (wire == null)
continue;
ArrayList list = (ArrayList) constraints.get(wire);
if (list != null) {
for (int j = 0; j < list.size(); j++) {
ResolverExport re = (ResolverExport) list.get(j);
if (re.isDropped())
continue;
if (re.getExporter().isResolvable() && exp.getName().equals(re.getName()) && !imp.isOnRootPath(re.getExporter()) && !imp.isOnRootPathSplit(imp.getMatchingExport().getExporter(), re.getExporter()))
return wire;
}
}
// Check previous wirings against constraints from new wiring
list = (ArrayList) constraints.get(exp);
if (list != null) {
for (int j = 0; j < list.size(); j++) {
ResolverExport re = (ResolverExport) list.get(j);
if (re.isDropped())
continue;
if (re.getExporter().isResolvable() && wire.getName().equals(re.getName()) && !imports[i].isOnRootPath(re.getExporter()) && !imp.isOnRootPathSplit(imp.getMatchingExport().getExporter(), re.getExporter()))
return wire;
// Check against requires
for (int k = 0; k < requires.length; k++) {
if (requires[k].getMatchingBundle() == null)
continue;
ResolverExport[] exports = requires[k].getMatchingBundle().getExportPackages();
for (int m = 0; m < exports.length; m++) {
if (re.getExporter().isResolvable() && exports[m].getName().equals(re.getName()) && !exports[m].isOnRootPath(re.getExporter()))
return re;
}
}
}
}
// Check against requires (split packages)
for (int j = 0; j < requires.length; j++) {
ResolverBundle matchingBundle = requires[j].getMatchingBundle();
if (matchingBundle == null)
continue;
ResolverExport[] exports = matchingBundle.getExportPackages();
for (int k = 0; k < exports.length; k++) {
if (imports[i].getName().equals(exports[k].getName()) && imports[i].getMatchingExport() != exports[k])
return imports[i].getMatchingExport();
}
}
}
// Check imports against requires
for (int i = 0; i < requires.length; i++) {
if (requires[i].getMatchingBundle() == null)
continue;
ResolverExport[] exports = requires[i].getMatchingBundle().getExportPackages();
for (int j = 0; j < exports.length; j++) {
ArrayList list = (ArrayList) constraints.get(exports[j]);
if (list != null) {
for (int k = 0; k < list.size(); k++) {
ResolverExport re = (ResolverExport) list.get(k);
if (re.getExporter().isResolvable() && exp.getName().equals(re.getName()) && !imp.isOnRootPath(re.getExporter()))
return re;
}
}
}
}
// No clash, so return null
return null;
}
boolean checkRequiresConstraints(ResolverBundle bundle) {
BundleConstraint[] requires = bundle.getRequires();
if (requires == null)
return true;
for (int i = 0; i < requires.length; i++) {
ResolverBundle matchingBundle = requires[i].getMatchingBundle();
if (matchingBundle == null)
continue;
ResolverExport[] exports = matchingBundle.getExportPackages();
for (int j = 0; j < exports.length; j++) {
ArrayList list = (ArrayList) constraints.get(exports[j]);
if (list == null)
continue;
for (int k = 0; k < list.size(); k++) {
ResolverExport constraint = (ResolverExport) list.get(k);
boolean foundPotential = false;
boolean found = false;
for (int m = 0; m < requires.length; m++) {
if (requires[m].getMatchingBundle() == null)
continue;
ResolverExport[] exps = requires[m].getMatchingBundle().getExportPackages();
for (int n = 0; n < exps.length; n++) {
if (constraint.getExporter().isResolvable() && constraint.getName().equals(exps[n].getName())) {
foundPotential = true;
if (exps[n] == constraint || exps[n].isOnRootPath(constraint.getExporter())) {
found = true;
break;
}
}
}
if (found)
break;
}
if (foundPotential && !found) {
return false;
}
}
}
}
return true;
}
// Add basic 'uses' constraints
void addInitialGroupingConstraints(ResolverBundle[] bundles) {
for (int i = 0; i < bundles.length; i++) {
ResolverExport[] exports = bundles[i].getExportPackages();
for (int j = 0; j < exports.length; j++) {
String[] uses = exports[j].getUses();
if (uses == null)
continue;
for (int k = 0; k < uses.length; k++) {
ResolverExport exp = bundles[i].getExport(uses[k]);
if (exp == null)
continue;
addConstraint(exports[j], exp);
addTransitiveGroupingConstraints(exports[j], exp);
}
}
}
}
// Add constraints from other exports (due to 'uses' being transitive)
private void addTransitiveGroupingConstraints(ResolverExport export, ResolverExport constraint) {
if (export == constraint)
return;
String[] uses = constraint.getUses();
if (uses == null)
return;
for (int i = 0; i < uses.length; i++) {
ResolverExport exp = export.getExporter().getExport(uses[i]);
if (exp == null || exp == constraint)
continue;
// Check if the constraint has already been added so
// we don't recurse infinitely
ArrayList list = (ArrayList) constraints.get(export);
if (list.contains(exp))
continue;
addConstraint(export, exp);
addTransitiveGroupingConstraints(export, exp);
}
}
// Add root constraints to re-exports
void addReExportConstraints(ResolverBundle bundle) {
ResolverExport[] exports = bundle.getExportPackages();
for (int i = 0; i < exports.length; i++) {
if (exports[i].getExportPackageDescription().isRoot())
continue;
ResolverExport root = exports[i].getRoot();
if (root == null)
continue;
ArrayList list = (ArrayList) constraints.get(root);
if (list == null)
continue;
addConstraints(exports[i], list);
}
}
// Add constraints to exports that 'use' imports
void addImportConstraints(ResolverBundle bundle) {
ResolverExport[] exports = bundle.getExportPackages();
for (int i = 0; i < exports.length; i++) {
String[] uses = exports[i].getUses();
if (uses == null)
continue;
for (int j = 0; j < uses.length; j++) {
ResolverImport imp = bundle.getImport(uses[j]);
if (imp == null)
continue;
ResolverExport root = imp.getRoot();
if (root == null)
continue;
addConstraint(exports[i], root);
}
}
}
// Add constraints to re-rexports (via a require)
void addRequireConstraints(ResolverExport[] exports, ResolverBundle bundle) {
BundleConstraint[] requires = bundle.getRequires();
for (int i = 0; i < exports.length; i++) {
if (exports[i].getExportPackageDescription().isRoot())
continue;
for (int j = 0; j < requires.length; j++) {
if (requires[j].getMatchingBundle() == null || exports[i].getExporter() == requires[j].getMatchingBundle())
continue;
ResolverExport[] requireExports = requires[j].getMatchingBundle().getExportPackages();
for (int k = 0; k < requireExports.length; k++) {
if (!exports[i].getName().equals(requireExports[k].getName()))
continue;
ArrayList list = (ArrayList) constraints.get(requireExports[k]);
if (list == null)
continue;
for (int m = 0; m < list.size(); m++) {
addConstraint(exports[i], (ResolverExport) list.get(m));
}
}
}
}
}
// Add constraints for reprovided exports
void addReprovideConstraints(ResolverExport re) {
BundleConstraint[] requires = re.getExporter().getRequires();
for (int i = 0; i < requires.length; i++) {
if (requires[i].getMatchingBundle() == null)
return;
ResolverExport[] requireExports = requires[i].getMatchingBundle().getExportPackages();
for (int j = 0; j < requireExports.length; j++) {
if (!re.getName().equals(requireExports[j].getName()))
continue;
ArrayList list = (ArrayList) constraints.get(requireExports[j]);
if (list == null)
continue;
for (int k = 0; k < list.size(); k++) {
addConstraint(re, (ResolverExport) list.get(k));
}
}
}
}
}