001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.views.dependencies;
011:
012: import java.util.HashMap;
013:
014: import org.eclipse.osgi.service.resolver.BaseDescription;
015: import org.eclipse.osgi.service.resolver.BundleDescription;
016: import org.eclipse.osgi.service.resolver.BundleSpecification;
017: import org.eclipse.osgi.service.resolver.ExportPackageDescription;
018: import org.eclipse.osgi.service.resolver.HostSpecification;
019: import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
020: import org.eclipse.pde.core.plugin.IPluginModelBase;
021: import org.osgi.framework.Constants;
022:
023: public class CalleesContentProvider extends
024: DependenciesViewPageContentProvider {
025: private BundleDescription fFragmentDescription;
026:
027: public CalleesContentProvider(DependenciesView view) {
028: super (view);
029: }
030:
031: protected Object[] findCallees(IPluginModelBase model) {
032: BundleDescription desc = model.getBundleDescription();
033: if (desc == null)
034: return new Object[0];
035: fFragmentDescription = null;
036: HostSpecification spec = desc.getHost();
037: if (spec != null) {
038: fFragmentDescription = desc;
039: Object[] fragmentDependencies = getDependencies(desc);
040: BaseDescription host = spec.getSupplier();
041: if (host instanceof BundleDescription) {
042: BundleDescription hostDesc = (BundleDescription) host;
043: // check to see if the host is already included as a dependency. If so, we don't need to include the host manually.
044: for (int i = 0; i < fragmentDependencies.length; i++) {
045: BundleDescription dependency = null;
046: if (fragmentDependencies[i] instanceof BundleSpecification)
047: dependency = ((BundleSpecification) fragmentDependencies[i])
048: .getBundle();
049: else if (fragmentDependencies[i] instanceof ImportPackageSpecification) {
050: ExportPackageDescription epd = (ExportPackageDescription) ((ImportPackageSpecification) fragmentDependencies[i])
051: .getSupplier();
052: if (epd != null)
053: dependency = epd.getSupplier();
054: }
055: if (dependency != null
056: && dependency.equals(hostDesc))
057: return fragmentDependencies;
058: }
059:
060: // host not included as dependency, include it manually.
061: Object[] result = new Object[fragmentDependencies.length + 1];
062: result[0] = hostDesc;
063: System.arraycopy(fragmentDependencies, 0, result, 1,
064: fragmentDependencies.length);
065: return result;
066: }
067: return fragmentDependencies;
068: }
069: return getDependencies(desc);
070: }
071:
072: protected Object[] findCallees(BundleDescription desc) {
073: if (desc == null)
074: return new Object[0];
075: return getDependencies(desc);
076: }
077:
078: private Object[] getDependencies(BundleDescription desc) {
079: // use map to store dependencies so if Import-Package is supplied by same BundleDescription as supplier of Require-Bundle, it only shows up once
080: // Also, have to use BundleSpecficiation instead of BundleDescroption to show re-exported icon on re-exported Required-Bundles
081: // Have to use ImportPackageSpecification to determine if an import is optional and should be filtered.
082: HashMap dependencies = new HashMap();
083: BundleSpecification[] requiredBundles = desc
084: .getRequiredBundles();
085: for (int i = 0; i < requiredBundles.length; i++) {
086: BaseDescription bd = requiredBundles[i].getSupplier();
087: if (bd != null)
088: dependencies.put(bd, requiredBundles[i]);
089: else
090: dependencies
091: .put(requiredBundles[i], requiredBundles[i]);
092: }
093: ImportPackageSpecification[] importedPkgs = desc
094: .getImportPackages();
095: for (int i = 0; i < importedPkgs.length; i++) {
096: BaseDescription bd = importedPkgs[i].getSupplier();
097: if (bd != null && bd instanceof ExportPackageDescription) {
098: BundleDescription exporter = ((ExportPackageDescription) bd)
099: .getExporter();
100: if (exporter != null) {
101: Object obj = dependencies.get(exporter);
102: if (obj == null) {
103: dependencies.put(exporter, importedPkgs[i]);
104: } else if (!Constants.RESOLUTION_OPTIONAL
105: .equals(importedPkgs[i]
106: .getDirective(Constants.RESOLUTION_DIRECTIVE))
107: && obj instanceof ImportPackageSpecification
108: && Constants.RESOLUTION_OPTIONAL
109: .equals(((ImportPackageSpecification) obj)
110: .getDirective(Constants.RESOLUTION_DIRECTIVE))) {
111: // if we have a non-optional Import-Package dependency on a bundle which we already depend on, check to make sure our
112: // current dependency is not optional. If it is, replace the optional dependency with the non-optional one
113: dependencies.put(exporter, importedPkgs[i]);
114: }
115: }
116: }
117: // ignore unresolved packages
118: }
119: // include fragments which are "linked" to this bundle
120: BundleDescription frags[] = desc.getFragments();
121: for (int i = 0; i < frags.length; i++) {
122: if (!frags[i].equals(fFragmentDescription))
123: dependencies.put(frags[i], frags[i]);
124: }
125: return dependencies.values().toArray();
126: }
127:
128: }
|