/*
 * 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 java.io.IOException;
import java.io.InputStream;
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;

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;

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

    synchronized void disposeContentPath()
    {
        for (int i = 0; (m_contentPath != null) && (i < m_contentPath.size()); i++)
        {
            m_contentPath.get(i).close();
        }
        m_contentPath = null;
    }

    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 long getContentTime(int index, String urlPath)
    {
        if (urlPath.startsWith("/"))
        {
            urlPath = urlPath.substring(1);
        }
        Content content;
        if (index == 0)
        {
            content = getContent();
        }
        else {
            content = getContentPath().get(index - 1);
        }
        long result = content.getContentTime(urlPath);
        return result > 0 ? result : m_bundle.getLastModified();
    }

    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 (Exception 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 + ")";
    }
}
