1 11 12 package org.eclipse.osgi.internal.baseadaptor; 13 14 import java.io.*; 15 import java.lang.reflect.InvocationTargetException ; 16 import java.lang.reflect.Method ; 17 import java.net.*; 18 import java.util.*; 19 import org.eclipse.core.runtime.adaptor.EclipseStarter; 20 import org.eclipse.core.runtime.adaptor.LocationManager; 21 import org.eclipse.core.runtime.internal.adaptor.EclipseAdaptorMsg; 22 import org.eclipse.osgi.baseadaptor.*; 23 import org.eclipse.osgi.baseadaptor.bundlefile.*; 24 import org.eclipse.osgi.baseadaptor.hooks.*; 25 import org.eclipse.osgi.framework.adaptor.*; 26 import org.eclipse.osgi.framework.debug.Debug; 27 import org.eclipse.osgi.framework.debug.FrameworkDebugOptions; 28 import org.eclipse.osgi.framework.internal.core.*; 29 import org.eclipse.osgi.framework.internal.core.Constants; 30 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 31 import org.eclipse.osgi.framework.util.KeyedHashSet; 32 import org.eclipse.osgi.service.datalocation.Location; 33 import org.eclipse.osgi.service.resolver.*; 34 import org.eclipse.osgi.storagemanager.ManagedOutputStream; 35 import org.eclipse.osgi.storagemanager.StorageManager; 36 import org.eclipse.osgi.util.ManifestElement; 37 import org.eclipse.osgi.util.NLS; 38 import org.osgi.framework.*; 39 40 public class BaseStorage implements SynchronousBundleListener { 41 private static final String RUNTIME_ADAPTOR = FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME + "/eclipseadaptor"; private static final String OPTION_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/debug/platformadmin"; private static final String OPTION_PLATFORM_ADMIN_RESOLVER = RUNTIME_ADAPTOR + "/debug/platformadmin/resolver"; private static final String OPTION_MONITOR_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/resolver/timing"; private static final String OPTION_RESOLVER_READER = RUNTIME_ADAPTOR + "/resolver/reader/timing"; private static final String PROP_FRAMEWORK_EXTENSIONS = "osgi.framework.extensions"; private static final String PROP_BUNDLE_STORE = "osgi.bundlestore"; static final String DATA_DIR_NAME = "data"; static final String LIB_TEMP = "libtemp"; private static final String PROP_ENABLE_STATE_SAVER = "eclipse.enableStateSaver"; static final String BUNDLEFILE_NAME = "bundlefile"; private static final String PROP_CLEAN = "osgi.clean"; 57 58 public static final byte BUNDLEDATA_VERSION = 18; 59 62 public static final byte EXTENSION_INITIALIZE = 0x01; 63 66 public static final byte EXTENSION_INSTALLED = 0x02; 67 70 public static final byte EXTENSION_UNINSTALLED = 0x04; 71 74 public static final byte EXTENSION_UPDATED = 0x08; 75 76 81 public static final String DELETE_FLAG = ".delete"; private static final String PERM_DATA_FILE = ".permdata"; private static final byte PERMDATA_VERSION = 1; 84 85 private BaseAdaptor adaptor; 86 private String installPath; 88 private StorageManager storageManager; 89 private StateManager stateManager; 90 private KeyedHashSet storageHooks = new KeyedHashSet(5, false); 92 private BundleContext context; 93 private SynchronousBundleListener extensionListener; 94 95 98 private Method addURLMethod; 99 102 private String [] configuredExtensions; 103 104 private long timeStamp = 0; 105 private int initialBundleStartLevel = 1; 106 private long nextId = 1; 107 110 private File bundleStoreRoot; 111 112 private BasePermissionStorage permissionStorage; 113 private StateSaver stateSaver; 114 private boolean invalidState; 115 private boolean storageManagerClosed; 116 117 BaseStorage() { 118 } 120 121 public void initialize(BaseAdaptor adaptor) throws IOException { 122 this.adaptor = adaptor; 123 setDebugOptions(); 124 if (Boolean.valueOf(FrameworkProperties.getProperty(BaseStorage.PROP_CLEAN)).booleanValue()) 125 cleanOSGiCache(); 126 ClassLoader fwloader = BaseStorage.class.getClassLoader(); 128 if (fwloader != null) 129 addURLMethod = findaddURLMethod(fwloader.getClass()); 130 Location installLoc = LocationManager.getInstallLocation(); 133 if (installLoc != null) { 134 URL installURL = installLoc.getURL(); 135 installPath = installURL.getPath(); 137 } 138 boolean readOnlyConfiguration = LocationManager.getConfigurationLocation().isReadOnly(); 139 storageManager = initFileManager(LocationManager.getOSGiConfigurationDir(), readOnlyConfiguration ? "none" : null, readOnlyConfiguration); storageManagerClosed = false; 141 StorageHook[] hooks = adaptor.getHookRegistry().getStorageHooks(); 143 for (int i = 0; i < hooks.length; i++) 144 storageHooks.add(hooks[i]); 145 } 146 147 private void setDebugOptions() { 148 FrameworkDebugOptions options = FrameworkDebugOptions.getDefault(); 149 if (options == null) 151 return; 152 StateManager.DEBUG = options != null; 153 StateManager.DEBUG_READER = options.getBooleanOption(OPTION_RESOLVER_READER, false); 154 StateManager.MONITOR_PLATFORM_ADMIN = options.getBooleanOption(OPTION_MONITOR_PLATFORM_ADMIN, false); 155 StateManager.DEBUG_PLATFORM_ADMIN = options.getBooleanOption(OPTION_PLATFORM_ADMIN, false); 156 StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER = options.getBooleanOption(OPTION_PLATFORM_ADMIN_RESOLVER, false); 157 } 158 159 protected StorageManager initFileManager(File baseDir, String lockMode, boolean readOnly) { 160 StorageManager sManager = new StorageManager(baseDir, lockMode, readOnly); 161 try { 162 sManager.open(!readOnly); 163 } catch (IOException ex) { 164 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 165 Debug.println("Error reading framework metadata: " + ex.getMessage()); Debug.printStackTrace(ex); 167 } 168 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, ex.getMessage()); 169 FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, ex, null); 170 adaptor.getFrameworkLog().log(logEntry); 171 } 172 return sManager; 173 } 174 175 public boolean isReadOnly() { 176 return storageManager.isReadOnly(); 177 } 178 179 public void compact() throws IOException { 180 if (!isReadOnly()) 181 compact(getBundleStoreRoot()); 182 } 183 184 private void compact(File directory) { 185 if (Debug.DEBUG && Debug.DEBUG_GENERAL) 186 Debug.println("compact(" + directory.getPath() + ")"); String list[] = directory.list(); 188 if (list == null) 189 return; 190 191 int len = list.length; 192 for (int i = 0; i < len; i++) { 193 if (BaseStorage.DATA_DIR_NAME.equals(list[i])) 194 continue; 195 File target = new File(directory, list[i]); 196 if (!target.isDirectory()) 198 continue; 199 File delete = new File(target, BaseStorage.DELETE_FLAG); 200 if (delete.exists()) { 202 if (!AdaptorUtil.rm(target) && !delete.exists()) { 204 try { 205 FileOutputStream out = new FileOutputStream(delete); 207 out.close(); 208 } catch (IOException e) { 209 if (Debug.DEBUG && Debug.DEBUG_GENERAL) 210 Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); } 212 } 213 } else { 214 compact(target); 215 } 216 } 217 } 218 219 public long getFreeSpace() throws IOException { 220 return -1; 222 } 223 224 public File getDataFile(BaseData data, String path) { 225 BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY); 226 if (storageHook == null) 227 return null; 228 return storageHook.getDataFile(path); 229 } 230 231 BaseAdaptor getAdaptor() { 232 return adaptor; 233 } 234 235 public void installNativeCode(BaseData data, String [] nativepaths) throws BundleException { 236 if (nativepaths.length > 0) { 237 BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY); 238 if (storageHook != null) 239 storageHook.installNativePaths(nativepaths); 240 } 241 } 242 243 public Dictionary loadManifest(BaseData data) throws BundleException { 244 return loadManifest(data, false); 245 } 246 247 public Dictionary loadManifest(BaseData bundleData, boolean firstTime) throws BundleException { 248 Dictionary result = null; 249 StorageHook[] dataStorageHooks = bundleData.getStorageHooks(); 250 for (int i = 0; i < dataStorageHooks.length && result == null; i++) 251 result = dataStorageHooks[i].getManifest(firstTime); 252 if (result == null) 253 result = AdaptorUtil.loadManifestFrom(bundleData); 254 if (result == null) 255 throw new BundleException(NLS.bind(AdaptorMsg.MANIFEST_NOT_FOUND_EXCEPTION, Constants.OSGI_BUNDLE_MANIFEST, bundleData.getLocation())); 256 return result; 257 } 258 259 public File getExtractFile(BaseData data, String path) { 260 BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY); 261 if (storageHook == null) 262 return null; 263 File childGenDir = storageHook.getGenerationDir(); 265 if (childGenDir != null) { 266 File childPath = new File(childGenDir, path); 267 if (childPath.exists()) 268 return childPath; 269 } 270 File parentGenDir = storageHook.getParentGenerationDir(); 272 if (parentGenDir != null) { 273 File parentPath = new File(parentGenDir, path); 275 if (parentPath.exists()) 276 return parentPath; 278 } 279 File bundleGenerationDir = storageHook.createGenerationDir(); 281 282 if (bundleGenerationDir != null && bundleGenerationDir.exists()) 283 return new File(bundleGenerationDir, path); 284 return null; 285 } 286 287 public BaseData[] getInstalledBundles() { 288 return readBundleDatas(); 289 } 290 291 private BaseData[] readBundleDatas() { 292 InputStream bundleDataStream = findStorageStream(LocationManager.BUNDLE_DATA_FILE); 293 if (bundleDataStream == null) 294 return null; 295 try { 296 DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream)); 297 try { 298 byte version = in.readByte(); 299 if (version != BUNDLEDATA_VERSION) 300 return null; 301 timeStamp = in.readLong(); 302 initialBundleStartLevel = in.readInt(); 303 nextId = in.readLong(); 304 305 int numStorageHooks = in.readInt(); 306 StorageHook[] storageHooks = adaptor.getHookRegistry().getStorageHooks(); 307 if (numStorageHooks != storageHooks.length) 308 return null; for (int i = 0; i < numStorageHooks; i++) { 310 Object storageKey = storageHooks[i].getKey(); 311 int storageVersion = storageHooks[i].getStorageVersion(); 312 if (!storageKey.equals(in.readUTF()) || storageVersion != in.readInt()) 313 return null; } 315 316 int bundleCount = in.readInt(); 317 ArrayList result = new ArrayList(bundleCount); 318 long id = -1; 319 boolean bundleDiscarded = false; 320 for (int i = 0; i < bundleCount; i++) { 321 boolean error = false; 322 BaseData data = null; 323 try { 324 id = in.readLong(); 325 if (id != 0) { 326 data = loadBaseData(id, in); 327 data.getBundleFile(); 328 StorageHook[] dataStorageHooks = data.getStorageHooks(); 329 for (int j = 0; j < dataStorageHooks.length; j++) 330 dataStorageHooks[j].validate(); 331 if (Debug.DEBUG && Debug.DEBUG_GENERAL) 332 Debug.println("BundleData created: " + data); processExtension(data, EXTENSION_INITIALIZE); 334 result.add(data); 335 } 336 } catch (IllegalArgumentException e) { 337 bundleDiscarded = true; 339 error = true; 340 } catch (BundleException e) { 341 bundleDiscarded = true; 343 error = true; 344 } catch (IOException e) { 345 bundleDiscarded = true; 346 error = true; 347 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 348 Debug.println("Error reading framework metadata: " + e.getMessage()); Debug.printStackTrace(e); 350 } 351 } 352 if (error && data != null) { 353 BaseStorageHook storageHook = (BaseStorageHook) data.getStorageHook(BaseStorageHook.KEY); 354 storageHook.delete(true, BaseStorageHook.DEL_BUNDLE_STORE); 355 } 356 } 357 if (bundleDiscarded) 358 FrameworkProperties.setProperty(EclipseStarter.PROP_REFRESH_BUNDLES, "true"); return (BaseData[]) result.toArray(new BaseData[result.size()]); 360 } finally { 361 in.close(); 362 } 363 } catch (IOException e) { 364 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 365 Debug.println("Error reading framework metadata: " + e.getMessage()); Debug.printStackTrace(e); 367 } 368 } 369 return null; 370 } 371 372 private void saveAllData(boolean shutdown) { 373 if (storageManagerClosed) 374 try { 375 storageManager.open(!LocationManager.getConfigurationLocation().isReadOnly()); 376 storageManagerClosed = false; 377 } catch (IOException e) { 378 String message = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, e.getMessage()); 379 FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, message, 0, e, null); 380 adaptor.getFrameworkLog().log(logEntry); 381 } 382 saveBundleDatas(); 383 saveStateData(shutdown); 384 savePermissionStorage(); 385 if (shutdown) 386 stateManager.stopDataManager(); 387 } 388 389 private BasePermissionStorage readPermissionData() { 390 BasePermissionStorage result = new BasePermissionStorage(this); 391 InputStream permDataStream = findStorageStream(PERM_DATA_FILE); 392 if (permDataStream == null) 393 return result; 394 try { 395 DataInputStream in = new DataInputStream(new BufferedInputStream(permDataStream)); 396 try { 397 if (PERMDATA_VERSION != in.readByte()) 398 return result; 399 int numPerms = in.readInt(); 401 if (numPerms > 0) { 402 String [] perms = new String [numPerms]; 403 for (int i = 0; i < numPerms; i++) 404 perms[i] = in.readUTF(); 405 result.setPermissionData(null, perms); 406 } 407 int numLocs = in.readInt(); 408 if (numLocs > 0) 409 for (int i = 0; i < numLocs; i++) { 410 String loc = in.readUTF(); 411 numPerms = in.readInt(); 412 String [] perms = new String [numPerms]; 413 for (int j = 0; j < numPerms; j++) 414 perms[j] = in.readUTF(); 415 result.setPermissionData(loc, perms); 416 } 417 int numCondPerms = in.readInt(); 418 if (numCondPerms > 0) { 419 String [] condPerms = new String [numCondPerms]; 420 for (int i = 0; i < numCondPerms; i++) 421 condPerms[i] = in.readUTF(); 422 result.saveConditionalPermissionInfos(condPerms); 423 } 424 result.setDirty(false); 425 } finally { 426 in.close(); 427 } 428 } catch (IOException e) { 429 adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); 430 } 431 return result; 432 } 433 434 private void savePermissionStorage() { 435 if (permissionStorage == null || isReadOnly() || !permissionStorage.isDirty()) 436 return; 437 try { 438 ManagedOutputStream fmos = storageManager.getOutputStream(PERM_DATA_FILE); 439 DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fmos)); 440 boolean error = true; 441 try { 442 out.writeByte(PERMDATA_VERSION); 443 String [] defaultPerms = permissionStorage.getPermissionData(null); 445 out.writeInt(defaultPerms == null ? 0 : defaultPerms.length); 446 if (defaultPerms != null) 447 for (int i = 0; i < defaultPerms.length; i++) 448 out.writeUTF(defaultPerms[i]); 449 String [] locations = permissionStorage.getLocations(); 450 out.writeInt(locations == null ? 0 : locations.length); 451 if (locations != null) 452 for (int i = 0; i < locations.length; i++) { 453 out.writeUTF(locations[i]); 454 String [] perms = permissionStorage.getPermissionData(locations[i]); 455 out.writeInt(perms == null ? 0 : perms.length); 456 if (perms != null) 457 for (int j = 0; j < perms.length; j++) 458 out.writeUTF(perms[j]); 459 } 460 String [] condPerms = permissionStorage.getConditionalPermissionInfos(); 461 out.writeInt(condPerms == null ? 0 : condPerms.length); 462 if (condPerms != null) 463 for (int i = 0; i < condPerms.length; i++) 464 out.writeUTF(condPerms[i]); 465 out.close(); 466 permissionStorage.setDirty(false); 467 error = false; 468 } finally { 469 if (error) { 471 fmos.abort(); 472 try { 473 out.close(); 474 } catch (IOException e) { 475 } 476 } 477 } 478 } catch (IOException e) { 479 adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); 480 return; 481 } 482 } 483 484 private void saveBundleDatas() { 485 if (stateManager == null || isReadOnly() || (timeStamp == stateManager.getSystemState().getTimeStamp() && !stateManager.saveNeeded())) 487 return; 488 try { 489 ManagedOutputStream fmos = storageManager.getOutputStream(LocationManager.BUNDLE_DATA_FILE); 490 DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fmos)); 491 boolean error = true; 492 try { 493 out.writeByte(BUNDLEDATA_VERSION); 494 out.writeLong(stateManager.getSystemState().getTimeStamp()); 495 out.writeInt(initialBundleStartLevel); 496 out.writeLong(nextId); 497 498 StorageHook[] storageHooks = adaptor.getHookRegistry().getStorageHooks(); 499 out.writeInt(storageHooks.length); 500 for (int i = 0; i < storageHooks.length; i++) { 501 out.writeUTF((String ) storageHooks[i].getKey()); 502 out.writeInt(storageHooks[i].getStorageVersion()); 503 } 504 505 Bundle[] bundles = context.getBundles(); 506 out.writeInt(bundles.length); 507 for (int i = 0; i < bundles.length; i++) { 508 long id = bundles[i].getBundleId(); 509 out.writeLong(id); 510 if (id != 0) { 511 BundleData data = ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundles[i]).getBundleData(); 512 saveBaseData((BaseData) data, out); 513 } 514 } 515 out.close(); 516 timeStamp = stateManager.getSystemState().getTimeStamp(); 518 error = false; 519 } finally { 520 if (error) { 522 fmos.abort(); 523 try { 524 out.close(); 525 } catch (IOException e) { 526 } 527 } 528 } 529 } catch (IOException e) { 530 adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); 531 return; 532 } 533 } 534 535 private void saveStateData(boolean shutdown) { 536 if (stateManager == null || isReadOnly() || !stateManager.saveNeeded()) 537 return; 538 try { 539 File stateTmpFile = File.createTempFile(LocationManager.STATE_FILE, ".new", LocationManager.getOSGiConfigurationDir()); File lazyTmpFile = File.createTempFile(LocationManager.LAZY_FILE, ".new", LocationManager.getOSGiConfigurationDir()); if (shutdown) 542 stateManager.shutdown(stateTmpFile, lazyTmpFile); 543 else 544 synchronized (stateManager) { 545 stateManager.update(stateTmpFile, lazyTmpFile); 546 } 547 storageManager.lookup(LocationManager.STATE_FILE, true); 548 storageManager.lookup(LocationManager.LAZY_FILE, true); 549 storageManager.update(new String [] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE}, new String [] {stateTmpFile.getName(), lazyTmpFile.getName()}); 550 } catch (IOException e) { 551 adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); 552 } 553 } 554 555 public PermissionStorage getPermissionStorage() throws IOException { 556 if (permissionStorage == null) 557 permissionStorage = readPermissionData(); 558 return permissionStorage; 559 } 560 561 public int getInitialBundleStartLevel() { 562 return initialBundleStartLevel; 563 } 564 565 public void setInitialBundleStartLevel(int value) { 566 this.initialBundleStartLevel = value; 567 requestSave(); 568 } 569 570 public void save(BaseData data) throws IOException { 571 if (data.isDirty()) { 572 timeStamp--; requestSave(); 574 data.setDirty(false); 575 } 576 } 577 578 public BundleOperation installBundle(String location, URLConnection source) { 579 BaseData data = createBaseData(getNextBundleId(), location); 580 return new BundleInstall(data, source, this); 581 } 582 583 public BundleOperation updateBundle(BaseData data, URLConnection source) { 584 return new BundleUpdate(data, source, this); 585 } 586 587 public BundleOperation uninstallBundle(BaseData data) { 588 return new BundleUninstall(data, this); 589 } 590 591 protected Object getBundleContent(BaseData bundledata) throws IOException { 592 BaseStorageHook storageHook = (BaseStorageHook) bundledata.getStorageHook(BaseStorageHook.KEY); 593 if (storageHook == null) 594 throw new IllegalStateException (); 595 return storageHook.isReference() ? new File(storageHook.getFileName()) : new File(storageHook.getGenerationDir(), storageHook.getFileName()); 596 } 597 598 public BundleFile createBundleFile(Object content, BaseData data) throws IOException { 599 boolean base = false; 600 if (content == null) { 601 base = true; 603 content = getBundleContent(data); 605 } 606 BundleFile result = null; 607 BundleFileFactoryHook[] factories = adaptor.getHookRegistry().getBundleFileFactoryHooks(); 609 for (int i = 0; i < factories.length && result == null; i++) 610 result = factories[i].createBundleFile(content, data, base); 611 612 if (result == null && content instanceof File) { 614 File file = (File) content; 615 if (file.isDirectory()) 616 result = new DirBundleFile(file); 617 else 618 result = new ZipBundleFile(file, data); 619 } 620 621 if (result == null && content instanceof String ) { 622 result = new NestedDirBundleFile(data.getBundleFile(), (String ) content); 624 } 625 if (result == null) 626 throw new IOException("Cannot create bundle file for content of type: " + content.getClass().getName()); 629 BundleFileWrapperFactoryHook[] wrapperFactories = adaptor.getHookRegistry().getBundleFileWrapperFactoryHooks(); 631 for (int i = 0; i < wrapperFactories.length; i++) { 632 BundleFile wrapperBundle = wrapperFactories[i].wrapBundleFile(result, content, data, base); 633 if (wrapperBundle != null) 634 result = wrapperBundle; 635 } 636 return result; 637 } 638 639 public synchronized StateManager getStateManager() { 640 if (stateManager != null) 641 return stateManager; 642 stateManager = readStateData(); 643 checkSystemState(stateManager.getSystemState()); 644 return stateManager; 645 } 646 647 private void checkSystemState(State state) { 648 BundleDescription[] bundles = state.getBundles(); 649 if (bundles == null) 650 return; 651 boolean removedBundle = false; 652 for (int i = 0; i < bundles.length; i++) { 653 if (context.getBundle(bundles[i].getBundleId()) == null) { 654 state.removeBundle(bundles[i]); 655 removedBundle = true; 656 } 657 } 658 if (removedBundle) 659 state.resolve(false); BundleDescription systemBundle = state.getBundle(0); 661 if (systemBundle == null || !systemBundle.isResolved()) { 662 ResolverError[] errors = systemBundle == null ? new ResolverError[0] : state.getResolverErrors(systemBundle); 663 StringBuffer sb = new StringBuffer (); 664 for (int i = 0; i < errors.length; i++) { 665 sb.append(errors[i].toString()); 666 if (i < errors.length - 1) 667 sb.append(", "); } 669 throw new IllegalStateException (NLS.bind(AdaptorMsg.SYSTEMBUNDLE_NOTRESOLVED, sb.toString())); 671 } 672 } 673 674 private StateManager readStateData() { 675 File[] stateFiles = findStorageFiles(new String [] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE}); 676 File stateFile = stateFiles[0]; 677 File lazyFile = stateFiles[1]; 678 679 stateManager = new StateManager(stateFile, lazyFile, context, timeStamp); 680 State systemState = null; 681 if (!invalidState) { 682 systemState = stateManager.readSystemState(); 683 if (systemState != null) 684 return stateManager; 685 } 686 systemState = stateManager.createSystemState(); 687 Bundle[] installedBundles = context.getBundles(); 688 if (installedBundles == null) 689 return stateManager; 690 StateObjectFactory factory = stateManager.getFactory(); 691 for (int i = 0; i < installedBundles.length; i++) { 692 AbstractBundle toAdd = (AbstractBundle) installedBundles[i]; 693 try { 694 Dictionary toAddManifest = loadManifest((BaseData) toAdd.getBundleData(), true); 696 BundleDescription newDescription = factory.createBundleDescription(systemState, toAddManifest, toAdd.getLocation(), toAdd.getBundleId()); 697 systemState.addBundle(newDescription); 698 } catch (BundleException be) { 699 } 701 } 702 systemState.resolve(); 705 invalidState = false; 706 return stateManager; 707 } 708 709 private File[] findStorageFiles(String [] fileNames) { 710 File[] storageFiles = new File[fileNames.length]; 711 try { 712 for (int i = 0; i < storageFiles.length; i++) 713 storageFiles[i] = storageManager.lookup(fileNames[i], false); 714 } catch (IOException ex) { 715 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 716 Debug.println("Error reading state file " + ex.getMessage()); Debug.printStackTrace(ex); 718 } 719 } 720 boolean success = true; 721 for (int i = 0; i < storageFiles.length; i++) 722 if (storageFiles[i] == null || !storageFiles[i].isFile()) { 723 success = false; 724 break; 725 } 726 if (success) 727 return storageFiles; 728 Location parentConfiguration = null; 730 Location currentConfiguration = LocationManager.getConfigurationLocation(); 731 if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) { 732 try { 733 File stateLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME); 734 StorageManager newFileManager = initFileManager(stateLocationDir, "none", true); for (int i = 0; i < storageFiles.length; i++) 736 storageFiles[i] = newFileManager.lookup(fileNames[i], false); 737 newFileManager.close(); 738 } catch (IOException ex) { 739 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 740 Debug.println("Error reading state file " + ex.getMessage()); Debug.printStackTrace(ex); 742 } 743 } 744 } else { 745 try { 746 if (!isReadOnly()) { 748 for (int i = 0; i < storageFiles.length; i++) 749 storageFiles[i] = storageManager.lookup(fileNames[i], true); 750 } 751 } catch (IOException ex) { 752 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 753 Debug.println("Error reading state file " + ex.getMessage()); Debug.printStackTrace(ex); 755 } 756 } 757 } 758 return storageFiles; 759 } 760 761 public void frameworkStart(BundleContext fwContext) throws BundleException { 762 this.context = fwContext; 763 if (Boolean.valueOf(FrameworkProperties.getProperty(BaseStorage.PROP_ENABLE_STATE_SAVER, "true")).booleanValue()) stateSaver = new StateSaver(); 766 767 } 768 769 public void frameworkStop(BundleContext fwContext) throws BundleException { 770 if (stateSaver != null) 771 stateSaver.shutdown(); 772 saveAllData(true); 773 storageManager.close(); 774 storageManagerClosed = true; 775 if (extensionListener != null) 776 context.removeBundleListener(extensionListener); 777 } 778 779 public void frameworkStopping(BundleContext fwContext) { 780 } 782 783 public void addProperties(Properties properties) { 784 if (addURLMethod != null) 786 properties.put(Constants.SUPPORTS_FRAMEWORK_EXTENSION, "true"); properties.put(BaseStorage.PROP_BUNDLE_STORE, getBundleStoreRoot().getAbsolutePath()); 789 } 790 791 private InputStream findStorageStream(String fileName) { 792 InputStream storageStream = null; 793 try { 794 storageStream = storageManager.getInputStream(fileName); 795 } catch (IOException ex) { 796 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 797 Debug.println("Error reading framework metadata: " + ex.getMessage()); Debug.printStackTrace(ex); 799 } 800 } 801 if (storageStream == null) { 802 Location currentConfiguration = LocationManager.getConfigurationLocation(); 803 Location parentConfiguration = null; 804 if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) { 805 try { 806 File bundledataLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME); 807 StorageManager newStorageManager = initFileManager(bundledataLocationDir, "none", true); storageStream = newStorageManager.getInputStream(fileName); 809 newStorageManager.close(); 810 } catch (MalformedURLException e1) { 811 } catch (IOException e1) { 814 } 816 } 817 } 818 return storageStream; 819 } 820 821 protected void saveBaseData(BaseData bundledata, DataOutputStream out) throws IOException { 822 StorageHook[] hooks = bundledata.getStorageHooks(); 823 out.writeInt(hooks.length); 824 for (int i = 0; i < hooks.length; i++) { 825 out.writeUTF((String ) hooks[i].getKey()); 826 hooks[i].save(out); 827 } 828 } 829 830 protected BaseData loadBaseData(long id, DataInputStream in) throws IOException { 831 BaseData result = new BaseData(id, adaptor); 832 int numHooks = in.readInt(); 833 StorageHook[] hooks = new StorageHook[numHooks]; 834 for (int i = 0; i < numHooks; i++) { 835 String hookKey = in.readUTF(); 836 StorageHook storageHook = (StorageHook) storageHooks.getByKey(hookKey); 837 if (storageHook == null) 838 throw new IOException(); 839 hooks[i] = storageHook.load(result, in); 840 } 841 result.setStorageHooks(hooks); 842 return result; 843 } 844 845 protected BaseData createBaseData(long id, String location) { 846 BaseData result = new BaseData(id, adaptor); 847 result.setLocation(location); 848 return result; 849 } 850 851 public String getInstallPath() { 852 return installPath; 853 } 854 855 private void cleanOSGiCache() { 856 File osgiConfig = LocationManager.getOSGiConfigurationDir(); 857 if (!AdaptorUtil.rm(osgiConfig)) { 858 } 860 } 861 862 868 protected void processExtension(BaseData bundleData, byte type) throws BundleException { 869 if ((bundleData.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0) { 870 validateExtension(bundleData); 871 processFrameworkExtension(bundleData, type); 872 } else if ((bundleData.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0) { 873 validateExtension(bundleData); 874 processBootExtension(bundleData, type); 875 } 876 } 877 878 883 private void validateExtension(BundleData bundleData) throws BundleException { 884 Dictionary extensionManifest = bundleData.getManifest(); 885 if (extensionManifest.get(Constants.IMPORT_PACKAGE) != null) 886 throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_IMPORT_ERROR, bundleData.getLocation())); 887 if (extensionManifest.get(Constants.REQUIRE_BUNDLE) != null) 888 throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_REQUIRE_ERROR, bundleData.getLocation())); 889 if (extensionManifest.get(Constants.BUNDLE_NATIVECODE) != null) 890 throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_EXTENSION_NATIVECODE_ERROR, bundleData.getLocation())); 891 } 892 893 899 protected void processFrameworkExtension(BaseData bundleData, byte type) throws BundleException { 900 if (addURLMethod == null) 901 throw new BundleException("Framework extensions are not supported.", new UnsupportedOperationException ()); if ((type & (EXTENSION_UNINSTALLED | EXTENSION_UPDATED)) != 0) 903 return; 905 906 String [] extensions = getConfiguredExtensions(); 908 for (int i = 0; i < extensions.length; i++) 909 if (extensions[i].equals(bundleData.getSymbolicName())) 910 return; 911 if ((type & EXTENSION_INSTALLED) != 0) { 912 if (extensionListener == null) { 913 extensionListener = this; 915 context.addBundleListener(extensionListener); 916 } 917 return; 918 } 919 File[] files = getExtensionFiles(bundleData); 920 if (files == null) 921 return; 922 ClassLoader cl = getClass().getClassLoader(); 923 for (int i = 0; i < files.length; i++) { 924 if (files[i] == null) 925 continue; 926 Throwable exceptionLog = null; 927 try { 928 addURLMethod.invoke(cl, new Object [] {files[i].toURL()}); 929 } catch (InvocationTargetException e) { 930 exceptionLog = e.getTargetException(); 931 } catch (Throwable t) { 932 exceptionLog = t; 933 } finally { 934 if (exceptionLog != null) 935 adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundleData.getBundle(), exceptionLog); 936 } 937 } 938 try { 939 cl.loadClass("thisIsNotAClass"); } catch (ClassNotFoundException e) { 941 } 943 } 944 945 949 protected String [] getConfiguredExtensions() { 950 if (configuredExtensions != null) 951 return configuredExtensions; 952 String prop = FrameworkProperties.getProperty(BaseStorage.PROP_FRAMEWORK_EXTENSIONS); 953 if (prop == null || prop.trim().length() == 0) 954 configuredExtensions = new String [0]; 955 else 956 configuredExtensions = ManifestElement.getArrayFromList(prop); 957 return configuredExtensions; 958 } 959 960 966 protected void processBootExtension(BundleData bundleData, byte type) throws BundleException { 967 throw new BundleException("Boot classpath extensions are not supported.", new UnsupportedOperationException ()); } 969 970 private void initBundleStoreRoot() { 971 File configurationLocation = LocationManager.getOSGiConfigurationDir(); 972 if (configurationLocation != null) 973 bundleStoreRoot = new File(configurationLocation, LocationManager.BUNDLES_DIR); 974 else 975 bundleStoreRoot = new File(LocationManager.BUNDLES_DIR); 977 } 978 979 public File getBundleStoreRoot() { 980 if (bundleStoreRoot == null) 981 initBundleStoreRoot(); 982 return bundleStoreRoot; 983 } 984 985 990 protected File[] getExtensionFiles(BaseData bundleData) { 991 File[] files = null; 992 try { 993 String [] paths = bundleData.getClassPath(); 994 if (FrameworkProperties.getProperty("osgi.dev") != null) { String [] origPaths = paths; 997 paths = new String [origPaths.length + 1]; 998 System.arraycopy(origPaths, 0, paths, 0, origPaths.length); 999 paths[paths.length - 1] = "bin"; } 1001 ArrayList results = new ArrayList(paths.length); 1002 for (int i = 0; i < paths.length; i++) { 1003 if (".".equals(paths[i])) results.add(bundleData.getBundleFile().getBaseFile()); 1005 else { 1006 File result = bundleData.getBundleFile().getFile(paths[i], false); 1007 if (result != null) 1008 results.add(result); 1009 } 1010 } 1011 return (File[]) results.toArray(new File[results.size()]); 1012 } catch (BundleException e) { 1013 adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, bundleData.getBundle(), e); 1014 } 1015 return files; 1016 } 1017 1018 void requestSave() { 1019 if (stateSaver == null) 1021 return; 1022 stateSaver.requestSave(); 1023 } 1024 1025 1031 public void updateState(BundleData bundleData, int type) throws BundleException { 1032 if (stateManager == null) { 1033 invalidState = true; 1034 return; 1035 } 1036 State systemState = stateManager.getSystemState(); 1037 switch (type) { 1038 case BundleEvent.UPDATED : 1039 systemState.removeBundle(bundleData.getBundleID()); 1040 case BundleEvent.INSTALLED : 1042 BundleDescription newDescription = stateManager.getFactory().createBundleDescription(systemState, bundleData.getManifest(), bundleData.getLocation(), bundleData.getBundleID()); 1043 systemState.addBundle(newDescription); 1044 break; 1045 case BundleEvent.UNINSTALLED : 1046 systemState.removeBundle(bundleData.getBundleID()); 1047 break; 1048 } 1049 } 1050 1051 private static Method findaddURLMethod(Class clazz) { 1052 if (clazz == null) 1053 return null; try { 1055 Method result = clazz.getDeclaredMethod("addURL", new Class [] {URL.class}); result.setAccessible(true); 1057 return result; 1058 } catch (NoSuchMethodException e) { 1059 } catch (SecurityException e) { 1061 } 1063 return findaddURLMethod(clazz.getSuperclass()); 1064 } 1065 1066 private class StateSaver implements Runnable { 1067 private long delay_interval = 30000; private long max_total_delay_interval = 1800000; private boolean shutdown = false; 1070 private long lastSaveTime = 0; 1071 private Thread runningThread = null; 1072 1073 StateSaver() { 1074 String prop = FrameworkProperties.getProperty("eclipse.stateSaveDelayInterval"); if (prop != null) { 1076 try { 1077 long val = Long.parseLong(prop); 1078 if (val >= 1000 && val <= 1800000) { 1079 delay_interval = val; 1080 max_total_delay_interval = val * 60; 1081 } 1082 } catch (NumberFormatException e) { 1083 } 1085 } 1086 } 1087 1088 public void run() { 1089 State systemState = adaptor.getState(); 1090 synchronized (systemState) { 1091 long firstSaveTime = lastSaveTime; 1092 long curSaveTime = 0; 1093 long delayTime; 1094 do { 1095 do { 1096 if ((System.currentTimeMillis() - firstSaveTime) > max_total_delay_interval) { 1097 curSaveTime = lastSaveTime; 1098 break; 1100 } 1101 delayTime = Math.min(delay_interval, lastSaveTime - curSaveTime); 1102 curSaveTime = lastSaveTime; 1103 try { 1105 if (!shutdown) 1106 systemState.wait(delayTime); 1107 } catch (InterruptedException ie) { 1108 curSaveTime = lastSaveTime; 1110 break; 1111 } 1112 } while (!shutdown && curSaveTime < lastSaveTime); 1114 saveAllData(false); 1116 } while (!shutdown && curSaveTime < lastSaveTime); 1118 runningThread = null; } 1120 } 1121 1122 void shutdown() { 1123 State systemState = adaptor.getState(); 1124 Thread joinWith = null; 1125 synchronized (systemState) { 1126 shutdown = true; 1127 joinWith = runningThread; 1128 systemState.notifyAll(); } 1130 try { 1131 if (joinWith != null) 1132 joinWith.join(); 1134 } catch (InterruptedException ie) { 1135 if (Debug.DEBUG && Debug.DEBUG_GENERAL) { 1136 Debug.println("Error shutdowning StateSaver: " + ie.getMessage()); Debug.printStackTrace(ie); 1138 } 1139 } 1140 } 1141 1142 void requestSave() { 1143 State systemState = adaptor.getState(); 1144 synchronized (systemState) { 1145 lastSaveTime = System.currentTimeMillis(); 1146 if (runningThread == null) { 1147 runningThread = new Thread (this, "State Saver"); runningThread.start(); 1149 } 1150 } 1151 } 1152 } 1153 1154 public long getNextBundleId() { 1155 return nextId++; 1156 } 1157 1158 public void bundleChanged(BundleEvent event) { 1159 if (event.getType() != BundleEvent.RESOLVED) 1160 return; 1161 BaseData data = (BaseData) ((AbstractBundle) event.getBundle()).getBundleData(); 1162 try { 1163 if ((data.getType() & BundleData.TYPE_FRAMEWORK_EXTENSION) != 0) 1164 processFrameworkExtension(data, EXTENSION_INITIALIZE); 1165 else if ((data.getType() & BundleData.TYPE_BOOTCLASSPATH_EXTENSION) != 0) 1166 processBootExtension(data, EXTENSION_INITIALIZE); 1167 } catch (BundleException e) { 1168 } 1170 } 1171 1172 public String copyToTempLibrary(BaseData data, String absolutePath) throws IOException { 1173 File storageRoot = getBundleStoreRoot(); 1174 File libTempDir = new File(storageRoot, LIB_TEMP); 1175 File realLib = new File(absolutePath); 1177 String libName = realLib.getName(); 1178 File bundleTempDir = null; 1180 File libTempFile = null; 1181 Long bundleID = new Long (data.getBundleID()); 1190 for (int i = 0; i < Integer.MAX_VALUE; i++) { 1191 bundleTempDir = new File(libTempDir, bundleID.toString() + "_" + new Integer (i).toString()); libTempFile = new File(bundleTempDir, libName); 1193 if (bundleTempDir.exists()) { 1194 if (libTempFile.exists()) 1195 continue; break; 1197 } 1198 break; 1199 } 1200 if (!bundleTempDir.exists()) { 1201 bundleTempDir.mkdirs(); 1202 bundleTempDir.deleteOnExit(); 1203 File deleteFlag = new File(libTempDir, BaseStorage.DELETE_FLAG); 1206 if (!deleteFlag.exists()) { 1207 try { 1209 FileOutputStream out = new FileOutputStream(deleteFlag); 1210 out.close(); 1211 } catch (IOException e) { 1212 } 1214 } 1215 } 1216 InputStream in = new FileInputStream(realLib); 1218 AdaptorUtil.readFile(in, libTempFile); 1219 BundleFile.setPermissions(libTempFile); 1221 libTempFile.deleteOnExit(); return libTempFile.getAbsolutePath(); 1224 } 1225 1226} 1227 | Popular Tags |