/*******************************************************************************
 * Copyright (c) 2007, 2008 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.equinox.internal.frameworkadmin.equinox;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.frameworkadmin.equinox.utils.FileUtils;
import org.eclipse.equinox.internal.frameworkadmin.utils.SimpleBundlesState;
import org.eclipse.equinox.internal.frameworkadmin.utils.Utils;
import org.eclipse.equinox.internal.provisional.configuratormanipulator.ConfiguratorManipulator;
import org.eclipse.equinox.internal.provisional.frameworkadmin.*;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.*;
import org.osgi.service.log.LogService;
import org.osgi.service.startlevel.StartLevel;
import org.osgi.util.tracker.ServiceTracker;

public class EquinoxManipulatorImpl implements Manipulator {
	private static final long DEFAULT_LASTMODIFIED = 0L;
	private static final boolean LOG_ILLEGALSTATEEXCEPTION = false;
	private static final String COMMA = ","; //$NON-NLS-1$
	private static final String FILE_PROTOCOL = "file:"; //$NON-NLS-1$

	/**
	 * If the fwConfigLocation is a file and its name does not equal "config.ini",
	 * throw an IllegaStateException. 
	 * If the fwConfigLocation is a file and its name equals "config.ini",
	 * fwConfigLocation will be updated by its parent directory.
	 * 
	 * Then, reset fwConfigLocation and fwPersistentDataLocation to be matched.
	 * 
	 * @param launcherData
	 */
	static void checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(LauncherData launcherData) {
		File fwConfigLocation = launcherData.getFwConfigLocation();
		File fwPersistentDataLocation = launcherData.getFwPersistentDataLocation();

		if (fwConfigLocation != null) {
			if (fwConfigLocation.isFile()) {
				if (fwConfigLocation.getName().equals(EquinoxConstants.CONFIG_INI))
					fwConfigLocation = fwConfigLocation.getParentFile();
				else
					throw new IllegalStateException("fwConfigLocation is not a directory but its name does NOT equal \"" + EquinoxConstants.CONFIG_INI + "\"!\n" + "\tfwConfigLocation=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwPersistentDataLocation=" + fwPersistentDataLocation.getAbsolutePath());
				launcherData.setFwConfigLocation(fwConfigLocation);
			}
			if (fwPersistentDataLocation != null) {
				//				Log.log(LogService.LOG_DEBUG, "fwConfigLocation=" + fwConfigLocation.getAbsolutePath() + ",\n\tfwInstancePrivateArea=" + fwPersistentDataLocation.getAbsolutePath());
				//if (!fwConfigLocation.getParentFile().equals(fwPersistentDataLocation))
				//throw new IllegalStateException("!configFile.getParentFile().equals(fwInstancePrivateArea)\n" + "\tconfigFile=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwInstancePrivateArea=" + fwPersistentDataLocation.getAbsolutePath());
				if (!fwConfigLocation.equals(fwPersistentDataLocation))
					throw new IllegalStateException("!fwConfigLocation.equals(fwPersistentDataLocation)\n" + "\t!fwConfigLocation=" + fwConfigLocation.getAbsolutePath() + "\n\t,fwPersistentDataLocation=" + fwPersistentDataLocation.getAbsolutePath());
			} else
				launcherData.setFwPersistentDataLocation(fwConfigLocation, launcherData.isClean());
			//launcherData.setFwPersistentDataLocation(fwConfigLocation.getParentFile(), launcherData.isClean());
		} else {
			if (fwPersistentDataLocation != null) {
				launcherData.setFwConfigLocation(fwPersistentDataLocation);
				//launcherData.setFwConfigLocation(new File(fwPersistentDataLocation, EquinoxConstants.CONFIG_INI));
			} else {
				File home = launcherData.getHome();
				if (home == null)
					throw new IllegalStateException("All of fwConfigLocation, fwPersistentDataLocation, and home are not set");
				fwConfigLocation = new File(home, "configuration");
				launcherData.setFwPersistentDataLocation(fwConfigLocation, launcherData.isClean());
				launcherData.setFwConfigLocation(fwConfigLocation);
			}
		}
	}

	static File getLauncherConfigLocation(LauncherData launcherData) {
		File launcherConfigLocation = launcherData.getLauncherConfigLocation();
		if (launcherConfigLocation != null)
			return launcherConfigLocation;

		File launcher = launcherData.getLauncher();
		if (launcher == null)
			return null;
		String launcherName = launcher.getName();
		int dotLocation = launcherName.lastIndexOf(".");
		if (dotLocation != -1)
			launcherName = launcherName.substring(0, dotLocation);
		File result = new File(launcher.getParent() + File.separator + launcherName + EquinoxConstants.INI_EXTENSION);
		//		launcherData.setLauncherConfigLocation(result);
		return result;
	}

	ConfigData configData = new ConfigData(EquinoxConstants.FW_NAME, EquinoxConstants.FW_VERSION, EquinoxConstants.LAUNCHER_NAME, EquinoxConstants.LAUNCHER_VERSION);
	EquinoxLauncherData launcherData = new EquinoxLauncherData(EquinoxConstants.FW_NAME, EquinoxConstants.FW_VERSION, EquinoxConstants.LAUNCHER_NAME, EquinoxConstants.LAUNCHER_VERSION);

	BundleContext context = null;
	private Properties platformProperties = new Properties();

	ServiceTracker cmTracker;
	int trackingCount = -1;

	//	private final boolean runtime;

	ConfiguratorManipulator configuratorManipulator;

	EquinoxFwAdminImpl fwAdmin = null;

	EquinoxManipulatorImpl(BundleContext context, EquinoxFwAdminImpl fwAdmin) {
		this(context, fwAdmin, false);
	}

	EquinoxManipulatorImpl(BundleContext context, EquinoxFwAdminImpl fwAdmin, boolean runtime) {
		this.context = context;
		this.fwAdmin = fwAdmin;
		if (context != null) {
			cmTracker = new ServiceTracker(context, ConfiguratorManipulator.class.getName(), null);
			cmTracker.open();
		}
		//		this.runtime = runtime;
		if (runtime)
			initializeRuntime();
		// XXX For Equinox, default value of Initial Bundle Start Level is 4.
		// Precisely speaking, it's not correct. 
		// Equinox doesn't support setting initial bundle start level as an OSGi terminology.
		// Only bundles installed by config.ini and updateconfigurator will have that start level(4).
		// Others has a start level of 1.
		configData.setInitialBundleStartLevel(4);
	}

	public BundlesState getBundlesState() throws FrameworkAdminRuntimeException {
		if (context == null)
			return new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME);

		if (!EquinoxBundlesState.checkFullySupported())
			return new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME);

		if (platformProperties.isEmpty())
			return new EquinoxBundlesState(context, fwAdmin, this, false);
		// XXX checking if fwDependent or fwIndependent platformProperties are updated after the platformProperties was created might be required for better implementation.		
		return new EquinoxBundlesState(context, fwAdmin, this, platformProperties);
	}

	public ConfigData getConfigData() throws FrameworkAdminRuntimeException {
		return configData;
	}

	public BundleInfo[] getExpectedState() throws IllegalArgumentException, FrameworkAdminRuntimeException {
		//Log.log(LogService.LOG_DEBUG, this, "getExpectedState()", "BEGIN");
		SimpleBundlesState.checkAvailability(fwAdmin);

		BundlesState bundleState = this.getBundlesState();
		if (bundleState instanceof SimpleBundlesState)
			return new BundleInfo[0];
		bundleState.resolve(true);

		return bundleState.getExpectedState();
	}

	public LauncherData getLauncherData() throws FrameworkAdminRuntimeException {
		return launcherData;
	}

	/**
	 * Return the configuration location.
	 * 
	 * @see Location
	 */
	private File getRunningConfigurationLocation() {
		ServiceTracker tracker = null;
		Filter filter = null;
		try {
			filter = context.createFilter(Location.CONFIGURATION_FILTER);
		} catch (InvalidSyntaxException e) {
			// ignore this. It should never happen as we have tested the above format.
		}
		tracker = new ServiceTracker(context, filter, null);
		tracker.open();
		Location location = (Location) tracker.getService();
		URL url = location.getURL();
		if (!url.getProtocol().equals("file"))
			return null;
		return new File(url.getFile());
	}

	private File getRunningLauncherFile() {
		File launcherFile = null;
		String eclipseCommandsSt = context.getProperty(EquinoxConstants.PROP_ECLIPSE_COMMANDS);
		if (eclipseCommandsSt == null)
			return null;

		StringTokenizer tokenizer = new StringTokenizer(eclipseCommandsSt, "\n");
		boolean found = false;
		String launcherSt = null;
		while (tokenizer.hasMoreTokens()) {
			String token = tokenizer.nextToken();
			if (found) {
				launcherSt = token;
				break;
			}
			if (token.equals("-launcher"))
				found = true;
		}
		if (launcherSt != null)
			launcherFile = new File(launcherSt);
		return launcherFile;
	}

	private Properties getRunningPlatformProperties() {
		Properties props = new Properties();
		for (int i = 0; i < EquinoxBundlesState.PROPS.length; i++) {
			String value = context.getProperty(EquinoxBundlesState.PROPS[i]);
			if (value != null)
				props.setProperty(EquinoxBundlesState.PROPS[i], value);
		}
		return props;
	}

	public long getTimeStamp() {
		long ret = this.getTimeStampWithoutFwPersistentData();
		if (this.launcherData.isClean())
			return ret;
		long lastModifiedFwPersistent = EquinoxBundlesState.getTimeStamp(launcherData.getFwPersistentDataLocation());
		return Math.max(ret, lastModifiedFwPersistent);
	}

	private long getTimeStampWithoutFwPersistentData() {
		SimpleBundlesState.checkAvailability(fwAdmin);
		File launcherConfigFile = getLauncherConfigLocation(launcherData);
		long lastModifiedLauncherConfigFile = DEFAULT_LASTMODIFIED;
		long lastModifiedFwConfigFile = DEFAULT_LASTMODIFIED;
		if (launcherConfigFile != null) {
			// use launcher. -- > load from LaucnherConfig file.
			lastModifiedLauncherConfigFile = launcherConfigFile.lastModified();
		}
		checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);

		if (launcherData.getFwConfigLocation() != null) {
			File fwConfigFile = new File(launcherData.getFwConfigLocation(), EquinoxConstants.CONFIG_INI);
			lastModifiedFwConfigFile = fwConfigFile.lastModified();
		}
		long ret = Math.max(lastModifiedLauncherConfigFile, lastModifiedFwConfigFile);
		return ret;
	}

	//	// 
	//	public void load() throws IllegalStateException, IOException, FrameworkAdminRuntimeException {
	//		this.load(true);
	//	}

	public void initialize() {
		Log.log(LogService.LOG_DEBUG, this, "initialize()", "BEGIN");
		configData.initialize();
		launcherData.initialize();
	}

	private void initializeRuntime() {
		//TODO refine the implementation. using some MAGIC dependent on Eclipse.exe and Equinox implementation,
		// set parameters according to the current running fw.

		// 1. retrieve location data from Location services registered by equinox fw.
		String fwJarLocation = context.getProperty(EquinoxConstants.PROP_OSGI_FW);
		if (!fwJarLocation.startsWith("file:"))
			throw new IllegalStateException("Current implementation assume that property value keyed by " + EquinoxConstants.PROP_OSGI_FW + " must start with \"file:\". But it was not:" + fwJarLocation);
		File fwJar = new File(fwJarLocation.substring("file:".length()));
		//System.out.println("fwJar=" + fwJar);
		File fwConfigLocation = getRunningConfigurationLocation();
		File launcherFile = getRunningLauncherFile();
		launcherData.setFwJar(fwJar);
		launcherData.setFwPersistentDataLocation(fwConfigLocation, false);
		launcherData.setLauncher(launcherFile);
		try {
			this.loadWithoutFwPersistentData();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		// 2. Create a Manipulator object fully initialized to the current running fw.

		ServiceReference reference = context.getServiceReference(StartLevel.class.getName());
		StartLevel startLevel = (StartLevel) context.getService(reference);
		Bundle[] bundles = context.getBundles();
		BundleInfo[] bInfos = new BundleInfo[bundles.length];
		for (int i = 0; i < bundles.length; i++) {
			//			System.out.println("bundles[" + i + "]=" + bundles[i]);
			try {
				if (bundles[i].getBundleId() == 0) // SystemBundle
					bInfos[i] = new BundleInfo(bundles[i].getSymbolicName(), (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION), FileLocator.getBundleFile(bundles[i]).getAbsolutePath(), -1, true);
				else {
					bInfos[i] = new BundleInfo(bundles[i].getSymbolicName(), (String) bundles[i].getHeaders().get(Constants.BUNDLE_VERSION), FileLocator.getBundleFile(bundles[i]).getAbsolutePath(), startLevel.getBundleStartLevel(bundles[i]), startLevel.isBundlePersistentlyStarted(bundles[i]));
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		configData.setBundles(bInfos);
		platformProperties = this.getRunningPlatformProperties();

		// copy system properties to ConfigData
		Properties props = System.getProperties();
		for (Enumeration enumeration = props.keys(); enumeration.hasMoreElements();) {
			String key = (String) enumeration.nextElement();
			String value = props.getProperty(key);
			if (toBeEliminated(key))
				continue;
			if (EquinoxFwConfigFileParser.isFwDependent(key))
				configData.setFwDependentProp(key, value);
			else
				configData.setFwIndependentProp(key, value);
		}

		// update initialBundleStartLevel
		StartLevel slAdmin = (StartLevel) Activator.acquireService(StartLevel.class.getName());
		int initialBSL = configData.getInitialBundleStartLevel();
		if (initialBSL != slAdmin.getInitialBundleStartLevel())
			configData.setInitialBundleStartLevel(slAdmin.getInitialBundleStartLevel());

		//		for (int j = 0; j < bInfos.length; j++)
		//			configData.addBundle(bInfos[j]);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.equinox.internal.provisional.frameworkadmin.Manipulator#load()
	 */
	public void load() throws IllegalStateException, IOException, FrameworkAdminRuntimeException {
		Log.log(LogService.LOG_DEBUG, this, "load()", "BEGIN");
		loadWithoutFwPersistentData();

		BundlesState bundlesState = null;
		if (EquinoxBundlesState.checkFullySupported()) {
			//	bundlesState = new EquinoxBundlesState(context, fwAdmin, this, true, runtime);
			bundlesState = new EquinoxBundlesState(context, fwAdmin, this, !launcherData.isClean());
			platformProperties = ((EquinoxBundlesState) bundlesState).getPlatformProperties();

		} else {
			bundlesState = new SimpleBundlesState(fwAdmin, this, EquinoxConstants.FW_SYMBOLIC_NAME);
			platformProperties.clear();
		}
		updateAccordingToExpectedState(bundlesState);
		//		if (!useConfigurator)
		//			return;
		setConfiguratorManipulator();
		if (this.configuratorManipulator == null)
			return;
		configuratorManipulator.updateBundles(this);
		return;
	}

	private void loadWithoutFwPersistentData() throws IOException {
		SimpleBundlesState.checkAvailability(fwAdmin);
		File launcherConfigFile = getLauncherConfigLocation(launcherData);
		if (launcherConfigFile != null) {
			// use launcher. -- > load from LaucnherConfig file.
			// the parameters in memory will be updated.
			EclipseLauncherParser parser = new EclipseLauncherParser();
			parser.read(launcherData);
		}
		checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);

		File fwConfigFile = new File(launcherData.getFwConfigLocation(), EquinoxConstants.CONFIG_INI);
		EquinoxFwConfigFileParser parser = new EquinoxFwConfigFileParser(context);
		if (fwConfigFile.exists())
			parser.readFwConfig(this, fwConfigFile);

	}

	// Save all parameter in memory into proper config files.
	public void save(boolean backup) throws IOException, FrameworkAdminRuntimeException {
		Log.log(LogService.LOG_DEBUG, this, "save()", "BEGIN");
		SimpleBundlesState.checkAvailability(fwAdmin);

		try {
			updateAccordingToExpectedState(this.getBundlesState());
		} catch (IllegalStateException e) {
			// ignore.
		}
		//		File fwJar = EquinoxBundlesState.getFwJar(launcherData, configData);
		//		if (fwJar != null)
		//			launcherData.setFwJar(fwJar);

		//if (context != null)
		ConfiguratorManipulator previousConfigurator = setConfiguratorManipulator();
		if (previousConfigurator != null)
			previousConfigurator.cleanup(this);

		BundleInfo[] newBInfos = null;
		if (configuratorManipulator != null) { // Optimize BundleInfo[] 
			try {
				newBInfos = configuratorManipulator.save(this, backup);
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				if (LOG_ILLEGALSTATEEXCEPTION)
					Log.log(LogService.LOG_WARNING, this, "save()", e);
				newBInfos = configData.getBundles();
			}
		} else {
			newBInfos = configData.getBundles();
		}

		boolean stateIsEmpty = configData.getBundles().length == 0;

		File launcherConfigFile = getLauncherConfigLocation(launcherData);
		if (launcherConfigFile != null) {
			if (!stateIsEmpty) {
				// Use launcher. -- > save LauncherConfig file.
				EclipseLauncherParser launcherParser = new EclipseLauncherParser();
				launcherParser.save(launcherData, true, backup);
			} else {
				// No bundles in configuration, so delete the launcher config file
				launcherConfigFile.delete();
			}
		}

		checkConsistencyOfFwConfigLocAndFwPersistentDataLoc(launcherData);

		//		//if (context != null)
		//		setConfiguratorManipulator();
		//
		//		BundleInfo[] newBInfos = null;
		//		if (configuratorManipulator != null) { // Optimize BundleInfo[] 
		//			try {
		//				newBInfos = configuratorManipulator.save(this, backup);
		//			} catch (IllegalStateException e) {
		//				// TODO Auto-generated catch block
		//				if (LOG_ILLEGALSTATEEXCEPTION)
		//					Log.log(LogService.LOG_WARNING, this, "save()", e);
		//				newBInfos = configData.getBundles();
		//			}
		//		} else {
		//			newBInfos = configData.getBundles();
		//		}

		if (!stateIsEmpty) {
			// Save FwConfigFile
			EquinoxFwConfigFileParser parser = new EquinoxFwConfigFileParser(context);
			parser.saveFwConfig(newBInfos.length != 0 ? newBInfos : getConfigData().getBundles(), this, backup, false);
		} else {
			File configDir = launcherData.getFwConfigLocation();
			File outputFile = new File(configDir, EquinoxConstants.CONFIG_INI);
			if (outputFile != null && outputFile.exists()) {
				outputFile.delete();
			}
			if (configDir != null && configDir.exists()) {
				configDir.delete();
			}
		}
	}

	public void setConfigData(ConfigData configData) {
		this.configData.initialize();
		this.configData.setInitialBundleStartLevel(configData.getInitialBundleStartLevel());
		this.configData.setBeginningFwStartLevel(configData.getBeginingFwStartLevel());
		BundleInfo[] bInfos = configData.getBundles();
		for (int i = 0; i < bInfos.length; i++)
			this.configData.addBundle(bInfos[i]);
		this.configData.setFwIndependentProps(configData.getFwIndependentProps());
		if (this.configData.getFwName().equals(configData.getFwName()))
			if (this.configData.getFwVersion().equals(configData.getFwVersion())) {
				// TODO refine the algorithm to copying fw dependent props.
				//  configData.getFwName()/getFwVersion()/
				//	getLauncherName()/getLauncherVersion() might be taken into consideration. 
				this.configData.setFwDependentProps(configData.getFwDependentProps());
			}
	}

	/**
	 * 1. get all ServiceReferences of ConfiguratorManipulator.   
	 * 2. Check if there any ConfiguratorBundle in the Bundles list that can be manipulated by 
	 * 	the available ConfiguratorManipulators.
	 * 3. Choose the one that will be firstly started among them.
	 * 4. set the object that corresponds to the chosen ConfiguratorBundle.  
	 * 
	 */
	private ConfiguratorManipulator setConfiguratorManipulator() {
		if (context == null) {
			this.configuratorManipulator = this.fwAdmin.getConfiguratorManipulator();
			return null;
		}
		ServiceReference[] references = cmTracker.getServiceReferences();
		if (references == null)
			return null;

		//		int count = cmTracker.getTrackingCount();
		//		if (count == this.trackingCount)
		//			return;
		//		this.trackingCount = count;

		BundleInfo[] bInfos = configData.getBundles();
		int initialBSL = configData.getInitialBundleStartLevel();
		bInfos = Utils.sortBundleInfos(bInfos, initialBSL);
		//int index = -1;	
		ConfiguratorManipulator previousConfiguratorManipulator = configuratorManipulator;
		configuratorManipulator = null;
		for (int i = 0; i < bInfos.length; i++) {
			String location = bInfos[i].getLocation();
			location = FileUtils.getRealLocation(this, location, true);
			if (!bInfos[i].isMarkedAsStarted())
				continue;
			for (int j = 0; j < references.length; j++)
				if (references[j].getProperty(ConfiguratorManipulator.SERVICE_PROP_KEY_CONFIGURATOR_BUNDLESYMBOLICNAME).equals(Utils.getPathFromClause(Utils.getManifestMainAttributes(location, Constants.BUNDLE_SYMBOLICNAME)))) {
					configuratorManipulator = (ConfiguratorManipulator) cmTracker.getService(references[j]);
					break;
				}
			if (configuratorManipulator != null)
				break;
		}
		if (configuratorManipulator != previousConfiguratorManipulator)
			return previousConfiguratorManipulator;
		return null;
	}

	public void setLauncherData(LauncherData value) {
		launcherData.initialize();
		launcherData.setFwConfigLocation(value.getFwConfigLocation());
		launcherData.setFwPersistentDataLocation(value.getFwPersistentDataLocation(), value.isClean());
		launcherData.setJvm(value.getJvm());
		launcherData.setJvmArgs(value.getJvmArgs());
		if (launcherData.getFwName().equals(value.getFwName()))
			if (launcherData.getFwVersion().equals(value.getFwVersion())) {
				// TODO launcherData.getFwName()/getFwVersion()/
				//	getLauncherName()/getLauncherVersion() might be taken into consideration
				//  for copying . 
				launcherData.setFwJar(value.getFwJar());
				launcherData.setHome(value.getHome());
				launcherData.setLauncher(value.getLauncher());
				launcherData.setLauncherConfigLocation(value.getLauncherConfigLocation());
			}
	}

	/**
	 * Temporal implementation.
	 * 
	 * If a property of the given key should be eliminated
	 *  from FwDependentProperties and FwIndependentProperties,
	 *  return true. Otherwise false.
	 * 
	 * @param key
	 * @return true if it should be elimineted from FwDependentProperties and FwIndependentProperties,
	 */
	private boolean toBeEliminated(String key) {
		if (key.startsWith("java."))
			return true;
		return false;
	}

	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("++++++++++++++++++++++++++++++++++++++++++\n" + "Class:" + this.getClass().getName() + "\n");
		sb.append("------------- LauncherData -----------\n");
		sb.append(launcherData.toString());
		sb.append("------------- ConfigData -----------\n");
		sb.append(configData.toString());
		sb.append("\n" + Utils.toStringProperties("platformProperties", this.platformProperties));
		sb.append("++++++++++++++++++++++++++++++++++++++++++\n");
		return sb.toString();
	}

	private void updateAccordingToExpectedState(BundlesState bundlesState) {
		//		File newFwJar = EquinoxBundlesState.getFwJar(launcherData, configData);
		//		if (bundlesState instanceof EquinoxBundlesState)
		//			((EquinoxBundlesState) bundlesState).setFwJar(newFwJar);
		//
		//		if (launcherData.getFwJar() == null && newFwJar != null)
		//			launcherData.setFwJar(newFwJar);
		BundleInfo[] newBundleInfos = bundlesState.getExpectedState();
		configData.setBundles(newBundleInfos);
	}

	public static String makeRelative(String original, String rootPath) {
		IPath path = new Path(original);
		// ensure we have an absolute path to start with
		if (!path.isAbsolute())
			return original;

		//Returns the original string if no relativization has been done
		String result = makeRelative(path, new Path(rootPath));
		return path.toOSString().equals(result) ? original : result;
	}

	/*
	 * Make the given path relative to the specified root, if applicable. If not, then
	 * return the path as-is.
	 * 
	 * Method similar to one from SimpleConfigurationManipulatorImpl.
	 */
	private static String makeRelative(IPath toRel, IPath base) {
		if (toRel.getDevice() != null && !toRel.getDevice().equalsIgnoreCase(base.getDevice()))
			return toRel.toOSString();
		int i = base.matchingFirstSegments(toRel);
		if (i == 0) {
			return toRel.toOSString();
		}
		String result = "";
		for (int j = 0; j < (base.segmentCount() - i); j++) {
			result += ".." + Path.SEPARATOR;
		}
		if (i == toRel.segmentCount())
			return ".";
		result += toRel.setDevice(null).removeFirstSegments(i).toOSString();
		return result;
	}

	public static String makeRelative(String urlString, URL rootURL) {
		// we only traffic in file: URLs
		int index = urlString.indexOf(FILE_PROTOCOL);
		if (index == -1)
			return urlString;
		index = index + 5;

		// ensure we have an absolute path to start with
		boolean done = false;
		URL url = null;
		String file = urlString;
		while (!done) {
			try {
				url = new URL(file);
				file = url.getFile();
			} catch (java.net.MalformedURLException e) {
				done = true;
			}
		}
		if (url == null || !new File(url.getFile()).isAbsolute())
			return urlString;

		String rootString = rootURL.toExternalForm();
		IPath one = new Path(urlString.substring(index));
		IPath two = new Path(rootString.substring(rootString.indexOf(FILE_PROTOCOL) + 5));
		String deviceOne = one.getDevice();
		String deviceTwo = two.getDevice();
		// do checking here because we want to return the exact string we got initially if
		// we are unable to make it relative.
		if (deviceOne != deviceTwo && (deviceOne == null || !deviceOne.equalsIgnoreCase(two.getDevice())))
			return urlString;

		return urlString.substring(0, index) + makeRelative(one, two);
	}

	public static String makeArrayRelative(String array, URL rootURL) {
		StringBuffer buffer = new StringBuffer();
		for (StringTokenizer tokenizer = new StringTokenizer(array, COMMA); tokenizer.hasMoreTokens();) {
			String token = tokenizer.nextToken();
			String absolute = makeRelative(token, rootURL);
			buffer.append(absolute);
			if (tokenizer.hasMoreTokens())
				buffer.append(',');
		}
		return buffer.toString();
	}

	public static String makeArrayAbsolute(String array, URL rootURL) {
		StringBuffer buffer = new StringBuffer();
		for (StringTokenizer tokenizer = new StringTokenizer(array, COMMA); tokenizer.hasMoreTokens();) {
			String token = tokenizer.nextToken();
			String absolute = makeAbsolute(token, rootURL);
			buffer.append(absolute);
			if (tokenizer.hasMoreTokens())
				buffer.append(',');
		}
		return buffer.toString();
	}

	/*
	 * Make the given path absolute to the specified root, if applicable. If not, then
	 * return the path as-is.
	 * 
	 * Method similar to one from SimpleConfigurationManipulatorImpl.
	 */
	public static String makeAbsolute(String original, String rootPath) {
		IPath path = new Path(original);
		// ensure we have a relative path to start with
		if (path.isAbsolute())
			return original;
		IPath root = new Path(rootPath);
		return root.addTrailingSeparator().append(original.replace(':', '}')).toOSString().replace('}', ':');
	}

	public static String makeAbsolute(String urlString, URL rootURL) {
		// we only traffic in file: URLs
		int index = urlString.indexOf(FILE_PROTOCOL);
		if (index == -1)
			return urlString;
		index = index + 5;

		// ensure we have a relative path to start with
		boolean done = false;
		URL url = null;
		String file = urlString;
		while (!done) {
			try {
				url = new URL(file);
				file = url.getFile();
			} catch (java.net.MalformedURLException e) {
				done = true;
			}
		}
		if (url == null || new File(url.getFile()).isAbsolute())
			return urlString;

		return urlString.substring(0, index - 5) + makeAbsolute(urlString.substring(index), rootURL.toExternalForm());
	}
}
