/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.framework;

import org.apache.felix.framework.cache.ConnectContentContent;
import org.apache.felix.framework.cache.Content;
import org.apache.felix.framework.cache.DirectoryContent;
import org.apache.felix.framework.cache.JarContent;
import org.apache.felix.framework.ext.ClassPathExtenderFactory;
import org.apache.felix.framework.util.ClassParser;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
import org.apache.felix.framework.util.manifestparser.NativeLibrary;
import org.apache.felix.framework.util.manifestparser.NativeLibraryClause;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * The ExtensionManager class is used as content loader of the systembundle. Added extension
 * bundles exports will be available via this loader.
 */
class ExtensionManager implements Content
{
    static final ClassPathExtenderFactory.ClassPathExtender m_extenderFramework;
    static final ClassPathExtenderFactory.ClassPathExtender m_extenderBoot;
    private static final Set<String> IDENTITY = new HashSet<String>(Arrays.asList(
        BundleNamespace.BUNDLE_NAMESPACE,
        HostNamespace.HOST_NAMESPACE,
        IdentityNamespace.IDENTITY_NAMESPACE));

    static
    {
        ClassPathExtenderFactory.ClassPathExtender extenderFramework = null;
        ClassPathExtenderFactory.ClassPathExtender extenderBoot = null;

        if (!"true".equalsIgnoreCase(Felix.m_secureAction.getSystemProperty(FelixConstants.FELIX_EXTENSIONS_DISABLE, "false")))
        {
            ServiceLoader<ClassPathExtenderFactory> loader = ServiceLoader.load(ClassPathExtenderFactory.class,
                ExtensionManager.class.getClassLoader());


            for (Iterator<ClassPathExtenderFactory> iter = loader.iterator();
                 iter.hasNext() && (extenderFramework == null || extenderBoot == null); )
            {
                try
                {
                    ClassPathExtenderFactory factory = iter.next();

                    if (extenderFramework == null)
                    {
                        try
                        {
                            extenderFramework = factory.getExtender(ExtensionManager.class.getClassLoader());
                        }
                        catch (Throwable t)
                        {
                            // Ignore
                        }
                    }
                    if (extenderBoot == null)
                    {
                        try
                        {
                            extenderBoot = factory.getExtender(null);
                        }
                        catch (Throwable t)
                        {
                            // Ignore
                        }
                    }
                }
                catch (Throwable t)
                {
                    // Ignore
                }
            }

            try
            {
                if (extenderFramework == null)
                {
                    extenderFramework = new ClassPathExtenderFactory.DefaultClassLoaderExtender()
                            .getExtender(ExtensionManager.class.getClassLoader());
                }
            }
            catch (Throwable t) {
                // Ignore
            }
        }

        m_extenderFramework = extenderFramework;
        m_extenderBoot = extenderBoot;
    }

    private final Logger m_logger;
    private volatile ExtensionManagerRevision m_systemBundleRevision;

    private final List<ExtensionTuple> m_extensionTuples = Collections.synchronizedList(new ArrayList<ExtensionTuple>());

    private final List<BundleRevisionImpl> m_resolvedExtensions = new CopyOnWriteArrayList<BundleRevisionImpl>();
    private final List<BundleRevisionImpl> m_unresolvedExtensions = new CopyOnWriteArrayList<BundleRevisionImpl>();
    private final List<BundleRevisionImpl> m_failedExtensions = new CopyOnWriteArrayList<BundleRevisionImpl>();

    private static class ExtensionTuple
    {
        private final BundleActivator m_activator;
        private final Bundle m_bundle;
        private volatile boolean m_failed;
        private volatile boolean m_started;

        public ExtensionTuple(BundleActivator activator, Bundle bundle)
        {
            m_activator = activator;
            m_bundle = bundle;
        }
    }

    /**
     * This constructor is used to create one instance per framework instance.
     * The general approach is to have one private static instance that we register
     * with the parent classloader and one instance per framework instance that
     * keeps track of extension bundles and systembundle exports for that framework
     * instance.
     *
     * @param logger the logger to use.
     */
    ExtensionManager(Logger logger, Map configMap, Felix felix)
    {
        m_logger = logger;

        m_systemBundleRevision = new ExtensionManagerRevision(configMap, felix);
    }

    protected BundleCapability buildNativeCapabilites(BundleRevisionImpl revision, Map configMap) {
        String osArchitecture = (String) configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
        String osName = (String) configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
        String osVersion = (String) configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
        String userLang = (String) configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
        Map<String, Object> attributes = new HashMap<String, Object>();

        //Add all startup properties so we can match selection-filters
        attributes.putAll(configMap);

        if( osArchitecture != null )
        {
            attributes.put(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, NativeLibraryClause.getProcessorWithAliases(osArchitecture));
        }

        if( osName != null)
        {
            attributes.put(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, NativeLibraryClause.getOsNameWithAliases(osName));
        }

        if( osVersion != null)
        {
            attributes.put(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, new Version(NativeLibraryClause.normalizeOSVersion(osVersion)));
        }

        if( userLang != null)
        {
            attributes.put(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, userLang);
        }

        return new BundleCapabilityImpl(revision, NativeNamespace.NATIVE_NAMESPACE, Collections.<String, String> emptyMap(), attributes);
    }

    @IgnoreJRERequirement
    void updateRevision(Felix felix, Map configMap)
    {
        Map config = new HashMap(configMap);
        Properties defaultProperties = Util.loadDefaultProperties(m_logger);

        Util.initializeJPMSEE(felix._getProperty("java.specification.version"), defaultProperties, m_logger);

        String sysprops = felix._getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);


        boolean subst = "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES));

        if (sysprops != null && sysprops.isEmpty())
        {
            if (felix.hasConnectFramework())
            {
                subst = true;
                sysprops = "${osgi-exports}";
                config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, sysprops);
            }
        }

        final Map<String, Set<String>> exports = Util.initializeJPMS(defaultProperties);

        if (exports != null && (sysprops == null || "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES))))
        {
            final ClassParser classParser = new ClassParser();
            final Set<String> imports = new HashSet<String>();
            for (Set<String> moduleImport : exports.values())
            {
                for (String pkg : moduleImport)
                {
                    if (!pkg.startsWith("java."))
                    {
                        imports.add(pkg);
                    }
                }
            }
            for (final String moduleKey : exports.keySet())
            {
                int idx = moduleKey.indexOf("@");
                String module = idx == -1 ? moduleKey : moduleKey.substring(0, idx);
                if (felix._getProperty(module) == null && !exports.get(moduleKey).isEmpty() && defaultProperties.getProperty(module) == null)
                {
                    final SortedMap<String, SortedSet<String>> referred = new TreeMap<String, SortedSet<String>>();
                    if ("true".equalsIgnoreCase(felix._getProperty(FelixConstants.CALCULATE_SYSTEMPACKAGES_USES)))
                    {
                        java.nio.file.FileSystem fs = java.nio.file.FileSystems.getFileSystem(URI.create("jrt:/"));
                        try
                        {
                            Properties cachedProps = new Properties();
                            File modulesDir = felix.getDataFile(felix, "modules");
                            Felix.m_secureAction.mkdirs(modulesDir);
                            File cached = new File(modulesDir, moduleKey + ".properties");
                            if (Felix.m_secureAction.isFile(cached))
                            {
                                InputStream input = Felix.m_secureAction.getInputStream(cached);
                                cachedProps.load(new InputStreamReader(input, "UTF-8"));
                                input.close();
                                for (Enumeration<?> keys = cachedProps.propertyNames(); keys.hasMoreElements();)
                                {
                                    String pkg = (String) keys.nextElement();
                                    referred.put(pkg, new TreeSet<String>(Arrays.asList(cachedProps.getProperty(pkg).split(","))));
                                }
                            }
                            else
                            {
                                java.nio.file.Path path = fs.getPath("modules", module.substring("felix.jpms.".length()));
                                java.nio.file.Files.walkFileTree(path, (java.nio.file.FileVisitor) Felix.class.getClassLoader().loadClass("org.apache.felix.framework.util.ClassFileVisitor")
                                    .getConstructor(Set.class, Set.class, ClassParser.class, SortedMap.class).newInstance(imports, exports.get(moduleKey), classParser, referred));
                                for (String pkg : referred.keySet())
                                {
                                    SortedSet<String> uses = referred.get(pkg);
                                    if (uses != null && !uses.isEmpty())
                                    {
                                        cachedProps.setProperty(pkg, String.join(",", uses));
                                    }
                                }
                                OutputStream output = Felix.m_secureAction.getOutputStream(cached);
                                cachedProps.store(new OutputStreamWriter(output, "UTF-8"), null);
                                output.close();
                            }
                        }
                        catch (Throwable e)
                        {
                            m_logger.log(Logger.LOG_WARNING, "Exception calculating JPMS module exports", e);
                        }
                    }

                    String pkgs = "";

                    for (String pkg : exports.get(moduleKey))
                    {
                        pkgs += "," + pkg;
                        SortedSet<String> uses = referred.get(pkg);
                        if (uses != null && !uses.isEmpty())
                        {
                            pkgs += ";uses:=\"";
                            String sep = "";
                            for (String u : uses)
                            {
                                pkgs += sep + u;
                                sep = ",";
                            }
                            pkgs += "\"";
                        }
                        pkgs += ";version=\"" + defaultProperties.getProperty("felix.detect.java.version") + "\"";
                    }
                    defaultProperties.put(module, pkgs);
                }
            }
        }

        for (Map.Entry entry : defaultProperties.entrySet())
        {
            if (!config.containsKey(entry.getKey()))
            {
                config.put(entry.getKey(), entry.getValue());
            }
        }

        if(sysprops != null && subst)
        {
            config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMPACKAGES));
        }
        else if (sysprops == null)
        {
            config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMPACKAGES));
        }

        String syspropsExtra = felix._getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
        if (syspropsExtra != null && "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)))
        {
            config.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA));
        }

        String syscaps = felix._getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
        if(syscaps != null && "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)))
        {
            config.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMCAPABILITIES));
        }
        else if(syscaps == null)
        {
            config.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMCAPABILITIES));
        }

        String syscapsExtra = felix._getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);
        if (syscapsExtra != null && "true".equalsIgnoreCase(felix._getProperty(FelixConstants.USE_PROPERTY_SUBSTITUTION_IN_SYSTEMPACKAGES)))
        {
            config.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA, Util.getPropertyWithSubs(Util.toProperties(config), Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA));
        }

        m_systemBundleRevision.update(config);
    }

    public BundleRevisionImpl getRevision()
    {
        return m_systemBundleRevision;
    }

    /**
     * Add an extension bundle. The bundle will be added to the parent classloader
     * and it's exported packages will be added to the module definition
     * exports of this instance. Subsequently, they are available form the
     * instance in it's role as content loader.
     *
     * @param bundle the extension bundle to add.
     * @throws BundleException if extension bundles are not supported or this is
     *          not a framework extension.
     * @throws SecurityException if the caller does not have the needed
     *          AdminPermission.EXTENSIONLIFECYCLE and security is enabled.
     * @throws Exception in case something goes wrong.
     */
    void addExtensionBundle(BundleImpl bundle) throws Exception
    {
        Object sm = System.getSecurityManager();
        if (sm != null)
        {
            ((SecurityManager) sm).checkPermission(
                new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));

            if (!((BundleProtectionDomain) bundle.getProtectionDomain()).impliesDirect(new AllPermission()))
            {
                throw new SecurityException("Extension Bundles must have AllPermission");
            }
        }

        String directive = ManifestParser.parseExtensionBundleHeader((String)
            ((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
                .getHeaders().get(Constants.FRAGMENT_HOST));

        Content content = bundle.adapt(BundleRevisionImpl.class).getContent();
        final File file;
        if (content instanceof JarContent)
        {
            file = ((JarContent) content).getFile();
        }
        else if (content instanceof DirectoryContent)
        {
            file = ((DirectoryContent) content).getFile();
        }
        else
        {
            file = null;
        }
        if (file == null && !(content instanceof ConnectContentContent))
        {
            // We don't support revision type for extension
            m_logger.log(bundle, Logger.LOG_WARNING,
                "Unable to add extension bundle - wrong revision type?");

            throw new UnsupportedOperationException(
                "Unable to add extension bundle.");
        }

        if (!Constants.EXTENSION_FRAMEWORK.equals(directive))
        {
           throw new BundleException("Unsupported Extension Bundle type: " +
                directive, new UnsupportedOperationException(
                "Unsupported Extension Bundle type!"));
        }
        else if (m_extenderFramework == null && file != null)
        {
            // We don't support extensions
            m_logger.log(bundle, Logger.LOG_WARNING,
                "Unable to add extension bundle - Maybe ClassLoader is not supported " +
                        "(on java9, try --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED)?");

            throw new UnsupportedOperationException(
                "Unable to add extension bundle.");
        }

        BundleRevisionImpl bri = bundle.adapt(BundleRevisionImpl.class);

        bri.resolve(null);

        // we have to try again for all previously failed extensions because maybe they can now resolve.
        m_unresolvedExtensions.addAll(m_failedExtensions);
        m_failedExtensions.clear();
        m_unresolvedExtensions.add(bri);
    }

    public synchronized List<Bundle> resolveExtensionBundles(Felix felix)
    {
        if (m_unresolvedExtensions.isEmpty())
        {
            return Collections.emptyList();
        }

        // Collect the highest version of unresolved that are not already resolved by bsn
        List<BundleRevisionImpl> extensions = new ArrayList<BundleRevisionImpl>();
        // Collect the unresolved that where filtered out as alternatives in case the highest version doesn't resolve
        List<BundleRevisionImpl> alt = new ArrayList<BundleRevisionImpl>();

        outer : for (BundleRevisionImpl revision : m_unresolvedExtensions)
        {
            // Already resolved by bsn?
            for (BundleRevisionImpl existing : m_resolvedExtensions)
            {
                if (existing.getSymbolicName().equals(revision.getSymbolicName()))
                {
                    // Then ignore it
                    continue outer;
                }
            }
            // Otherwise, does a higher version exist by bsn?
            for (BundleRevisionImpl other : m_unresolvedExtensions)
            {
                if ((revision != other) && (revision.getSymbolicName().equals(other.getSymbolicName())) &&
                    revision.getVersion().compareTo(other.getVersion()) < 0)
                {
                    // Add this one to alternatives and filter it
                    alt.add(revision);
                    continue outer;
                }
            }

            // no higher version and not resolved yet by bsn - try to resolve it
            extensions.add(revision);
        }

        // This will return all resolvable revisions with the wires they need
        Map<BundleRevisionImpl, List<BundleWire>> wirings = findResolvableExtensions(extensions, alt);

        List<Bundle> result = new ArrayList<Bundle>();

        for (Map.Entry<BundleRevisionImpl, List<BundleWire>> entry : wirings.entrySet())
        {
            BundleRevisionImpl revision = entry.getKey();

            // move this revision from unresolved to resolved
            m_unresolvedExtensions.remove(revision);
            m_resolvedExtensions.add(revision);

            BundleWire wire = new BundleWireImpl(revision,
                revision.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE).get(0),
                m_systemBundleRevision,  m_systemBundleRevision.getWiring().getCapabilities(BundleRevision.HOST_NAMESPACE).get(0));

            try
            {
                revision.resolve(new BundleWiringImpl(m_logger, m_systemBundleRevision.m_configMap, null, revision, null,
                    Collections.singletonList(wire), Collections.EMPTY_MAP, Collections.EMPTY_MAP));
            }
            catch (Exception ex)
            {
                m_logger.log(revision.getBundle(), Logger.LOG_ERROR,
                        "Error resolving extension bundle : " + revision.getBundle(), ex);
            }

            felix.getDependencies().addDependent(wire);

            List<BundleCapability> caps = new ArrayList<BundleCapability>();
            for (BundleCapability cap : entry.getKey().getDeclaredCapabilities(null))
            {
                if (!IDENTITY.contains(cap.getNamespace()))
                {
                    caps.add(cap);
                }
            }
            m_systemBundleRevision.appendCapabilities(caps);
            for (BundleWire w : entry.getValue())
            {
                if (!w.getRequirement().getNamespace().equals(BundleRevision.HOST_NAMESPACE) &&
                    !w.getRequirement().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
                {
                    ((BundleWiringImpl) w.getRequirer().getWiring()).addDynamicWire(w);
                    felix.getDependencies().addDependent(w);
                }
            }

            final File f;
            Content revisionContent = revision.getContent();
            if (revisionContent instanceof JarContent)
            {
                f = ((JarContent) revisionContent).getFile();
            }
            else if (revisionContent instanceof DirectoryContent)
            {
                f = ((DirectoryContent) revisionContent).getFile();
            }
            else
            {
                f = null;
            }
            if (f != null)
            {
                try
                {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Void>()
                    {
                        @Override
                        public Void run() throws Exception
                        {
                            m_extenderFramework.add(f);
                            return null;
                        }
                    });
                }
                catch (Exception ex)
                {
                    m_logger.log(revision.getBundle(), Logger.LOG_ERROR,
                        "Error adding extension bundle to framework classloader: " + revision.getBundle(), ex);
                }
            }

            felix.setBundleStateAndNotify(revision.getBundle(), Bundle.RESOLVED);
            result.add(revision.getBundle());
        }

        // at this point, all revisions left in unresolved are not resolvable
        m_failedExtensions.addAll(m_unresolvedExtensions);
        m_unresolvedExtensions.clear();

        return result;
    }

    /**
     * Start extension bundle if it has an activator
     *
     * @param felix the framework instance the extension bundle is installed in.
     * @param bundle the extension bundle to start if it has a an extension bundle activator.
     */
    void startExtensionBundle(Felix felix, BundleImpl bundle)
    {
        Map<?,?> headers = bundle.adapt(BundleRevisionImpl.class).getHeaders();
        String activatorClass = (String) headers.get(Constants.EXTENSION_BUNDLE_ACTIVATOR);
        boolean felixExtension = false;
        if (activatorClass == null)
        {
            felixExtension = true;
            activatorClass = (String) headers.get(FelixConstants.FELIX_EXTENSION_ACTIVATOR);
        }

        if (activatorClass != null)
        {
            ExtensionTuple tuple = null;
            try
            {
// TODO: SECURITY - Should this consider security?
                BundleActivator activator = (BundleActivator)
                    Felix.m_secureAction.getClassLoader(felix.getClass()).loadClass(
                        activatorClass.trim()).newInstance();

                BundleContext context = felix._getBundleContext();

                bundle.setBundleContext(context);

// TODO: EXTENSIONMANAGER - This is kind of hacky, can we improve it?
                if (!felixExtension)
                {
                    tuple = new ExtensionTuple(activator, bundle);
                    m_extensionTuples.add(tuple);
                }
                else
                {
                    felix.m_activatorList.add(activator);
                }

                if ((felix.getState() == Bundle.ACTIVE) || (felix.getState() == Bundle.STARTING))
                {
                    if (tuple != null)
                    {
                        tuple.m_started = true;
                    }
                    Felix.m_secureAction.startActivator(activator, context);
                }
            }
            catch (Throwable ex)
            {
                if (tuple != null)
                {
                    tuple.m_failed = true;
                }
                felix.fireFrameworkEvent(FrameworkEvent.ERROR, bundle,
                            new BundleException("Unable to start Bundle", ex));

                m_logger.log(bundle, Logger.LOG_WARNING,
                    "Unable to start Extension Activator", ex);
            }
        }
    }

    void startPendingExtensionBundles(Felix felix)
    {
        for (int i = 0;i < m_extensionTuples.size();i++)
        {
            if (!m_extensionTuples.get(i).m_started)
            {
                m_extensionTuples.get(i).m_started = true;
                try
                {
                    Felix.m_secureAction.startActivator(m_extensionTuples.get(i).m_activator, felix._getBundleContext());
                }
                catch (Throwable ex)
                {
                    m_extensionTuples.get(i).m_failed = true;

                    felix.fireFrameworkEvent(FrameworkEvent.ERROR, m_extensionTuples.get(i).m_bundle,
                                new BundleException("Unable to start Bundle", BundleException.ACTIVATOR_ERROR, ex));

                    m_logger.log(m_extensionTuples.get(i).m_bundle, Logger.LOG_WARNING,
                        "Unable to start Extension Activator", ex);
                }
            }
        }
    }

    void stopExtensionBundles(Felix felix)
    {
        for (int i = m_extensionTuples.size() - 1; i >= 0;i--)
        {
            if (m_extensionTuples.get(i).m_started && !m_extensionTuples.get(i).m_failed)
            {
                try
                {
                    Felix.m_secureAction.stopActivator(m_extensionTuples.get(i).m_activator, felix._getBundleContext());
                }
                catch (Throwable ex)
                {
                    felix.fireFrameworkEvent(FrameworkEvent.ERROR, m_extensionTuples.get(i).m_bundle,
                                new BundleException("Unable to stop Bundle", BundleException.ACTIVATOR_ERROR, ex));

                    m_logger.log(m_extensionTuples.get(i).m_bundle, Logger.LOG_WARNING,
                        "Unable to stop Extension Activator", ex);
                }
            }
        }
        m_extensionTuples.clear();
    }

    public synchronized void removeExtensionBundles()
    {
        m_resolvedExtensions.clear();
        m_unresolvedExtensions.clear();
        m_failedExtensions.clear();
    }

    private Map<BundleRevisionImpl, List<BundleWire>> findResolvableExtensions(List<BundleRevisionImpl> extensions, List<BundleRevisionImpl> alt)
    {
        // The idea is to loop through the extensions and try to resolve all unresolved extension. If we can't resolve
        // a given extension, we will call the method again with the extension in question removed or replaced if there
        // is a replacement for it in alt.
        // This resolve doesn't take into account that maybe a revision could be resolved with a revision from alt but
        // not with the current extensions. In that case, it will be removed (assuming the current extension can be resolved)
        // in other words, it will prefer to resolve the highest version of each extension over install order
        Map<BundleRevisionImpl, List<BundleWire>> wires = new LinkedHashMap<BundleRevisionImpl, List<BundleWire>>();

        for (BundleRevisionImpl bri : extensions)
        {
            List<BundleWire> wi = new ArrayList<BundleWire>();
            boolean resolved = true;
            outer: for (BundleRequirement req : bri.getDeclaredRequirements(null))
            {
                // first see if we can resolve from the system bundle
                for (BundleCapability cap : m_systemBundleRevision.getWiring().getCapabilities(req.getNamespace()))
                {
                    if (req.matches(cap))
                    {
                        // we can, create the wire but in the case of an ee requirement, make it from the extension
                        wi.add(new BundleWireImpl(
                                req.getNamespace().equals(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE) ?
                                        bri : m_systemBundleRevision, req, m_systemBundleRevision, cap));

                        continue outer;
                    }
                }

                // now loop through the resolved extensions
                for (BundleRevisionImpl extension : m_resolvedExtensions)
                {
                    // and check the caps that will not be lifted (i.e., identity)
                    for (BundleCapability cap : extension.getDeclaredCapabilities(req.getNamespace()))
                    {
                        if (req.matches(cap))
                        {
                            // it was identity - hence, use the extension itself as provider
                            wi.add(new BundleWireImpl(m_systemBundleRevision, req, extension, cap));
                            continue outer;
                        }
                    }
                }
                // now loop through the other extensions
                for (BundleRevisionImpl extension : extensions)
                {
                    for (BundleCapability cap : extension.getDeclaredCapabilities(req.getNamespace()))
                    {
                        if (req.matches(cap))
                        {
                            // we can use a yet unresolved extension (resolved one are implicitly checked by the
                            // system bundle loop above as they would be attached.
                            wi.add(new BundleWireImpl(m_systemBundleRevision, req,
                                // lift identity
                                IDENTITY.contains(cap.getNamespace()) ?
                                extension : m_systemBundleRevision, cap));
                            continue outer;
                        }
                    }
                    // and check the caps that will not be lifted (i.e., identity)
                    for (BundleCapability cap : extension.getDeclaredCapabilities(req.getNamespace()))
                    {
                        if (req.matches(cap))
                        {
                            // it was identity - hence, use the extension itself as provider
                            wi.add(new BundleWireImpl(m_systemBundleRevision, req, extension, cap));
                            continue outer;
                        }
                    }
                }
                // we couldn't find a provider - was it optional?
                if (!((BundleRequirementImpl)req).isOptional())
                {
                    resolved = false;
                    break;
                }
            }
            if(resolved)
            {
                wires.put(bri, wi);
            }
            else
            {
                // we failed to resolve this extension - try again without it. Yes, this throws away the work done
                // up to this point
                List<BundleRevisionImpl> next = new ArrayList<BundleRevisionImpl>(extensions);
                List<BundleRevisionImpl> nextAlt = new ArrayList<BundleRevisionImpl>();

                outer : for (BundleRevisionImpl replacement : alt)
                {
                    if (bri.getSymbolicName().equals(replacement.getSymbolicName()))
                    {
                        for (BundleRevisionImpl other : alt)
                        {
                            if ((replacement != other) && (replacement.getSymbolicName().equals(other.getSymbolicName())) &&
                                    replacement.getVersion().compareTo(other.getVersion()) < 0)
                            {
                                nextAlt.add(replacement);
                                continue outer;
                            }
                        }
                        next.set(next.indexOf(bri), replacement);
                        break;
                    }
                    nextAlt.add(replacement);
                }
                
                next.remove(bri);

                return next.isEmpty() ? Collections.EMPTY_MAP : findResolvableExtensions(next, nextAlt);
            }
        }
        return wires;
    }

    public void close()
    {
        // Do nothing on close, since we have nothing open.
    }

    public Enumeration getEntries()
    {
        return new Enumeration()
        {
            public boolean hasMoreElements()
            {
                return false;
            }

            public Object nextElement() throws NoSuchElementException
            {
                throw new NoSuchElementException();
            }
        };
    }

    public boolean hasEntry(String name) {
        return false;
    }

    public byte[] getEntryAsBytes(String name)
    {
        return null;
    }

    public InputStream getEntryAsStream(String name) throws IOException
    {
        return null;
    }

    public Content getEntryAsContent(String name)
    {
        return null;
    }

    public String getEntryAsNativeLibrary(String name)
    {
        return null;
    }

    public URL getEntryAsURL(String name)
    {
        return null;
    }

    @Override
    public long getContentTime(String name)
    {
        return -1L;
    }

    //
    // Utility methods.
    //

    class ExtensionManagerRevision extends BundleRevisionImpl
    {
        private volatile Map m_configMap;
        private final Map m_headerMap = new StringMap();
        private volatile List<BundleCapability> m_capabilities = Collections.EMPTY_LIST;
        private volatile Version m_version;
        private volatile BundleWiring m_wiring;

        ExtensionManagerRevision(Map configMap, Felix felix)
        {
            super(felix, "0");

            m_configMap = configMap;

// TODO: FRAMEWORK - Not all of this stuff really belongs here
            // Populate system bundle header map.
            m_headerMap.put(FelixConstants.BUNDLE_VERSION,
                m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));
            m_headerMap.put(FelixConstants.BUNDLE_SYMBOLICNAME,
                FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
            m_headerMap.put(FelixConstants.BUNDLE_NAME, "System Bundle");
            m_headerMap.put(FelixConstants.BUNDLE_DESCRIPTION,
                "This bundle is system specific; it implements various system services.");
            m_headerMap.put(FelixConstants.EXPORT_SERVICE,
                "org.osgi.service.packageadmin.PackageAdmin," +
                    "org.osgi.service.startlevel.StartLevel," +
                    "org.osgi.service.url.URLHandlers");


            m_headerMap.put(FelixConstants.BUNDLE_MANIFESTVERSION, "2");


            m_version = new Version((String) m_configMap.get(FelixConstants.FELIX_VERSION_PROPERTY));

            try
            {
                ManifestParser mp = new ManifestParser(
                    m_logger, m_configMap, this, m_headerMap);
                List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), this);
                caps.add(buildNativeCapabilites(this, m_configMap));
                appendCapabilities(caps);
                m_headerMap.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(caps));
            }
            catch (Exception ex)
            {
                m_capabilities = Collections.EMPTY_LIST;
                m_logger.log(
                    Logger.LOG_ERROR,
                    "Error parsing system bundle statement", ex);
            }
        }

        private void update(Map configMap)
        {
            Properties configProps = Util.toProperties(configMap);
            // The system bundle exports framework packages as well as
            // arbitrary user-defined packages from the system class path.
            // We must construct the system bundle's export metadata.
            // Get configuration property that specifies which class path
            // packages should be exported by the system bundle.
            String syspkgs = configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES);

            syspkgs = (syspkgs == null) ? "" : syspkgs;

            // If any extra packages are specified, then append them.
            String pkgextra = configProps.getProperty(FelixConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);

            syspkgs = ((pkgextra == null) || (pkgextra.trim().length() == 0))
                ? syspkgs : syspkgs + (pkgextra.trim().startsWith(",") ? pkgextra : "," + pkgextra);

            if (syspkgs.startsWith(","))
            {
                syspkgs = syspkgs.substring(1);
            }
            
            m_headerMap.put(FelixConstants.EXPORT_PACKAGE, syspkgs);

            // The system bundle alsp provides framework generic capabilities
            // as well as arbitrary user-defined generic capabilities. We must
            // construct the system bundle's capabilities metadata. Get the
            // configuration property that specifies which capabilities should
            // be provided by the system bundle.
            String syscaps = configProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);

            syscaps = (syscaps == null) ? "" : syscaps;

            // If any extra capabilities are specified, then append them.
            String capextra = configProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA);

            syscaps = ((capextra == null) || (capextra.trim().length() == 0))
                ? syscaps : syscaps + (capextra.trim().startsWith(",") ? capextra : "," + capextra);

            m_headerMap.put(FelixConstants.PROVIDE_CAPABILITY, syscaps);

            try
            {
                ManifestParser mp = new ManifestParser(
                    m_logger, m_configMap, this, m_headerMap);
                List<BundleCapability> caps = ManifestParser.aliasSymbolicName(mp.getCapabilities(), this);
                caps.add(buildNativeCapabilites(this, m_configMap));
                m_capabilities = Collections.EMPTY_LIST;
                appendCapabilities(caps);
                m_headerMap.put(Constants.EXPORT_PACKAGE, convertCapabilitiesToHeaders(caps));
            }
            catch (Exception ex)
            {
                m_capabilities = Collections.EMPTY_LIST;
                m_logger.log(
                    Logger.LOG_ERROR,
                    "Error parsing system bundle statement.", ex);
            }
        }

        private void appendCapabilities(List<BundleCapability> caps)
        {
            List<BundleCapability> newCaps = new ArrayList<BundleCapability>(m_capabilities.size() + caps.size());
            newCaps.addAll(m_capabilities);
            newCaps.addAll(caps);
            m_capabilities = Util.newImmutableList(newCaps);
        }

        private String convertCapabilitiesToHeaders(List<BundleCapability> caps)
        {
            StringBuilder exportSB = new StringBuilder();

            for (BundleCapability cap : caps)
            {
                if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
                {
                    // Add a comma separate if there is an existing package.
                    if (exportSB.length() > 0)
                    {
                        exportSB.append(", ");
                    }

                    // Append exported package information.
                    exportSB.append(cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
                    for (Entry<String, String> entry : cap.getDirectives().entrySet())
                    {
                        exportSB.append("; ");
                        exportSB.append(entry.getKey());
                        exportSB.append(":=\"");
                        exportSB.append(entry.getValue());
                        exportSB.append("\"");
                    }
                    for (Entry<String, Object> entry : cap.getAttributes().entrySet())
                    {
                        if (!entry.getKey().equals(BundleRevision.PACKAGE_NAMESPACE)
                            && !entry.getKey().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)
                            && !entry.getKey().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
                        {
                            exportSB.append("; ");
                            exportSB.append(entry.getKey());
                            exportSB.append("=\"");
                            exportSB.append(entry.getValue());
                            exportSB.append("\"");
                        }
                    }
                }
            }

            return exportSB.toString();
        }

        @Override
        public Map getHeaders()
        {
            return Util.newImmutableMap(m_headerMap);
        }

        @Override
        public List<BundleCapability> getDeclaredCapabilities(String namespace)
        {
            List<BundleCapability> caps = m_capabilities;
            List<BundleCapability> result;
            if (namespace != null)
            {
                result = new ArrayList<BundleCapability>();
                for (BundleCapability cap : caps)
                {
                    if (cap.getNamespace().equals(namespace))
                    {
                        result.add(cap);
                    }
                }
            }
            else
            {
                result = new ArrayList<BundleCapability>(m_capabilities);
            }
            return result;
        }

        @Override
        public String getSymbolicName()
        {
            return FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME;
        }

        @Override
        public Version getVersion()
        {
            return m_version;
        }

        @Override
        public void close()
        {
            // Nothing needed here.
        }

        @Override
        public Content getContent()
        {
            return ExtensionManager.this;
        }

        @Override
        public URL getEntry(String name)
        {
            // There is no content for the system bundle, so return null.
            return null;
        }

        @Override
        public boolean hasInputStream(int index, String urlPath)
        {
            return (getClass().getClassLoader().getResource(urlPath) != null);
        }

        @Override
        public InputStream getInputStream(int index, String urlPath)
        {
            return getClass().getClassLoader().getResourceAsStream(urlPath);
        }

        @Override
        public URL getLocalURL(int index, String urlPath)
        {
            return getClass().getClassLoader().getResource(urlPath);
        }

        @Override
        public void resolve(BundleWiringImpl wire)
        {
            try
            {
                m_wiring = new ExtensionManagerWiring(
                    m_logger, m_configMap, this);
            }
            catch (Exception ex)
            {
                // This should never happen.
            }
        }

        @Override
        public BundleWiring getWiring()
        {
            return m_wiring;
        }
    }

    class ExtensionManagerWiring extends BundleWiringImpl
    {
        ExtensionManagerWiring(
            Logger logger, Map configMap, BundleRevisionImpl revision)
            throws Exception
        {
            super(logger, configMap, null, revision,
                null, Collections.EMPTY_LIST, null, null);
        }

        @Override
        public ClassLoader getClassLoader()
        {
            return getClass().getClassLoader();
        }

        @Override
        public List<BundleCapability> getCapabilities(String namespace)
        {
            return m_systemBundleRevision.getDeclaredCapabilities(namespace);
        }

        @Override
        public List<NativeLibrary> getNativeLibraries()
        {
            return Collections.EMPTY_LIST;
        }

        @Override
        public Class getClassByDelegation(String name) throws ClassNotFoundException
        {
            return getClass().getClassLoader().loadClass(name);
        }

        @Override
        public URL getResourceByDelegation(String name)
        {
            return getClass().getClassLoader().getResource(name);
        }

        @Override
        public Enumeration getResourcesByDelegation(String name)
        {
           try
           {
               return getClass().getClassLoader().getResources(name);
           }
           catch (IOException ex)
           {
               return null;
           }
        }

        @Override
        public void dispose()
        {
            // Nothing needed here.
        }
    }
}
