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.io.*;
00038 import java.net.*;
00039 import java.security.*;
00040
00041 import java.util.Enumeration;
00042 import java.util.Set;
00043 import java.util.Dictionary;
00044 import java.util.Hashtable;
00045 import java.util.ArrayList;
00046 import java.util.Map;
00047 import java.util.HashSet;
00048 import java.util.HashMap;
00049 import java.util.Iterator;
00050 import java.util.List;
00051 import java.util.Locale;
00052 import java.util.Vector;
00053
00054 import org.osgi.framework.*;
00055
00056
00066 class BundleImpl implements Bundle {
00067
00074 static int RESOLVED_FLAGS = RESOLVED | STARTING | ACTIVE | STOPPING;
00075
00079 final Framework framework;
00080
00084 final PermissionOps secure;
00085
00089 final long id;
00090
00094 final String location;
00095
00099 boolean v2Manifest;
00100
00104 String symbolicName;
00105
00109 boolean singleton;
00110
00114 Version version;
00115
00119 int state;
00120
00124 BundlePackages bpkgs;
00125
00129 BundleArchive archive;
00130
00134 int generation = 0;
00135
00139 private ProtectionDomain protectionDomain;
00140
00144 private ClassLoader classLoader = null;
00145
00149 private HashMap oldClassLoaders = null;
00150
00154 protected FileTree bundleDir = null;
00155
00159 protected BundleContextImpl bundleContext = null;
00160
00164 protected BundleActivator bactivator = null;
00165
00170 protected long lastModified;
00171
00176 boolean bDelayedStart = false;
00177
00181 ArrayList fragments = null;
00182
00186 String attachPolicy;
00187
00192 Fragment fragment = null;
00193
00197 private HeaderDictionary cachedHeaders = null;
00198
00202 private HeaderDictionary cachedRawHeaders = null;
00203
00204
00212 BundleImpl(Framework fw, long id, String loc, ProtectionDomain pd, String sym, Version ver) {
00213 this.framework = fw;
00214 this.secure = fw.perm;
00215 this.id = id;
00216 this.location = loc;
00217 this.protectionDomain = pd;
00218 this.symbolicName = sym;
00219 this.singleton = false;
00220 this.version = ver;
00221 this.v2Manifest = true;
00222 this.attachPolicy = Constants.FRAGMENT_ATTACHMENT_ALWAYS;
00223 modified();
00224 }
00225
00238 BundleImpl(Framework fw, BundleArchive ba) {
00239 framework = fw;
00240 secure = fw.perm;
00241 id = ba.getBundleId();
00242 location = ba.getBundleLocation();
00243 archive = ba;
00244 state = INSTALLED;
00245 checkManifestHeaders();
00246 protectionDomain = secure.getProtectionDomain(this);
00247 doExportImport();
00248 bundleDir = fw.getDataStorage(id);
00249
00250 int oldStartLevel = archive.getStartLevel();
00251 try {
00252 if (framework.startLevelService == null) {
00253 archive.setStartLevel(0);
00254 } else {
00255 if (oldStartLevel == -1) {
00256 archive.setStartLevel(framework.startLevelService.getInitialBundleStartLevel());
00257 }
00258 }
00259 } catch (Exception e) {
00260 Debug.println("Failed to set start level on #" + id + ": " + e);
00261 }
00262
00263
00264
00265 if (isExtension() && resolveFragment(framework.systemBundle)) {
00266 state = RESOLVED;
00267 }
00268
00269 lastModified = archive.getLastModified();
00270 if (lastModified == 0) {
00271 modified();
00272 }
00273 }
00274
00275
00276
00277
00278
00279
00285 public int getState() {
00286 return state;
00287 }
00288
00289
00295 synchronized public void start() throws BundleException {
00296 secure.checkExecuteAdminPerm(this);
00297
00298 if (isFragment()) {
00299 throw new BundleException("Cannot start a fragment bundle");
00300 }
00301
00302 if (framework.startLevelService != null) {
00303 if (state != UNINSTALLED &&
00304 getStartLevel() > framework.startLevelService.getStartLevel()) {
00305 secure.callSetPersistent(this, true);
00306 bDelayedStart = true;
00307 return;
00308 }
00309 }
00310
00311 switch (getUpdatedState()) {
00312 case INSTALLED:
00313 throw new BundleException("Failed, " + bpkgs.getResolveFailReason());
00314 case RESOLVED:
00315 if (framework.active) {
00316 state = STARTING;
00317 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.STARTING, this));
00318 bundleContext = new BundleContextImpl(this);
00319 try {
00320 secure.callStart0(this);
00321 } catch (BundleException e) {
00322 removeBundleResources();
00323 bundleContext.invalidate();
00324 bundleContext = null;
00325 state = RESOLVED;
00326 throw e;
00327 }
00328 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.STARTED, this));
00329 } else {
00330 secure.callSetPersistent(this, true);
00331 startOnLaunch(true);
00332 }
00333 break;
00334 case ACTIVE:
00335 break;
00336 case STARTING:
00337
00338
00339 throw new BundleException("called from BundleActivator.start");
00340 case STOPPING:
00341
00342
00343 throw new BundleException("called from BundleActivator.stop");
00344 case UNINSTALLED:
00345 throw new IllegalStateException("Bundle is in UNINSTALLED state");
00346 }
00347 }
00348
00349
00350 void start0() throws BundleException {
00351 final String ba = archive.getAttribute(Constants.BUNDLE_ACTIVATOR);
00352 boolean bStarted = false;
00353
00354 ClassLoader oldLoader = null;
00355
00356 if (Framework.SETCONTEXTCLASSLOADER) {
00357 oldLoader = Thread.currentThread().getContextClassLoader();
00358 }
00359
00360 try {
00361
00362
00363
00364
00365 if (Framework.SETCONTEXTCLASSLOADER) {
00366 Thread.currentThread().setContextClassLoader(getClassLoader());
00367 }
00368
00369 if (ba != null) {
00370 Class c = getClassLoader().loadClass(ba.trim());
00371 bactivator = (BundleActivator)c.newInstance();
00372
00373 bactivator.start(bundleContext);
00374 bStarted = true;
00375 } else {
00376
00377
00378
00379 final String mc = archive.getAttribute("Main-class");
00380
00381 if (mc != null) {
00382 if(Debug.packages) {
00383 Debug.println("starting main class " + mc);
00384 }
00385 Class mainClass = getClassLoader().loadClass(mc.trim());
00386
00387 bactivator = MainClassBundleActivator.create(getClassLoader(), mainClass);
00388 bactivator.start(bundleContext);
00389 bStarted = true;
00390 }
00391 }
00392
00393 if (!bStarted) {
00394
00395
00396
00397
00398 }
00399
00400 state = ACTIVE;
00401 setPersistent(true);
00402 startOnLaunch(true);
00403 } catch (Throwable t) {
00404 t.printStackTrace();
00405 throw new BundleException("BundleActivator start failed", t);
00406 } finally {
00407 if (Framework.SETCONTEXTCLASSLOADER) {
00408 Thread.currentThread().setContextClassLoader(oldLoader);
00409 }
00410 }
00411 }
00412
00413
00417 boolean allowSetStartOnLaunchFalse() {
00418
00419
00420
00421
00422 return
00423
00424 !framework.shuttingdown && !archive.isPersistent();
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 }
00435
00441 synchronized public void stop() throws BundleException {
00442 secure.checkExecuteAdminPerm(this);
00443
00444 if (isFragment()) {
00445 throw new BundleException("Cannot stop a fragment bundle");
00446 }
00447
00448 bDelayedStart = false;
00449
00450 switch (state) {
00451 case INSTALLED:
00452 case RESOLVED:
00453 secure.callSetPersistent(this, false);
00454
00455
00456 if (allowSetStartOnLaunchFalse()) {
00457 secure.callStartOnLaunch(this, false);
00458 }
00459 break;
00460 case ACTIVE:
00461 BundleException savedException = secure.callStop0(this, true);
00462 if (savedException != null) {
00463 throw savedException;
00464 }
00465 break;
00466 case STARTING:
00467
00468
00469 throw new BundleException("Bundle.start called from BundleActivator.stop");
00470 case STOPPING:
00471
00472
00473 throw new BundleException("Bundle.stop called from BundleActivator.stop");
00474 case UNINSTALLED:
00475 throw new IllegalStateException("Bundle.stop: Bundle is in UNINSTALLED state");
00476 }
00477 }
00478
00479 synchronized BundleException stop0(boolean resetPersistent) {
00480 BundleException res = null;
00481
00482 state = STOPPING;
00483 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.STOPPING, this));
00484
00485 if (resetPersistent) {
00486 setPersistent(false);
00487 }
00488
00489 if (allowSetStartOnLaunchFalse()) {
00490 startOnLaunch(false);
00491 }
00492 if (bactivator != null) {
00493 try {
00494 bactivator.stop(bundleContext);
00495 } catch (Throwable e) {
00496 res = new BundleException("Bundle.stop: BundleActivator stop failed", e);
00497 }
00498 bactivator = null;
00499 }
00500
00501 bundleContext.invalidate();
00502 bundleContext = null;
00503 removeBundleResources();
00504 state = RESOLVED;
00505 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.STOPPED, this));
00506 return res;
00507 }
00508
00509
00515 public void update() throws BundleException {
00516 update(null);
00517 }
00518
00519
00525 synchronized public void update(final InputStream in) throws BundleException {
00526 try {
00527 secure.checkLifecycleAdminPerm(this);
00528 if (isExtension()) {
00529 secure.checkExtensionLifecycleAdminPerm(this);
00530 }
00531 final boolean wasActive = state == ACTIVE;
00532
00533 switch (getUpdatedState()) {
00534 case ACTIVE:
00535 stop();
00536
00537 case RESOLVED:
00538 case INSTALLED:
00539
00540 secure.callUpdate0(this, in, wasActive);
00541 break;
00542 case STARTING:
00543
00544
00545 throw new IllegalStateException("Bundle is in STARTING state");
00546 case STOPPING:
00547
00548
00549 throw new IllegalStateException("Bundle is in STOPPING state");
00550 case UNINSTALLED:
00551 throw new IllegalStateException("Bundle is in UNINSTALLED state");
00552 }
00553 } finally {
00554 if (in != null) {
00555 try {
00556 in.close();
00557 } catch (IOException ignore) {}
00558 }
00559
00560 }
00561 }
00562
00563
00564 void update0(InputStream in, boolean wasActive) throws BundleException {
00565 final boolean wasResolved = state == RESOLVED;
00566 final int oldStartLevel = getStartLevel();
00567 BundleArchive newArchive = null;
00568
00569 try {
00570
00571 InputStream bin;
00572 if (in == null) {
00573
00574 String update = archive.getAttribute(Constants.BUNDLE_UPDATELOCATION);
00575 if (update == null) {
00576
00577 update = location;
00578 }
00579 bin = (new URL(update)).openStream();
00580 } else {
00581 bin = in;
00582 }
00583
00584 newArchive = framework.storage.updateBundleArchive(archive, bin);
00585 checkEE(newArchive);
00586 checkManifestHeaders();
00587 newArchive.setStartLevel(oldStartLevel);
00588 framework.storage.replaceBundleArchive(archive, newArchive);
00589 } catch (Exception e) {
00590 if (newArchive != null) {
00591 newArchive.purge();
00592 }
00593
00594 if (wasActive) {
00595 try {
00596 start();
00597 } catch (BundleException be) {
00598 framework.listeners.frameworkError(this, be);
00599 }
00600 }
00601 if (e instanceof BundleException) {
00602 throw (BundleException)e;
00603 } else {
00604 throw new BundleException("Failed to get update bundle", e);
00605 }
00606 }
00607
00608 boolean purgeOld;
00609
00610 if (isFragment()) {
00611 if (isAttached()) {
00612 fragment.setHost(null);
00613 purgeOld = false;
00614 } else {
00615 purgeOld = true;
00616 }
00617 } else {
00618
00619 boolean allRemoved = bpkgs.unregisterPackages(false);
00620
00621
00622 if (allRemoved) {
00623 if (classLoader != null) {
00624 ((BundleClassLoader)classLoader).close();
00625 classLoader = null;
00626 }
00627 purgeOld = true;
00628 } else {
00629 saveZombiePackages();
00630 purgeOld = false;
00631 }
00632 }
00633
00634
00635 BundleArchive oldArchive = archive;
00636 archive = newArchive;
00637 cachedRawHeaders = null;
00638 state = INSTALLED;
00639 ProtectionDomain oldProtectionDomain = protectionDomain;
00640 protectionDomain = secure.getProtectionDomain(this);
00641 doExportImport();
00642
00643
00644 if (purgeOld) {
00645 secure.purge(this, oldProtectionDomain);
00646 oldArchive.purge();
00647 }
00648
00649
00650 if (wasResolved) {
00651 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED,
00652 this));
00653 }
00654 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.UPDATED,
00655 this));
00656
00657
00658 if (wasActive) {
00659 try {
00660 start();
00661 } catch (BundleException be) {
00662 framework.listeners.frameworkError(this, be);
00663 }
00664 }
00665
00666 modified();
00667 }
00668
00669
00670 void checkEE(BundleArchive ba) throws BundleException {
00671 String ee = ba.getAttribute(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
00672 if (ee != null) {
00673 if (Debug.packages) {
00674 Debug.println("bundle #" + ba.getBundleId() + " has EE=" + ee);
00675 }
00676 if (!framework.isValidEE(ee)) {
00677 throw new BundleException("Execution environment '" + ee + "' is not supported");
00678 }
00679 }
00680 }
00681
00682
00688 synchronized public void uninstall() throws BundleException {
00689 secure.checkLifecycleAdminPerm(this);
00690 if (isExtension()) {
00691 secure.checkExtensionLifecycleAdminPerm(this);
00692 }
00693 secure.callUninstall0(this);
00694 }
00695
00696 void uninstall0() {
00697 boolean wasResolved = false;
00698
00699 try {
00700 archive.setStartLevel(-2);
00701 } catch (Exception ignored) { }
00702
00703 cachedHeaders = getHeaders0(null);
00704
00705 bDelayedStart = false;
00706
00707 switch (state) {
00708 case ACTIVE:
00709 try {
00710 stop();
00711 } catch (BundleException be) {
00712 framework.listeners.frameworkError(this, be);
00713 }
00714
00715 case RESOLVED:
00716 wasResolved = true;
00717
00718 case INSTALLED:
00719
00720 framework.bundles.remove(location);
00721
00722 if (isFragment()) {
00723 if (isAttached()) {
00724 classLoader = null;
00725 fragment.setHost(null);
00726 } else {
00727 secure.purge(this, protectionDomain);
00728 archive.purge();
00729 }
00730 } else {
00731 if (bpkgs.unregisterPackages(false)) {
00732 if (classLoader != null) {
00733 ((BundleClassLoader)classLoader).purge();
00734 classLoader = null;
00735 } else {
00736 secure.purge(this, protectionDomain);
00737 archive.purge();
00738 }
00739 } else {
00740 saveZombiePackages();
00741 classLoader = null;
00742 }
00743 if (isFragmentHost()) {
00744 detachFragments(true);
00745 }
00746 }
00747
00748 bpkgs = null;
00749 bactivator = null;
00750 if (bundleDir != null) {
00751 if (!bundleDir.delete()) {
00752
00753
00754 try {
00755 archive.setStartLevel(-2);
00756 } catch (Exception e) {
00757 Debug.println("Failed to mark bundle " + id +
00758 " as uninstalled, " + bundleDir +
00759 " must be deleted manually: " + e);
00760 }
00761 }
00762 bundleDir = null;
00763 }
00764
00765
00766 state = UNINSTALLED;
00767 modified();
00768
00769 if (wasResolved) {
00770 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED, this));
00771 }
00772 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.UNINSTALLED, this));
00773 break;
00774 case STARTING:
00775
00776
00777 throw new IllegalStateException("Bundle is in STARTING state");
00778 case STOPPING:
00779
00780
00781 throw new IllegalStateException("Bundle is in STOPPING state");
00782 case UNINSTALLED:
00783 throw new IllegalStateException("Bundle is in UNINSTALLED state");
00784 }
00785 }
00786
00787
00794 public Dictionary getHeaders() {
00795 return getHeaders(null);
00796 }
00797
00798
00804 public long getBundleId() {
00805 return id;
00806 }
00807
00808
00814 public String getLocation() {
00815 secure.checkMetadataAdminPerm(this);
00816 return location;
00817 }
00818
00819
00825 public ServiceReference[] getRegisteredServices() {
00826 Set sr = framework.services.getRegisteredByBundle(this);
00827 secure.filterGetServicePermission(sr);
00828 ServiceReference[] res = new ServiceReference[sr.size()];
00829 int pos = 0;
00830 for (Iterator i = sr.iterator(); i.hasNext(); ) {
00831 res[pos++] = ((ServiceRegistration)i.next()).getReference();
00832 }
00833 return res;
00834 }
00835
00836
00842 public ServiceReference[] getServicesInUse() {
00843 Set sr = framework.services.getUsedByBundle(this);
00844 secure.filterGetServicePermission(sr);
00845 ServiceReference[] res = new ServiceReference[sr.size()];
00846 int pos = 0;
00847 for (Iterator i = sr.iterator(); i.hasNext(); ) {
00848 res[pos++] = ((ServiceRegistration)i.next()).getReference();
00849 }
00850 return res;
00851 }
00852
00853
00859 public boolean hasPermission(Object permission) {
00860 checkUninstalled();
00861 if (permission instanceof Permission) {
00862 if (secure.checkPermissions()) {
00863
00864 PermissionCollection pc = protectionDomain.getPermissions();
00865 return pc != null ? pc.implies((Permission)permission) : false;
00866 } else {
00867 return true;
00868 }
00869 } else {
00870 return false;
00871 }
00872 }
00873
00874
00878 public URL getResource(String name) {
00879
00880 checkUninstalled();
00881 if (isFragment()) {
00882 return null;
00883 }
00884 if (state == INSTALLED && !secure.okResourceAdminPerm(this)) {
00885
00886 return null;
00887 }
00888 if (getUpdatedState() != INSTALLED) {
00889 BundleClassLoader cl = (BundleClassLoader)getClassLoader();
00890 if (cl != null) {
00891 Enumeration res = cl.getBundleResources(name, true);
00892 if (res != null) {
00893 return (URL)res.nextElement();
00894 }
00895 }
00896 }
00897 return null;
00898 }
00899
00900
00904 public String getSymbolicName() {
00905 return symbolicName;
00906 }
00907
00908
00909
00910
00911
00912
00919 int getUpdatedState() {
00920 if (state == INSTALLED) {
00921 synchronized (this) {
00922 if (state == INSTALLED) {
00923 if (isFragment()) {
00924 BundleImpl host = getFragmentHost();
00925 if (host != null) {
00926 if (host.state == INSTALLED) {
00927
00928 host.getUpdatedState();
00929 } else {
00930
00931 }
00932 }
00933 } else {
00934
00935 attachFragments();
00936 if (bpkgs.resolvePackages()) {
00937 if (fragments != null) {
00938 for (Iterator i = fragments.iterator(); i.hasNext(); ) {
00939 BundleImpl b = (BundleImpl)i.next();
00940 b.state = RESOLVED;
00941 }
00942 }
00943 state = RESOLVED;
00944 if (fragments != null) {
00945 for (Iterator i = fragments.iterator(); i.hasNext(); ) {
00946 BundleImpl b = (BundleImpl)i.next();
00947 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.RESOLVED, b));
00948 }
00949 }
00950 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.RESOLVED, this));
00951
00952 if (id != 0) {
00953 List fe = archive.getFailedClassPathEntries();
00954 if (fe != null) {
00955 for (Iterator i = fe.iterator(); i.hasNext(); ) {
00956 Exception e = new IOException("Failed to classpath entry: " + i.next());
00957 framework.listeners.frameworkInfo(this, e);
00958 }
00959 }
00960 }
00961 } else {
00962 detachFragments(false);
00963 }
00964 }
00965 }
00966 }
00967 }
00968 return state;
00969 }
00970
00971
00975 boolean resolveFragment(BundleImpl host) {
00976 if (host == getFragmentHost() && secure.okFragmentBundlePerm(this)) {
00977 try {
00978 host.attachFragment(this);
00979 fragment.setHost(host);
00980 return true;
00981 } catch (Exception _ignore) { }
00982 }
00983
00984 return false;
00985 }
00986
00987
00993 File getDataRoot() {
00994 return bundleDir;
00995 }
00996
00997
01005 ClassLoader getClassLoader() {
01006 if (classLoader == null) {
01007 synchronized (this) {
01008 if (classLoader == null && (state & RESOLVED_FLAGS) != 0) {
01009 classLoader = secure.callGetClassLoader0(this);
01010 }
01011 }
01012 }
01013 return classLoader;
01014 }
01015
01016
01017 ClassLoader getClassLoader0() {
01018 if (isFragment()) {
01019 if (isAttached()) {
01020 if (isBootClassPathExtension()) {
01021 ClassLoader root = ClassLoader.getSystemClassLoader();
01022 while (root.getParent() != null) {
01023 root = root.getParent();
01024 }
01025 return root;
01026 } else {
01027 return getFragmentHost().getClassLoader();
01028 }
01029 }
01030 return null;
01031 } else {
01032 ArrayList frags;
01033 if (isFragmentHost()) {
01034 frags = new ArrayList();
01035 for (Iterator i = fragments.iterator(); i.hasNext(); ) {
01036 frags.add(((BundleImpl)i.next()).archive);
01037 }
01038 } else {
01039 frags = null;
01040 }
01041 return new BundleClassLoader(bpkgs, archive, frags, protectionDomain, secure);
01042 }
01043 }
01044
01045
01051 synchronized void setStateInstalled(boolean sendEvent) {
01052 if (isFragment()) {
01053 classLoader = null;
01054 fragment.setHost(null);
01055 } else {
01056 if (classLoader != null) {
01057 ((BundleClassLoader)classLoader).close();
01058 classLoader = null;
01059 }
01060 bpkgs.unregisterPackages(true);
01061 if (isFragmentHost()) {
01062 detachFragments(true);
01063 }
01064 bpkgs.registerPackages();
01065 }
01066
01067 state = INSTALLED;
01068 if (sendEvent) {
01069 framework.listeners.bundleChanged(new BundleEvent(BundleEvent.UNRESOLVED, this));
01070 }
01071 }
01072
01073
01080 ClassLoader getClassLoader(BundlePackages ebpkgs) {
01081 if (bpkgs == ebpkgs) {
01082 return getClassLoader();
01083 } else if (oldClassLoaders != null) {
01084 return (ClassLoader)oldClassLoaders.get(ebpkgs);
01085 }
01086 return null;
01087 }
01088
01089
01094 void purge() {
01095 if (state == UNINSTALLED) {
01096 framework.bundles.remove(location);
01097 }
01098 if (oldClassLoaders != null) {
01099 for (Iterator i = oldClassLoaders.values().iterator(); i.hasNext();) {
01100 ((BundleClassLoader)i.next()).purge();
01101 }
01102 oldClassLoaders = null;
01103 }
01104 }
01105
01106
01112 BundleArchive getBundleArchive(long gen, long frag) {
01113
01114 if (gen == -1 || (bpkgs != null && bpkgs.generation == gen)) {
01115 if (frag == -1) {
01116 return archive;
01117 } else {
01118 return ((BundleClassLoader)getClassLoader()).getBundleArchive(frag);
01119 }
01120 } else {
01121 for (Iterator i = oldClassLoaders.values().iterator(); i.hasNext();) {
01122 BundleClassLoader cl = (BundleClassLoader)i.next();
01123 if (cl.getBpkgs().generation == gen) {
01124 return cl.getBundleArchive(frag);
01125 }
01126 }
01127 return null;
01128 }
01129 }
01130
01131
01137 Iterator getExports() {
01138 if (oldClassLoaders != null) {
01139 HashSet res = new HashSet();
01140 for (Iterator i = oldClassLoaders.values().iterator(); i.hasNext();) {
01141 for (Iterator j = ((BundleClassLoader)i.next()).getBpkgs().getExports(); j.hasNext();) {
01142 res.add(j.next());
01143 }
01144 }
01145 if (bpkgs != null) {
01146 for (Iterator i = bpkgs.getExports(); i.hasNext();) {
01147 res.add(i.next());
01148 }
01149 }
01150 return res.iterator();
01151 } else if (bpkgs != null) {
01152 return bpkgs.getExports();
01153 } else {
01154 return (new ArrayList(0)).iterator();
01155 }
01156 }
01157
01158
01164 Iterator getImports() {
01165 if (oldClassLoaders != null) {
01166 HashSet res = new HashSet();
01167 for (Iterator i = oldClassLoaders.values().iterator(); i.hasNext();) {
01168 for (Iterator j = ((BundleClassLoader)i.next()).getBpkgs().getImports(); j.hasNext();) {
01169 res.add(j.next());
01170 }
01171 }
01172 if (bpkgs != null) {
01173 for (Iterator i = bpkgs.getImports(); i.hasNext();) {
01174 res.add(i.next());
01175 }
01176 }
01177 return res.iterator();
01178 } else if (bpkgs != null) {
01179 return bpkgs.getImports();
01180 } else {
01181 return (new ArrayList(0)).iterator();
01182 }
01183 }
01184
01185
01189 URL getURL(long gen, long frag, int bcpElem, String path) {
01190 try {
01191 StringBuffer u = new StringBuffer(BundleURLStreamHandler.PROTOCOL);
01192 u.append("://");
01193 u.append(id);
01194 if (gen != -1) {
01195 u.append('.').append(gen);
01196 }
01197 if (frag != -1 && frag != id) {
01198 u.append('_').append(frag);
01199 }
01200 if (bcpElem >= 0) {
01201 u.append(':').append(bcpElem);
01202 }
01203 if (!path.startsWith("/")) {
01204 u.append('/');
01205 }
01206 u.append(path);
01207 return new URL(u.toString());
01208 } catch (MalformedURLException e) {
01209 return null;
01210 }
01211 }
01212
01213
01214
01215
01216
01217
01221 private void checkManifestHeaders() {
01222
01223 v2Manifest = "2".equals(archive.getAttribute(Constants.BUNDLE_MANIFESTVERSION));
01224 Iterator i = Util.parseEntries(Constants.BUNDLE_SYMBOLICNAME,
01225 archive.getAttribute(Constants.BUNDLE_SYMBOLICNAME),
01226 true, true, true);
01227 Map e = null;
01228 if (i.hasNext()) {
01229 e = (Map)i.next();
01230 symbolicName = (String)e.get("key");
01231 } else {
01232 if (v2Manifest) {
01233 throw new IllegalArgumentException("Bundle has no symbolic name, location=" +
01234 location);
01235 } else {
01236 symbolicName = null;
01237 }
01238 }
01239 String mbv = archive.getAttribute(Constants.BUNDLE_VERSION);
01240 if (mbv != null) {
01241 try {
01242 version = new Version(mbv);
01243 } catch (Throwable ee) {
01244 if (v2Manifest) {
01245 throw new IllegalArgumentException("Bundle does not specify a valid " +
01246 Constants.BUNDLE_VERSION + " header. Got exception: " + ee.getMessage());
01247 } else {
01248 version = Version.emptyVersion;
01249 }
01250 }
01251
01252 } else {
01253 version = Version.emptyVersion;
01254 }
01255
01256 attachPolicy = Constants.FRAGMENT_ATTACHMENT_ALWAYS;
01257 if (e != null) {
01258 singleton = "true".equals((String)e.get(Constants.SINGLETON_DIRECTIVE));
01259 BundleImpl snb = framework.bundles.getBundle(symbolicName, version);
01260 String tmp = (String)e.get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
01261 attachPolicy = tmp == null ? Constants.FRAGMENT_ATTACHMENT_ALWAYS : tmp;
01262
01263 if (snb != null && snb != this) {
01264 throw new IllegalArgumentException("Bundle with same symbolic name and version " +
01265 "is already installed (" + symbolicName + ", " +
01266 version);
01267 }
01268 } else {
01269 singleton = false;
01270 }
01271
01272 i = Util.parseEntries(Constants.FRAGMENT_HOST,
01273 archive.getAttribute(Constants.FRAGMENT_HOST),
01274 true, true, true);
01275
01276 if (i.hasNext()) {
01277
01278 if (archive.getAttribute(Constants.BUNDLE_ACTIVATOR) != null) {
01279 throw new IllegalArgumentException("A fragment bundle can not have a Bundle-Activator.");
01280 }
01281
01282 e = (Map)i.next();
01283 String extension = (String)e.get(Constants.EXTENSION_DIRECTIVE);
01284 String key = (String)e.get("key");
01285
01286 if (Constants.EXTENSION_FRAMEWORK.equals(extension) ||
01287 Constants.EXTENSION_BOOTCLASSPATH.equals(extension)) {
01288
01289
01290 if (!Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(key) &&
01291 !"org.knopflerfish.framework".equals(key)) {
01292 throw new IllegalArgumentException("An extension bundle must target " +
01293 "the system bundle(=" +
01294 Constants.SYSTEM_BUNDLE_SYMBOLICNAME + ")");
01295 }
01296
01297 if (archive.getAttribute(Constants.IMPORT_PACKAGE) != null ||
01298 archive.getAttribute(Constants.REQUIRE_BUNDLE) != null ||
01299 archive.getAttribute(Constants.BUNDLE_NATIVECODE) != null ||
01300 archive.getAttribute(Constants.DYNAMICIMPORT_PACKAGE) != null ||
01301 archive.getAttribute(Constants.BUNDLE_ACTIVATOR) != null) {
01302 throw new IllegalArgumentException("An extension bundle cannot specify: " +
01303 Constants.IMPORT_PACKAGE + ", " +
01304 Constants.REQUIRE_BUNDLE + ", " +
01305 Constants.BUNDLE_NATIVECODE + ", " +
01306 Constants.DYNAMICIMPORT_PACKAGE + " or " +
01307 Constants.BUNDLE_ACTIVATOR);
01308 }
01309 if (!Framework.SUPPORTS_EXTENSION_BUNDLES) {
01310 if (Framework.bIsMemoryStorage) {
01311 throw new UnsupportedOperationException("Extension bundles are not supported in memory storage mode.");
01312 } else if (!Framework.EXIT_ON_SHUTDOWN) {
01313 throw new UnsupportedOperationException("Extension bundles require that the property " +
01314 Main.EXITONSHUTDOWN_PROP + " is set to \"true\"");
01315 } else if (!Framework.USING_WRAPPER_SCRIPT) {
01316 throw new UnsupportedOperationException("Extension bundles require the use of a wrapper script. " +
01317 "Consult the documentation");
01318 } else {
01319 throw new UnsupportedOperationException("Extension bundles are not supported.");
01320 }
01321 }
01322 } else {
01323 if (extension != null) {
01324 throw new IllegalArgumentException("Did not recognize directive " +
01325 Constants.EXTENSION_DIRECTIVE
01326 + ":=" + extension + "." );
01327 }
01328 }
01329
01330 if (fragment == null) {
01331 fragment = new Fragment(key,
01332 extension,
01333 (String)e.get(Constants.BUNDLE_VERSION_ATTRIBUTE));
01334 }
01335 }
01336 }
01337
01338
01344 void startOnLaunch(boolean value) {
01345 try {
01346 archive.setStartOnLaunchFlag(value);
01347 } catch (IOException e) {
01348 framework.listeners.frameworkError(this, e);
01349 }
01350 }
01351
01352
01356 void setPersistent(final boolean value) {
01357 try {
01358 archive.setPersistent(value);
01359 } catch (Exception e) {
01360 framework.listeners.frameworkError(this, e);
01361 }
01362 }
01363
01364
01370 void doExportImport() {
01371 bpkgs = new BundlePackages(this,
01372 generation++,
01373 archive.getAttribute(Constants.EXPORT_PACKAGE),
01374 archive.getAttribute(Constants.IMPORT_PACKAGE),
01375 archive.getAttribute(Constants.DYNAMICIMPORT_PACKAGE),
01376 archive.getAttribute(Constants.REQUIRE_BUNDLE));
01377 if (!isFragment()) {
01378
01379 bpkgs.registerPackages();
01380 }
01381 }
01382
01383
01389 private void removeBundleResources() {
01390 framework.listeners.removeAllListeners(this);
01391 Set srs = framework.services.getRegisteredByBundle(this);
01392 for (Iterator i = srs.iterator(); i.hasNext();) {
01393 try {
01394 ((ServiceRegistration)i.next()).unregister();
01395 } catch (IllegalStateException ignore) {
01396
01397
01398
01399 }
01400 }
01401 Set s = framework.services.getUsedByBundle(this);
01402 for (Iterator i = s.iterator(); i.hasNext(); ) {
01403 ((ServiceRegistrationImpl) i.next()).reference.ungetService(this, false);
01404 }
01405 }
01406
01407
01412 private void saveZombiePackages() {
01413 if (oldClassLoaders == null) {
01414 oldClassLoaders = new HashMap();
01415 }
01416 oldClassLoaders.put(bpkgs, getClassLoader());
01417 classLoader = null;
01418 }
01419
01420
01421
01422
01426 boolean isPersistent() {
01427 return bDelayedStart || archive.isPersistent();
01428 }
01429
01430
01434 int getStartLevel() {
01435 if (archive != null) {
01436 return archive.getStartLevel();
01437 } else {
01438 return 0;
01439 }
01440 }
01441
01442
01446 void setStartLevel(int n) {
01447
01448
01449
01450 if(archive != null) {
01451 try {
01452 archive.setStartLevel(n);
01453 } catch (Exception e) {
01454 Debug.println("Failed to set start level on #" + getBundleId());
01455 }
01456 }
01457 }
01458
01459
01460
01468 public String toString() {
01469 return toString(0);
01470 }
01471
01472 String toString(int detail) {
01473 StringBuffer sb = new StringBuffer();
01474
01475 sb.append("BundleImpl[");
01476 sb.append("id=" + getBundleId());
01477 if(detail > 0) {
01478 sb.append(", state=" + getState());
01479 }
01480
01481 if(detail > 1) {
01482 sb.append(", startlevel=" + getStartLevel());
01483 }
01484
01485 if(detail > 3) {
01486 sb.append(", bDelayedStart=" + bDelayedStart);
01487 }
01488
01489 if(detail > 4) {
01490 try {
01491 sb.append(", bPersistant=" + isPersistent());
01492 } catch (Exception e) {
01493 sb.append(", bPersistant=" + e);
01494 }
01495 }
01496 if(detail > 4) {
01497 sb.append(", loc=" + location);
01498 }
01499
01500 if(detail > 4) {
01501 sb.append(", symName=" + symbolicName);
01502 }
01503
01504 sb.append("]");
01505
01506 return sb.toString();
01507 }
01508
01509
01515 public Enumeration findEntries(String path, String filePattern, boolean recurse) {
01516 if (secure.okResourceAdminPerm(this)) {
01517 if (state == INSTALLED) {
01518
01519 if (!framework.bundles.getFragmentBundles(this).isEmpty()) {
01520 getUpdatedState();
01521 }
01522 }
01523 return secure.callFindEntries0(this, path, filePattern, recurse);
01524 } else {
01525 return null;
01526 }
01527 }
01528
01529
01533 Enumeration findEntries0(String path, String filePattern, boolean recurse) {
01534 Vector res = new Vector();
01535 if (isFragmentHost()) {
01536 for (Iterator i = fragments.iterator(); i.hasNext(); ) {
01537 BundleImpl fb = (BundleImpl)i.next();
01538 fb.addResourceEntries(res, path, filePattern, recurse);
01539 }
01540 }
01541 addResourceEntries(res, path, filePattern, recurse);
01542 return res.size() != 0 ? res.elements() : null;
01543 }
01544
01545
01549 void addResourceEntries(Vector res, String path, String pattern, boolean recurse) {
01550 Enumeration e = archive.findResourcesPath(path);
01551 if (e != null) {
01552 while (e.hasMoreElements()) {
01553 String fp = (String)e.nextElement();
01554 if (fp.endsWith("/")) {
01555 if (recurse) {
01556 addResourceEntries(res, fp, pattern, recurse);
01557 }
01558 } else {
01559 int l = fp.lastIndexOf('/');
01560 if (pattern == null || Util.filterMatch(pattern, fp.substring(l + 1))) {
01561 URL url = getURL(-1, -1, -1, fp);
01562 if (url != null) {
01563 res.add(url);
01564 }
01565 }
01566 }
01567 }
01568 }
01569 }
01570
01571
01575 public URL getEntry(String name) {
01576 if (secure.okResourceAdminPerm(this)) {
01577 checkUninstalled();
01578 try {
01579 InputStream is = secure.callGetInputStream(archive, name, 0);
01580 if (is != null) {
01581 is.close();
01582 return getURL(-1, -1, -1, name);
01583 }
01584 } catch (IOException _ignore) { }
01585 }
01586 return null;
01587 }
01588
01589
01593 public Enumeration getEntryPaths(String path) {
01594 if (secure.okResourceAdminPerm(this)) {
01595 checkUninstalled();
01596 return secure.callFindResourcesPath(archive, path);
01597 } else {
01598 return null;
01599 }
01600 }
01601
01602
01606 private Dictionary getLocaleDictionary(String locale, String baseName) {
01607 String defaultLocale = Locale.getDefault().toString();
01608
01609 if (locale == null) {
01610 locale = defaultLocale;
01611 } else if (locale.equals("")) {
01612 return null;
01613 }
01614
01615 Hashtable localization_entries = new Hashtable();
01616 readLocalization("", localization_entries, baseName);
01617 readLocalization(Locale.getDefault().toString(), localization_entries, baseName);
01618 if (!locale.equals(defaultLocale)) {
01619 readLocalization(locale, localization_entries, baseName);
01620 }
01621
01622 return localization_entries;
01623 }
01624
01625
01631 private HeaderDictionary localize(Dictionary localization_entries) {
01632 HeaderDictionary localized = (HeaderDictionary)cachedRawHeaders.clone();
01633
01634 if (localization_entries != null) {
01635 for (Enumeration e = localized.keys();
01636 e.hasMoreElements(); ) {
01637 String key = (String)e.nextElement();
01638 String unlocalizedEntry = (String)localized.get(key);
01639
01640 if (unlocalizedEntry.startsWith("%")) {
01641 String k = unlocalizedEntry.substring(1);
01642 String val = (String)localization_entries.get(k);
01643
01644 if (val == null) {
01645 localized.put(key, k);
01646 } else {
01647 localized.put(key, val);
01648 }
01649 }
01650 }
01651 }
01652 return localized;
01653 }
01654
01662 protected void readLocalization(String locale,
01663 Hashtable localization_entries,
01664 String baseName) {
01665 if (baseName == null) {
01666 baseName = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
01667 }
01668 int o = 0;
01669 String[] parts = Util.splitwords(locale, "_");
01670 String tmploc;
01671 if ("".equals(parts[0])) {
01672 tmploc = baseName;
01673 } else {
01674 tmploc = baseName + "_" + parts[0];
01675 }
01676 do {
01677 Hashtable tmp;
01678 if ((state & RESOLVED_FLAGS) != 0) {
01679 tmp = ((BundleClassLoader)getClassLoader()).getLocalizationEntries(tmploc +
01680 ".properties");
01681 } else if (archive != null) {
01682 tmp = archive.getLocalizationEntries(tmploc + ".properties");
01683 } else {
01684
01685 return;
01686 }
01687 if (tmp != null) {
01688 localization_entries.putAll(tmp);
01689 }
01690
01691 if (++o >= parts.length) {
01692 break;
01693 }
01694 tmploc = tmploc + "_" + parts[o];
01695
01696 } while (true);
01697 }
01698
01699
01703 public Dictionary getHeaders(String locale) {
01704 secure.checkMetadataAdminPerm(this);
01705 return secure.callGetHeaders0(this, locale);
01706 }
01707
01708 HeaderDictionary getHeaders0(String locale) {
01709 if (cachedRawHeaders == null) {
01710 cachedRawHeaders = archive.getUnlocalizedAttributes();
01711 }
01712
01713 if ("".equals(locale)) {
01714 return (HeaderDictionary)cachedRawHeaders.clone();
01715 }
01716
01717 if (state == UNINSTALLED) {
01718 return (HeaderDictionary)cachedHeaders.clone();
01719 }
01720
01721 String base = (String)cachedRawHeaders.get(Constants.BUNDLE_LOCALIZATION);
01722 Dictionary d;
01723 if (isFragment() && fragment.host != null) {
01724 d = fragment.host.getLocaleDictionary(locale, base);
01725 } else {
01726 d = getLocaleDictionary(locale, base);
01727 }
01728 return localize(d);
01729 }
01730
01731
01735 private void modified(){
01736 lastModified = System.currentTimeMillis();
01737
01738 if(archive != null){
01739 try{
01740 archive.setLastModified(lastModified);
01741 }
01742 catch(IOException e){}
01743 }
01744 }
01745
01750 public long getLastModified() {
01751 return lastModified;
01752 }
01753
01754
01758 public Enumeration getResources(String name) throws IOException {
01759
01760 checkUninstalled();
01761 if (isFragment()) {
01762 return null;
01763 }
01764 if (state == INSTALLED && !secure.okResourceAdminPerm(this)) {
01765
01766 return null;
01767 }
01768 if (getUpdatedState() != INSTALLED) {
01769 BundleClassLoader cl = (BundleClassLoader)getClassLoader();
01770 if (cl != null) {
01771 return cl.getBundleResources(name, false);
01772 }
01773 }
01774 return null;
01775 }
01776
01777
01782 public Class loadClass(final String name) throws ClassNotFoundException {
01783 if (secure.okClassAdminPerm(this)) {
01784 checkUninstalled();
01785 if (isFragment() && !isExtension()) {
01786 throw new ClassNotFoundException("Can not load classes from fragment bundles");
01787 }
01788 if (getUpdatedState() == INSTALLED) {
01789 framework.listeners.frameworkError(this, new BundleException("Unable to resolve bundle: " + bpkgs.getResolveFailReason()));
01790 throw new ClassNotFoundException("Unable to resolve bundle");
01791 }
01792
01793 ClassLoader cl = getClassLoader();
01794 if (cl == null) {
01795 throw new IllegalStateException("state is uninstalled?");
01796 }
01797 return cl.loadClass(name);
01798 } else {
01799 throw new ClassNotFoundException("No AdminPermission to get class: " + name);
01800 }
01801 }
01802
01803
01807 boolean isFragment() {
01808 return fragment != null;
01809 }
01810
01811
01815 boolean isExtension() {
01816 return isFragment() &&
01817 fragment.extension != null;
01818 }
01819
01824 boolean extensionNeedsRestart() {
01825 return isExtension() &&
01826 (state & (INSTALLED|UNINSTALLED)) != 0;
01827
01828
01829
01830 }
01831
01835 boolean isBootClassPathExtension() {
01836 return isExtension() &&
01837 fragment.extension.equals(Constants.EXTENSION_BOOTCLASSPATH);
01838 }
01839
01843 boolean isFrameworkExtension() {
01844 return isExtension() &&
01845 fragment.extension.equals(Constants.EXTENSION_FRAMEWORK);
01846 }
01847
01848
01852 boolean isAttached() {
01853 return isFragment() &&
01854 fragment.host != null;
01855 }
01856
01857
01862 String getFragmentHostName() {
01863 if (isFragment()) {
01864 return fragment.name;
01865 } else {
01866 return null;
01867 }
01868 }
01869
01870
01875 BundleImpl getFragmentHost() {
01876 return isFragment() ? fragment.targets() : null;
01877 }
01878
01879
01884 boolean isFragmentHost() {
01885 return fragments != null && fragments.size() > 0;
01886 }
01887
01888
01892 void attachFragments() {
01893 if (!attachPolicy.equals(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
01894 List hosting = framework.bundles.getFragmentBundles(this);
01895 if (hosting.size() > 0 && secure.okHostBundlePerm(this)) {
01896
01897 for (Iterator iter = hosting.iterator(); iter.hasNext(); ) {
01898 BundleImpl fb = (BundleImpl)iter.next();
01899 if (fb.state == INSTALLED) {
01900 fb.resolveFragment(this);
01901 }
01902 }
01903 }
01904 }
01905 }
01906
01907
01911 void attachFragment(BundleImpl fragmentBundle) {
01912 checkUninstalled();
01913 if (attachPolicy.equals(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
01914 throw new IllegalStateException("Bundle does not allow fragments to attach");
01915 }
01916 if (attachPolicy.equals(Constants.FRAGMENT_ATTACHMENT_RESOLVETIME) &&
01917 (state & RESOLVED_FLAGS) != 0) {
01918 throw new IllegalStateException("Bundle does not allow fragments to attach dynamicly");
01919 }
01920
01921 String failReason = bpkgs.attachFragment(fragmentBundle.bpkgs);
01922 if (failReason != null) {
01923 throw new IllegalStateException(failReason);
01924 }
01925
01926 if (fragments == null) {
01927 fragments = new ArrayList();
01928 }
01929 int i = 0;
01930 for (; i < fragments.size(); i++) {
01931 BundleImpl b = (BundleImpl)fragments.get(i);
01932 if (b.id > fragmentBundle.id) {
01933 break;
01934 }
01935 }
01936 fragments.add(i, fragmentBundle);
01937 }
01938
01939
01943 Iterator getFragments() {
01944 return fragments == null ?
01945 new ArrayList(0).iterator() : fragments.iterator();
01946 }
01947
01948
01952 private void detachFragments(boolean sendEvent) {
01953 if (fragments != null) {
01954 while (fragments.size() > 0) {
01955 detachFragment((BundleImpl)fragments.get(0), sendEvent);
01956 }
01957 }
01958 }
01959
01960
01964 private void detachFragment(BundleImpl fb, boolean sendEvent) {
01965
01966 if (fragments.remove(fb)) {
01967
01968 bpkgs.detachFragment(fb);
01969 if (fb.state != UNINSTALLED) {
01970 fb.setStateInstalled(sendEvent);
01971 }
01972 }
01973 }
01974
01978 private void checkUninstalled() {
01979 if (state == UNINSTALLED) {
01980 throw new IllegalStateException("Bundle is in UNINSTALLED state");
01981 }
01982 }
01983
01984
01987 class Fragment {
01988 final String name;
01989 final String extension;
01990 final VersionRange versionRange;
01991 BundleImpl host = null;
01992
01993 Fragment(String name, String extension, String range) {
01994 this.name = name;
01995 this.extension = extension;
01996 this.versionRange = range == null ?
01997 VersionRange.defaultVersionRange :
01998 new VersionRange(range);
01999 }
02000
02001 void setHost(BundleImpl host) {
02002 this.host = host;
02003 }
02004
02005 BundleImpl targets() {
02006 if (host != null) {
02007 return host;
02008 }
02009
02010 List bundles = framework.bundles.getBundles(name, versionRange);
02011
02012 if (bundles.isEmpty()) {
02013 return null;
02014 }
02015
02016 BundleImpl best = null;
02017
02018 for (Iterator iter = bundles.iterator(); iter.hasNext(); ) {
02019 BundleImpl challenger = (BundleImpl)iter.next();
02020
02021 if (challenger.state != UNINSTALLED &&
02022 !challenger.attachPolicy.
02023 equals(Constants.FRAGMENT_ATTACHMENT_NEVER) &&
02024 (best == null ||
02025 challenger.version.compareTo(best.version) > 0)) {
02026
02027 best = challenger;
02028 }
02029 }
02030
02031 return best;
02032 }
02033 }
02034
02035 }