/*
 * 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.Content;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.MultiReleaseContent;
import org.apache.felix.framework.util.SecureAction;
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.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

public class BundleRevisionImpl implements BundleRevision, Resource
{
    public final static int EAGER_ACTIVATION = 0;
    public final static int LAZY_ACTIVATION = 1;

    private final String m_id;
    private final Map<String, Object> m_headerMap;

    private final String m_manifestVersion;
    private final boolean m_isExtension;
    private final boolean m_isFragment;
    private final String m_symbolicName;
    private final Version m_version;

    private final List<BundleCapability> m_declaredCaps;
    private final List<BundleRequirement> m_declaredReqs;
    private final List<NativeLibrary> m_declaredNativeLibs;
    private final int m_declaredActivationPolicy;
    private final List<String> m_activationIncludes;
    private final List<String> m_activationExcludes;

    private final BundleImpl m_bundle;

    private volatile Content m_content;
    private volatile List<Content> m_contentPath;
    private volatile ProtectionDomain m_protectionDomain = null;
    private final static SecureAction m_secureAction = new SecureAction();

    // Bundle wiring when resolved.
    private volatile BundleWiringImpl m_wiring = null;

    /**
     * This constructor is used by the extension manager, since it needs
     * a constructor that does not throw an exception.
     * @param bundle
     * @param id
     * @throws org.osgi.framework.BundleException
     */
    public BundleRevisionImpl(BundleImpl bundle, String id)
    {
        m_bundle = bundle;
        m_id = id;
        m_headerMap = null;
        m_content = null;
        m_manifestVersion = "";
        m_symbolicName = null;
        m_isExtension = false;
        m_isFragment = false;
        m_version = null;
        m_declaredCaps = Collections.emptyList();
        m_declaredReqs = Collections.emptyList();
        m_declaredNativeLibs = null;
        m_declaredActivationPolicy = EAGER_ACTIVATION;
        m_activationExcludes = null;
        m_activationIncludes = null;
    }

    BundleRevisionImpl(
        BundleImpl bundle, String id, Map<String, Object> headerMap, Content content)
        throws BundleException
    {
        m_bundle = bundle;
        m_id = id;
        m_headerMap = headerMap;
        m_content = content;

        ManifestParser mp = new ManifestParser(
            bundle.getFramework().getLogger(),
            bundle.getFramework().getConfig(),
            this,
            m_headerMap);

        // Record some of the parsed metadata. Note, if this is an extension
        // bundle it's exports are removed, since they will be added to the
        // system bundle directly later on.

        m_isExtension = mp.isExtension();
        m_manifestVersion = mp.getManifestVersion();
        m_version = mp.getBundleVersion();
        m_declaredCaps = mp.getCapabilities();
        m_declaredReqs = mp.getRequirements();
        m_declaredNativeLibs = mp.getLibraries();
        m_declaredActivationPolicy = mp.getActivationPolicy();
        m_activationExcludes = (mp.getActivationExcludeDirective() == null)
            ? null
            : ManifestParser.parseDelimitedString(mp.getActivationExcludeDirective(), ",");
        m_activationIncludes = (mp.getActivationIncludeDirective() == null)
            ? null
            : ManifestParser.parseDelimitedString(mp.getActivationIncludeDirective(), ",");
        m_symbolicName = mp.getSymbolicName();
        m_isFragment = m_headerMap.containsKey(Constants.FRAGMENT_HOST);
    }

    static SecureAction getSecureAction()
    {
        return m_secureAction;
    }

    int getDeclaredActivationPolicy()
    {
        return m_declaredActivationPolicy;
    }

    boolean isActivationTrigger(String pkgName)
    {
        if ((m_activationIncludes == null) && (m_activationExcludes == null))
        {
            return true;
        }

        // If there are no include filters then all classes are included
        // by default, otherwise try to find one match.
        boolean included = (m_activationIncludes == null);
        for (int i = 0;
            (!included) && (m_activationIncludes != null) && (i < m_activationIncludes.size());
            i++)
        {
            included = m_activationIncludes.get(i).equals(pkgName);
        }

        // If there are no exclude filters then no classes are excluded
        // by default, otherwise try to find one match.
        boolean excluded = false;
        for (int i = 0;
            (!excluded) && (m_activationExcludes != null) && (i < m_activationExcludes.size());
            i++)
        {
            excluded = m_activationExcludes.get(i).equals(pkgName);
        }
        return included && !excluded;
    }

    //
    // BundleRevision methods.
    //

    public String getSymbolicName()
    {
        return m_symbolicName;
    }

    public Version getVersion()
    {
        return m_version;
    }

    public List<Capability> getCapabilities(String namespace)
    {
        return asCapabilityList(getDeclaredCapabilities(namespace));
    }

    static List<Capability> asCapabilityList(List reqs)
    {
        return reqs;
    }

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

    public List<Requirement> getRequirements(String namespace)
    {
        return asRequirementList(getDeclaredRequirements(namespace));
    }

    static List<Requirement> asRequirementList(List reqs)
    {
        return reqs;
    }

    public List<BundleRequirement> getDeclaredRequirements(String namespace)
    {
        List<BundleRequirement> result = m_declaredReqs;
        if (namespace != null)
        {
            result = new ArrayList<BundleRequirement>();
            for (BundleRequirement req : m_declaredReqs)
            {
                if (req.getNamespace().equals(namespace))
                {
                    result.add(req);
                }
            }
        }
        return result;
    }

    public int getTypes()
    {
        return (getManifestVersion().equals("2") && m_isFragment) ? BundleRevision.TYPE_FRAGMENT : 0;
    }

    public BundleWiring getWiring()
    {
        return m_wiring;
    }

    public BundleImpl getBundle()
    {
        return m_bundle;
    }

    //
    // Implementating details.
    //

    public Map<String, Object> getHeaders()
    {
        return m_headerMap;
    }

    public boolean isExtension()
    {
        return m_isExtension;
    }

    public String getManifestVersion()
    {
        return m_manifestVersion;
    }

    public List<NativeLibrary> getDeclaredNativeLibraries()
    {
        return m_declaredNativeLibs;
    }

    public String getId()
    {
        return m_id;
    }

    public synchronized void resolve(BundleWiringImpl wiring)
    {
        if (m_wiring != null)
        {
            m_wiring.dispose();
            m_wiring = null;
        }

        if (wiring != null)
        {
            // If the wiring has fragments, then close the old content path,
            // since it'll need to be recalculated to include fragments.
            if (!Util.getFragments(wiring).isEmpty())
            {
                for (int i = 0; (m_contentPath != null) && (i < m_contentPath.size()); i++)
                {
                    // Don't close this module's content, if it is on the content path.
                    if (m_content != m_contentPath.get(i))
                    {
                        m_contentPath.get(i).close();
                    }
                }
                m_contentPath = null;
            }

            m_wiring = wiring;
        }
    }

    public void setProtectionDomain(ProtectionDomain pd)
    {
        m_protectionDomain = pd;
    }

    public ProtectionDomain getProtectionDomain()
    {
        return m_protectionDomain;
    }

    //
    // Content access methods.
    //

    public Content getContent()
    {
        return m_content;
    }

    void resetContent(Content content)
    {
        m_content = content;
    }

    List<Content> getContentPath()
    {
        if (m_contentPath == null)
        {
            try
            {
                m_contentPath = initializeContentPath();
            }
            catch (Exception ex)
            {
                m_bundle.getFramework().getLogger().log(
                    m_bundle, Logger.LOG_ERROR, "Unable to get module class path.", ex);
            }
        }
        return m_contentPath;
    }

    private synchronized List<Content> initializeContentPath() throws Exception
    {
        if (m_contentPath != null)
        {
            return m_contentPath;
        }
        List<Content> contentList = new ArrayList();
        calculateContentPath(this, getContent(), contentList, true);

        List<BundleRevision> fragments = null;
        List<Content> fragmentContents = null;
        if (m_wiring != null)
        {
            // Get fragments and their contents from the wiring.
            // Note that we don't use Util.getFragments() here because
            // the wiring returns parallel arrays and the utility method
            // doesn't necessarily return the correct order.
            fragments = m_wiring.getFragments();
            fragmentContents = m_wiring.getFragmentContents();
        }
        if (fragments != null)
        {
            for (int i = 0; i < fragments.size(); i++)
            {
                calculateContentPath(
                    fragments.get(i), fragmentContents.get(i), contentList, false);
            }
        }
        return contentList;
    }

    private List calculateContentPath(
        BundleRevision revision, Content content, List<Content> contentList,
        boolean searchFragments)
    {
        // Creating the content path entails examining the bundle's
        // class path to determine whether the bundle JAR file itself
        // is on the bundle's class path and then creating content
        // objects for everything on the class path.

        // Create a list to contain the content path for the specified content.
        List localContentList = new ArrayList();

        // Find class path meta-data.
        String classPath = (String) ((BundleRevisionImpl) revision)
            .getHeaders().get(FelixConstants.BUNDLE_CLASSPATH);
        // Parse the class path into strings.
        List<String> classPathStrings = ManifestParser.parseDelimitedString(
            classPath, FelixConstants.CLASS_PATH_SEPARATOR);

        if (classPathStrings == null)
        {
            classPathStrings = new ArrayList<String>(0);
        }

        // Create the bundles class path.
        for (int i = 0; i < classPathStrings.size(); i++)
        {
            // Remove any leading slash, since all bundle class path
            // entries are relative to the root of the bundle.
            classPathStrings.set(i, (classPathStrings.get(i).startsWith("/"))
                ? classPathStrings.get(i).substring(1)
                : classPathStrings.get(i));

            // Check for the bundle itself on the class path.
            if (classPathStrings.get(i).equals(FelixConstants.CLASS_PATH_DOT))
            {
                localContentList.add(MultiReleaseContent.wrap(
                    getBundle().getFramework()._getProperty("java.specification.version"), content));
            }
            else
            {
                // Try to find the embedded class path entry in the current
                // content.
                Content embeddedContent = content.getEntryAsContent(classPathStrings.get(i));
                // If the embedded class path entry was not found, it might be
                // in one of the fragments if the current content is the bundle,
                // so try to search the fragments if necessary.
                List<Content> fragmentContents = (m_wiring == null)
                    ? null : m_wiring.getFragmentContents();
                for (int fragIdx = 0;
                    searchFragments && (embeddedContent == null)
                        && (fragmentContents != null) && (fragIdx < fragmentContents.size());
                    fragIdx++)
                {
                    embeddedContent =
                        fragmentContents.get(fragIdx).getEntryAsContent(classPathStrings.get(i));
                }
                // If we found the embedded content, then add it to the
                // class path content list.
                if (embeddedContent != null)
                {
                    localContentList.add(MultiReleaseContent.wrap(
                        getBundle().getFramework()._getProperty("java.specification.version"),embeddedContent));
                }
                else
                {
// TODO: FRAMEWORK - Per the spec, this should fire a FrameworkEvent.INFO event;
//       need to create an "Eventer" class like "Logger" perhaps.
                    ((BundleImpl) m_bundle).getFramework().getLogger().log(
                        getBundle(), Logger.LOG_INFO,
                        "Class path entry not found: "
                        + classPathStrings.get(i));
                }
            }
        }

        // If there is nothing on the class path, then include
        // "." by default, as per the spec.
        if (localContentList.isEmpty())
        {
            localContentList.add(MultiReleaseContent.wrap(
                getBundle().getFramework()._getProperty("java.specification.version"),content));
        }

        // Now add the local contents to the global content list and return it.
        contentList.addAll(localContentList);
        return contentList;
    }

    URL getResourceLocal(String name)
    {
        URL url = null;

        // Remove leading slash, if present, but special case
        // "/" so that it returns a root URL...this isn't very
        // clean or meaningful, but the Spring guys want it.
        if (name.equals("/"))
        {
            // Just pick a class path index since it doesn't really matter.
            url = createURL(1, name);
        }
        else if (name.startsWith("/"))
        {
            name = name.substring(1);
        }

        // Check the module class path.
        List<Content> contentPath = getContentPath();
        for (int i = 0;
            (url == null) &&
            (i < contentPath.size()); i++)
        {
            if (contentPath.get(i).hasEntry(name))
            {
                url = createURL(i + 1, name);
            }
        }

        return url;
    }

    Enumeration getResourcesLocal(String name)
    {
        List l = new ArrayList();

        // Special case "/" so that it returns a root URLs for
        // each bundle class path entry...this isn't very
        // clean or meaningful, but the Spring guys want it.
        final List<Content> contentPath = getContentPath();
        if (contentPath == null)
            return Collections.enumeration(Collections.emptyList());

        if (name.equals("/"))
        {
            for (int i = 0; i < contentPath.size(); i++)
            {
                l.add(createURL(i + 1, name));
            }
        }
        else
        {
            // Remove leading slash, if present.
            if (name.startsWith("/"))
            {
                name = name.substring(1);
            }

            // Check the module class path.
            for (int i = 0; i < contentPath.size(); i++)
            {
                if (contentPath.get(i).hasEntry(name))
                {
                    // Use the class path index + 1 for creating the path so
                    // that we can differentiate between module content URLs
                    // (where the path will start with 0) and module class
                    // path URLs.
                    l.add(createURL(i + 1, name));
                }
            }
        }

        return Collections.enumeration(l);
    }

    // TODO: API: Investigate how to handle this better, perhaps we need
    // multiple URL policies, one for content -- one for class path.
    public URL getEntry(String name)
    {
        URL url = null;

        // Check for the special case of "/", which represents
        // the root of the bundle according to the spec.
        if (name.equals("/"))
        {
            url = createURL(0, "/");
        }

        if (url == null)
        {
            // Remove leading slash, if present.
            if (name.startsWith("/"))
            {
                name = name.substring(1);
            }

            // Check the module content.
            if (getContent().hasEntry(name))
            {
                // Module content URLs start with 0, whereas module
                // class path URLs start with the index into the class
                // path + 1.
                url = createURL(0, name);
            }
        }

        return url;
    }

    public boolean hasInputStream(int index, String urlPath)
    {
        if (urlPath.startsWith("/"))
        {
            urlPath = urlPath.substring(1);
        }
        if (index == 0)
        {
            return getContent().hasEntry(urlPath);
        }
        return getContentPath().get(index - 1).hasEntry(urlPath);
    }

    public InputStream getInputStream(int index, String urlPath)
        throws IOException
    {
        if (urlPath.startsWith("/"))
        {
            urlPath = urlPath.substring(1);
        }
        if (index == 0)
        {
            return getContent().getEntryAsStream(urlPath);
        }
        return getContentPath().get(index - 1).getEntryAsStream(urlPath);
    }

    public URL getLocalURL(int index, String urlPath)
    {
        if (urlPath.startsWith("/"))
        {
            urlPath = urlPath.substring(1);
        }
        if (index == 0)
        {
            return getContent().getEntryAsURL(urlPath);
        }
        return getContentPath().get(index - 1).getEntryAsURL(urlPath);
    }

    private URL createURL(int port, String path)
    {
        // Add a slash if there is one already, otherwise
        // the is no slash separating the host from the file
        // in the resulting URL.
        if (!path.startsWith("/"))
        {
            path = "/" + path;
        }

        try
        {
            return m_secureAction.createURL(null,
                FelixConstants.BUNDLE_URL_PROTOCOL + "://" +
                m_bundle.getFramework()._getProperty(Constants.FRAMEWORK_UUID) + "_" + m_id + ":" + port + path,
                getBundle().getFramework().getBundleStreamHandler());
        }
        catch (MalformedURLException ex)
        {
            m_bundle.getFramework().getLogger().log(
                m_bundle,
                Logger.LOG_ERROR,
                "Unable to create resource URL.",
                ex);
        }
        return null;
    }

    synchronized void close()
    {
        try
        {
            resolve(null);
        }
        catch (Exception ex)
        {
            ((BundleImpl) m_bundle).getFramework().getLogger().log(
                Logger.LOG_ERROR, "Error releasing revision: " + ex.getMessage(), ex);
        }
        m_content.close();
        m_content = null;
        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.size()); i++)
        {
            m_contentPath.get(i).close();
        }
        m_contentPath = null;
    }

    @Override
    public String toString()
    {
        return m_bundle.toString() + "(R " + m_id + ")";
    }
}
