KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > internal > resolver > ResolverImpl


1 /*******************************************************************************
2  * Copyright (c) 2003, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.osgi.internal.resolver;
12
13 import java.util.*;
14 import org.eclipse.core.internal.dependencies.*;
15 import org.eclipse.osgi.service.resolver.*;
16 import org.osgi.framework.Bundle;
17
18 public class ResolverImpl implements Resolver {
19     private State state;
20     private DependencySystem dependencies;
21
22     public void resolve(BundleDescription[] reRefresh) {
23         // unresolving the given bundles will force them to be re-resolved
24
for (int i = 0; i < reRefresh.length; i++)
25             unresolveBundle(reRefresh[i]);
26         resolve();
27     }
28
29     /**
30      * TODO: need to devise a way to report problems (a la IStatus)
31      */

32     public synchronized void resolve() {
33         if (state == null)
34             throw new IllegalStateException JavaDoc("RESOLVER_NO_STATE"); //$NON-NLS-1$
35
if (dependencies == null)
36             dependencies = ResolverHelper.buildDependencySystem(state, new Eclipse30SelectionPolicy());
37         ResolutionDelta delta = null;
38         // try resolving as many times as necessary to remove all cycles
39
boolean success;
40         do {
41             success = true;
42             try {
43                 delta = dependencies.resolve();
44             } catch (DependencySystem.CyclicSystemException e) {
45                 success = false;
46                 Object JavaDoc[][] cycles = e.getCycles();
47                 // disable all element sets involved in the cycle
48
for (int i = 0; i < cycles.length; i++)
49                     for (int j = 0; j < cycles[i].length; j++)
50                         ((ElementSet) cycles[i][j]).removeFromCycle();
51             }
52         } while (!success);
53         processInnerDelta(delta);
54         resolvePackages();
55     }
56
57     public void setState(State newState) {
58         // to avoid infinite (mutual) recursion
59
if (state == newState)
60             return;
61         // if it was linked to a previous state, unlink first
62
if (state != null) {
63             State oldState = state;
64             state = null;
65             oldState.setResolver(null);
66         }
67         state = newState;
68         if (newState != null)
69             state.setResolver(this);
70         // forget any dependency state created before
71
flush();
72     }
73
74     /*
75      * Applies changes in the constraint system to the state object.
76      */

77     private void processInnerDelta(ResolutionDelta delta) {
78         // now apply changes reported in the inner delta to the state
79
ElementChange[] changes = delta.getAllChanges();
80         for (int i = 0; i < changes.length; i++) {
81             Element element = changes[i].getElement();
82             BundleDescription bundle = (BundleDescription) element.getUserObject();
83             int kind = changes[i].getKind();
84             if ((kind & ElementChange.RESOLVED) != 0) {
85                 state.resolveBundle(bundle, Bundle.RESOLVED);
86                 resolveConstraints(element);
87             } else if ((kind & ElementChange.UNRESOLVED) != 0)
88                 state.resolveBundle(bundle, Bundle.INSTALLED);
89             else if (kind == ElementChange.LINKAGE_CHANGED)
90                 resolveConstraints(element);
91         }
92     }
93
94     private void resolveConstraints(Element element) {
95         // tells the state that some of the constraints have
96
// changed
97
Dependency[] dependencies = element.getDependencies();
98         for (int j = 0; j < dependencies.length; j++) {
99             if (dependencies[j].getResolvedVersionId() == null)
100                 // an optional requisite that was not resolved
101
continue;
102             VersionConstraint constraint = (VersionConstraint) dependencies[j].getUserObject();
103             Version actualVersion = (Version) dependencies[j].getResolvedVersionId();
104             BundleDescription supplier = state.getBundle(constraint.getName(), actualVersion);
105             state.resolveConstraint(constraint, actualVersion, supplier);
106         }
107     }
108
109     public void bundleAdded(BundleDescription bundle) {
110         if (dependencies == null)
111             return;
112         ResolverHelper.add(bundle, dependencies);
113     }
114
115     public void bundleRemoved(BundleDescription bundle) {
116         if (dependencies == null)
117             return;
118         ResolverHelper.remove(bundle, dependencies);
119     }
120
121     public void bundleUpdated(BundleDescription newDescription, BundleDescription existingDescription) {
122         if (dependencies == null)
123             return;
124         ResolverHelper.update(newDescription, existingDescription, dependencies);
125     }
126
127     public State getState() {
128         return state;
129     }
130
131     public void flush() {
132         dependencies = null;
133     }
134
135     /*
136      * Ensures that all currently resolved bundles have their import-package
137      * clauses satisfied.
138      */

139     private boolean resolvePackages() {
140         /* attempt to resolve the proposed bundles */
141         Map availablePackages;
142         boolean success;
143         int tries = 0;
144         do {
145             tries++;
146             success = true;
147             BundleDescription[] initialBundles = state.getResolvedBundles();
148             availablePackages = new HashMap(11);
149             /* do all exports first */
150             for (int i = 0; i < initialBundles.length; i++) {
151                 PackageSpecification[] required = initialBundles[i].getPackages();
152                 for (int j = 0; j < required.length; j++)
153                     // override previously exported package if any (could
154
// preserve instead)
155
if (required[j].isExported()) {
156                         Version toExport = required[j].getVersionRange().getMinimum();
157                         PackageSpecification existing = (PackageSpecification) availablePackages.get(required[j].getName());
158                         Version existingVersion = existing == null ? null : existing.getVersionRange().getMinimum();
159                         if (existingVersion == null || (toExport != null && toExport.isGreaterThan(existingVersion)))
160                             availablePackages.put(required[j].getName(), required[j]);
161                     }
162             }
163             /* now try to resolve imported packages */
164             for (int i = 0; i < initialBundles.length; i++) {
165                 PackageSpecification[] required = initialBundles[i].getPackages();
166                 for (int j = 0; j < required.length; j++) {
167                     PackageSpecification exported = (PackageSpecification) availablePackages.get(required[j].getName());
168                     Version exportedVersion = exported == null ? null : exported.getVersionRange().getMinimum();
169                     if (exported == null || !required[j].isSatisfiedBy(exportedVersion)) {
170                         unresolveRequirementChain(initialBundles[i]);
171                         success = false;
172                         // one missing import is enough to discard this bundle
173
break;
174                     }
175                 }
176             }
177         } while (!success);
178         /* now bind the exports/imports */
179         BundleDescription[] resolvedBundles = state.getResolvedBundles();
180         for (int i = 0; i < resolvedBundles.length; i++) {
181             PackageSpecification[] required = resolvedBundles[i].getPackages();
182             for (int j = 0; j < required.length; j++) {
183                 PackageSpecification exported = (PackageSpecification) availablePackages.get(required[j].getName());
184                 state.resolveConstraint(required[j], exported.getVersionRange().getMinimum(), exported.getBundle());
185             }
186         }
187         /* return false if a at least one bundle was unresolved during this */
188         return tries > 1;
189     }
190
191     /*
192      * Unresolves a bundle and all bundles that require it.
193      */

194     private void unresolveRequirementChain(BundleDescription bundle) {
195         if (!bundle.isResolved())
196             return;
197         state.resolveBundle(bundle, Bundle.INSTALLED);
198         if (bundle.getSymbolicName() == null)
199             return;
200         ElementSet bundleElementSet = dependencies.getElementSet(bundle.getSymbolicName());
201         Collection requiring = bundleElementSet.getRequiringElements(bundle.getVersion());
202         for (Iterator requiringIter = requiring.iterator(); requiringIter.hasNext();) {
203             Element requiringElement = (Element) requiringIter.next();
204             BundleDescription requiringBundle = state.getBundle((String JavaDoc) requiringElement.getId(), (Version) requiringElement.getVersionId());
205             if (requiringBundle != null)
206                 unresolveRequirementChain(requiringBundle);
207         }
208     }
209
210     private void unresolveBundle(BundleDescription bundle) {
211         if (!bundle.isResolved())
212             return;
213         if (dependencies != null)
214             ResolverHelper.unresolve(bundle, dependencies);
215     }
216 }
Popular Tags