00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 package org.knopflerfish.framework;
00036
00037 import java.util.*;
00038
00039 import org.osgi.framework.*;
00040
00041
00048 class Packages {
00049
00053 final Framework framework;
00054
00058 private Hashtable packages = new Hashtable();
00059
00063 private HashSet tempResolved = null;
00064
00068 private HashMap tempProvider = null;
00069
00073 private HashMap tempRequired = null;
00074
00078 private HashSet tempBlackList = null;
00079
00083 private HashSet tempBackTracked = null;
00084
00085
00086 int tempBlackListChecks = 0;
00087 int tempBlackListHits = 0;
00088
00089
00093 Packages(Framework fw) {
00094 framework = fw;
00095 }
00096
00097
00105 synchronized void registerPackages(Iterator exports, Iterator imports) {
00106 while (exports.hasNext()) {
00107 ExportPkg pe = (ExportPkg)exports.next();
00108 Pkg p = (Pkg)packages.get(pe.name);
00109 if (p == null) {
00110 p = new Pkg(pe.name);
00111 packages.put(pe.name, p);
00112 }
00113 p.addExporter(pe);
00114 if (Debug.packages) {
00115 Debug.println("registerPackages: export, " + pe);
00116 }
00117 }
00118 while (imports.hasNext()) {
00119 ImportPkg pe = (ImportPkg)imports.next();
00120 Pkg p = (Pkg)packages.get(pe.name);
00121 if (p == null) {
00122 p = new Pkg(pe.name);
00123 packages.put(pe.name, p);
00124 }
00125 p.addImporter(pe);
00126 if (Debug.packages) {
00127 Debug.println("registerPackages: import, " + pe);
00128 }
00129 }
00130 }
00131
00132
00139 synchronized ExportPkg registerDynamicImport(ImportPkg ip) {
00140 if (Debug.packages) {
00141 Debug.println("registerDynamicImport: try " + ip);
00142 }
00143 ExportPkg res = null;
00144 Pkg p = (Pkg)packages.get(ip.name);
00145 if (p != null) {
00146 tempResolved = new HashSet();
00147 tempProvider = new HashMap();
00148 tempRequired = new HashMap();
00149 tempBlackList = new HashSet();
00150 tempBackTracked = new HashSet();
00151 backTrackUses(ip);
00152 tempBackTracked = null;
00153 ArrayList pkgs = new ArrayList(1);
00154 pkgs.add(ip);
00155 p.addImporter(ip);
00156 List r = resolvePackages(pkgs.iterator());
00157 tempBlackList = null;
00158 if (r.size() == 0) {
00159 registerNewProviders(ip.bpkgs.bundle);
00160 res = (ExportPkg)tempProvider.get(ip.name);
00161 ip.provider = res;
00162 } else {
00163 p.removeImporter(ip);
00164 }
00165 tempProvider = null;
00166 tempRequired = null;
00167 tempResolved = null;
00168 }
00169 if (Debug.packages) {
00170 Debug.println("registerDynamicImport: Done for " + ip.name + ", res = " + res);
00171 }
00172 return res;
00173 }
00174
00175
00188 synchronized boolean unregisterPackages(List exports, List imports, boolean force) {
00189
00190 if (!force) {
00191 for (Iterator i = exports.iterator(); i.hasNext(); ) {
00192 ExportPkg ep = (ExportPkg)i.next();
00193 Pkg p = ep.pkg;
00194 if (p.providers.contains(ep)) {
00195 for (Iterator ii = p.importers.iterator(); ii.hasNext(); ) {
00196 ImportPkg ip = (ImportPkg) ii.next();
00197 if (ep == ip.provider && ep.bpkgs != ip.bpkgs) {
00198 if (Debug.packages) {
00199 Debug.println("unregisterPackages: Failed to unregister, " + ep +
00200 " is still in use.");
00201 }
00202 markAsZombies(exports);
00203 return false;
00204 }
00205 }
00206 }
00207 }
00208 }
00209
00210 for (Iterator i = exports.iterator(); i.hasNext(); ) {
00211 ExportPkg ep = (ExportPkg)i.next();
00212 Pkg p = ep.pkg;
00213 if (Debug.packages) {
00214 Debug.println("unregisterPackages: unregister export - " + ep);
00215 }
00216 p.removeExporter(ep);
00217 if (p.isEmpty()) {
00218 packages.remove(ep.name);
00219 }
00220 }
00221
00222 for (Iterator i = imports.iterator(); i.hasNext(); ) {
00223 ImportPkg ip = (ImportPkg)i.next();
00224 Pkg p = ip.pkg;
00225 if (Debug.packages) {
00226 Debug.println("unregisterPackages: unregister import - " + ip.pkgString());
00227 }
00228 p.removeImporter(ip);
00229 if (p.isEmpty()) {
00230 packages.remove(ip.name);
00231 }
00232 }
00233 return true;
00234 }
00235
00236
00244 synchronized String resolve(BundleImpl bundle, Iterator pkgs) {
00245 String res;
00246 if (Debug.packages) {
00247 Debug.println("resolve: " + bundle);
00248 }
00249
00250
00251 if (tempResolved != null) {
00252 if (!tempResolved.contains(bundle)) {
00253 framework.listeners.frameworkError(bundle,
00254 new Exception("resolve: InternalError1!"));
00255 }
00256 return null;
00257 }
00258
00259 tempResolved = new HashSet();
00260 BundleImpl sb = checkBundleSingleton(bundle);
00261 if (sb != null) {
00262 tempResolved = null;
00263 return "Singleton bundle failed to resolve because " + sb + " is already resolved";
00264 }
00265
00266 tempProvider = new HashMap();
00267 tempRequired = new HashMap();
00268 tempBlackList = new HashSet();
00269 tempResolved.add(bundle);
00270 String br = checkRequireBundle(bundle);
00271 if (br == null) {
00272 List failed = resolvePackages(pkgs);
00273 if (failed.size() == 0) {
00274 registerNewProviders(bundle);
00275 res = null;
00276 } else {
00277 StringBuffer r = new StringBuffer("missing package(s) or can not resolve all of the them: ");
00278 Iterator mi = failed.iterator();
00279 r.append(((ImportPkg)mi.next()).pkgString());
00280 while (mi.hasNext()) {
00281 r.append(", ");
00282 r.append(((ImportPkg)mi.next()).pkgString());
00283 }
00284 res = r.toString();
00285 }
00286 } else {
00287 res = "Failed to resolve required bundle or host: " + br;
00288 }
00289 tempResolved = null;
00290 tempProvider = null;
00291 tempRequired = null;
00292 tempBlackList = null;
00293 if (Debug.packages) {
00294 Debug.println("resolve: Done for " + bundle);
00295 }
00296 return res;
00297 }
00298
00299
00306 Pkg getPkg(String pkg) {
00307 return (Pkg)packages.get(pkg);
00308 }
00309
00310
00326 synchronized Collection getZombieAffected(Bundle [] bundles) {
00327
00328 TreeSet affected = new TreeSet(new Comparator() {
00329 public int compare(Object o1, Object o2) {
00330 BundleImpl b1 = (BundleImpl)o1;
00331 BundleImpl b2 = (BundleImpl)o2;
00332 int dif = b1.getStartLevel() - b2.getStartLevel();
00333 if (dif == 0) {
00334 dif = (int)(b1.getBundleId() - b2.getBundleId());
00335 }
00336 return dif;
00337 }
00338 public boolean equals(Object o) {
00339 return ((o != null) && getClass().equals(o.getClass()));
00340 }
00341 });
00342 if (bundles == null) {
00343 if (Debug.packages) {
00344 Debug.println("getZombieAffected: check - null");
00345 }
00346 for (Iterator i = packages.values().iterator(); i.hasNext();) {
00347 Pkg p = (Pkg)i.next();
00348 for (Iterator ps = p.providers.iterator(); ps.hasNext(); ) {
00349 ExportPkg ep = (ExportPkg)ps.next();
00350 if (ep.zombie) {
00351 if (Debug.packages) {
00352 Debug.println("getZombieAffected: found zombie - " + ep.bpkgs.bundle);
00353 }
00354 affected.add(ep.bpkgs.bundle);
00355 }
00356 }
00357 }
00358 } else {
00359 for (int i = 0; i < bundles.length; i++) {
00360 if (bundles[i] != null) {
00361 if (Debug.packages) {
00362 Debug.println("getZombieAffected: check - " + bundles[i]);
00363 }
00364 BundleImpl tmp = (BundleImpl)bundles[i];
00365
00366 if (tmp.isFragment() &&
00367 tmp.isAttached() &&
00368 !affected.contains(tmp.getFragmentHost())) {
00369 affected.add(tmp.getFragmentHost());
00370 } else {
00371 affected.add(bundles[i]);
00372 }
00373 }
00374 }
00375 }
00376 ArrayList moreBundles = new ArrayList(affected);
00377 for (int i = 0; i < moreBundles.size(); i++) {
00378 BundleImpl b = (BundleImpl)moreBundles.get(i);
00379 for (Iterator j = b.getExports(); j.hasNext(); ) {
00380 ExportPkg ep = (ExportPkg)j.next();
00381 if (ep.pkg != null && ep.pkg.providers.contains(ep)) {
00382 for (Iterator k = ep.getPackageImporters().iterator(); k.hasNext(); ) {
00383 Bundle ib = (Bundle)k.next();
00384 if (!affected.contains(ib)) {
00385 moreBundles.add(ib);
00386 if (Debug.packages) {
00387 Debug.println("getZombieAffected: added - " + ib);
00388 }
00389 affected.add(ib);
00390 }
00391 }
00392 }
00393 }
00394 }
00395 return affected;
00396 }
00397
00398
00399
00400
00401
00411 private boolean backTrackUses(ImportPkg ip) {
00412 if (Debug.packages) {
00413 Debug.println("backTrackUses: check - " + ip.pkgString());
00414 }
00415 if (tempBackTracked.contains(ip.bpkgs)) {
00416 return false;
00417 }
00418 tempBackTracked.add(ip.bpkgs);
00419 Iterator i = getPackagesProvidedBy(ip.bpkgs).iterator();
00420 if (i.hasNext()) {
00421 do {
00422 ExportPkg ep = (ExportPkg)i.next();
00423 boolean foundUses = false;
00424 for (Iterator ii = ep.pkg.importers.iterator(); ii.hasNext(); ) {
00425 ImportPkg iip = (ImportPkg)ii.next();
00426 if (iip.provider == ep) {
00427 if (backTrackUses(iip)) {
00428 foundUses = true;
00429 }
00430 }
00431 }
00432 if (!foundUses) {
00433 checkUses(ep);
00434 }
00435 } while (i.hasNext());
00436 return true;
00437 } else {
00438 return false;
00439 }
00440 }
00441
00442
00448 private void markAsZombies(List exports) {
00449 for (Iterator i = exports.iterator(); i.hasNext();) {
00450 ((ExportPkg)i.next()).zombie = true;
00451 }
00452 }
00453
00454
00461 private Collection getPackagesProvidedBy(BundlePackages bpkgs) {
00462 ArrayList res = new ArrayList();
00463
00464 for (Iterator i = bpkgs.getExports(); i.hasNext();) {
00465 ExportPkg ep = (ExportPkg) i.next();
00466 if (ep.pkg.providers.contains(ep)) {
00467 res.add(ep);
00468 }
00469 }
00470 return res;
00471 }
00472
00473
00480 private List resolvePackages(Iterator pkgs) {
00481 ArrayList res = new ArrayList();
00482
00483 while (pkgs.hasNext()) {
00484 ExportPkg provider = null;
00485 ImportPkg ip = (ImportPkg)pkgs.next();
00486 if (ip.provider != null) {
00487 framework.listeners.frameworkError(ip.bpkgs.bundle,
00488 new Exception("resolvePackages: InternalError1!"));
00489 }
00490 if (Debug.packages) {
00491 Debug.println("resolvePackages: check - " + ip.pkgString());
00492 }
00493 provider = (ExportPkg)tempProvider.get(ip.name);
00494 if (provider != null) {
00495 if (Debug.packages) {
00496 Debug.println("resolvePackages: " + ip.name + " - has temporary provider - "
00497 + provider);
00498 }
00499 if (provider.zombie && provider.bpkgs.bundle.state == Bundle.UNINSTALLED) {
00500 if (Debug.packages) {
00501 Debug.println("resolvePackages: " + ip.name +
00502 " - provider not used since it is an uninstalled zombie - "
00503 + provider);
00504 }
00505 provider = null;
00506 } else if (!ip.okPackageVersion(provider.version)) {
00507 if (Debug.packages) {
00508 Debug.println("resolvePackages: " + ip.name +
00509 " - provider has wrong version - " + provider +
00510 ", need " + ip.packageRange + ", has " + provider.version);
00511 }
00512 provider = null;
00513 }
00514 } else {
00515 for (Iterator i = ip.pkg.providers.iterator(); i.hasNext(); ) {
00516 ExportPkg ep = (ExportPkg)i.next();
00517 tempBlackListChecks++;
00518 if (tempBlackList.contains(ep)) {
00519 tempBlackListHits++;
00520 continue;
00521 }
00522 if (ep.zombie) {
00523
00524 continue;
00525 }
00526 if (ip.okPackageVersion(ep.version)) {
00527 if (Debug.packages) {
00528 Debug.println("resolvePackages: " + ip.name + " - has provider - " + ep);
00529 }
00530 HashMap oldTempProvider = (HashMap)tempProvider.clone();
00531 if (!checkUses(ep)) {
00532 tempProvider = oldTempProvider;
00533 tempBlackList.add(ep);
00534 continue;
00535 }
00536 provider = ep;
00537 break;
00538 }
00539 }
00540 if (provider == null) {
00541 provider = pickProvider(ip);
00542 }
00543 if (provider != null) {
00544 tempProvider.put(ip.pkg.pkg, provider);
00545 }
00546 }
00547 if (provider == null) {
00548 if (ip.resolution == Constants.RESOLUTION_MANDATORY) {
00549 res.add(ip);
00550 } else {
00551 if (Debug.packages) {
00552 Debug.println("resolvePackages: Ok, no provider for optional " + ip.name);
00553 }
00554 }
00555 }
00556 }
00557 return res;
00558 }
00559
00560
00567 private ExportPkg pickProvider(ImportPkg ip) {
00568 if (Debug.packages) {
00569 Debug.println("pickProvider: for - " + ip);
00570 }
00571 ExportPkg provider = null;
00572 for (Iterator i = ip.pkg.exporters.iterator(); i.hasNext(); ) {
00573 ExportPkg ep = (ExportPkg)i.next();
00574 tempBlackListChecks++;
00575 if (tempBlackList.contains(ep)) {
00576 tempBlackListHits++;
00577 continue;
00578 }
00579 if (!checkAttributes(ep, ip)) {
00580 if (Debug.packages) {
00581 Debug.println("pickProvider: attribute match failed for - " + ep);
00582 }
00583 continue;
00584 }
00585 if (tempResolved.contains(ep.bpkgs.bundle)) {
00586 provider = ep;
00587 break;
00588 }
00589 if ((ep.bpkgs.bundle.state & BundleImpl.RESOLVED_FLAGS) != 0) {
00590 HashMap oldTempProvider = (HashMap)tempProvider.clone();
00591 if (checkUses(ep)) {
00592 provider = ep;
00593 break;
00594 } else {
00595 tempProvider = oldTempProvider;
00596 tempBlackList.add(ep);
00597 continue;
00598 }
00599 }
00600 if (ep.bpkgs.bundle.state == Bundle.INSTALLED && checkResolve(ep.bpkgs.bundle)) {
00601 provider = ep;
00602 break;
00603 }
00604 }
00605 if (Debug.packages) {
00606 if (provider != null) {
00607 Debug.println("pickProvider: " + ip + " - got provider - " + provider);
00608 } else {
00609 Debug.println("pickProvider: " + ip + " - found no provider");
00610 }
00611 }
00612 return provider;
00613 }
00614
00615
00623 private boolean checkAttributes(ExportPkg ep, ImportPkg ip) {
00624
00625 if (!ip.checkMandatory(ep.mandatory)) {
00626 return false;
00627 }
00628
00629 if (!ip.okPackageVersion(ep.version) ||
00630 (ip.bundleSymbolicName != null &&
00631 !ip.bundleSymbolicName.equals(ep.bpkgs.bundle.symbolicName)) ||
00632 !ip.bundleRange.withinRange(ep.bpkgs.bundle.version)) {
00633 return false;
00634 }
00635
00636 for (Iterator i = ip.attributes.entrySet().iterator(); i.hasNext(); ) {
00637 Map.Entry e = (Map.Entry)i.next();
00638 String a = (String)ep.attributes.get(e.getKey());
00639 if (a == null || !a.equals(e.getValue())) {
00640 return false;
00641 }
00642 }
00643 return true;
00644 }
00645
00646
00655 private boolean checkResolve(BundleImpl b) {
00656 ArrayList okImports = new ArrayList();
00657 if (framework.perm.missingMandatoryPackagePermissions(b.bpkgs, okImports) == null &&
00658 checkBundleSingleton(b) == null) {
00659 HashSet oldTempResolved = (HashSet)tempResolved.clone();
00660 HashMap oldTempProvider = (HashMap)tempProvider.clone();
00661 HashMap oldTempRequired = (HashMap)tempRequired.clone();
00662 HashSet oldTempBlackList = (HashSet)tempBlackList.clone();
00663 tempResolved.add(b);
00664 if (checkRequireBundle(b) == null) {
00665 List r = resolvePackages(okImports.iterator());
00666 if (r.size() == 0) {
00667 return true;
00668 }
00669 }
00670 tempResolved = oldTempResolved;
00671 tempProvider = oldTempProvider;
00672 tempRequired = oldTempRequired;
00673 tempBlackList = oldTempBlackList;
00674 }
00675 return false;
00676 }
00677
00678
00687 private boolean checkUses(ExportPkg pkg) {
00688 Iterator ui = null;
00689 String next_uses = null;
00690 if (Debug.packages) {
00691 Debug.println("checkUses: check if packages used by " + pkg + " is okay.");
00692 }
00693 if (pkg.uses != null) {
00694 ui = pkg.uses.iterator();
00695 if (ui.hasNext()) {
00696 next_uses = (String)ui.next();
00697 }
00698 }
00699 if (Debug.packages) {
00700 Debug.println("checkUses: provider with bpkgs=" + pkg.bpkgs);
00701 }
00702 ArrayList checkList = new ArrayList();
00703 for (Iterator i = pkg.bpkgs.getActiveImports(); i.hasNext(); ) {
00704 ImportPkg ip = (ImportPkg)i.next();
00705 if (ui != null) {
00706 if (next_uses == null || !ip.pkg.pkg.equals(next_uses)) {
00707 continue;
00708 }
00709 if (ui.hasNext()) {
00710 next_uses = (String)ui.next();
00711 } else {
00712 next_uses = null;
00713 }
00714 }
00715 ExportPkg ep = (ExportPkg)tempProvider.get(ip.pkg.pkg);
00716 if (Debug.packages) {
00717 Debug.println("checkUses: check import, " + ip +
00718 " with provider, " + ip.provider);
00719 }
00720 if (ep == null) {
00721 tempProvider.put(ip.pkg.pkg, ip.provider);
00722 checkList.add(ip.provider);
00723 } else if (ep != ip.provider) {
00724 if (Debug.packages) {
00725 Debug.println("checkUses: mismatch in providers for, " +
00726 ip.pkg.pkg);
00727 }
00728 return false;
00729 }
00730 }
00731 for (Iterator i = checkList.iterator(); i.hasNext(); ) {
00732 if (!checkUses((ExportPkg)i.next())) {
00733 return false;
00734 }
00735 }
00736 if (Debug.packages) {
00737 Debug.println("checkUses: package " + pkg + " is okay.");
00738 }
00739 return true;
00740 }
00741
00742
00750 private BundleImpl checkBundleSingleton(BundleImpl b) {
00751
00752 if (b.symbolicName != null && b.singleton) {
00753 if (Debug.packages) {
00754 Debug.println("checkBundleSingleton: check singleton bundle " + b);
00755 }
00756 List bl = framework.bundles.getBundles(b.symbolicName);
00757 if (bl.size() > 1) {
00758 for (Iterator i = bl.iterator(); i.hasNext(); ) {
00759 BundleImpl b2 = (BundleImpl)i.next();
00760 if (b2.singleton && ((b2.state & BundleImpl.RESOLVED_FLAGS) != 0 ||
00761 tempResolved.contains(b2))) {
00762 if (Debug.packages) {
00763 Debug.println("checkBundleSingleton: Reject resolve because of bundle: " + b2);
00764 }
00765 return b2;
00766 }
00767 }
00768 }
00769 }
00770 return null;
00771 }
00772
00773
00780 private String checkRequireBundle(BundleImpl b) {
00781
00782 if (b.bpkgs.require != null) {
00783 if (Debug.packages) {
00784 Debug.println("checkRequireBundle: check requiring bundle " + b);
00785 }
00786 if (!framework.perm.okRequireBundlePerm(b)) {
00787 return b.symbolicName;
00788 }
00789 HashMap res = new HashMap();
00790 for (Iterator i = b.bpkgs.require.iterator(); i.hasNext(); ) {
00791 RequireBundle br = (RequireBundle)i.next();
00792 List bl = framework.bundles.getBundles(br.name, br.bundleRange);
00793 BundleImpl ok = null;
00794 for (Iterator bci = bl.iterator(); bci.hasNext() && ok == null; ) {
00795 BundleImpl b2 = (BundleImpl)bci.next();
00796 if (tempResolved.contains(b2)) {
00797 ok = b2;
00798 } else if ((b2.state & BundleImpl.RESOLVED_FLAGS) != 0) {
00799 HashMap oldTempProvider = (HashMap)tempProvider.clone();
00800 ok = b2;
00801 for (Iterator epi = b2.bpkgs.getExports(); epi.hasNext(); ) {
00802 ExportPkg ep = (ExportPkg)epi.next();
00803 if (!checkUses(ep)) {
00804 tempProvider = oldTempProvider;
00805 tempBlackList.add(ep);
00806 ok = null;
00807 }
00808 }
00809 } else if (b2.state == Bundle.INSTALLED &&
00810 framework.perm.okProvideBundlePerm(b2) &&
00811 checkResolve(b2)) {
00812 ok = b2;
00813 }
00814 }
00815 if (ok != null) {
00816 if (Debug.packages) {
00817 Debug.println("checkRequireBundle: added required bundle " + ok);
00818 }
00819 res.put(br, ok.bpkgs);
00820 } else if (br.resolution == Constants.RESOLUTION_MANDATORY) {
00821 if (Debug.packages) {
00822 Debug.println("checkRequireBundle: failed to satisfy: " + br.name);
00823 }
00824 return br.name;
00825 }
00826 }
00827 tempRequired.putAll(res);
00828 }
00829 return null;
00830 }
00831
00832
00836 private void registerNewProviders(BundleImpl bundle) {
00837 for (Iterator i = tempProvider.values().iterator(); i.hasNext();) {
00838 ExportPkg ep = (ExportPkg)i.next();
00839 ep.pkg.addProvider(ep);
00840 }
00841 for (Iterator i = tempRequired.entrySet().iterator(); i.hasNext();) {
00842 Map.Entry e = (Map.Entry)i.next();
00843 BundlePackages bpkgs = (BundlePackages)e.getValue();
00844 RequireBundle br = (RequireBundle)e.getKey();
00845 br.bpkgs = bpkgs;
00846 if (bpkgs.requiredBy == null) {
00847 bpkgs.requiredBy = new ArrayList(1);
00848 }
00849 bpkgs.requiredBy.add(br.requestor);
00850 if (br.visibility == Constants.VISIBILITY_REEXPORT) {
00851
00852 for (Iterator be = bpkgs.getExports(); be.hasNext(); ) {
00853 br.requestor.checkReExport((ExportPkg)be.next());
00854 }
00855 }
00856 }
00857 for (Iterator i = tempResolved.iterator(); i.hasNext();) {
00858 BundleImpl bs = (BundleImpl)i.next();
00859 if (bs.getState() == Bundle.INSTALLED) {
00860 for (Iterator bi = bs.bpkgs.getImports(); bi.hasNext(); ) {
00861 ImportPkg ip = (ImportPkg)bi.next();
00862 ip.provider = (ExportPkg)tempProvider.get(ip.name);
00863 }
00864 if (bs != bundle) {
00865 if (bs.getUpdatedState() == Bundle.INSTALLED) {
00866 framework.listeners.frameworkError(bs,
00867 new Exception("registerNewProviders: InternalError!"));
00868 }
00869 }
00870 }
00871 }
00872 }
00873
00874 }