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.Set;
00042 import java.util.List;
00043 import java.util.HashSet;
00044 import java.util.Iterator;
00045 import java.util.Locale;
00046 import java.util.Dictionary;
00047
00048 import org.osgi.framework.*;
00049 import org.osgi.service.packageadmin.PackageAdmin;
00050 import org.osgi.service.startlevel.StartLevel;
00051
00058 public class Framework {
00059
00063 static final String SPEC_VERSION = "1.3";
00064
00068 boolean active;
00069
00073 boolean shuttingdown ;
00074
00078 public Bundles bundles;
00079
00083 Listeners listeners;
00084
00088 Packages packages;
00089
00093 Services services;
00094
00098 PermissionOps perm;
00099
00100
00104 SystemBundle systemBundle;
00105
00106 BundleContextImpl systemBC;
00107
00111 BundleStorage storage;
00112
00116 FileTree dataStorage ;
00117
00121 Object mainHandle;
00122
00126 StartLevelImpl startLevelService;
00127
00128
00132 ServiceURLStreamHandlerFactory urlStreamHandlerFactory;
00133
00137 ServiceContentHandlerFactory contentHandlerFactory;
00138
00142 final static String TRUE = "true";
00143 final static String FALSE = "false";
00144
00145 final static String osArch = System.getProperty("os.arch");
00146 final static String osName = System.getProperty("os.name");
00147 static String osVersion;
00148
00149
00150
00151 public final static boolean UNREGISTERSERVICE_VALID_DURING_UNREGISTERING =
00152 TRUE.equals(System.getProperty("org.knopflerfish.servicereference.valid.during.unregistering",
00153 FALSE));
00154
00155
00156
00157
00158 final static boolean SETCONTEXTCLASSLOADER =
00159 TRUE.equals(System.getProperty("org.knopflerfish.osgi.setcontextclassloader", FALSE));
00160
00161 final static boolean REGISTERSERVICEURLHANDLER =
00162 TRUE.equals(System.getProperty("org.knopflerfish.osgi.registerserviceurlhandler", TRUE));
00163
00164
00165
00166 static boolean bIsMemoryStorage ;
00167
00168 private static final String USESTARTLEVEL_PROP = "org.knopflerfish.startlevel.use";
00169
00173 private final static String CLASSPATH_DIR = "classpath";
00174 private final static String BOOT_CLASSPATH_FILE = "boot";
00175 private final static String FRAMEWORK_CLASSPATH_FILE = "framework";
00176
00181 private Set eeCacheSet = new HashSet();
00182 private String eeCache = null;
00183
00188 static boolean SUPPORTS_EXTENSION_BUNDLES;
00189
00190 final static boolean EXIT_ON_SHUTDOWN =
00191 TRUE.equals(System.getProperty(Main.EXITONSHUTDOWN_PROP, TRUE));
00192
00193 final static int EXIT_CODE_NORMAL = 0;
00194 final static int EXIT_CODE_RESTART = 200;
00195
00196 final static boolean USING_WRAPPER_SCRIPT = TRUE.equals(System.getProperty(Main.USINGWRAPPERSCRIPT_PROP, FALSE));
00197
00202 public Framework(Object m) throws Exception {
00203
00204 String whichStorageImpl = "org.knopflerfish.framework.bundlestorage." +
00205 System.getProperty("org.knopflerfish.framework.bundlestorage", "file") +
00206 ".BundleStorageImpl";
00207
00208 bIsMemoryStorage = whichStorageImpl.equals("org.knopflerfish.framework.bundlestorage.memory.BundleStorageImpl");
00209 if (bIsMemoryStorage ||
00210 !EXIT_ON_SHUTDOWN ||
00211 !USING_WRAPPER_SCRIPT) {
00212 SUPPORTS_EXTENSION_BUNDLES = false;
00213
00214 } else {
00215 SUPPORTS_EXTENSION_BUNDLES = true;
00216 }
00217
00218 String ver = System.getProperty("os.version");
00219 if (ver != null) {
00220 int dots = 0;
00221 int i = 0;
00222 for ( ; i < ver.length(); i++) {
00223 char c = ver.charAt(i);
00224 if (Character.isDigit(c)) {
00225 continue;
00226 } else if (c == '.') {
00227 if (++dots < 3) {
00228 continue;
00229 }
00230 }
00231 break;
00232 }
00233 osVersion = ver.substring(0, i);
00234 }
00235
00236 ProtectionDomain pd = null;
00237 if (System.getSecurityManager() != null) {
00238 try {
00239 pd = getClass().getProtectionDomain();
00240 } catch (Throwable t) {
00241 if(Debug.classLoader) {
00242 Debug.println("Failed to get protection domain: " + t);
00243 }
00244 }
00245 perm = new SecurePermissionOps(this);
00246 } else {
00247 perm = new PermissionOps();
00248 }
00249
00250
00251 Class storageImpl = Class.forName(whichStorageImpl);
00252 storage = (BundleStorage)storageImpl.newInstance();
00253
00254 dataStorage = Util.getFileStorage("data");
00255 packages = new Packages(this);
00256
00257 listeners = new Listeners(perm);
00258 services = new Services(perm);
00259
00260 systemBundle = new SystemBundle(this, pd);
00261 systemBC = new BundleContextImpl(systemBundle);
00262 bundles = new Bundles(this);
00263
00264 systemBundle.setBundleContext(systemBC);
00265
00266 perm.registerService();
00267
00268 String[] classes = new String [] { PackageAdmin.class.getName() };
00269 services.register(systemBundle,
00270 classes,
00271 new PackageAdminImpl(this),
00272 null);
00273
00274 registerStartLevel();
00275
00276 urlStreamHandlerFactory = new ServiceURLStreamHandlerFactory(this);
00277 contentHandlerFactory = new ServiceContentHandlerFactory(this);
00278
00279 urlStreamHandlerFactory
00280 .setURLStreamHandler(BundleURLStreamHandler.PROTOCOL,
00281 new BundleURLStreamHandler(bundles, perm));
00282 urlStreamHandlerFactory
00283 .setURLStreamHandler(ReferenceURLStreamHandler.PROTOCOL,
00284 new ReferenceURLStreamHandler());
00285
00286
00287
00288 if(REGISTERSERVICEURLHANDLER) {
00289 try {
00290 URL.setURLStreamHandlerFactory(urlStreamHandlerFactory);
00291
00292 URLConnection.setContentHandlerFactory(contentHandlerFactory);
00293 } catch (Throwable e) {
00294 Debug.println("Cannot set global URL handlers, continuing without OSGi service URL handler (" + e + ")");
00295 e.printStackTrace();
00296 }
00297 }
00298 bundles.load();
00299
00300 mainHandle = m;
00301 }
00302
00303
00304 private void registerStartLevel(){
00305 String useStartLevel = System.getProperty(USESTARTLEVEL_PROP, TRUE);
00306
00307 if(TRUE.equals(useStartLevel)) {
00308 if(Debug.startlevel) {
00309 Debug.println("[using startlevel service]");
00310 }
00311 startLevelService = new StartLevelImpl(this);
00312
00313
00314
00315
00316 startLevelService.restoreState();
00317
00318 services.register(systemBundle,
00319 new String [] { StartLevel.class.getName() },
00320 startLevelService,
00321 null);
00322 }
00323 }
00324
00325
00354 public void launch(long startBundle) throws BundleException {
00355 if (!active) {
00356 active = true;
00357 if (startBundle > 0) {
00358 startBundle(startBundle);
00359 } else {
00360 for (Iterator i = storage.getStartOnLaunchBundles().iterator(); i.hasNext(); ) {
00361 Bundle b = bundles.getBundle((String)i.next());
00362 try {
00363 b.start();
00364 } catch (BundleException be) {
00365 listeners.frameworkError(b, be);
00366 }
00367 }
00368 }
00369 systemBundle.systemActive();
00370
00371
00372
00373 if (startLevelService != null) {
00374 startLevelService.open();
00375 }
00376
00377 listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.STARTED, systemBundle, null));
00378 }
00379 }
00380
00381
00400 public void shutdown() {
00401 if (active) {
00402
00403
00404 active = false;
00405 List slist = storage.getStartOnLaunchBundles();
00406 shuttingdown = true;
00407 systemBundle.systemShuttingdown();
00408 if (startLevelService != null) {
00409 startLevelService.shutdown();
00410 }
00411
00412 for (int i = slist.size()-1; i >= 0; i--) {
00413 Bundle b = bundles.getBundle((String)slist.get(i));
00414 try {
00415 if(b != null) {
00416 synchronized (b) {
00417 if (b.getState() == Bundle.ACTIVE) {
00418 b.stop();
00419 }
00420 }
00421 }
00422 } catch (BundleException be) {
00423 listeners.frameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, b, be));
00424 }
00425 }
00426 shuttingdown = false;
00427
00428 List all = bundles.getBundles();
00429 for (Iterator i = all.iterator(); i.hasNext(); ) {
00430 ((BundleImpl)i.next()).purge();
00431 }
00432 }
00433
00434 StringBuffer bootClasspath = new StringBuffer();
00435 StringBuffer frameworkClasspath = new StringBuffer();
00436 for (Iterator i = bundles.getFragmentBundles(systemBundle).iterator(); i.hasNext(); ) {
00437 BundleImpl eb = (BundleImpl)i.next();
00438 String path = eb.archive.getJarLocation();
00439 StringBuffer sb = eb.isBootClassPathExtension() ? bootClasspath : frameworkClasspath;
00440 sb.append(path);
00441 if (i.hasNext()) {
00442 sb.append(File.pathSeparator);
00443 }
00444 }
00445
00446 try {
00447 FileTree storage = Util.getFileStorage(CLASSPATH_DIR);
00448 File bcpf = new File(storage, BOOT_CLASSPATH_FILE);
00449 File fcpf = new File(storage, FRAMEWORK_CLASSPATH_FILE);
00450 if (bootClasspath.length() > 0) {
00451 saveStringBuffer(bcpf, bootClasspath);
00452 } else {
00453 bcpf.delete();
00454 }
00455 if (frameworkClasspath.length() > 0) {
00456 saveStringBuffer(fcpf, frameworkClasspath);
00457 } else {
00458 fcpf.delete();
00459 }
00460 } catch (IOException e) {
00461 System.err.println("Could not save classpath " + e);
00462 }
00463 }
00464
00465
00466 private void saveStringBuffer(File f, StringBuffer content) throws IOException {
00467 PrintStream out = null;
00468 try {
00469 out = new PrintStream(new FileOutputStream(f));
00470 out.println(content.toString());
00471 } finally {
00472 if (out != null) {
00473 out.close();
00474 }
00475 }
00476 }
00477
00478
00487 public long installBundle(String location, InputStream in) throws BundleException {
00488 return bundles.install(location, in).id;
00489 }
00490
00491
00498 public void startBundle(long id) throws BundleException {
00499 Bundle b = bundles.getBundle(id);
00500 if (b != null) {
00501 b.start();
00502 } else {
00503 throw new BundleException("No such bundle: " + id);
00504 }
00505 }
00506
00507
00514 public void stopBundle(long id) throws BundleException {
00515 Bundle b = bundles.getBundle(id);
00516 if (b != null) {
00517 b.stop();
00518 } else {
00519 throw new BundleException("No such bundle: " + id);
00520 }
00521 }
00522
00523
00530 public void uninstallBundle(long id) throws BundleException {
00531 Bundle b = bundles.getBundle(id);
00532 if (b != null) {
00533 b.uninstall();
00534 } else {
00535 throw new BundleException("No such bundle: " + id);
00536 }
00537 }
00538
00539
00546 public void updateBundle(long id) throws BundleException {
00547 Bundle b = bundles.getBundle(id);
00548 if (b != null) {
00549 b.update();
00550 } else {
00551 throw new BundleException("No such bundle: " + id);
00552 }
00553 }
00554
00555
00564 public String getBundleLocation(long id) {
00565 Bundle b = bundles.getBundle(id);
00566 if (b != null) {
00567 return b.getLocation();
00568 } else {
00569 return null;
00570 }
00571 }
00572
00581 public long getBundleId(String location) {
00582 Bundle b = bundles.getBundle(location);
00583 if (b != null) {
00584 return b.getBundleId();
00585 } else {
00586 return -1;
00587 }
00588 }
00589
00593 public FileTree getDataStorage(long id) {
00594 if (dataStorage != null) {
00595 return new FileTree(dataStorage, Long.toString(id));
00596 }
00597 return null;
00598 }
00599
00603 boolean isValidEE(String ee) {
00604 ee = ee.trim();
00605 if(ee == null || "".equals(ee)) {
00606 return true;
00607 }
00608
00609 String fwEE = System.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
00610
00611 if(fwEE == null) {
00612
00613 return true;
00614 } else if (!fwEE.equals(eeCache)) {
00615 eeCacheSet.clear();
00616
00617 String[] l = Util.splitwords(fwEE, ",");
00618 for(int i = 0 ; i < l.length; i++) {
00619 eeCacheSet.add(l[i]);
00620 }
00621 eeCache = fwEE;
00622 }
00623
00624 String[] eel = Util.splitwords(ee, ",");
00625 for(int i = 0 ; i < eel.length; i++) {
00626 if(eeCacheSet.contains(eel[i])) {
00627 return true;
00628 }
00629 }
00630 return false;
00631 }
00632
00633
00634
00635
00636
00641 public static String getProperty(String key) {
00642 if (Constants.FRAMEWORK_VERSION.equals(key)) {
00643
00644 return SPEC_VERSION;
00645 } else if (Constants.FRAMEWORK_VENDOR.equals(key)) {
00646
00647 return "Knopflerfish";
00648 } else if (Constants.FRAMEWORK_LANGUAGE.equals(key)) {
00649
00650 return Locale.getDefault().getLanguage();
00651 } else if (Constants.FRAMEWORK_OS_NAME.equals(key)) {
00652
00653 return osName;
00654 } else if (Constants.FRAMEWORK_OS_VERSION.equals(key)) {
00655
00656 return osVersion;
00657 } else if (Constants.FRAMEWORK_PROCESSOR.equals(key)) {
00658
00659 return osArch;
00660 } else if (Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE.equals(key)) {
00661 return TRUE;
00662 } else if (Constants.SUPPORTS_FRAMEWORK_FRAGMENT.equals(key)) {
00663 return TRUE;
00664 } else if (Constants.SUPPORTS_FRAMEWORK_EXTENSION.equals(key)) {
00665 return SUPPORTS_EXTENSION_BUNDLES ? TRUE : FALSE;
00666 } else if (Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION.equals(key)) {
00667 return SUPPORTS_EXTENSION_BUNDLES ? TRUE : FALSE;
00668 } else {
00669 return System.getProperty(key);
00670 }
00671 }
00672
00673 public static Dictionary getProperties(){
00674 Dictionary props = System.getProperties();
00675 props.put(Constants.FRAMEWORK_VERSION, SPEC_VERSION);
00676 props.put(Constants.FRAMEWORK_VENDOR, "Knopflerfish");
00677 props.put(Constants.FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage());
00678 props.put(Constants.FRAMEWORK_OS_NAME, osName);
00679 props.put(Constants.FRAMEWORK_OS_VERSION, osVersion);
00680 props.put(Constants.FRAMEWORK_PROCESSOR, osArch);
00681 props.put(Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, TRUE);
00682 props.put(Constants.SUPPORTS_FRAMEWORK_FRAGMENT, TRUE);
00683 props.put(Constants.SUPPORTS_FRAMEWORK_EXTENSION, SUPPORTS_EXTENSION_BUNDLES ? TRUE : FALSE);
00684 props.put(Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, SUPPORTS_EXTENSION_BUNDLES ? TRUE : FALSE);
00685 return props;
00686 }
00687
00691 public BundleContext getSystemBundleContext() {
00692 return systemBC;
00693 }
00694 }