/*******************************************************************************
 * 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;
	}
}
