blob: e3cc01e879862199bb38c18572269266e35cd7c5 [file] [log] [blame]
/*******************************************************************************
* Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC,
* Canada. 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: The Chisel Group, University of Victoria IBM CAS, IBM Toronto
* Lab
******************************************************************************/
package org.eclipse.pde.internal.visualization.dependency.views;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.BundleSpecification;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
/**
* General utility classes for dealing with bundle dependencies.
* @author Ian Bull
*
*/
public class AnalysisUtil {
public static Object[] getPath(Object root, Object bundle) {
LinkedList q = new LinkedList();
Set orderedSet = new HashSet();
LinkedList orderedList = new LinkedList();
q.add(root);
while (!q.isEmpty()) {
Object head = q.remove(0);
if (!orderedSet.contains(head)) {
orderedSet.add(head);
orderedList.add(head);
buildQueue(head, q);
}
}
Object[] path = modifiedDijkstra(orderedList, root, bundle);
return path;
}
private static void buildQueue(Object root, LinkedList q) {
Object[] descriptions = getDependencies(root);
if (descriptions == null || descriptions.length == 0) {
return;
}
for (int i = 0; i < descriptions.length; i++) {
q.add(descriptions[i]);
}
}
public static Object[] modifiedDijkstra(LinkedList q, Object s, Object t) {
HashMap previous = new HashMap();
HashMap dValues = new HashMap();
for (Iterator iter = q.iterator(); iter.hasNext();) {
dValues.put(iter.next(), new Integer(Integer.MAX_VALUE / 10));
}
dValues.put(s, new Integer(0));
while (!q.isEmpty()) {
Object head = q.remove(0);
Object[] outgoing = getDependencies(head);
if (outgoing == null) {
// @tag PDE bug : I get null in my array of dependencies
continue;
}
for (int i = 0; i < outgoing.length; i++) {
Object v = outgoing[i];
if (((Integer) dValues.get(head)).intValue() + 1 < ((Integer) dValues.get(v)).intValue()) {
previous.put(v, head);
dValues.put(v, new Integer(((Integer) dValues.get(head)).intValue() + 1));
}
}
}
LinkedList path = new LinkedList();
Object currentNode = t;
while (previous.containsKey(currentNode)) {
path.add(currentNode);
currentNode = previous.get(currentNode);
}
path.add(currentNode);
return path.toArray(new Object[path.size()]);
}
public static BundleDescription[] getCallers(BundleDescription bundle, BundleDescription[] bundles) {
HashSet callers = new HashSet();
for (int i = 0; i < bundles.length; i++) {
HashSet hashSet = new HashSet();
hashSet.addAll(Arrays.asList(getDependencies(bundles[i])));
if (hashSet.contains(bundle)) {
callers.add(bundles[i]);
}
}
return (BundleDescription[]) callers.toArray(new BundleDescription[callers.size()]);
}
/**
* Finds all the callers for bundle within bunldes[]
*
* @return
*/
public static Object[] getAllCallers(Object bundle, Object[] bundles) {
HashSet callers = new HashSet();
for (int i = 0; i < bundles.length; i++) {
HashSet hashSet = new HashSet();
hashSet.addAll(Arrays.asList(getPrerequisites(new Object[] { bundles[i] })));
if (hashSet.contains(bundle)) {
callers.add(bundles[i]);
}
}
return callers.toArray(new Object[callers.size()]);
}
public static Object[] getPrerequisites(Object[] bundles) {
if (bundles == null || bundles.length == 0) {
return new BundleDescription[0];
}
Set reachable = new HashSet(bundles.length);
for (int i = 0; i < bundles.length; i++) {
addPrerequisites(bundles[i], reachable);
}
return reachable.toArray(new Object[reachable.size()]);
}
private static Collection getExportedDescription(BundleDescription element, ExportPackageDescription[] exportedPackages) {
Set descriptionList = new HashSet();
for (int i = 0; i < exportedPackages.length; i++) {
ExportPackageDescription exportedPackage = exportedPackages[i];
if (!element.getLocation().equals(exportedPackage.getExporter().getLocation())) {
descriptionList.add(exportedPackage.getExporter());
}
}
return descriptionList;
}
public static Object[] getDependencies(Object bundle) {
if (bundle == null || bundle instanceof BundleSpecification) {
return new Object[0];
}
BundleDescription bundleDescription = (BundleDescription) bundle;
Collection c = AnalysisUtil.getDescription(bundleDescription.getRequiredBundles());
c.addAll(getExportedDescription(bundleDescription, bundleDescription.getResolvedImports()));
if (bundleDescription.getHost() != null) {
c.add(bundleDescription.getHost().getSupplier());
}
/*
* Iterator iterator = c.iterator(); while (iterator.hasNext() ) { if (
* iterator.next() == null ) iterator.remove(); }
*/
return c.toArray(new Object[c.size()]);
}
private static void addPrerequisites(Object bundle, Set reachable) {
if (reachable.contains(bundle)) {
return;
}
reachable.add(bundle);
Object[] dependencies = getDependencies(bundle);
for (int i = 0; i < dependencies.length; i++) {
if (dependencies[i] instanceof BundleSpecification ) {
reachable.add(dependencies[i]);
}
else {
addPrerequisites(dependencies[i], reachable);
}
}
}
public static Collection getDescription(BundleSpecification[] specifications) {
ArrayList descriptionList = new ArrayList();
for (int i = 0; i < specifications.length; i++) {
BundleSpecification specification = specifications[i];
if ( specification.getSupplier() == null ) {
// We can't get a description, so just keep the bundle specification
descriptionList.add(specification);
}
else {
descriptionList.add(specification.getSupplier());
}
}
return descriptionList;
}
}