/*******************************************************************************
 * Copyright (c) 2012, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *      Christoph Laeubrich - Bug 527175 - Storage#getSystemContent() should first make the file absolute 
 *******************************************************************************/
package org.eclipse.osgi.storage;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleCapability;
import org.eclipse.osgi.container.ModuleContainer;
import org.eclipse.osgi.container.ModuleContainerAdaptor;
import org.eclipse.osgi.container.ModuleDatabase;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.container.ModuleRevisionBuilder;
import org.eclipse.osgi.container.ModuleWire;
import org.eclipse.osgi.container.ModuleWiring;
import org.eclipse.osgi.container.builders.OSGiManifestBuilderFactory;
import org.eclipse.osgi.container.namespaces.EclipsePlatformNamespace;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.FilePath;
import org.eclipse.osgi.framework.util.ObjectPool;
import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor;
import org.eclipse.osgi.internal.framework.FilterImpl;
import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
import org.eclipse.osgi.internal.location.EquinoxLocations;
import org.eclipse.osgi.internal.location.LocationHelper;
import org.eclipse.osgi.internal.log.EquinoxLogServices;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
import org.eclipse.osgi.internal.url.URLStreamHandlerFactoryImpl;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
import org.eclipse.osgi.storage.bundlefile.BundleFileWrapperChain;
import org.eclipse.osgi.storage.bundlefile.DirBundleFile;
import org.eclipse.osgi.storage.bundlefile.MRUBundleFileList;
import org.eclipse.osgi.storage.bundlefile.NestedDirBundleFile;
import org.eclipse.osgi.storage.bundlefile.ZipBundleFile;
import org.eclipse.osgi.storage.url.reference.Handler;
import org.eclipse.osgi.storage.url.reference.ReferenceInputStream;
import org.eclipse.osgi.storagemanager.ManagedOutputStream;
import org.eclipse.osgi.storagemanager.StorageManager;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;

public class Storage {
	public static class StorageException extends RuntimeException {
		private static final long serialVersionUID = 1L;

		public StorageException() {
			super();
		}

		public StorageException(String message, Throwable cause) {
			super(message, cause);
		}

		public StorageException(String message) {
			super(message);
		}

		public StorageException(Throwable cause) {
			super(cause);
		}

	}

	public static final int VERSION = 5;
	private static final int MR_JAR_VERSION = 4;
	private static final int CACHED_SYSTEM_CAPS_VERION = 5;
	private static final int LOWEST_VERSION_SUPPORTED = 3;
	public static final String BUNDLE_DATA_DIR = "data"; //$NON-NLS-1$
	public static final String BUNDLE_FILE_NAME = "bundleFile"; //$NON-NLS-1$
	public static final String FRAMEWORK_INFO = "framework.info"; //$NON-NLS-1$
	public static final String ECLIPSE_SYSTEMBUNDLE = "Eclipse-SystemBundle"; //$NON-NLS-1$
	public static final String DELETE_FLAG = ".delete"; //$NON-NLS-1$
	public static final String LIB_TEMP = "libtemp"; //$NON-NLS-1$

	private static final String JAVASE = "JavaSE"; //$NON-NLS-1$
	private static final String PROFILE_EXT = ".profile"; //$NON-NLS-1$
	private static final String NUL = new String(new byte[] {0});
	private static final String INITIAL_LOCATION = "initial@"; //$NON-NLS-1$

	static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());

	private final EquinoxContainer equinoxContainer;
	private final String installPath;
	private final Location osgiLocation;
	private final File childRoot;
	private final File parentRoot;
	private final PermissionData permissionData;
	private final SecurityAdmin securityAdmin;
	private final EquinoxContainerAdaptor adaptor;
	private final ModuleDatabase moduleDatabase;
	private final ModuleContainer moduleContainer;
	private final Object saveMonitor = new Object();
	private long lastSavedTimestamp = -1;
	private final MRUBundleFileList mruList;
	private final FrameworkExtensionInstaller extensionInstaller;
	private final List<String> cachedHeaderKeys = Arrays.asList(Constants.BUNDLE_SYMBOLICNAME, Constants.BUNDLE_ACTIVATIONPOLICY, "Service-Component"); //$NON-NLS-1$
	private final boolean allowRestrictedProvides;
	private final AtomicBoolean refreshMRBundles = new AtomicBoolean(false);
	private final Version runtimeVersion;
	private final String javaSpecVersion;

	public static Storage createStorage(EquinoxContainer container) throws IOException, BundleException {
		String[] cachedInfo = new String[3];
		Storage storage = new Storage(container, cachedInfo);
		// Do some operations that need to happen on the fully constructed Storage before returning it
		storage.checkSystemBundle(cachedInfo);
		storage.refreshStaleBundles();
		storage.installExtensions();
		// TODO hack to make sure all bundles are in UNINSTALLED state before system bundle init is called
		storage.getModuleContainer().setInitialModuleStates();
		return storage;
	}

	private Storage(EquinoxContainer container, String[] cachedInfo) throws IOException {
		// default to Java 7 since that is our min
		Version javaVersion = Version.valueOf("1.7"); //$NON-NLS-1$
		// set the profile and EE based off of the java.specification.version
		String javaSpecVersionProp = System.getProperty(EquinoxConfiguration.PROP_JVM_SPEC_VERSION);
		StringTokenizer st = new StringTokenizer(javaSpecVersionProp, " _-"); //$NON-NLS-1$
		javaSpecVersionProp = st.nextToken();
		try {
			String[] vComps = javaSpecVersionProp.split("\\."); //$NON-NLS-1$
			// only pay attention to the first three components of the version
			int major = vComps.length > 0 ? Integer.parseInt(vComps[0]) : 0;
			int minor = vComps.length > 1 ? Integer.parseInt(vComps[1]) : 0;
			int micro = vComps.length > 2 ? Integer.parseInt(vComps[2]) : 0;
			javaVersion = new Version(major, minor, micro);
		} catch (IllegalArgumentException e) {
			// do nothing
		}
		runtimeVersion = javaVersion;
		javaSpecVersion = javaSpecVersionProp;
		mruList = new MRUBundleFileList(getBundleFileLimit(container.getConfiguration()), container.getConfiguration().getDebug());
		equinoxContainer = container;
		extensionInstaller = new FrameworkExtensionInstaller(container.getConfiguration());
		allowRestrictedProvides = Boolean.parseBoolean(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_ALLOW_RESTRICTED_PROVIDES));

		// we need to set the install path as soon as possible so we can determine
		// the absolute location of install relative URLs
		Location installLoc = container.getLocations().getInstallLocation();
		URL installURL = installLoc.getURL();
		// assume install URL is file: based
		installPath = installURL.getPath();

		Location configLocation = container.getLocations().getConfigurationLocation();
		Location parentConfigLocation = configLocation.getParentLocation();
		Location osgiParentLocation = null;
		if (parentConfigLocation != null) {
			osgiParentLocation = parentConfigLocation.createLocation(null, parentConfigLocation.getDataArea(EquinoxContainer.NAME), true);
		}
		this.osgiLocation = configLocation.createLocation(osgiParentLocation, configLocation.getDataArea(EquinoxContainer.NAME), configLocation.isReadOnly());
		this.childRoot = new File(osgiLocation.getURL().getPath());

		if (Boolean.valueOf(container.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_CLEAN)).booleanValue()) {
			cleanOSGiStorage(osgiLocation, childRoot);
		}
		if (!this.osgiLocation.isReadOnly()) {
			this.childRoot.mkdirs();
		}
		Location parent = this.osgiLocation.getParentLocation();
		parentRoot = parent == null ? null : new File(parent.getURL().getPath());

		if (container.getConfiguration().getConfiguration(Constants.FRAMEWORK_STORAGE) == null) {
			// Set the derived value if not already set as part of configuration.
			// Note this is the parent directory of where the framework stores data (org.eclipse.osgi/)
			container.getConfiguration().setConfiguration(Constants.FRAMEWORK_STORAGE, childRoot.getParentFile().getAbsolutePath());
		}

		InputStream info = getInfoInputStream();
		DataInputStream data = info == null ? null : new DataInputStream(new BufferedInputStream(info));
		try {
			Map<Long, Generation> generations;
			try {
				generations = loadGenerations(data, cachedInfo);
			} catch (IllegalArgumentException e) {
				equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "The persistent format for the framework data has changed.  The framework will be reinitialized: " + e.getMessage(), null); //$NON-NLS-1$
				generations = new HashMap<>(0);
				data = null;
				cleanOSGiStorage(osgiLocation, childRoot);
			}
			this.permissionData = loadPermissionData(data);
			this.securityAdmin = new SecurityAdmin(null, this.permissionData);
			this.adaptor = new EquinoxContainerAdaptor(equinoxContainer, this, generations);
			this.moduleDatabase = new ModuleDatabase(this.adaptor);
			this.moduleContainer = new ModuleContainer(this.adaptor, this.moduleDatabase);
			if (data != null) {
				try {
					moduleDatabase.load(data);
					lastSavedTimestamp = moduleDatabase.getTimestamp();
				} catch (IllegalArgumentException e) {
					equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Incompatible version.  Starting with empty framework.", e); //$NON-NLS-1$
					// Clean up the cache.
					// No need to clean up the database. Nothing got loaded.
					cleanOSGiStorage(osgiLocation, childRoot);
					// should free up the generations map
					generations.clear();
				}
			}
		} finally {
			if (data != null) {
				try {
					data.close();
				} catch (IOException e) {
					// just move on
				}
			}
		}
	}

	public Version getRuntimeVersion() {
		return runtimeVersion;
	}

	public MRUBundleFileList getMRUBundleFileList() {
		return mruList;
	}

	private int getBundleFileLimit(EquinoxConfiguration configuration) {
		int propValue = 100; // enable to 100 open files by default
		try {
			String prop = configuration.getConfiguration(EquinoxConfiguration.PROP_FILE_LIMIT);
			if (prop != null)
				propValue = Integer.parseInt(prop);
		} catch (NumberFormatException e) {
			// use default of 100
		}
		return propValue;
	}

	private void installExtensions() {
		Module systemModule = moduleContainer.getModule(0);
		ModuleRevision systemRevision = systemModule == null ? null : systemModule.getCurrentRevision();
		ModuleWiring systemWiring = systemRevision == null ? null : systemRevision.getWiring();
		if (systemWiring == null) {
			return;
		}
		Collection<ModuleRevision> fragments = new ArrayList<>();
		for (ModuleWire hostWire : systemWiring.getProvidedModuleWires(HostNamespace.HOST_NAMESPACE)) {
			fragments.add(hostWire.getRequirer());
		}
		try {
			getExtensionInstaller().addExtensionContent(fragments, null);
		} catch (BundleException e) {
			getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e);
		}
	}

	private static PermissionData loadPermissionData(DataInputStream in) throws IOException {
		PermissionData permData = new PermissionData();
		if (in != null) {
			permData.readPermissionData(in);
		}
		return permData;
	}

	private void refreshStaleBundles() throws BundleException {
		Collection<Module> needsRefresh = new ArrayList<>(0);

		// First uninstall any modules that had their content changed or deleted
		for (Module module : moduleContainer.getModules()) {
			if (module.getId() == Constants.SYSTEM_BUNDLE_ID)
				continue;
			ModuleRevision revision = module.getCurrentRevision();
			Generation generation = (Generation) revision.getRevisionInfo();
			if (needsDiscarding(generation)) {
				needsRefresh.add(module);
				moduleContainer.uninstall(module);
				generation.delete();
			}
		}
		// Next check if we need to refresh Multi-Release Jar bundles
		// because the runtime version changed.
		if (refreshMRBundles.get()) {
			needsRefresh.addAll(refreshMRJarBundles());
		}

		// refresh the modules that got deleted or are Multi-Release bundles
		if (!needsRefresh.isEmpty()) {
			moduleContainer.refresh(needsRefresh);
		}
	}

	private boolean needsDiscarding(Generation generation) {
		for (StorageHook<?, ?> hook : generation.getStorageHooks()) {
			try {
				hook.validate();
			} catch (IllegalStateException e) {
				equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error validating installed bundle.", e); //$NON-NLS-1$
				return true;
			}
		}
		File content = generation.getContent();
		if (getConfiguration().inCheckConfigurationMode()) {
			if (generation.isDirectory()) {
				content = new File(content, "META-INF/MANIFEST.MF"); //$NON-NLS-1$
			}
			return generation.getLastModified() != secureAction.lastModified(content);
		}
		if (!content.exists()) {
			// the content got deleted since last time!
			return true;
		}
		return false;
	}

	private void checkSystemBundle(String[] cachedInfo) {
		Module systemModule = moduleContainer.getModule(0);
		Generation newGeneration = null;
		try {
			if (systemModule == null) {
				BundleInfo info = new BundleInfo(this, 0, Constants.SYSTEM_BUNDLE_LOCATION, 0);
				newGeneration = info.createGeneration();

				File contentFile = getSystemContent();
				newGeneration.setContent(contentFile, false);

				// First we must make sure the VM profile has been loaded
				loadVMProfile(newGeneration);
				// dealing with system bundle find the extra capabilities and exports
				String extraCapabilities = getSystemExtraCapabilities();
				String extraExports = getSystemExtraPackages();

				ModuleRevisionBuilder builder = getBuilder(newGeneration, extraCapabilities, extraExports);
				systemModule = moduleContainer.install(null, Constants.SYSTEM_BUNDLE_LOCATION, builder, newGeneration);
				moduleContainer.resolve(Collections.singletonList(systemModule), false);
			} else {
				ModuleRevision currentRevision = systemModule.getCurrentRevision();
				Generation currentGeneration = currentRevision == null ? null : (Generation) currentRevision.getRevisionInfo();
				if (currentGeneration == null) {
					throw new IllegalStateException("No current revision for system bundle."); //$NON-NLS-1$
				}
				try {
					// First we must make sure the VM profile has been loaded
					loadVMProfile(currentGeneration);
					// dealing with system bundle find the extra capabilities and exports
					String extraCapabilities = getSystemExtraCapabilities();
					String extraExports = getSystemExtraPackages();
					File contentFile = currentGeneration.getContent();
					if (systemNeedsUpdate(contentFile, currentRevision, currentGeneration, extraCapabilities, extraExports, cachedInfo)) {
						newGeneration = currentGeneration.getBundleInfo().createGeneration();
						newGeneration.setContent(contentFile, false);
						ModuleRevisionBuilder newBuilder = getBuilder(newGeneration, extraCapabilities, extraExports);
						moduleContainer.update(systemModule, newBuilder, newGeneration);
						moduleContainer.refresh(Collections.singleton(systemModule));
					} else {
						if (currentRevision.getWiring() == null) {
							// must resolve before continuing to ensure extensions get attached
							moduleContainer.resolve(Collections.singleton(systemModule), true);
						}
					}
				} catch (BundleException e) {
					throw new IllegalStateException("Could not create a builder for the system bundle.", e); //$NON-NLS-1$
				}
			}
			ModuleRevision currentRevision = systemModule.getCurrentRevision();
			List<ModuleCapability> nativeEnvironments = currentRevision.getModuleCapabilities(NativeNamespace.NATIVE_NAMESPACE);
			Map<String, Object> configMap = equinoxContainer.getConfiguration().getInitialConfig();
			for (ModuleCapability nativeEnvironment : nativeEnvironments) {
				nativeEnvironment.setTransientAttrs(configMap);
			}
			Version frameworkVersion = null;
			if (newGeneration != null) {
				frameworkVersion = findFrameworkVersion();
			} else {
				String sVersion = cachedInfo[0];
				frameworkVersion = sVersion == null ? findFrameworkVersion() : Version.parseVersion(sVersion);
			}
			if (frameworkVersion != null) {
				this.equinoxContainer.getConfiguration().setConfiguration(Constants.FRAMEWORK_VERSION, frameworkVersion.toString());
			}
		} catch (Exception e) {
			if (e instanceof RuntimeException) {
				throw (RuntimeException) e;
			}
			throw new RuntimeException("Error occurred while checking the system module.", e); //$NON-NLS-1$
		} finally {
			if (newGeneration != null) {
				newGeneration.getBundleInfo().unlockGeneration(newGeneration);
			}
		}
	}

	private Version findFrameworkVersion() {
		Requirement osgiPackageReq = ModuleContainer.createRequirement(PackageNamespace.PACKAGE_NAMESPACE, Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, "(" + PackageNamespace.PACKAGE_NAMESPACE + "=org.osgi.framework)"), Collections.<String, String> emptyMap()); //$NON-NLS-1$ //$NON-NLS-2$
		Collection<BundleCapability> osgiPackages = moduleContainer.getFrameworkWiring().findProviders(osgiPackageReq);
		for (BundleCapability packageCapability : osgiPackages) {
			if (packageCapability.getRevision().getBundle().getBundleId() == 0) {
				Version v = (Version) packageCapability.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
				if (v != null) {
					return v;
				}
			}
		}
		return null;
	}

	private Collection<Module> refreshMRJarBundles() throws BundleException {
		Collection<Module> mrJarBundles = new ArrayList<>();
		for (Module m : moduleContainer.getModules()) {
			Generation generation = (Generation) m.getCurrentRevision().getRevisionInfo();
			// Note that we check the raw headers here incase we are working off an old version of the persistent storage
			if (Boolean.parseBoolean(generation.getRawHeaders().get(BundleInfo.MULTI_RELEASE_HEADER))) {
				refresh(m);
				mrJarBundles.add(m);
			}
		}
		return mrJarBundles;
	}

	public void close() {
		try {
			save();
		} catch (IOException e) {
			getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error saving on shutdown", e); //$NON-NLS-1$
		}

		// close all the generations
		List<Module> modules = moduleContainer.getModules();
		for (Module module : modules) {
			for (ModuleRevision revision : module.getRevisions().getModuleRevisions()) {
				Generation generation = (Generation) revision.getRevisionInfo();
				if (generation != null) {
					generation.close();
				}
			}
		}
		for (ModuleRevision removalPending : moduleContainer.getRemovalPending()) {
			Generation generation = (Generation) removalPending.getRevisionInfo();
			if (generation != null) {
				generation.close();
			}
		}
		mruList.shutdown();
		adaptor.shutdownExecutors();
	}

	private boolean systemNeedsUpdate(File systemContent, ModuleRevision currentRevision, Generation existing, String extraCapabilities, String extraExports, String[] cachedInfo) throws BundleException {
		if (!extraCapabilities.equals(cachedInfo[1])) {
			return true;
		}
		if (!extraExports.equals(cachedInfo[2])) {
			return true;
		}
		if (systemContent == null) {
			// only do a version check in this case
			ModuleRevisionBuilder newBuilder = getBuilder(existing, extraCapabilities, extraExports);
			return !currentRevision.getVersion().equals(newBuilder.getVersion());
		}
		if (existing.isDirectory()) {
			systemContent = new File(systemContent, "META-INF/MANIFEST.MF"); //$NON-NLS-1$
		}
		return existing.getLastModified() != secureAction.lastModified(systemContent);

	}

	private void cleanOSGiStorage(Location location, File root) {
		if (location.isReadOnly() || !StorageUtil.rm(root, getConfiguration().getDebug().DEBUG_STORAGE)) {
			equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "The -clean (osgi.clean) option was not successful. Unable to clean the storage area: " + root.getAbsolutePath(), null); //$NON-NLS-1$
		}
		if (!location.isReadOnly()) {
			// make sure to recreate to root folder
			root.mkdirs();
		}
	}

	public ModuleDatabase getModuleDatabase() {
		return moduleDatabase;
	}

	public ModuleContainerAdaptor getAdaptor() {
		return adaptor;
	}

	public ModuleContainer getModuleContainer() {
		return moduleContainer;
	}

	public EquinoxConfiguration getConfiguration() {
		return equinoxContainer.getConfiguration();
	}

	public EquinoxLogServices getLogServices() {
		return equinoxContainer.getLogServices();
	}

	public FrameworkExtensionInstaller getExtensionInstaller() {
		return extensionInstaller;
	}

	public boolean isReadOnly() {
		return osgiLocation.isReadOnly();
	}

	public URLConnection getContentConnection(Module module, String bundleLocation, final InputStream in) throws IOException {
		List<StorageHookFactory<?, ?, ?>> storageHooks = getConfiguration().getHookRegistry().getStorageHookFactories();
		for (StorageHookFactory<?, ?, ?> storageHook : storageHooks) {
			URLConnection hookContent = storageHook.handleContentConnection(module, bundleLocation, in);
			if (hookContent != null) {
				return hookContent;
			}
		}

		if (in != null) {
			return new URLConnection(null) {
				/**
				 * @throws IOException  
				 */
				@Override
				public void connect() throws IOException {
					connected = true;
				}

				/**
				 * @throws IOException  
				 */
				@Override
				public InputStream getInputStream() throws IOException {
					return (in);
				}
			};
		}
		if (module == null) {
			if (bundleLocation == null) {
				throw new IllegalArgumentException("Module and location cannot be null"); //$NON-NLS-1$
			}
			return getContentConnection(bundleLocation);
		}
		return getContentConnection(getUpdateLocation(module));
	}

	private String getUpdateLocation(final Module module) {
		if (System.getSecurityManager() == null)
			return getUpdateLocation0(module);
		return AccessController.doPrivileged(new PrivilegedAction<String>() {
			@Override
			public String run() {
				return getUpdateLocation0(module);
			}
		});
	}

	String getUpdateLocation0(Module module) {
		ModuleRevision current = module.getCurrentRevision();
		Generation generation = (Generation) current.getRevisionInfo();
		String updateLocation = generation.getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
		if (updateLocation == null) {
			updateLocation = module.getLocation();
		}
		if (updateLocation.startsWith(INITIAL_LOCATION)) {
			updateLocation = updateLocation.substring(INITIAL_LOCATION.length());
		}
		return updateLocation;
	}

	private URLConnection getContentConnection(final String spec) throws IOException {
		if (System.getSecurityManager() == null) {
			return LocationHelper.getConnection(createURL(spec));
		}
		try {
			return AccessController.doPrivileged(new PrivilegedExceptionAction<URLConnection>() {
				@Override
				public URLConnection run() throws IOException {
					return LocationHelper.getConnection(createURL(spec));
				}
			});
		} catch (PrivilegedActionException e) {
			if (e.getException() instanceof IOException)
				throw (IOException) e.getException();
			throw (RuntimeException) e.getException();
		}
	}

	URL createURL(String spec) throws MalformedURLException {
		if (spec.startsWith(URLStreamHandlerFactoryImpl.PROTOCOL_REFERENCE)) {
			return new URL(null, spec, new Handler(equinoxContainer.getConfiguration().getConfiguration(EquinoxLocations.PROP_INSTALL_AREA)));
		}
		return new URL(spec);
	}

	public Generation install(Module origin, String bundleLocation, URLConnection content) throws BundleException {
		if (osgiLocation.isReadOnly()) {
			throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
		}
		URL sourceURL = content.getURL();
		InputStream in;
		try {
			in = content.getInputStream();
		} catch (Throwable e) {
			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
		}

		// Check if the bundle already exists at this location
		// before doing the staging and generation creation.
		// This is important since some installers seem to continually
		// re-install bundles using the same location each startup
		Module existingLocation = moduleContainer.getModule(bundleLocation);
		if (existingLocation != null) {
			// NOTE this same logic is also in the ModuleContainer
			// This is necessary because the container does the location locking.
			// Another thread could win the location lock and install before this thread does.
			try {
				in.close();
			} catch (IOException e) {
				// ignore
			}
			if (origin != null) {
				// Check that the existing location is visible from the origin module
				Bundle bundle = origin.getBundle();
				BundleContext context = bundle == null ? null : bundle.getBundleContext();
				if (context != null && context.getBundle(existingLocation.getId()) == null) {
					Bundle b = existingLocation.getBundle();
					throw new BundleException(NLS.bind(Msg.ModuleContainer_NameCollisionWithLocation, new Object[] {b.getSymbolicName(), b.getVersion(), bundleLocation}), BundleException.REJECTED_BY_HOOK);
				}
			}
			return (Generation) existingLocation.getCurrentRevision().getRevisionInfo();
		}

		boolean isReference = in instanceof ReferenceInputStream;
		File staged = stageContent(in, sourceURL);
		Generation generation = null;
		try {
			Long nextID = moduleDatabase.getAndIncrementNextId();
			BundleInfo info = new BundleInfo(this, nextID, bundleLocation, 0);
			generation = info.createGeneration();

			File contentFile = getContentFile(staged, isReference, nextID, generation.getGenerationId());
			generation.setContent(contentFile, isReference);
			// Check that we can open the bundle file
			generation.getBundleFile().open();
			setStorageHooks(generation);

			ModuleRevisionBuilder builder = getBuilder(generation);
			builder.setId(nextID);

			Module m = moduleContainer.install(origin, bundleLocation, builder, generation);
			if (!nextID.equals(m.getId())) {
				// this revision is already installed. delete the generation
				generation.delete();
				return (Generation) m.getCurrentRevision().getRevisionInfo();
			}
			return generation;
		} catch (Throwable t) {
			if (!isReference) {
				try {
					delete(staged);
				} catch (IOException e) {
					// tried our best
				}
			}
			if (generation != null) {
				generation.delete();
				generation.getBundleInfo().delete();
			}
			if (t instanceof SecurityException) {
				// TODO hack from ModuleContainer
				// if the cause is a bundle exception then throw that
				if (t.getCause() instanceof BundleException) {
					throw (BundleException) t.getCause();
				}
				throw (SecurityException) t;
			}
			if (t instanceof BundleException) {
				throw (BundleException) t;
			}
			throw new BundleException("Error occurred installing a bundle.", t); //$NON-NLS-1$
		} finally {
			if (generation != null) {
				generation.getBundleInfo().unlockGeneration(generation);
			}
		}
	}

	private void setStorageHooks(Generation generation) throws BundleException {
		if (generation.getBundleInfo().getBundleId() == 0) {
			return; // ignore system bundle
		}
		List<StorageHookFactory<?, ?, ?>> factories = new ArrayList<>(getConfiguration().getHookRegistry().getStorageHookFactories());
		List<StorageHook<?, ?>> hooks = new ArrayList<>(factories.size());
		for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
			@SuppressWarnings("unchecked")
			StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
			StorageHook<Object, Object> hook = next.createStorageHookAndValidateFactoryClass(generation);
			if (hook != null) {
				hooks.add(hook);
			}
		}
		generation.setStorageHooks(Collections.unmodifiableList(hooks), true);
		for (StorageHook<?, ?> hook : hooks) {
			hook.initialize(generation.getHeaders());
		}
	}

	public ModuleRevisionBuilder getBuilder(Generation generation) throws BundleException {
		return getBuilder(generation, null, null);
	}

	public ModuleRevisionBuilder getBuilder(Generation generation, String extraCapabilities, String extraExports) throws BundleException {
		Dictionary<String, String> headers = generation.getHeaders();
		Map<String, String> mapHeaders;
		if (headers instanceof Map) {
			@SuppressWarnings("unchecked")
			Map<String, String> unchecked = (Map<String, String>) headers;
			mapHeaders = unchecked;
		} else {
			mapHeaders = new HashMap<>();
			for (Enumeration<String> eKeys = headers.keys(); eKeys.hasMoreElements();) {
				String key = eKeys.nextElement();
				mapHeaders.put(key, headers.get(key));
			}
		}
		if (generation.getBundleInfo().getBundleId() != 0) {
			ModuleRevisionBuilder builder = allowRestrictedProvides ? OSGiManifestBuilderFactory.createBuilder(mapHeaders, null, null, "") : OSGiManifestBuilderFactory.createBuilder(mapHeaders); //$NON-NLS-1$
			if ((builder.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
				for (ModuleRevisionBuilder.GenericInfo reqInfo : builder.getRequirements()) {
					if (HostNamespace.HOST_NAMESPACE.equals(reqInfo.getNamespace())) {
						if (HostNamespace.EXTENSION_BOOTCLASSPATH.equals(reqInfo.getDirectives().get(HostNamespace.REQUIREMENT_EXTENSION_DIRECTIVE))) {
							throw new BundleException("Boot classpath extensions are not supported.", BundleException.UNSUPPORTED_OPERATION, new UnsupportedOperationException()); //$NON-NLS-1$
						}
					}
				}
			}
			return builder;
		}

		return OSGiManifestBuilderFactory.createBuilder(mapHeaders, Constants.SYSTEM_BUNDLE_SYMBOLICNAME, extraExports, extraCapabilities);
	}

	private String getSystemExtraCapabilities() {
		EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
		StringBuilder result = new StringBuilder();

		String systemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
		if (systemCapabilities != null && systemCapabilities.trim().length() > 0) {
			result.append(systemCapabilities).append(", "); //$NON-NLS-1$
		}

		String extraSystemCapabilities = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
		if (extraSystemCapabilities != null && extraSystemCapabilities.trim().length() > 0) {
			result.append(extraSystemCapabilities).append(", "); //$NON-NLS-1$
		}

		result.append(EclipsePlatformNamespace.ECLIPSE_PLATFORM_NAMESPACE).append("; "); //$NON-NLS-1$
		result.append(EquinoxConfiguration.PROP_OSGI_OS).append("=").append(equinoxConfig.getOS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
		result.append(EquinoxConfiguration.PROP_OSGI_WS).append("=").append(equinoxConfig.getWS()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
		result.append(EquinoxConfiguration.PROP_OSGI_ARCH).append("=").append(equinoxConfig.getOSArch()).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
		result.append(EquinoxConfiguration.PROP_OSGI_NL).append("=").append(equinoxConfig.getNL()); //$NON-NLS-1$

		String osName = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_NAME);
		osName = osName == null ? null : osName.toLowerCase();
		String processor = equinoxConfig.getConfiguration(Constants.FRAMEWORK_PROCESSOR);
		processor = processor == null ? null : processor.toLowerCase();
		String osVersion = equinoxConfig.getConfiguration(Constants.FRAMEWORK_OS_VERSION);
		osVersion = osVersion == null ? null : osVersion.toLowerCase();
		String language = equinoxConfig.getConfiguration(Constants.FRAMEWORK_LANGUAGE);
		language = language == null ? null : language.toLowerCase();

		result.append(", "); //$NON-NLS-1$
		result.append(NativeNamespace.NATIVE_NAMESPACE).append("; "); //$NON-NLS-1$
		if (osName != null) {
			osName = getAliasList(equinoxConfig.getAliasMapper().getOSNameAliases(osName));
			result.append(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE).append(":List<String>=").append(osName).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (processor != null) {
			processor = getAliasList(equinoxConfig.getAliasMapper().getProcessorAliases(processor));
			result.append(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE).append(":List<String>=").append(processor).append("; "); //$NON-NLS-1$ //$NON-NLS-2$
		}
		result.append(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE).append(":Version").append("=\"").append(osVersion).append("\"; "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		result.append(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE).append("=\"").append(language).append('\"'); //$NON-NLS-1$
		return result.toString();
	}

	String getAliasList(Collection<String> aliases) {
		if (aliases.isEmpty()) {
			return null;
		}
		StringBuilder builder = new StringBuilder();
		builder.append('"');
		for (String alias : aliases) {
			builder.append(alias).append(',');
		}
		builder.setLength(builder.length() - 1);
		builder.append('"');
		return builder.toString();
	}

	private String getSystemExtraPackages() {
		EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
		StringBuilder result = new StringBuilder();

		String systemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES);
		if (systemPackages != null) {
			result.append(systemPackages);
		}

		String extraSystemPackages = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
		if (extraSystemPackages != null && extraSystemPackages.trim().length() > 0) {
			if (result.length() > 0) {
				result.append(", "); //$NON-NLS-1$
			}
			result.append(extraSystemPackages);
		}

		return result.toString();
	}

	private void refresh(Module module) throws BundleException {
		ModuleRevision current = module.getCurrentRevision();
		Generation currentGen = (Generation) current.getRevisionInfo();
		File content = currentGen.getContent();
		String spec = (currentGen.isReference() ? "reference:" : "") + content.toURI().toString(); //$NON-NLS-1$ //$NON-NLS-2$
		URLConnection contentConn;
		try {
			contentConn = getContentConnection(spec);
		} catch (IOException e) {
			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
		}
		update(module, contentConn);
	}

	public Generation update(Module module, URLConnection content) throws BundleException {
		if (osgiLocation.isReadOnly()) {
			throw new BundleException("The framework storage area is read only.", BundleException.INVALID_OPERATION); //$NON-NLS-1$
		}
		URL sourceURL = content.getURL();
		InputStream in;
		try {
			in = content.getInputStream();
		} catch (Throwable e) {
			throw new BundleException("Error reading bundle content.", e); //$NON-NLS-1$
		}
		boolean isReference = in instanceof ReferenceInputStream;
		File staged = stageContent(in, sourceURL);
		ModuleRevision current = module.getCurrentRevision();
		Generation currentGen = (Generation) current.getRevisionInfo();

		BundleInfo bundleInfo = currentGen.getBundleInfo();
		Generation newGen = bundleInfo.createGeneration();

		try {
			File contentFile = getContentFile(staged, isReference, bundleInfo.getBundleId(), newGen.getGenerationId());
			newGen.setContent(contentFile, isReference);
			// Check that we can open the bundle file
			newGen.getBundleFile().open();
			setStorageHooks(newGen);

			ModuleRevisionBuilder builder = getBuilder(newGen);
			moduleContainer.update(module, builder, newGen);
		} catch (Throwable t) {
			if (!isReference) {
				try {
					delete(staged);
				} catch (IOException e) {
					// tried our best
				}
			}
			newGen.delete();
			if (t instanceof SecurityException) {
				// TODO hack from ModuleContainer
				// if the cause is a bundle exception then throw that
				if (t.getCause() instanceof BundleException) {
					throw (BundleException) t.getCause();
				}
				throw (SecurityException) t;
			}
			if (t instanceof BundleException) {
				throw (BundleException) t;
			}
			throw new BundleException("Error occurred updating a bundle.", t); //$NON-NLS-1$
		} finally {
			bundleInfo.unlockGeneration(newGen);
		}
		return newGen;
	}

	private File getContentFile(final File staged, final boolean isReference, final long bundleID, final long generationID) throws BundleException {
		if (System.getSecurityManager() == null)
			return getContentFile0(staged, isReference, bundleID, generationID);
		try {
			return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
				@Override
				public File run() throws BundleException {
					return getContentFile0(staged, isReference, bundleID, generationID);
				}
			});
		} catch (PrivilegedActionException e) {
			if (e.getException() instanceof BundleException)
				throw (BundleException) e.getException();
			throw (RuntimeException) e.getException();
		}
	}

	File getContentFile0(File staged, boolean isReference, long bundleID, long generationID) throws BundleException {
		File contentFile;
		if (!isReference) {
			File generationRoot = new File(childRoot, bundleID + "/" + generationID); //$NON-NLS-1$
			generationRoot.mkdirs();
			if (!generationRoot.isDirectory()) {
				throw new BundleException("Could not create generation directory: " + generationRoot.getAbsolutePath()); //$NON-NLS-1$
			}
			contentFile = new File(generationRoot, BUNDLE_FILE_NAME);
			if (!StorageUtil.move(staged, contentFile, getConfiguration().getDebug().DEBUG_STORAGE)) {
				throw new BundleException("Error while renaming bundle file to final location: " + contentFile); //$NON-NLS-1$
			}
		} else {
			contentFile = staged;
		}
		return contentFile;
	}

	private static String getBundleFilePath(long bundleID, long generationID) {
		return bundleID + "/" + generationID + "/" + BUNDLE_FILE_NAME; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Gets a file from storage and conditionally checks the parent storage area
	 * if the file does not exist in the child configuration.
	 * Note, this method does not check for escaping of paths from the root storage area.
	 * @param path the path relative to the root of the storage area
	 * @param checkParent if true then check the parent storage (if any) when the file
	 * does not exist in the child storage area
	 * @return the file being requested. A {@code null} value is never returned.  The file
	 * returned may not exist.
	 * @throws StorageException if there was an issue getting the file
	 */
	public File getFile(String path, boolean checkParent) throws StorageException {
		return getFile(null, path, checkParent);
	}

	/**
	 * Same as {@link #getFile(String, boolean)} except takes a base parameter which is
	 * appended to the root storage area before looking for the path.  If base is not
	 * null then additional checks are done to make sure the path does not escape out
	 * of the base path.
	 * @param base the additional base path to append to the root storage area.  May be
	 * {@code null}, in which case no check is done for escaping out of the base path.
	 * @param path the path relative to the root + base storage area.
	 * @param checkParent if true then check the parent storage (if any) when the file
	 * does not exist in the child storage area
	 * @return the file being requested. A {@code null} value is never returned.  The file
	 * returned may not exist.
	 * @throws StorageException if there was an issue getting the file
	 */
	public File getFile(String base, String path, boolean checkParent) throws StorageException {
		// first check the child location
		File childPath = getFile(childRoot, base, path);
		// now check the parent
		if (checkParent && parentRoot != null) {
			if (childPath.exists()) {
				return childPath;
			}
			File parentPath = getFile(parentRoot, base, path);
			if (parentPath.exists()) {
				// only use the parent file only if it exists;
				return parentPath;
			}
		}
		// did not exist in both locations; use the child path
		return childPath;
	}

	private static File getFile(File root, String base, String path) {
		if (base == null) {
			// return quick; no need to check for path traversal
			return new File(root, path);
		}

		// if base is not null then move root to include the base
		root = new File(root, base);
		File result = new File(root, path);

		// do the extra check to make sure the path did not escape the root path
		try {
			String resultCanonical = result.getCanonicalPath();
			String rootCanonical = root.getCanonicalPath();
			if (!resultCanonical.startsWith(rootCanonical + File.separator) && !resultCanonical.equals(rootCanonical)) {
				throw new StorageException("Invalid path: " + path); //$NON-NLS-1$
			}
		} catch (IOException e) {
			throw new StorageException("Invalid path: " + path, e); //$NON-NLS-1$
		}
		return result;
	}

	private File stageContent(final InputStream in, final URL sourceURL) throws BundleException {
		if (System.getSecurityManager() == null)
			return stageContent0(in, sourceURL);
		try {
			return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
				@Override
				public File run() throws BundleException {
					return stageContent0(in, sourceURL);
				}
			});
		} catch (PrivilegedActionException e) {
			if (e.getException() instanceof BundleException)
				throw (BundleException) e.getException();
			throw (RuntimeException) e.getException();
		}
	}

	File stageContent0(InputStream in, URL sourceURL) throws BundleException {
		File outFile = null;
		try {
			if (in instanceof ReferenceInputStream) {
				return ((ReferenceInputStream) in).getReference();
			}

			outFile = File.createTempFile(BUNDLE_FILE_NAME, ".tmp", childRoot); //$NON-NLS-1$
			String protocol = sourceURL == null ? null : sourceURL.getProtocol();

			if ("file".equals(protocol)) { //$NON-NLS-1$
				File inFile = new File(sourceURL.getPath());
				inFile = LocationHelper.decodePath(inFile);
				if (inFile.isDirectory()) {
					// need to delete the outFile because it is not a directory
					outFile.delete();
					StorageUtil.copyDir(inFile, outFile);
				} else {
					StorageUtil.readFile(in, outFile);
				}
			} else {
				StorageUtil.readFile(in, outFile);
			}
			return outFile;
		} catch (IOException e) {
			if (outFile != null) {
				outFile.delete();
			}
			throw new BundleException(Msg.BUNDLE_READ_EXCEPTION, BundleException.READ_ERROR, e);
		}
	}

	/**
	 * Attempts to set the permissions of the file in a system dependent way.
	 * @param file the file to set the permissions on
	 */
	public void setPermissions(File file) {
		String commandProp = getConfiguration().getConfiguration(EquinoxConfiguration.PROP_SETPERMS_CMD);
		if (commandProp == null)
			commandProp = getConfiguration().getConfiguration(Constants.FRAMEWORK_EXECPERMISSION);
		if (commandProp == null)
			return;
		String[] commandComponents = ManifestElement.getArrayFromList(commandProp, " "); //$NON-NLS-1$
		List<String> command = new ArrayList<>(commandComponents.length + 1);
		boolean foundFullPath = false;
		for (String commandComponent : commandComponents) {
			if ("[fullpath]".equals(commandComponent) || "${abspath}".equals(commandComponent)) { //$NON-NLS-1$ //$NON-NLS-2$
				command.add(file.getAbsolutePath());
				foundFullPath = true;
			} else {
				command.add(commandComponent);
			}
		}
		if (!foundFullPath)
			command.add(file.getAbsolutePath());
		try {
			Runtime.getRuntime().exec(command.toArray(new String[command.size()])).waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public BundleFile createBundleFile(File content, Generation generation, boolean isDirectory, boolean isBase) {
		BundleFile result;
		try {
			if (isDirectory) {
				boolean strictPath = Boolean.parseBoolean(equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROPERTY_STRICT_BUNDLE_ENTRY_PATH, Boolean.FALSE.toString()));
				result = new DirBundleFile(content, strictPath);
			} else {
				result = new ZipBundleFile(content, generation, mruList, getConfiguration().getDebug());
			}
		} catch (IOException e) {
			throw new RuntimeException("Could not create bundle file.", e); //$NON-NLS-1$
		}
		return wrapBundleFile(result, generation, isBase);
	}

	public BundleFile createNestedBundleFile(String nestedDir, BundleFile bundleFile, Generation generation) {
		return createNestedBundleFile(nestedDir, bundleFile, generation, Collections.<String> emptyList());
	}

	public BundleFile createNestedBundleFile(String nestedDir, BundleFile bundleFile, Generation generation, Collection<String> filterPrefixes) {
		// here we assume the content is a path offset into the base bundle file;  create a NestedDirBundleFile
		return wrapBundleFile(new NestedDirBundleFile(bundleFile, nestedDir, filterPrefixes), generation, false);
	}

	public BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean isBase) {
		// try creating a wrapper bundlefile out of it.
		List<BundleFileWrapperFactoryHook> wrapperFactories = getConfiguration().getHookRegistry().getBundleFileWrapperFactoryHooks();
		BundleFileWrapperChain wrapped = wrapperFactories.isEmpty() ? null : new BundleFileWrapperChain(bundleFile, null);
		for (BundleFileWrapperFactoryHook wrapperFactory : wrapperFactories) {
			BundleFileWrapper wrapperBundle = wrapperFactory.wrapBundleFile(bundleFile, generation, isBase);
			if (wrapperBundle != null && wrapperBundle != bundleFile)
				bundleFile = wrapped = new BundleFileWrapperChain(wrapperBundle, wrapped);
		}

		return bundleFile;
	}

	public void compact() {
		if (!osgiLocation.isReadOnly()) {
			compact(childRoot);
		}
	}

	private void compact(File directory) {
		if (getConfiguration().getDebug().DEBUG_STORAGE)
			Debug.println("compact(" + directory.getPath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
		String list[] = directory.list();
		if (list == null)
			return;

		int len = list.length;
		for (int i = 0; i < len; i++) {
			if (BUNDLE_DATA_DIR.equals(list[i]))
				continue; /* do not examine the bundles data dir. */
			File target = new File(directory, list[i]);
			// if the file is a directory
			if (!target.isDirectory())
				continue;
			File delete = new File(target, DELETE_FLAG);
			// and the directory is marked for delete
			if (delete.exists()) {
				// if rm fails to delete the directory and .delete was removed
				if (!StorageUtil.rm(target, getConfiguration().getDebug().DEBUG_STORAGE) && !delete.exists()) {
					try {
						// recreate .delete
						FileOutputStream out = new FileOutputStream(delete);
						out.close();
					} catch (IOException e) {
						if (getConfiguration().getDebug().DEBUG_STORAGE)
							Debug.println("Unable to write " + delete.getPath() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
					}
				}
			} else {
				compact(target); /* descend into directory */
			}
		}
	}

	void delete(final File delete) throws IOException {
		if (System.getSecurityManager() == null) {
			delete0(delete);
		} else {
			try {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
					@Override
					public Void run() throws IOException {
						delete0(delete);
						return null;
					}
				});
			} catch (PrivilegedActionException e) {
				if (e.getException() instanceof IOException)
					throw (IOException) e.getException();
				throw (RuntimeException) e.getException();
			}
		}
	}

	void delete0(File delete) throws IOException {
		if (!StorageUtil.rm(delete, getConfiguration().getDebug().DEBUG_STORAGE)) {
			/* create .delete */
			FileOutputStream out = new FileOutputStream(new File(delete, DELETE_FLAG));
			out.close();
		}
	}

	public void save() throws IOException {
		if (isReadOnly()) {
			return;
		}
		if (System.getSecurityManager() == null) {
			save0();
		} else {
			try {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
					@Override
					public Void run() throws IOException {
						save0();
						return null;
					}
				});
			} catch (PrivilegedActionException e) {
				if (e.getException() instanceof IOException)
					throw (IOException) e.getException();
				throw (RuntimeException) e.getException();
			}
		}
	}

	void save0() throws IOException {
		StorageManager childStorageManager = null;
		ManagedOutputStream mos = null;
		DataOutputStream out = null;
		boolean success = false;
		moduleDatabase.readLock();
		try {
			synchronized (this.saveMonitor) {
				if (lastSavedTimestamp == moduleDatabase.getTimestamp())
					return;
				childStorageManager = getChildStorageManager();
				mos = childStorageManager.getOutputStream(FRAMEWORK_INFO);
				out = new DataOutputStream(new BufferedOutputStream(mos));
				saveGenerations(out);
				savePermissionData(out);
				moduleDatabase.store(out, true);
				lastSavedTimestamp = moduleDatabase.getTimestamp();
				success = true;
			}
		} finally {
			if (!success) {
				if (mos != null) {
					mos.abort();
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					// tried our best
				}
			}
			if (childStorageManager != null) {
				childStorageManager.close();
			}
			moduleDatabase.readUnlock();
		}
	}

	private void savePermissionData(DataOutputStream out) throws IOException {
		permissionData.savePermissionData(out);
	}

	private void saveGenerations(DataOutputStream out) throws IOException {
		List<Module> modules = moduleContainer.getModules();
		List<Generation> generations = new ArrayList<>();
		for (Module module : modules) {
			ModuleRevision revision = module.getCurrentRevision();
			if (revision != null) {
				Generation generation = (Generation) revision.getRevisionInfo();
				if (generation != null) {
					generations.add(generation);
				}
			}
		}
		out.writeInt(VERSION);

		out.writeUTF(runtimeVersion.toString());

		Version curFrameworkVersion = findFrameworkVersion();
		out.writeUTF(curFrameworkVersion == null ? Version.emptyVersion.toString() : curFrameworkVersion.toString());

		saveLongString(out, getSystemExtraCapabilities());
		saveLongString(out, getSystemExtraPackages());

		out.writeInt(cachedHeaderKeys.size());
		for (String headerKey : cachedHeaderKeys) {
			out.writeUTF(headerKey);
		}

		out.writeInt(generations.size());
		for (Generation generation : generations) {
			BundleInfo bundleInfo = generation.getBundleInfo();
			out.writeLong(bundleInfo.getBundleId());
			out.writeUTF(bundleInfo.getLocation());
			out.writeLong(bundleInfo.getNextGenerationId());
			out.writeLong(generation.getGenerationId());
			out.writeBoolean(generation.isDirectory());
			out.writeBoolean(generation.isReference());
			out.writeBoolean(generation.hasPackageInfo());
			if (bundleInfo.getBundleId() == 0) {
				// just write empty string for system bundle content in this case
				out.writeUTF(""); //$NON-NLS-1$
			} else {
				if (generation.isReference()) {
					// make reference installs relative to the install path
					out.writeUTF(new FilePath(installPath).makeRelative(new FilePath(generation.getContent().getAbsolutePath())));
				} else {
					// make normal installs relative to the storage area
					out.writeUTF(Storage.getBundleFilePath(bundleInfo.getBundleId(), generation.getGenerationId()));
				}
			}
			out.writeLong(generation.getLastModified());

			Dictionary<String, String> headers = generation.getHeaders();
			for (String headerKey : cachedHeaderKeys) {
				String value = headers.get(headerKey);
				if (value != null) {
					out.writeUTF(value);
				} else {
					out.writeUTF(NUL);
				}
			}

			out.writeBoolean(generation.isMRJar());
		}

		saveStorageHookData(out, generations);
	}

	private void saveLongString(DataOutputStream out, String value) throws IOException {
		if (value == null) {
			out.writeInt(0);
		} else {
			// don't use out.writeUTF because it has a hard string limit
			byte[] data = value.getBytes("UTF-8"); //$NON-NLS-1$
			out.writeInt(data.length);
			out.write(data);
		}
	}

	private String readLongString(DataInputStream in) throws IOException {
		int length = in.readInt();
		byte[] data = new byte[length];
		in.readFully(data);
		return new String(data, "UTF-8"); //$NON-NLS-1$
	}

	private void saveStorageHookData(DataOutputStream out, List<Generation> generations) throws IOException {
		List<StorageHookFactory<?, ?, ?>> factories = getConfiguration().getHookRegistry().getStorageHookFactories();
		out.writeInt(factories.size());
		for (StorageHookFactory<?, ?, ?> factory : factories) {
			out.writeUTF(factory.getKey());
			out.writeInt(factory.getStorageVersion());

			// create a temporary in memory stream so we can figure out the length
			ByteArrayOutputStream tempBytes = new ByteArrayOutputStream();
			DataOutputStream temp = new DataOutputStream(tempBytes);
			try {
				Object saveContext = factory.createSaveContext();
				for (Generation generation : generations) {
					if (generation.getBundleInfo().getBundleId() == 0) {
						continue; // ignore system bundle
					}
					@SuppressWarnings({"rawtypes", "unchecked"})
					StorageHook<Object, Object> hook = generation.getStorageHook((Class) factory.getClass());
					if (hook != null) {
						hook.save(saveContext, temp);
					}
				}
			} finally {
				temp.close();
			}
			out.writeInt(tempBytes.size());
			out.write(tempBytes.toByteArray());
		}
	}

	private Map<Long, Generation> loadGenerations(DataInputStream in, String[] cachedInfo) throws IOException {
		if (in == null) {
			return new HashMap<>(0);
		}
		int version = in.readInt();
		if (version > VERSION || version < LOWEST_VERSION_SUPPORTED) {
			throw new IllegalArgumentException("Found persistent version \"" + version + "\" expecting \"" + VERSION + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		Version savedRuntimeVersion = (version >= MR_JAR_VERSION) ? Version.parseVersion(in.readUTF()) : null;
		if (savedRuntimeVersion == null || !savedRuntimeVersion.equals(runtimeVersion)) {
			refreshMRBundles.set(true);
		}

		cachedInfo[0] = (version >= CACHED_SYSTEM_CAPS_VERION) ? in.readUTF() : null;
		cachedInfo[1] = (version >= CACHED_SYSTEM_CAPS_VERION) ? readLongString(in) : null;
		cachedInfo[2] = (version >= CACHED_SYSTEM_CAPS_VERION) ? readLongString(in) : null;

		int numCachedHeaders = in.readInt();
		List<String> storedCachedHeaderKeys = new ArrayList<>(numCachedHeaders);
		for (int i = 0; i < numCachedHeaders; i++) {
			storedCachedHeaderKeys.add(ObjectPool.intern(in.readUTF()));
		}

		int numInfos = in.readInt();
		Map<Long, Generation> result = new HashMap<>(numInfos);
		List<Generation> generations = new ArrayList<>(numInfos);
		for (int i = 0; i < numInfos; i++) {
			long infoId = in.readLong();
			String infoLocation = ObjectPool.intern(in.readUTF());
			long nextGenId = in.readLong();
			long generationId = in.readLong();
			boolean isDirectory = in.readBoolean();
			boolean isReference = in.readBoolean();
			boolean hasPackageInfo = in.readBoolean();
			String contentPath = in.readUTF();
			long lastModified = in.readLong();

			Map<String, String> cachedHeaders = new HashMap<>(storedCachedHeaderKeys.size());
			for (String headerKey : storedCachedHeaderKeys) {
				String value = in.readUTF();
				if (NUL.equals(value)) {
					value = null;
				} else {
					value = ObjectPool.intern(value);
				}
				cachedHeaders.put(headerKey, value);
			}
			boolean isMRJar = (version >= MR_JAR_VERSION) ? in.readBoolean() : false;

			File content;
			if (infoId == 0) {
				content = getSystemContent();
				isDirectory = content != null ? content.isDirectory() : false;
				// Note that we do not do any checking for absolute paths with
				// the system bundle.  We always take the content as discovered
				// by getSystemContent()
			} else {
				content = new File(contentPath);
				if (!content.isAbsolute()) {
					// make sure it has the absolute location instead
					if (isReference) {
						// reference installs are relative to the installPath
						content = new File(installPath, contentPath);
					} else {
						// normal installs are relative to the storage area
						content = getFile(contentPath, true);
					}
				}
			}

			BundleInfo info = new BundleInfo(this, infoId, infoLocation, nextGenId);
			Generation generation = info.restoreGeneration(generationId, content, isDirectory, isReference, hasPackageInfo, cachedHeaders, lastModified, isMRJar);
			result.put(infoId, generation);
			generations.add(generation);
		}

		loadStorageHookData(generations, in);
		return result;
	}

	private void loadStorageHookData(List<Generation> generations, DataInputStream in) throws IOException {
		List<StorageHookFactory<?, ?, ?>> factories = new ArrayList<>(getConfiguration().getHookRegistry().getStorageHookFactories());
		Map<Generation, List<StorageHook<?, ?>>> hookMap = new HashMap<>();
		int numFactories = in.readInt();
		for (int i = 0; i < numFactories; i++) {
			String factoryName = in.readUTF();
			int version = in.readInt();
			StorageHookFactory<Object, Object, StorageHook<Object, Object>> factory = null;
			for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
				@SuppressWarnings("unchecked")
				StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
				if (next.getKey().equals(factoryName)) {
					factory = next;
					iFactories.remove();
					break;
				}
			}
			int dataSize = in.readInt();
			byte[] bytes = new byte[dataSize];
			in.readFully(bytes);
			if (factory != null) {
				DataInputStream temp = new DataInputStream(new ByteArrayInputStream(bytes));
				try {
					if (factory.isCompatibleWith(version)) {
						Object loadContext = factory.createLoadContext(version);
						for (Generation generation : generations) {
							if (generation.getBundleInfo().getBundleId() == 0) {
								continue; // ignore system bundle
							}
							StorageHook<Object, Object> hook = factory.createStorageHookAndValidateFactoryClass(generation);
							if (hook != null) {
								hook.load(loadContext, temp);
								getHooks(hookMap, generation).add(hook);
							}
						}
					} else {
						// recover by reinitializing the hook
						for (Generation generation : generations) {
							if (generation.getBundleInfo().getBundleId() == 0) {
								continue; // ignore system bundle
							}
							StorageHook<Object, Object> hook = factory.createStorageHookAndValidateFactoryClass(generation);
							if (hook != null) {
								hook.initialize(generation.getHeaders());
								getHooks(hookMap, generation).add(hook);
							}
						}
					}
				} catch (BundleException e) {
					throw new IOException(e);
				} finally {
					temp.close();
				}
			}
		}
		// now we need to recover for any hooks that are left
		for (Iterator<StorageHookFactory<?, ?, ?>> iFactories = factories.iterator(); iFactories.hasNext();) {
			@SuppressWarnings("unchecked")
			StorageHookFactory<Object, Object, StorageHook<Object, Object>> next = (StorageHookFactory<Object, Object, StorageHook<Object, Object>>) iFactories.next();
			// recover by reinitializing the hook
			for (Generation generation : generations) {
				if (generation.getBundleInfo().getBundleId() == 0) {
					continue; // ignore system bundle
				}
				StorageHook<Object, Object> hook = next.createStorageHookAndValidateFactoryClass(generation);
				if (hook != null) {
					try {
						hook.initialize(generation.getHeaders());
						getHooks(hookMap, generation).add(hook);
					} catch (BundleException e) {
						throw new IOException(e);
					}
				}
			}
		}
		// now set the hooks to the generations
		for (Generation generation : generations) {
			generation.setStorageHooks(Collections.unmodifiableList(getHooks(hookMap, generation)), false);
		}
	}

	private static List<StorageHook<?, ?>> getHooks(Map<Generation, List<StorageHook<?, ?>>> hookMap, Generation generation) {
		List<StorageHook<?, ?>> result = hookMap.get(generation);
		if (result == null) {
			result = new ArrayList<>();
			hookMap.put(generation, result);
		}
		return result;
	}

	private File getSystemContent() {
		String frameworkValue = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_FRAMEWORK);
		if (frameworkValue == null || !frameworkValue.startsWith("file:")) { //$NON-NLS-1$
			return null;
		}
		// TODO assumes the location is a file URL
		File result = new File(frameworkValue.substring(5)).getAbsoluteFile();
		if (!result.exists()) {
			throw new IllegalStateException("Configured framework location does not exist: " + result.getAbsolutePath()); //$NON-NLS-1$
		}
		return result;
	}

	@SuppressWarnings("deprecation")
	private void loadVMProfile(Generation systemGeneration) {
		EquinoxConfiguration equinoxConfig = equinoxContainer.getConfiguration();
		Properties profileProps = findVMProfile(systemGeneration);
		String systemExports = equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES);
		// set the system exports property using the vm profile; only if the property is not already set
		if (systemExports == null) {
			systemExports = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
			if (systemExports != null)
				equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMPACKAGES, systemExports);
		}

		// set the org.osgi.framework.bootdelegation property according to the java profile
		String type = equinoxConfig.getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore
		String profileBootDelegation = profileProps.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
		if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) {
			if (profileBootDelegation == null)
				equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // override with a null value
			else
				equinoxConfig.setConfiguration(Constants.FRAMEWORK_BOOTDELEGATION, profileBootDelegation); // override with the profile value
		} else if (EquinoxConfiguration.PROP_OSGI_BOOTDELEGATION_NONE.equals(type))
			equinoxConfig.clearConfiguration(Constants.FRAMEWORK_BOOTDELEGATION); // remove the bootdelegation property in case it was set
		// set the org.osgi.framework.executionenvironment property according to the java profile
		if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) {
			// get the ee from the java profile; if no ee is defined then try the java profile name
			String ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME));
			if (ee != null)
				equinoxConfig.setConfiguration(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
		}
		// set the org.osgi.framework.system.capabilities property according to the java profile
		if (equinoxConfig.getConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES) == null) {
			String systemCapabilities = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
			if (systemCapabilities != null)
				equinoxConfig.setConfiguration(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities);
		}
	}

	private Properties findVMProfile(Generation systemGeneration) {
		Properties result = readConfiguredJavaProfile(systemGeneration);
		String vmProfile = null;
		try {
			if (result != null) {
				return result;
			}

			if (Version.valueOf("9").compareTo(runtimeVersion) <= 0) { //$NON-NLS-1$
				result = calculateVMProfile(runtimeVersion);
				if (result != null) {
					return result;
				}
				// could not calculate; fall back to reading profile files
			}

			String embeddedProfileName = "-"; //$NON-NLS-1$
			// If javaSE 1.8 then check for release file for profile name.
			if (runtimeVersion != null && Version.valueOf("1.8").compareTo(runtimeVersion) <= 0) { //$NON-NLS-1$
				String javaHome = System.getProperty("java.home"); //$NON-NLS-1$
				if (javaHome != null) {
					File release = new File(javaHome, "release"); //$NON-NLS-1$
					if (release.exists()) {
						Properties releaseProps = new Properties();
						try (InputStream releaseStream = new FileInputStream(release)) {
							releaseProps.load(releaseStream);
							String releaseName = releaseProps.getProperty("JAVA_PROFILE"); //$NON-NLS-1$
							if (releaseName != null) {
								// make sure to remove extra quotes
								releaseName = releaseName.replaceAll("^\\s*\"?|\"?\\s*$", ""); //$NON-NLS-1$ //$NON-NLS-2$
								embeddedProfileName = "_" + releaseName + "-"; //$NON-NLS-1$ //$NON-NLS-2$
							}
						} catch (IOException e) {
							// ignore
						}
					}
				}
			}

			result = new Properties();
			vmProfile = JAVASE + embeddedProfileName + javaSpecVersion;
			InputStream profileIn = null;
			if (vmProfile != null) {
				// look for a profile in the system bundle based on the vm profile
				String javaProfile = vmProfile + PROFILE_EXT;
				profileIn = findInSystemBundle(systemGeneration, javaProfile);
				if (profileIn == null)
					profileIn = getNextBestProfile(systemGeneration, JAVASE, runtimeVersion, embeddedProfileName);
			}
			if (profileIn == null)
				// the profile url is still null then use the min profile the framework can use
				profileIn = findInSystemBundle(systemGeneration, "JavaSE-1.7.profile"); //$NON-NLS-1$
			if (profileIn != null) {
				try {
					result.load(new BufferedInputStream(profileIn));
				} catch (IOException e) {
					// TODO consider logging ...
				} finally {
					try {
						profileIn.close();
					} catch (IOException ee) {
						// do nothing
					}
				}
			}
		} finally {
			// set the profile name if it does not provide one
			if (result != null && result.getProperty(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME) == null) {
				if (vmProfile != null) {
					result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/'));
				} else {
					// last resort; default to the absolute minimum profile name for the framework
					result.put(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE_NAME, "JavaSE-1.7"); //$NON-NLS-1$
				}
			}
		}
		return result;
	}

	private Properties readConfiguredJavaProfile(Generation systemGeneration) {
		// check for the java profile property for a url
		String propJavaProfile = equinoxContainer.getConfiguration().getConfiguration(EquinoxConfiguration.PROP_OSGI_JAVA_PROFILE);
		if (propJavaProfile != null) {
			InputStream profileIn = null;
			try {
				// we assume a URL
				profileIn = new URL(propJavaProfile).openStream();
			} catch (IOException e) {
				// try using a relative path in the system bundle
				profileIn = findInSystemBundle(systemGeneration, propJavaProfile);
			}
			if (profileIn != null) {
				Properties result = new Properties();
				try {
					result.load(new BufferedInputStream(profileIn));
				} catch (IOException e) {
					// consider logging
				} finally {
					try {
						profileIn.close();
					} catch (IOException e) {
						// nothing to do
					}
				}
				return result;
			}
		}
		return null;
	}

	@SuppressWarnings("deprecation")
	private Properties calculateVMProfile(Version javaVersion) {
		String systemPackages = calculateVMPackages();
		if (systemPackages == null) {
			return null;
		}
		String executionEnvs = calculateVMExecutionEnvs(javaVersion);
		String eeCapabilities = calculateEECapabilities(javaVersion);

		Properties result = new Properties();
		result.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages);
		result.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, executionEnvs);
		result.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, eeCapabilities);
		return result;
	}

	private String calculateVMExecutionEnvs(Version javaVersion) {
		StringBuilder result = new StringBuilder("OSGi/Minimum-1.0, OSGi/Minimum-1.1, OSGi/Minimum-1.2, JavaSE/compact1-1.8, JavaSE/compact2-1.8, JavaSE/compact3-1.8, JRE-1.1, J2SE-1.2, J2SE-1.3, J2SE-1.4, J2SE-1.5, JavaSE-1.6, JavaSE-1.7, JavaSE-1.8"); //$NON-NLS-1$
		Version v = new Version(9, 0, 0);
		while (v.compareTo(javaVersion) <= 0) {
			result.append(',').append(' ').append(JAVASE).append('-').append(v.getMajor());
			if (v.getMinor() > 0) {
				result.append('.').append(v.getMinor());
			}
			if (v.getMajor() == javaVersion.getMajor()) {
				v = new Version(v.getMajor(), v.getMinor() + 1, 0);
			} else {
				v = new Version(v.getMajor() + 1, 0, 0);
			}
		}
		return result.toString();
	}

	private String calculateEECapabilities(Version javaVersion) {
		Version v = new Version(9, 0, 0);
		StringBuilder versionsBulder = new StringBuilder();
		while (v.compareTo(javaVersion) <= 0) {
			versionsBulder.append(',').append(' ').append(v.getMajor()).append('.').append(v.getMinor());
			if (v.getMajor() == javaVersion.getMajor()) {
				v = new Version(v.getMajor(), v.getMinor() + 1, 0);
			} else {
				v = new Version(v.getMajor() + 1, 0, 0);
			}
		}
		String versionsList = versionsBulder.toString();

		StringBuilder result = new StringBuilder("osgi.ee; osgi.ee=\"OSGi/Minimum\"; version:List<Version>=\"1.0, 1.1, 1.2\", osgi.ee; osgi.ee=\"JRE\"; version:List<Version>=\"1.0, 1.1\", osgi.ee; osgi.ee=\"JavaSE\"; version:List<Version>=\"1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8"); //$NON-NLS-1$
		result.append(versionsList).append("\""); //$NON-NLS-1$
		result.append(",osgi.ee; osgi.ee=\"JavaSE/compact1\"; version:List<Version>=\"1.8"); //$NON-NLS-1$
		result.append(versionsList).append("\""); //$NON-NLS-1$
		result.append(",osgi.ee; osgi.ee=\"JavaSE/compact2\"; version:List<Version>=\"1.8"); //$NON-NLS-1$
		result.append(versionsList).append("\""); //$NON-NLS-1$
		result.append(",osgi.ee; osgi.ee=\"JavaSE/compact3\"; version:List<Version>=\"1.8"); //$NON-NLS-1$
		result.append(versionsList).append("\""); //$NON-NLS-1$

		return result.toString();
	}

	@SuppressWarnings("unchecked")
	private String calculateVMPackages() {
		try {
			List<String> packages = new ArrayList<>();
			Class<?> moduleLayerClass = Class.forName("java.lang.ModuleLayer"); //$NON-NLS-1$
			Method boot = moduleLayerClass.getMethod("boot"); //$NON-NLS-1$
			Method modules = moduleLayerClass.getMethod("modules"); //$NON-NLS-1$
			Class<?> moduleClass = Class.forName("java.lang.Module"); //$NON-NLS-1$
			Method getDescriptor = moduleClass.getMethod("getDescriptor"); //$NON-NLS-1$
			Class<?> moduleDescriptorClass = Class.forName("java.lang.module.ModuleDescriptor"); //$NON-NLS-1$
			Method exports = moduleDescriptorClass.getMethod("exports"); //$NON-NLS-1$
			Method isAutomatic = moduleDescriptorClass.getMethod("isAutomatic"); //$NON-NLS-1$
			Method packagesMethod = moduleDescriptorClass.getMethod("packages"); //$NON-NLS-1$
			Class<?> exportsClass = Class.forName("java.lang.module.ModuleDescriptor$Exports"); //$NON-NLS-1$
			Method isQualified = exportsClass.getMethod("isQualified"); //$NON-NLS-1$
			Method source = exportsClass.getMethod("source"); //$NON-NLS-1$

			Object bootLayer = boot.invoke(null);
			Set<?> bootModules = (Set<?>) modules.invoke(bootLayer);
			for (Object m : bootModules) {
				Object descriptor = getDescriptor.invoke(m);
				if ((Boolean) isAutomatic.invoke(descriptor)) {
					/*
					 * Automatic modules are supposed to export all their packages.
					 * However, java.lang.module.ModuleDescriptor::exports returns an empty set for them.
					 * Add all their packages (as returned by java.lang.module.ModuleDescriptor::packages)
					 * to the list of VM supplied packages.
					 */
					packages.addAll((Set<String>) packagesMethod.invoke(descriptor));
				} else {
					for (Object export : (Set<?>) exports.invoke(descriptor)) {
						String pkg = (String) source.invoke(export);
						if (!((Boolean) isQualified.invoke(export))) {
							packages.add(pkg);
						}
					}
				}
			}
			Collections.sort(packages);
			StringBuilder result = new StringBuilder();
			for (String pkg : packages) {
				if (result.length() != 0) {
					result.append(',').append(' ');
				}
				result.append(pkg);
			}
			return result.toString();
		} catch (Exception e) {
			equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, "Error determining system packages.", e); //$NON-NLS-1$
			return null;
		}
	}

	private InputStream getNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion, String embeddedProfileName) {
		if (javaVersion == null || javaEdition != JAVASE)
			return null; // we cannot automatically choose the next best profile unless this is a JavaSE vm
		InputStream bestProfile = findNextBestProfile(systemGeneration, javaEdition, javaVersion, embeddedProfileName);
		if (bestProfile == null && !"-".equals(embeddedProfileName)) { //$NON-NLS-1$
			// Just use the base javaEdition name without the profile name as backup
			return getNextBestProfile(systemGeneration, javaEdition, javaVersion, "-"); //$NON-NLS-1$
		}
		return bestProfile;
	}

	private InputStream findNextBestProfile(Generation systemGeneration, String javaEdition, Version javaVersion, String embeddedProfileName) {
		InputStream result = null;
		int major = javaVersion.getMajor();
		int minor = javaVersion.getMinor();
		do {
			// If minor is zero then it is not included in the name
			String profileResourceName = javaEdition + embeddedProfileName + major + ((minor > 0) ? "." + minor : "") + PROFILE_EXT; //$NON-NLS-1$ //$NON-NLS-2$
			result = findInSystemBundle(systemGeneration, profileResourceName);
			if (minor > 0) {
				minor -= 1;
			} else if (major > 9) {
				major -= 1;
			} else if (major <= 9 && major > 1) {
				minor = 8;
				major = 1;
			} else {
				// we have reached the end of our search; return the existing result;
				return result;
			}
		} while (result == null && minor >= 0);
		return result;
	}

	private InputStream findInSystemBundle(Generation systemGeneration, String entry) {
		BundleFile systemContent = systemGeneration.getBundleFile();
		BundleEntry systemEntry = systemContent != null ? systemContent.getEntry(entry) : null;
		InputStream result = null;
		if (systemEntry != null) {
			try {
				result = systemEntry.getInputStream();
			} catch (IOException e) {
				// Do nothing
			}
		}
		if (result == null) {
			// Check the ClassLoader in case we're launched off the Java boot classpath
			ClassLoader loader = getClass().getClassLoader();
			result = loader == null ? ClassLoader.getSystemResourceAsStream(entry) : loader.getResourceAsStream(entry);
		}
		return result;
	}

	public static Enumeration<URL> findEntries(List<Generation> generations, String path, String filePattern, int options) {
		List<BundleFile> bundleFiles = new ArrayList<>(generations.size());
		for (Generation generation : generations)
			bundleFiles.add(generation.getBundleFile());
		// search all the bundle files
		List<String> pathList = listEntryPaths(bundleFiles, path, filePattern, options);
		// return null if no entries found
		if (pathList.size() == 0)
			return null;
		// create an enumeration to enumerate the pathList
		final String[] pathArray = pathList.toArray(new String[pathList.size()]);
		final Generation[] generationArray = generations.toArray(new Generation[generations.size()]);
		return new Enumeration<URL>() {
			private int curPathIndex = 0;
			private int curDataIndex = 0;
			private URL nextElement = null;

			@Override
			public boolean hasMoreElements() {
				if (nextElement != null)
					return true;
				getNextElement();
				return nextElement != null;
			}

			@Override
			public URL nextElement() {
				if (!hasMoreElements())
					throw new NoSuchElementException();
				URL result = nextElement;
				// force the next element search
				getNextElement();
				return result;
			}

			private void getNextElement() {
				nextElement = null;
				if (curPathIndex >= pathArray.length)
					// reached the end of the pathArray; no more elements
					return;
				while (nextElement == null && curPathIndex < pathArray.length) {
					String curPath = pathArray[curPathIndex];
					// search the generation until we have searched them all
					while (nextElement == null && curDataIndex < generationArray.length)
						nextElement = generationArray[curDataIndex++].getEntry(curPath);
					// we have searched all datas then advance to the next path 
					if (curDataIndex >= generationArray.length) {
						curPathIndex++;
						curDataIndex = 0;
					}
				}
			}
		};
	}

	/**
	 * Returns the names of resources available from a list of bundle files.
	 * No duplicate resource names are returned, each name is unique.
	 * @param bundleFiles the list of bundle files to search in
	 * @param path The path name in which to look.
	 * @param filePattern The file name pattern for selecting resource names in
	 *        the specified path.
	 * @param options The options for listing resource names.
	 * @return a list of resource names.  If no resources are found then
	 * the empty list is returned.
	 * @see BundleWiring#listResources(String, String, int)
	 */
	public static List<String> listEntryPaths(List<BundleFile> bundleFiles, String path, String filePattern, int options) {
		// Use LinkedHashSet for optimized performance of contains() plus
		// ordering guarantees.
		LinkedHashSet<String> pathList = new LinkedHashSet<>();
		Filter patternFilter = null;
		Hashtable<String, String> patternProps = null;
		if (filePattern != null) {
			// Optimization: If the file pattern does not include a wildcard  or escape char then it must represent a single file.
			// Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested.
			if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) {
				if (path.length() == 0)
					path = filePattern;
				else
					path += path.charAt(path.length() - 1) == '/' ? filePattern : '/' + filePattern;
				for (BundleFile bundleFile : bundleFiles) {
					if (bundleFile.getEntry(path) != null && !pathList.contains(path))
						pathList.add(path);
				}
				return new ArrayList<>(pathList);
			}
			// For when the file pattern includes a wildcard.
			try {
				// create a file pattern filter with 'filename' as the key
				patternFilter = FilterImpl.newInstance("(filename=" + sanitizeFilterInput(filePattern) + ")"); //$NON-NLS-1$ //$NON-NLS-2$
				// create a single hashtable to be shared during the recursive search
				patternProps = new Hashtable<>(2);
			} catch (InvalidSyntaxException e) {
				// TODO something unexpected happened; log error and return nothing
				//				Bundle b = context == null ? null : context.getBundle();
				//				eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e);
				return new ArrayList<>(pathList);
			}
		}
		// find the entry paths for the datas
		for (BundleFile bundleFile : bundleFiles) {
			listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList);
		}
		return new ArrayList<>(pathList);
	}

	public static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException {
		StringBuilder buffer = null;
		boolean foundEscape = false;
		for (int i = 0; i < filePattern.length(); i++) {
			char c = filePattern.charAt(i);
			switch (c) {
				case '\\' :
					// we either used the escape found or found a new escape.
					foundEscape = foundEscape ? false : true;
					if (buffer != null)
						buffer.append(c);
					break;
				case '(' :
				case ')' :
					if (!foundEscape) {
						if (buffer == null) {
							buffer = new StringBuilder(filePattern.length() + 16);
							buffer.append(filePattern.substring(0, i));
						}
						// must escape with '\'
						buffer.append('\\');
					} else {
						foundEscape = false; // used the escape found
					}
					if (buffer != null)
						buffer.append(c);
					break;
				default :
					// if we found an escape it has been used
					foundEscape = false;
					if (buffer != null)
						buffer.append(c);
					break;
			}
		}
		if (foundEscape)
			throw new InvalidSyntaxException("Trailing escape characters must be escaped.", filePattern); //$NON-NLS-1$
		return buffer == null ? filePattern : buffer.toString();
	}

	// Use LinkedHashSet for optimized performance of contains() plus ordering 
	// guarantees.
	private static LinkedHashSet<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, LinkedHashSet<String> pathList) {
		if (pathList == null)
			pathList = new LinkedHashSet<>();
		Enumeration<String> entryPaths;
		if ((options & BundleWiring.FINDENTRIES_RECURSE) != 0)
			entryPaths = bundleFile.getEntryPaths(path, true);
		else
			entryPaths = bundleFile.getEntryPaths(path);
		if (entryPaths == null)
			return pathList;
		while (entryPaths.hasMoreElements()) {
			String entry = entryPaths.nextElement();
			int lastSlash = entry.lastIndexOf('/');
			if (patternProps != null) {
				int secondToLastSlash = entry.lastIndexOf('/', lastSlash - 1);
				int fileStart;
				int fileEnd = entry.length();
				if (lastSlash < 0)
					fileStart = 0;
				else if (lastSlash != entry.length() - 1)
					fileStart = lastSlash + 1;
				else {
					fileEnd = lastSlash; // leave the lastSlash out
					if (secondToLastSlash < 0)
						fileStart = 0;
					else
						fileStart = secondToLastSlash + 1;
				}
				String fileName = entry.substring(fileStart, fileEnd);
				// set the filename to the current entry
				patternProps.put("filename", fileName); //$NON-NLS-1$
			}
			// prevent duplicates and match on the patternFilter
			if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps)))
				pathList.add(entry);
		}
		return pathList;
	}

	public String copyToTempLibrary(Generation generation, String absolutePath) {
		File libTempDir = new File(childRoot, LIB_TEMP);
		// we assume the absolutePath is a File path
		File realLib = new File(absolutePath);
		String libName = realLib.getName();
		// find a temp dir for the bundle data and the library;
		File bundleTempDir = null;
		File libTempFile = null;
		// We need a somewhat predictable temp dir for the libraries of a given bundle;
		// This is not strictly necessary but it does help scenarios where one native library loads another native library without using java.
		// On some OSes this causes issues because the second library is cannot be found.
		// This has been worked around by the bundles loading the libraries in a particular order (and setting some LIB_PATH env).
		// The one catch is that the libraries need to be in the same directory and they must use their original lib names.
		//
		// This bit of code attempts to do that by using the bundle ID as an ID for the temp dir along with an incrementing ID 
		// in cases where the temp dir may already exist.
		Long bundleID = new Long(generation.getBundleInfo().getBundleId());
		for (int i = 0; i < Integer.MAX_VALUE; i++) {
			bundleTempDir = new File(libTempDir, bundleID.toString() + "_" + Integer.valueOf(i).toString()); //$NON-NLS-1$
			libTempFile = new File(bundleTempDir, libName);
			if (bundleTempDir.exists()) {
				if (libTempFile.exists())
					continue; // to to next temp file
				break;
			}
			break;
		}
		if (!bundleTempDir.isDirectory()) {
			bundleTempDir.mkdirs();
			bundleTempDir.deleteOnExit();
			// This is just a safeguard incase the VM is terminated unexpectantly, it also looks like deleteOnExit cannot really work because
			// the VM likely will still have a lock on the lib file at the time of VM exit.
			File deleteFlag = new File(libTempDir, DELETE_FLAG);
			if (!deleteFlag.exists()) {
				// need to create a delete flag to force removal the temp libraries
				try {
					FileOutputStream out = new FileOutputStream(deleteFlag);
					out.close();
				} catch (IOException e) {
					// do nothing; that would mean we did not make the temp dir successfully
				}
			}
		}
		// copy the library file
		try {
			InputStream in = new FileInputStream(realLib);
			StorageUtil.readFile(in, libTempFile);
			// set permissions if needed
			setPermissions(libTempFile);
			libTempFile.deleteOnExit(); // this probably will not work because the VM will probably have the lib locked at exit
			// return the temporary path
			return libTempFile.getAbsolutePath();
		} catch (IOException e) {
			equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, e.getMessage(), e);
			return null;
		}
	}

	public SecurityAdmin getSecurityAdmin() {
		return securityAdmin;
	}

	protected StorageManager getChildStorageManager() throws IOException {
		String locking = getConfiguration().getConfiguration(LocationHelper.PROP_OSGI_LOCKING, LocationHelper.LOCKING_NIO);
		StorageManager sManager = new StorageManager(childRoot, isReadOnly() ? LocationHelper.LOCKING_NONE : locking, isReadOnly());
		try {
			sManager.open(!isReadOnly());
		} catch (IOException ex) {
			if (getConfiguration().getDebug().DEBUG_STORAGE) {
				Debug.println("Error reading framework.info: " + ex.getMessage()); //$NON-NLS-1$
				Debug.printStackTrace(ex);
			}
			String message = NLS.bind(Msg.ECLIPSE_STARTUP_FILEMANAGER_OPEN_ERROR, ex.getMessage());
			equinoxContainer.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, message, ex);
			getConfiguration().setProperty(EclipseStarter.PROP_EXITCODE, "15"); //$NON-NLS-1$
			String errorDialog = "<title>" + Msg.ADAPTOR_STORAGE_INIT_FAILED_TITLE + "</title>" + NLS.bind(Msg.ADAPTOR_STORAGE_INIT_FAILED_MSG, childRoot) + "\n" + ex.getMessage(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			getConfiguration().setProperty(EclipseStarter.PROP_EXITDATA, errorDialog);
			throw ex;
		}
		return sManager;
	}

	private InputStream getInfoInputStream() throws IOException {
		StorageManager storageManager = getChildStorageManager();
		InputStream storageStream = null;
		try {
			storageStream = storageManager.getInputStream(FRAMEWORK_INFO);
		} catch (IOException ex) {
			if (getConfiguration().getDebug().DEBUG_STORAGE) {
				Debug.println("Error reading framework.info: " + ex.getMessage()); //$NON-NLS-1$
				Debug.printStackTrace(ex);
			}
		} finally {
			storageManager.close();
		}
		if (storageStream == null && parentRoot != null) {
			StorageManager parentStorageManager = null;
			try {
				parentStorageManager = new StorageManager(parentRoot, LocationHelper.LOCKING_NONE, true);
				parentStorageManager.open(false);
				storageStream = parentStorageManager.getInputStream(FRAMEWORK_INFO);
			} catch (IOException e1) {
				// That's ok we will regenerate the framework.info
			} finally {
				if (parentStorageManager != null) {
					parentStorageManager.close();
				}
			}
		}
		return storageStream;
	}
}
