| /******************************************************************************* |
| * Copyright (c) 2003, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.core.runtime.adaptor; |
| |
| import java.io.*; |
| import java.net.MalformedURLException; |
| import java.util.*; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.SAXParserFactory; |
| import org.eclipse.osgi.framework.adaptor.*; |
| import org.eclipse.osgi.framework.adaptor.core.*; |
| import org.eclipse.osgi.framework.console.CommandProvider; |
| import org.eclipse.osgi.framework.debug.Debug; |
| import org.eclipse.osgi.framework.debug.DebugOptions; |
| import org.eclipse.osgi.framework.log.FrameworkLog; |
| import org.eclipse.osgi.framework.log.FrameworkLogEntry; |
| import org.eclipse.osgi.framework.stats.StatsManager; |
| import org.eclipse.osgi.internal.resolver.StateImpl; |
| import org.eclipse.osgi.internal.resolver.StateManager; |
| import org.eclipse.osgi.service.datalocation.FileManager; |
| import org.eclipse.osgi.service.datalocation.Location; |
| import org.eclipse.osgi.service.pluginconversion.PluginConverter; |
| import org.eclipse.osgi.service.resolver.*; |
| import org.eclipse.osgi.service.urlconversion.URLConverter; |
| import org.osgi.framework.*; |
| |
| /** |
| * Internal class. |
| */ |
| public class EclipseAdaptor extends AbstractFrameworkAdaptor { |
| public static final String PROP_CLEAN = "osgi.clean"; //$NON-NLS-1$ |
| |
| public static final String PROP_EXITONERROR = "eclipse.exitOnError"; //$NON-NLS-1$ |
| |
| static final String F_LOG = ".log"; //$NON-NLS-1$ |
| |
| // TODO rename it to Eclipse-PluginClass |
| public static final String PLUGIN_CLASS = "Plugin-Class"; //$NON-NLS-1$ |
| |
| public static final String ECLIPSE_AUTOSTART = "Eclipse-AutoStart"; //$NON-NLS-1$ |
| |
| // TODO rename constant to ECLIPSE_AUTOSTART_EXCEPTIONS |
| public static final String ECLIPSE_AUTOSTART_EXCEPTIONS = "exceptions"; //$NON-NLS-1$ |
| |
| public static final String SAXFACTORYNAME = "javax.xml.parsers.SAXParserFactory"; //$NON-NLS-1$ |
| |
| public static final String DOMFACTORYNAME = "javax.xml.parsers.DocumentBuilderFactory"; //$NON-NLS-1$ |
| |
| private static final String RUNTIME_ADAPTOR = FRAMEWORK_SYMBOLICNAME + "/eclipseadaptor"; //$NON-NLS-1$ |
| |
| private static final String OPTION_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/debug/platformadmin"; //$NON-NLS-1$ |
| |
| private static final String OPTION_PLATFORM_ADMIN_RESOLVER = RUNTIME_ADAPTOR + "/debug/platformadmin/resolver"; //$NON-NLS-1$ |
| |
| private static final String OPTION_MONITOR_PLATFORM_ADMIN = RUNTIME_ADAPTOR + "/resolver/timing"; //$NON-NLS-1$ |
| |
| private static final String OPTION_RESOLVER_READER = RUNTIME_ADAPTOR + "/resolver/reader/timing"; //$NON-NLS-1$ |
| |
| private static final String OPTION_CONVERTER = RUNTIME_ADAPTOR + "/converter/debug"; //$NON-NLS-1$ |
| |
| private static final String OPTION_LOCATION = RUNTIME_ADAPTOR + "/debug/location"; //$NON-NLS-1$ |
| |
| public static final byte BUNDLEDATA_COMPATIBLE_VERSION = 10; |
| public static final byte BUNDLEDATA_VERSION_11 = 11; |
| public static final byte BUNDLEDATA_VERSION_12 = 12; |
| public static final byte BUNDLEDATA_VERSION = 12; |
| |
| public static final byte NULL = 0; |
| |
| public static final byte OBJECT = 1; |
| |
| private static EclipseAdaptor instance; |
| |
| private byte cacheVersion; |
| |
| private long timeStamp = 0; |
| |
| private String installURL = null; |
| |
| private boolean exitOnError = true; |
| |
| private BundleStopper stopper; |
| |
| private FileManager fileManager; |
| |
| private boolean reinitialize = false; |
| |
| /* |
| * Should be instantiated only by the framework (through reflection). |
| */ |
| public EclipseAdaptor(String[] args) { |
| super(args); |
| instance = this; |
| setDebugOptions(); |
| } |
| |
| public static EclipseAdaptor getDefault() { |
| return instance; |
| } |
| |
| private FrameworkLog createPerformanceLog() { |
| String logFileProp = System.getProperty(EclipseStarter.PROP_LOGFILE); |
| if (logFileProp != null) { |
| int lastSlash = logFileProp.lastIndexOf(File.separatorChar); |
| if (lastSlash > 0) { |
| String logFile = logFileProp.substring(0, lastSlash + 1) + "performance.log"; //$NON-NLS-1$ |
| return new EclipseLog(new File(logFile)); |
| } |
| } |
| //if all else fails, write to std err |
| return new EclipseLog(new PrintWriter(System.err)); |
| } |
| |
| public void initialize(EventPublisher publisher) { |
| if (Boolean.getBoolean(EclipseAdaptor.PROP_CLEAN)) |
| cleanOSGiCache(); |
| boolean readOnlyConfiguration = LocationManager.getConfigurationLocation().isReadOnly(); |
| fileManager = initFileManager(LocationManager.getOSGiConfigurationDir(), readOnlyConfiguration ? "none" : null, readOnlyConfiguration); //$NON-NLS-1$ |
| readHeaders(); |
| checkLocationAndReinitialize(); |
| super.initialize(publisher); |
| } |
| |
| public void initializeMetadata() { |
| // do nothing here; metadata is already initialized by readHeaders. |
| } |
| |
| protected void initBundleStoreRootDir() { |
| File configurationLocation = LocationManager.getOSGiConfigurationDir(); |
| if (configurationLocation != null) { |
| bundleStoreRootDir = new File(configurationLocation, LocationManager.BUNDLES_DIR); |
| bundleStore = bundleStoreRootDir.getAbsolutePath(); |
| } else { |
| // last resort just default to "bundles" |
| bundleStore = LocationManager.BUNDLES_DIR; |
| bundleStoreRootDir = new File(bundleStore); |
| } |
| |
| /* store bundleStore back into adaptor properties for others to see */ |
| properties.put(BUNDLE_STORE, bundleStoreRootDir.getAbsolutePath()); |
| } |
| |
| protected FrameworkLog createFrameworkLog() { |
| if (frameworkLog != null) |
| return frameworkLog; |
| return EclipseStarter.createFrameworkLog(); |
| } |
| |
| private File[] findStateFiles() { |
| if (reinitialize) |
| return new File[2]; // return null enties to indicate reinitialize |
| File stateFile = null; |
| File lazyFile = null; |
| try { |
| stateFile = fileManager.lookup(LocationManager.STATE_FILE, false); |
| lazyFile = fileManager.lookup(LocationManager.LAZY_FILE, false); |
| } catch (IOException ex) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(ex); |
| } |
| } |
| //if it does not exist, try to read it from the parent |
| if (stateFile == null || !stateFile.isFile()) { // NOTE this check is redundant since it |
| // is done in StateManager, however it |
| // is more convenient to have it here |
| Location parentConfiguration = null; |
| Location currentConfiguration = LocationManager.getConfigurationLocation(); |
| if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) { |
| try { |
| File stateLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME); |
| FileManager newFileManager = initFileManager(stateLocationDir, "none", true); //$NON-NLS-1$); |
| stateFile = newFileManager.lookup(LocationManager.STATE_FILE, false); |
| lazyFile = newFileManager.lookup(LocationManager.LAZY_FILE, false); |
| } catch (IOException ex) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(ex); |
| } |
| } |
| } else { |
| try { |
| //it did not exist in either place, so create it in the original location |
| if (canWrite()) { |
| stateFile = fileManager.lookup(LocationManager.STATE_FILE, true); |
| lazyFile = fileManager.lookup(LocationManager.LAZY_FILE, true); |
| } |
| } catch (IOException ex) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading state file " + ex.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(ex); |
| } |
| } |
| } |
| } |
| return new File[] {stateFile, lazyFile}; |
| } |
| |
| protected StateManager createStateManager() { |
| File[] stateFiles = findStateFiles(); |
| File stateFile = stateFiles[0]; |
| File lazyFile = stateFiles[1]; |
| |
| stateManager = new StateManager(stateFile, lazyFile, context, timeStamp); |
| stateManager.setInstaller(new EclipseBundleInstaller()); |
| StateImpl systemState = null; |
| if (!invalidState) { |
| systemState = stateManager.readSystemState(); |
| if (systemState != null) |
| return stateManager; |
| } |
| systemState = stateManager.createSystemState(); |
| Bundle[] installedBundles = context.getBundles(); |
| if (installedBundles == null) |
| return stateManager; |
| StateObjectFactory factory = stateManager.getFactory(); |
| for (int i = 0; i < installedBundles.length; i++) { |
| Bundle toAdd = installedBundles[i]; |
| try { |
| Dictionary toAddManifest = toAdd.getHeaders(""); //$NON-NLS-1$ |
| // if this is a cached manifest need to get the real one |
| if (toAddManifest instanceof CachedManifest) |
| toAddManifest = ((CachedManifest) toAddManifest).getManifest(); |
| BundleDescription newDescription = factory.createBundleDescription(systemState, toAddManifest, toAdd.getLocation(), toAdd.getBundleId()); |
| systemState.addBundle(newDescription); |
| } catch (BundleException be) { |
| // just ignore bundle datas with invalid manifests |
| } |
| } |
| // we need the state resolved |
| systemState.setTimeStamp(timeStamp); |
| systemState.resolve(); |
| invalidState = false; |
| return stateManager; |
| } |
| |
| public void shutdownStateManager() { |
| if (!canWrite() || stateManager.getCachedTimeStamp() == stateManager.getSystemState().getTimeStamp()) |
| return; |
| try { |
| File stateTmpFile = File.createTempFile(LocationManager.STATE_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$ |
| File lazyTmpFile = File.createTempFile(LocationManager.LAZY_FILE, ".new", LocationManager.getOSGiConfigurationDir()); //$NON-NLS-1$ |
| stateManager.shutdown(stateTmpFile, lazyTmpFile); |
| fileManager.lookup(LocationManager.STATE_FILE, true); |
| fileManager.lookup(LocationManager.LAZY_FILE, true); |
| fileManager.update(new String[] {LocationManager.STATE_FILE, LocationManager.LAZY_FILE}, new String[] {stateTmpFile.getName(), lazyTmpFile.getName()}); |
| } catch (IOException e) { |
| frameworkLog.log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); |
| } |
| } |
| |
| private void cleanOSGiCache() { |
| File osgiConfig = LocationManager.getOSGiConfigurationDir(); |
| if (!rm(osgiConfig)) { |
| // TODO log error? |
| } |
| } |
| |
| private void checkLocationAndReinitialize() { |
| if (installURL == null) { |
| installURL = EclipseStarter.getSysPath(); // TODO This reference to the starter should be avoided |
| return; |
| } |
| if (!EclipseStarter.getSysPath().equals(installURL)) { |
| // reinitialize bundledata and state files |
| reinitialize = true; |
| |
| installURL = EclipseStarter.getSysPath(); |
| } |
| } |
| |
| private void readHeaders() { |
| InputStream bundleDataStream = findBundleDataFile(); |
| if (bundleDataStream == null) |
| return; |
| |
| try { |
| DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream)); |
| try { |
| cacheVersion = in.readByte(); |
| if (cacheVersion >= BUNDLEDATA_COMPATIBLE_VERSION) { |
| timeStamp = in.readLong(); |
| installURL = in.readUTF(); |
| initialBundleStartLevel = in.readInt(); |
| nextId = in.readLong(); |
| } |
| } finally { |
| in.close(); |
| } |
| } catch (IOException e) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(e); |
| } |
| } |
| } |
| |
| public AdaptorElementFactory getElementFactory() { |
| if (elementFactory == null) |
| elementFactory = new EclipseElementFactory(); |
| return elementFactory; |
| } |
| |
| public void frameworkStart(BundleContext aContext) throws BundleException { |
| // EnvironmentInfo has to be initialized first to compute defaults for system context (see bug 88925) |
| EnvironmentInfo.getDefault(); |
| // must register the xml parser and initialize the plugin converter |
| // instance first because we may need it when creating the statemanager |
| // in super.frameworkStart(context) |
| registerEndorsedXMLParser(aContext); |
| PluginConverter converter = new PluginConverterImpl(aContext); |
| super.frameworkStart(aContext); |
| Bundle bundle = aContext.getBundle(); |
| Location location; |
| |
| // Less than optimal reference to EclipseStarter here. Not sure how we |
| // can make the location |
| // objects available. They are needed very early in EclipseStarter but |
| // these references tie the adaptor to that starter. |
| location = LocationManager.getUserLocation(); |
| Hashtable locationProperties = new Hashtable(1); |
| if (location != null) { |
| locationProperties.put("type", LocationManager.PROP_USER_AREA); //$NON-NLS-1$ |
| aContext.registerService(Location.class.getName(), location, locationProperties); |
| } |
| location = LocationManager.getInstanceLocation(); |
| if (location != null) { |
| locationProperties.put("type", LocationManager.PROP_INSTANCE_AREA); //$NON-NLS-1$ |
| aContext.registerService(Location.class.getName(), location, locationProperties); |
| } |
| location = LocationManager.getConfigurationLocation(); |
| if (location != null) { |
| locationProperties.put("type", LocationManager.PROP_CONFIG_AREA); //$NON-NLS-1$ |
| aContext.registerService(Location.class.getName(), location, locationProperties); |
| } |
| location = LocationManager.getInstallLocation(); |
| if (location != null) { |
| locationProperties.put("type", LocationManager.PROP_INSTALL_AREA); //$NON-NLS-1$ |
| aContext.registerService(Location.class.getName(), location, locationProperties); |
| } |
| |
| register(org.eclipse.osgi.service.environment.EnvironmentInfo.class.getName(), EnvironmentInfo.getDefault(), bundle); |
| register(PlatformAdmin.class.getName(), stateManager, bundle); |
| register(PluginConverter.class.getName(), converter, bundle); |
| register(URLConverter.class.getName(), new URLConverterImpl(), bundle); |
| register(CommandProvider.class.getName(), new EclipseCommandProvider(aContext), bundle); |
| register(FrameworkLog.class.getName(), getFrameworkLog(), bundle); |
| registerPerformanceLog(bundle); |
| register(org.eclipse.osgi.service.localization.BundleLocalization.class.getName(), new BundleLocalizationImpl(), bundle); |
| } |
| |
| private void registerPerformanceLog(Bundle bundle) { |
| Object service = createPerformanceLog(); |
| String serviceName = FrameworkLog.class.getName(); |
| Hashtable serviceProperties = new Hashtable(7); |
| Dictionary headers = bundle.getHeaders(); |
| |
| serviceProperties.put(Constants.SERVICE_VENDOR, headers.get(Constants.BUNDLE_VENDOR)); |
| serviceProperties.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE)); |
| serviceProperties.put(Constants.SERVICE_PID, bundle.getBundleId() + '.' + service.getClass().getName()); |
| serviceProperties.put(FrameworkLog.SERVICE_PERFORMANCE, Boolean.TRUE.toString()); |
| |
| context.registerService(serviceName, service, serviceProperties); |
| } |
| |
| private void setDebugOptions() { |
| DebugOptions options = DebugOptions.getDefault(); |
| // may be null if debugging is not enabled |
| if (options == null) |
| return; |
| StateManager.DEBUG = options != null; |
| StateManager.DEBUG_READER = options.getBooleanOption(OPTION_RESOLVER_READER, false); |
| StateManager.MONITOR_PLATFORM_ADMIN = options.getBooleanOption(OPTION_MONITOR_PLATFORM_ADMIN, false); |
| StateManager.DEBUG_PLATFORM_ADMIN = options.getBooleanOption(OPTION_PLATFORM_ADMIN, false); |
| StateManager.DEBUG_PLATFORM_ADMIN_RESOLVER = options.getBooleanOption(OPTION_PLATFORM_ADMIN_RESOLVER, false); |
| PluginConverterImpl.DEBUG = options.getBooleanOption(OPTION_CONVERTER, false); |
| BasicLocation.DEBUG = options.getBooleanOption(OPTION_LOCATION, false); |
| } |
| |
| private void registerEndorsedXMLParser(BundleContext bc) { |
| try { |
| Class.forName(SAXFACTORYNAME); |
| bc.registerService(SAXFACTORYNAME, new SaxParsingService(), new Hashtable()); |
| Class.forName(DOMFACTORYNAME); |
| bc.registerService(DOMFACTORYNAME, new DomParsingService(), new Hashtable()); |
| } catch (ClassNotFoundException e) { |
| // In case the JAXP API is not on the boot classpath |
| String message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_ERROR_XML_SERVICE; |
| getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, e, null)); |
| } |
| } |
| |
| private class SaxParsingService implements ServiceFactory { |
| public Object getService(Bundle bundle, ServiceRegistration registration) { |
| return SAXParserFactory.newInstance(); |
| } |
| |
| public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { |
| // Do nothing. |
| } |
| } |
| |
| private class DomParsingService implements ServiceFactory { |
| public Object getService(Bundle bundle, ServiceRegistration registration) { |
| return DocumentBuilderFactory.newInstance(); |
| } |
| |
| public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { |
| // Do nothing. |
| } |
| } |
| |
| public boolean canWrite() { |
| return !fileManager.isReadOnly(); |
| } |
| |
| public void frameworkStop(BundleContext aContext) throws BundleException { |
| saveMetaData(); |
| super.frameworkStop(aContext); |
| printStats(); |
| PluginParser.releaseXMLParsing(); |
| fileManager.close(); |
| } |
| |
| private void printStats() { |
| DebugOptions debugOptions = DebugOptions.getDefault(); |
| if (debugOptions == null) |
| return; |
| String registryParsing = debugOptions.getOption("org.eclipse.core.runtime/registry/parsing/timing/value"); //$NON-NLS-1$ |
| if (registryParsing != null) |
| EclipseAdaptorMsg.debug("Time spent in registry parsing: " + registryParsing); //$NON-NLS-1$ |
| String packageAdminResolution = debugOptions.getOption("debug.packageadmin/timing/value"); //$NON-NLS-1$ |
| if (packageAdminResolution != null) |
| System.out.println("Time spent in package admin resolve: " + packageAdminResolution); //$NON-NLS-1$ |
| String constraintResolution = debugOptions.getOption("org.eclipse.core.runtime.adaptor/resolver/timing/value"); //$NON-NLS-1$ |
| if (constraintResolution != null) |
| System.out.println("Time spent resolving the dependency system: " + constraintResolution); //$NON-NLS-1$ |
| } |
| |
| private InputStream findBundleDataFile() { |
| if (reinitialize) |
| return null; // return null to indicate we are reinitializing |
| File metadata = null; |
| try { |
| metadata = fileManager.lookup(LocationManager.BUNDLE_DATA_FILE, false); |
| } catch (IOException ex) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(ex); |
| } |
| } |
| InputStream bundleDataStream = null; |
| if (metadata != null && metadata.isFile()) { |
| try { |
| bundleDataStream = new FileInputStream(metadata); |
| } catch (FileNotFoundException e1) { |
| // this can not happen since it is tested before entering here. |
| } |
| } else { |
| Location currentConfiguration = LocationManager.getConfigurationLocation(); |
| Location parentConfiguration = null; |
| if (currentConfiguration != null && (parentConfiguration = currentConfiguration.getParentLocation()) != null) { |
| try { |
| File bundledataLocationDir = new File(parentConfiguration.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME); |
| FileManager newFileManager = initFileManager(bundledataLocationDir, "none", true); //$NON-NLS-1$ |
| File bundleData = newFileManager.lookup(LocationManager.BUNDLE_DATA_FILE, false); |
| if (bundleData != null) |
| bundleDataStream = new FileInputStream(bundleData); |
| } catch (MalformedURLException e1) { |
| // This will not happen since all the URLs are derived by us |
| // and we are GODS! |
| } catch (IOException e1) { |
| // That's ok we will regenerate the .bundleData |
| } |
| } |
| } |
| return bundleDataStream; |
| } |
| |
| /** |
| * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getInstalledBundles() |
| */ |
| public BundleData[] getInstalledBundles() { |
| InputStream bundleDataStream = findBundleDataFile(); |
| if (bundleDataStream == null) |
| return null; |
| |
| try { |
| DataInputStream in = new DataInputStream(new BufferedInputStream(bundleDataStream)); |
| try { |
| if (in.readByte() < BUNDLEDATA_COMPATIBLE_VERSION) |
| return null; |
| // skip timeStamp - was read by readHeaders |
| in.readLong(); |
| in.readUTF(); |
| in.readInt(); |
| in.readLong(); |
| |
| int bundleCount = in.readInt(); |
| ArrayList result = new ArrayList(bundleCount); |
| long id = -1; |
| |
| for (int i = 0; i < bundleCount; i++) { |
| try { |
| try { |
| id = in.readLong(); |
| if (id != 0) { |
| EclipseBundleData data = (EclipseBundleData) getElementFactory().createBundleData(this, id); |
| loadMetaDataFor(data, in); |
| data.initializeExistingBundle(); |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) |
| Debug.println("BundleData created: " + data); //$NON-NLS-1$ |
| processExtension(data, EXTENSION_INITIALIZE); |
| result.add(data); |
| } |
| } catch (NumberFormatException e) { |
| // should never happen |
| } catch (BundleException e) { |
| // should never happen |
| } |
| } catch (IOException e) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(e); |
| } |
| } |
| } |
| return (BundleData[]) result.toArray(new BundleData[result.size()]); |
| } finally { |
| in.close(); |
| } |
| } catch (IOException e) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading framework metadata: " + e.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(e); |
| } |
| } |
| return null; |
| } |
| |
| protected void loadMetaDataFor(EclipseBundleData data, DataInputStream in) throws IOException { |
| byte flag = in.readByte(); |
| if (flag == NULL) |
| return; |
| data.setLocation(readString(in, false)); |
| data.setFileName(readString(in, false)); |
| data.setSymbolicName(readString(in, false)); |
| data.setVersion(Version.parseVersion(readString(in, false))); |
| data.setActivator(readString(in, false)); |
| data.setAutoStart(in.readBoolean()); |
| int exceptionsCount = in.readInt(); |
| String[] autoStartExceptions = exceptionsCount > 0 ? new String[exceptionsCount] : null; |
| for (int i = 0; i < exceptionsCount; i++) |
| autoStartExceptions[i] = in.readUTF(); |
| data.setAutoStartExceptions(autoStartExceptions); |
| data.setPluginClass(readString(in, false)); |
| data.setClassPathString(readString(in, false)); |
| data.setNativePaths(readString(in, false)); |
| data.setExecutionEnvironment(readString(in, false)); |
| data.setDynamicImports(readString(in, false)); |
| data.setGeneration(in.readInt()); |
| data.setStartLevel(in.readInt()); |
| data.setStatus(in.readInt()); |
| data.setReference(in.readBoolean()); |
| if (cacheVersion <= BUNDLEDATA_VERSION_11) |
| if (in.readBoolean()) |
| data.setType(BundleData.TYPE_FRAGMENT); |
| data.setManifestTimeStamp(in.readLong()); |
| data.setManifestType(in.readByte()); |
| if (cacheVersion >= BUNDLEDATA_VERSION_11) |
| data.setLastModified(in.readLong()); |
| if (cacheVersion >= BUNDLEDATA_VERSION_12) |
| data.setType(in.readInt()); |
| } |
| |
| public void saveMetaDataFor(EclipseBundleData data) throws IOException { |
| if (!data.isAutoStartable()) { |
| timeStamp--; // Change the value of the timeStamp, as a marker |
| // that something changed. |
| } |
| } |
| |
| public void persistInitialBundleStartLevel(int value) { |
| // Change the value of the timeStamp, as a marker that something |
| // changed. |
| timeStamp--; |
| } |
| |
| public void persistNextBundleID(long value) { |
| // Do nothing the timeStamp will have changed because the state will be |
| // updated. |
| } |
| |
| protected void saveMetaDataFor(BundleData data, DataOutputStream out) throws IOException { |
| if (data.getBundleID() == 0 || !(data instanceof AbstractBundleData)) { |
| out.writeByte(NULL); |
| return; |
| } |
| EclipseBundleData bundleData = (EclipseBundleData) data; |
| out.writeByte(OBJECT); |
| writeStringOrNull(out, bundleData.getLocation()); |
| writeStringOrNull(out, bundleData.getFileName()); |
| writeStringOrNull(out, bundleData.getSymbolicName()); |
| writeStringOrNull(out, bundleData.getVersion().toString()); |
| writeStringOrNull(out, bundleData.getActivator()); |
| out.writeBoolean(bundleData.isAutoStart()); |
| String[] autoStartExceptions = bundleData.getAutoStartExceptions(); |
| if (autoStartExceptions == null) |
| out.writeInt(0); |
| else { |
| out.writeInt(autoStartExceptions.length); |
| for (int i = 0; i < autoStartExceptions.length; i++) |
| out.writeUTF(autoStartExceptions[i]); |
| } |
| writeStringOrNull(out, bundleData.getPluginClass()); |
| writeStringOrNull(out, bundleData.getClassPathString()); |
| writeStringOrNull(out, bundleData.getNativePathsString()); |
| writeStringOrNull(out, bundleData.getExecutionEnvironment()); |
| writeStringOrNull(out, bundleData.getDynamicImports()); |
| out.writeInt(bundleData.getGeneration()); |
| out.writeInt(bundleData.getStartLevel()); |
| out.writeInt(bundleData.getPersistentStatus()); |
| out.writeBoolean(bundleData.isReference()); |
| out.writeLong(bundleData.getManifestTimeStamp()); |
| out.writeByte(bundleData.getManifestType()); |
| out.writeLong(bundleData.getLastModified()); |
| out.writeInt(bundleData.getType()); |
| } |
| |
| private String readString(DataInputStream in, boolean intern) throws IOException { |
| byte type = in.readByte(); |
| if (type == NULL) |
| return null; |
| return intern ? in.readUTF().intern() : in.readUTF(); |
| } |
| |
| private void writeStringOrNull(DataOutputStream out, String string) throws IOException { |
| if (string == null) |
| out.writeByte(NULL); |
| else { |
| out.writeByte(OBJECT); |
| out.writeUTF(string); |
| } |
| } |
| |
| public void saveMetaData() { |
| // the cache and the state match |
| if (!canWrite() | timeStamp == stateManager.getSystemState().getTimeStamp()) |
| return; |
| File metadata = null; |
| try { |
| metadata = File.createTempFile(LocationManager.BUNDLE_DATA_FILE, ".new", LocationManager.getOSGiConfigurationDir());//$NON-NLS-1$ |
| DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(metadata))); |
| try { |
| out.writeByte(BUNDLEDATA_VERSION); |
| out.writeLong(stateManager.getSystemState().getTimeStamp()); |
| out.writeUTF(installURL); |
| out.writeInt(initialBundleStartLevel); |
| out.writeLong(nextId); |
| Bundle[] bundles = context.getBundles(); |
| out.writeInt(bundles.length); |
| for (int i = 0; i < bundles.length; i++) { |
| long id = bundles[i].getBundleId(); |
| out.writeLong(id); |
| if (id != 0) { |
| BundleData data = ((org.eclipse.osgi.framework.internal.core.AbstractBundle) bundles[i]).getBundleData(); |
| saveMetaDataFor(data, out); |
| } |
| } |
| } finally { |
| out.close(); |
| } |
| fileManager.lookup(LocationManager.BUNDLE_DATA_FILE, true); //the BundleData file may not have been created at this point. |
| fileManager.update(new String[] {LocationManager.BUNDLE_DATA_FILE}, new String[] {metadata.getName()}); |
| } catch (IOException e) { |
| frameworkLog.log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), e)); |
| return; |
| } |
| } |
| |
| public BundleWatcher getBundleWatcher() { |
| return StatsManager.getDefault(); |
| } |
| |
| protected BundleContext getContext() { |
| return context; |
| } |
| |
| public void frameworkStopping(BundleContext aContext) { |
| super.frameworkStopping(aContext); |
| stopper = new BundleStopper(); |
| stopper.stopBundles(); |
| } |
| |
| private boolean isFatalException(Throwable error) { |
| if (error instanceof VirtualMachineError) { |
| return true; |
| } |
| if (error instanceof ThreadDeath) { |
| return true; |
| } |
| return false; |
| } |
| |
| public void handleRuntimeError(Throwable error) { |
| try { |
| // check the prop each time this happens (should NEVER happen!) |
| exitOnError = Boolean.valueOf(System.getProperty(PROP_EXITONERROR, "true")).booleanValue(); //$NON-NLS-1$ |
| String message = EclipseAdaptorMsg.ECLIPSE_ADAPTOR_RUNTIME_ERROR; |
| if (exitOnError && isFatalException(error)) |
| message += ' ' + EclipseAdaptorMsg.ECLIPSE_ADAPTOR_EXITING; |
| FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, message, 0, error, null); |
| frameworkLog.log(logEntry); |
| } catch (Throwable t) { |
| // we may be in a currupted state and must be able to handle any |
| // errors (ie OutOfMemoryError) |
| // that may occur when handling the first error; this is REALLY the |
| // last resort. |
| try { |
| error.printStackTrace(); |
| t.printStackTrace(); |
| } catch (Throwable t1) { |
| // if we fail that then we are beyond help. |
| } |
| } finally { |
| // do the exit outside the try block just incase another runtime |
| // error was thrown while logging |
| if (exitOnError && isFatalException(error)) |
| System.exit(13); |
| } |
| } |
| |
| protected void setLog(FrameworkLog log) { |
| frameworkLog = log; |
| } |
| |
| public BundleStopper getBundleStopper() { |
| return stopper; |
| } |
| |
| private FileManager initFileManager(File baseDir, String lockMode, boolean readOnly) { |
| FileManager fManager = new FileManager(baseDir, lockMode, readOnly); |
| try { |
| fManager.open(!readOnly); |
| } catch (IOException ex) { |
| if (Debug.DEBUG && Debug.DEBUG_GENERAL) { |
| Debug.println("Error reading framework metadata: " + ex.getMessage()); //$NON-NLS-1$ |
| Debug.printStackTrace(ex); |
| } |
| } |
| return fManager; |
| } |
| } |