/******************************************************************************* * Copyright (c) 2003, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.core.runtime.adaptor; import java.io.*; import java.util.*; import javax.xml.parsers.SAXParserFactory; import org.eclipse.osgi.framework.adaptor.*; import org.eclipse.osgi.framework.adaptor.Version; 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.internal.defaultadaptor.*; import org.eclipse.osgi.framework.log.*; 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.pluginconversion.PluginConverter; import org.eclipse.osgi.service.resolver.*; import org.eclipse.osgi.service.urlconversion.URLConverter; import org.osgi.framework.*; public class EclipseAdaptor extends DefaultAdaptor { static final String F_LOG = ".log"; //$NON-NLS-1$ public static boolean MONITOR_CLASSES = false; public static boolean MONITOR_RESOURCE_BUNDLES = false; public static String TRACE_FILENAME = "runtime.traces"; //$NON-NLS-1$ public static String TRACE_FILTERS = "trace.properties"; //$NON-NLS-1$ public static boolean TRACE_CLASSES = false; public static boolean TRACE_BUNDLES = false; private static final String RUNTIME_ADAPTOR = "org.eclipse.osgi/eclipseadaptor"; //Option names for spies private static final String OPTION_MONITOR_CLASSES = RUNTIME_ADAPTOR + "/monitor/classes"; //$NON-NLS-1$ private static final String OPTION_MONITOR_RESOURCEBUNDLES = RUNTIME_ADAPTOR + "/monitor/resourcebundles"; //$NON-NLS-1$ private static final String OPTION_TRACE_BUNDLES = RUNTIME_ADAPTOR + "/trace/bundleActivation"; //$NON-NLS-1$ private static final String OPTION_TRACE_CLASSES = RUNTIME_ADAPTOR + "/trace/classLoading"; //$NON-NLS-1$ private static final String OPTION_TRACE_FILENAME = RUNTIME_ADAPTOR + "/trace/filename"; //$NON-NLS-1$ private static final String OPTION_TRACE_FILTERS = RUNTIME_ADAPTOR + "/trace/filters"; //$NON-NLS-1$ private static final String OPTION_STATE_READER = RUNTIME_ADAPTOR + "/state/reader";//$NON-NLS-1$ private static final String OPTION_RESOLVER = RUNTIME_ADAPTOR + "/resolver/timing"; //$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$ public static final byte BUNDLEDATA_VERSION = 4; public static final byte NULL = 0; public static final byte OBJECT = 1; private static EclipseAdaptor insta private int startLevel = 1; private long timeStamp = 0; private String installURL = null; public EclipseAdaptor(String[] args) { super(args); setDebugOptions(); } protected void initDataRootDir(){ dataRootDir = new File(System.getProperty(EclipseStarter.PROP_INSTANCE_AREA)); } protected FrameworkLog createFrameworkLog() { FrameworkLog frameworkLog; String configArea = System.getProperty(EclipseStarter.PROP_CONFIG_AREA); if (configArea != null) { File logFile = new File(configArea, Long.toString(System.currentTimeMillis()) + F_LOG); frameworkLog = new EclipseLog(logFile); } else { frameworkLog = new EclipseLog(); } return frameworkLog; } protected StateManager createStateManager() { readHeaders(); checkLocationAndReinitialize(); stateManager = new StateManager(getStateBaseLocation(), timeStamp); StateImpl systemState = stateManager.getSystemState(); if (systemState != null) return stateManager; systemState = stateManager.createSystemState(); Vector installedBundles = getInstalledBundles(); if (installedBundles == null) return stateManager; StateObjectFactory factory = stateManager.getFactory(); for (Iterator iter = installedBundles.iterator(); iter.hasNext(); ) { BundleData toAdd = (BundleData) iter.next(); try { Dictionary manifest = toAdd.getManifest(); BundleDescription newDescription = factory.createBundleDescription(manifest, 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(); return stateManager; } private void checkLocationAndReinitialize() { if (installURL == null) { installURL = EclipseStarter.getSysPath(); return; } if( ! EclipseStarter.getSysPath().equals(installURL) ) { //delete the metadata file and the framework file when the location of the basic bundles has changed getMetaDataLocation().delete(); getMetaDataFile().delete(); installURL = EclipseStarter.getSysPath(); } } private void readHeaders() { File metadata = getMetaDataLocation(); if (!metadata.isFile()) return; try { DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(metadata))); try { if (in.readByte() == BUNDLEDATA_VERSION) { timeStamp = in.readLong(); installURL = in.readUTF(); startLevel = in.readInt(); nextId = in.readInt(); } } finally { in.close(); } } catch (IOException e) { if (Debug.DEBUG && Debug.DEBUG_GENERAL) { Debug.println("Error reading framework metadata: " + e.getMessage()); Debug.printStackTrace(e); } } } public AdaptorElementFactory getElementFactory() { if (elementFactory == null) elementFactory = new EclipseElementFactory(); return elementFactory; } public void frameworkStart(BundleContext context) throws BundleException { super.frameworkStart(context); Bundle bundle = context.getBundle(); register(org.eclipse.osgi.service.environment.EnvironmentInfo.class.getName(), EnvironmentInfo.getDefault(), bundle); register(PlatformAdmin.class.getName(), stateManager, bundle); register(PluginConverter.class.getName(), new PluginConverterImpl(context), bundle); register(URLConverter.class.getName(), new URLConverterImpl(),bundle); register(CommandProvider.class.getName(), new EclipseCommandProvider(context),bundle); register(FrameworkLog.class.getName(), getFrameworkLog(), bundle); registerEndorsedXMLParser(); } private void setDebugOptions() { DebugOptions options = DebugOptions.getDefault(); // may be null if debugging is not enabled if (options == null) return; MONITOR_CLASSES = options.getBooleanOption(OPTION_MONITOR_CLASSES, false); MONITOR_RESOURCE_BUNDLES = options.getBooleanOption(OPTION_MONITOR_RESOURCEBUNDLES, false); TRACE_CLASSES = options.getBooleanOption(OPTION_TRACE_CLASSES, false); TRACE_BUNDLES = options.getBooleanOption(OPTION_TRACE_BUNDLES, false); TRACE_FILENAME = options.getOption(OPTION_TRACE_FILENAME); TRACE_FILTERS = options.getOption(OPTION_TRACE_FILTERS); 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); } private void registerEndorsedXMLParser() { if (!is14VMorGreater()) return; new ParsingService(); } private static boolean is14VMorGreater() { final String DELIM = "."; String vmVersionString = System.getProperty("java.version"); //$NON-NLS-1$ StringTokenizer tokenizer = new StringTokenizer(vmVersionString, DELIM); int major, minor; // major if (tokenizer.hasMoreTokens()) { major = Integer.parseInt(tokenizer.nextToken()); if (major > 1) return true; } // minor if (tokenizer.hasMoreTokens()) { minor = Integer.parseInt(tokenizer.nextToken()); if (minor > 3) return true; } return false; } private class ParsingService implements ServiceFactory { public static final String SAXFACTORYNAME = "javax.xml.parsers.SAXParserFactory"; public Object getService(Bundle bundle, ServiceRegistration registration) { return SAXParserFactory.newInstance(); } public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { } public ParsingService() { context.registerService(SAXFACTORYNAME, this, new Hashtable()); } } public void frameworkStop(BundleContext context) throws BundleException { saveMetaData(); super.frameworkStop(context); if (DebugOptions.getDefault() != null) { System.out.println("Time spent in registry parsing: " + DebugOptions.getDefault().getOption("org.eclipse.core.runtime/registry/parsing/timing/value")); System.out.println("Time spent in package admin resolve: " + DebugOptions.getDefault().getOption("debug.packageadmin/timing/value")); System.out.println("Time spent resolving the dependency system: " + DebugOptions.getDefault().getOption("org.eclipse.core.runtime.adaptor/resolver/timing/value")); } } private File getMetaDataLocation() { String configArea = (String) System.getProperty("osgi.configuration.area"); return new File(configArea, ".bundledata"); } /** * @see org.eclipse.osgi.framework.adaptor.FrameworkAdaptor#getInstalledBundles() */ public Vector getInstalledBundles() { File metadata = getMetaDataLocation(); if (!metadata.isFile()) return null; try { DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(metadata))); try { if (in.readByte() != BUNDLEDATA_VERSION) return null; // skip timeStamp - was read by readTimeStamp in.readLong(); in.readUTF(); in.readInt(); in.readLong(); int bundleCount = in.readInt(); Vector result = new Vector(bundleCount); long id = -1; State state = stateManager.getSystemState(); long stateTimeStamp = state.getTimeStamp(); for (int i = 0; i < bundleCount; i++) { try { try { id = in.readLong(); if (id != 0) { EclipseBundleData data = (EclipseBundleData) getElementFactory().getBundleData(this,id); loadMetaDataFor(data, in); data.initializeExistingBundle(Long.toString(id)); if (Debug.DEBUG && Debug.DEBUG_GENERAL) Debug.println("BundleData created: " + data); result.addElement(data); } } catch (NumberFormatException e) { // should never happen } } catch (IOException e) { state.removeBundle(id); if (Debug.DEBUG && Debug.DEBUG_GENERAL) { Debug.println("Error reading framework metadata: " + e.getMessage()); Debug.printStackTrace(e); } } } if (stateTimeStamp != state.getTimeStamp()) state.resolve(false); //time stamp changed force a full resolve return result; } finally { in.close(); } } catch (IOException e) { if (Debug.DEBUG && Debug.DEBUG_GENERAL) { Debug.println("Error reading framework metadata: " + e.getMessage()); 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.setName(readString(in, false)); data.setUniqueId(readString(in, false)); data.setVersion(new Version(readString(in, false))); data.setActivator(readString(in, false)); data.setPluginClass(readString(in, false)); data.setLegacy(readString(in, false)); data.setClassPath(readString(in, false)); data.setNativeCodePath(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()); data.setFragment(in.readBoolean()); data.setManifestTimeStamp(in.readLong()); data.setManifestType(in.readByte()); } protected void saveMetaDataFor(BundleData data, DataOutputStream out) throws IOException { if (data.getBundleID() == 0 || !(data instanceof DefaultBundleData)) { out.writeByte(NULL); return; } EclipseBundleData bundleData = (EclipseBundleData) data; out.writeByte(OBJECT); writeStringOrNull(out, bundleData.getLocation()); writeStringOrNull(out, bundleData.getFileName()); //TODO Check how this works regarding localization writeStringOrNull(out, bundleData.getUniqueId()); writeStringOrNull(out, bundleData.getVersion().toString()); writeStringOrNull(out, bundleData.getActivator()); writeStringOrNull(out, bundleData.getPluginClass()); writeStringOrNull(out, bundleData.isLegacy()); writeStringOrNull(out, bundleData.getClassPath()); writeStringOrNull(out, bundleData.getNativeCodePath()); writeStringOrNull(out, bundleData.getExecutionEnvironment()); writeStringOrNull(out, bundleData.getDynamicImports()); out.writeInt(bundleData.getGeneration()); out.writeInt(bundleData.getStartLevel()); out.writeInt(bundleData.getStatus()); out.writeBoolean(bundleData.isReference()); out.writeBoolean(bundleData.isFragment()); out.writeLong(bundleData.getManifestTimeStamp()); out.writeByte(bundleData.getManifestType()); } private String readString(DataInputStream in, boolean intern) throws IOException { byte type = in.readByte(); if (type == NULL) return null; if (intern) return in.readUTF().intern(); else return in.readUTF(); } private void writeStringOrNull(DataOutputStream out, String string) throws IOException { if (string == null) out.writeByte(NULL); else { out.writeByte(OBJECT); out.writeUTF(string); } } protected BundleContext getContext() { return context; } public void saveMetaData() { File metadata = getMetaDataLocation(); // the cache and the state match if (timeStamp == stateManager.getSystemState().getTimeStamp() && metadata.isFile()) return; try { DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(metadata))); try { out.write(BUNDLEDATA_VERSION); out.writeLong(stateManager.getSystemState().getTimeStamp()); out.writeUTF(installURL); out.writeInt(startLevel); 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.Bundle) bundles[i]).getBundleData(); saveMetaDataFor(data, out); } } } finally { out.close(); } } catch (IOException e) { if (Debug.DEBUG && Debug.DEBUG_GENERAL) { Debug.println("Error writing framework metadata: " + e.getMessage()); Debug.printStackTrace(e); } } } public int getStartLevel() { return startLevel; } public void setStartLevel(int value) { startLevel = value; } public IBundleStats getBundleStats() { return StatsManager.getDefault(); } protected File getStateBaseLocation() { return new File(System.getProperty("osgi.configuration.area")); } protected File getMetaDataFile() { File configAreaDirectory = getStateBaseLocation(); if (!configAreaDirectory.exists()) configAreaDirectory.mkdirs(); return new File(configAreaDirectory, ".framework"); } }