/*
 * 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.util;

import org.apache.felix.framework.Felix;
import org.apache.felix.framework.Logger;
import org.apache.felix.framework.cache.BundleArchiveRevision;
import org.apache.felix.framework.cache.BundleCache;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
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.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Resource;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

public class Util
{
    /**
     * The default name used for the default configuration properties file.
    **/
    private static final String DEFAULT_PROPERTIES_FILE = "default.properties";

    public static Properties loadDefaultProperties(Logger logger)
    {
        Properties defaultProperties = new Properties();
        URL propURL = Util.class.getClassLoader().getResource(DEFAULT_PROPERTIES_FILE);
        if (propURL != null)
        {
            InputStream is = null;
            try
            {
                // Load properties from URL.
                is = propURL.openConnection().getInputStream();
                defaultProperties.load(is);
                is.close();
            }
            catch (Exception ex)
            {
                // Try to close input stream if we have one.
                try
                {
                    if (is != null) is.close();
                }
                catch (IOException ex2)
                {
                    // Nothing we can do.
                }

                logger.log(
                    Logger.LOG_ERROR, "Unable to load any configuration properties.", ex);
            }
        }
        return defaultProperties;
    }

    public static void initializeJPMSEE(String javaVersion, Properties properties, Logger logger)
    {
        try
        {
            Version version = new Version(javaVersion);

            if (version.getMajor() >= 9)
            {
                StringBuilder eecap = new StringBuilder(", osgi.ee; osgi.ee=\"OSGi/Minimum\"; version:List<Version>=\"1.0,1.1,1.2\",osgi.ee; osgi.ee=\"JavaSE\"; version:List<Version>=\"1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,9");
                for (int i = 10; i <= version.getMajor();i++)
                {
                    eecap.append(',').append(Integer.toString(i));
                }
                eecap.append("\",osgi.ee; osgi.ee=\"JavaSE/compact1\"; version:List<Version>=\"1.8,9");
                for (int i = 10; i <= version.getMajor();i++)
                {
                    eecap.append(',').append(Integer.toString(i));
                }
                eecap.append("\",osgi.ee; osgi.ee=\"JavaSE/compact2\"; version:List<Version>=\"1.8,9");
                for (int i = 10; i <= version.getMajor();i++)
                {
                    eecap.append(',').append(Integer.toString(i));
                }
                eecap.append("\",osgi.ee; osgi.ee=\"JavaSE/compact3\"; version:List<Version>=\"1.8,9");
                for (int i = 10; i <= version.getMajor();i++)
                {
                    eecap.append(',').append(Integer.toString(i));
                }
                eecap.append("\"");

                StringBuilder ee = new StringBuilder();

                for (int i = version.getMajor(); i > 9;i--)
                {
                    ee.append("JavaSE-").append(Integer.toString(i)).append(',');
                }

                ee.append("JavaSE-9,JavaSE-1.8,JavaSE-1.7,JavaSE-1.6,J2SE-1.5,J2SE-1.4,J2SE-1.3,J2SE-1.2,JRE-1.1,JRE-1.0,OSGi/Minimum-1.2,OSGi/Minimum-1.1,OSGi/Minimum-1.0");

                properties.put("ee-jpms", ee.toString());

                properties.put("eecap-jpms", eecap.toString());
            }

            properties.put("felix.detect.java.specification.version", version.getMajor() < 9 ? ("1." + (version.getMinor() > 6 ? version.getMinor() : 6)) : Integer.toString(version.getMajor()));

            if (version.getMajor() < 9)
            {
                properties.put("felix.detect.java.version", String.format("0.0.0.JavaSE_001_%03d", version.getMinor() > 6 ? version.getMinor() : 6));
            }
            else
            {
                properties.put("felix.detect.java.version", String.format("0.0.0.JavaSE_%03d", version.getMajor()));
            }
        }
        catch (Exception ex)
        {
            logger.log(Logger.LOG_ERROR, "Exception parsing java version", ex);
        }
    }

    public static Map<String, Set<String>> initializeJPMS(Properties properties)
    {
        Map<String,Set<String>> exports = null;
        try
        {
            Class<?> c_ModuleLayer = Felix.class.getClassLoader().loadClass("java.lang.ModuleLayer");
            Class<?> c_Module = Felix.class.getClassLoader().loadClass("java.lang.Module");
            Class<?> c_Descriptor = Felix.class.getClassLoader().loadClass("java.lang.module.ModuleDescriptor");
            Class<?> c_Exports = Felix.class.getClassLoader().loadClass("java.lang.module.ModuleDescriptor$Exports");
            Method m_getLayer = c_Module.getMethod("getLayer");
            Method m_getModule = Class.class.getMethod("getModule");
            Method m_canRead = c_Module.getMethod("canRead", c_Module);
            Method m_getName = c_Module.getMethod("getName");

            Object self = m_getModule.invoke(Felix.class);
            Object moduleLayer = m_getLayer.invoke(self);

            if (moduleLayer == null)
            {
                moduleLayer = c_ModuleLayer.getMethod("boot").invoke(null);
            }

            Set<String> modules = new TreeSet<String>();
            exports = new HashMap<String, Set<String>>();
            for (Object module : ((Iterable) c_ModuleLayer.getMethod("modules").invoke(moduleLayer)))
            {
                if ((Boolean) m_canRead.invoke(self, module))
                {
                    Object name = m_getName.invoke(module);
                    properties.put("felix.detect.jpms." + name, name);
                    modules.add("felix.jpms." + name);
                    Set<String> pkgs = new HashSet<String>();

                    Object descriptor = c_Module.getMethod("getDescriptor").invoke(module);

                    for (Object export :((Set) c_Descriptor.getMethod("exports").invoke(descriptor)))
                    {
                        if (((Set) c_Exports.getMethod("targets").invoke(export)).isEmpty())
                        {
                            pkgs.add((String) c_Exports.getMethod("source").invoke(export));
                        }
                    }
                    if (!pkgs.isEmpty())
                    {
                        exports.put("felix.jpms." + c_Descriptor.getMethod("toNameAndVersion").invoke(descriptor), pkgs);
                    }
                }
            }

            properties.put("felix.detect.jpms", "jpms");
            String modulesString = "";
            for (String module : modules) {
                modulesString += "${" + module + "}";
            }
            properties.put("jre-jpms", modulesString);
        }
        catch (Exception ex)
        {
            // Not much we can do - probably not on java9
        }
        return exports;
    }

    public static String getPropertyWithSubs(Properties props, String name)
    {
        // Perform variable substitution for property.
        String value = props.getProperty(name);
        value = (value != null)
            ? Util.substVars(value, name, null, props): null;
        return value;
    }

    public static Map<String, String> getPropertiesWithPrefix(Properties props, String prefix)
    {
        Map<String, String> result = new HashMap<String, String>();

        Set<String> propertySet = props.stringPropertyNames();

        for(String currentPropertyKey: propertySet)
        {
            if(currentPropertyKey.startsWith(prefix))
            {
                String value = props.getProperty(currentPropertyKey);
                // Perform variable substitution for property.
                value = (value != null)
                    ? Util.substVars(value, currentPropertyKey, null, props): null;
                result.put(currentPropertyKey, value);
            }
        }
        return result;
    }

    public static Properties toProperties(Map map)
    {
        Properties result = new Properties();
        for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
        {
            Entry entry = (Entry) iter.next();
            if (entry.getKey() != null && entry.getValue() != null)
            {
                result.setProperty(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        return result;
    }

    /**
     * Converts a revision identifier to a bundle identifier. Revision IDs
     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
     * method returns only the portion corresponding to the bundle ID.
    **/
    public static long getBundleIdFromRevisionId(String id)
    {
        try
        {
            String bundleId = (id.indexOf('.') >= 0)
                ? id.substring(0, id.indexOf('.')) : id;
            return Long.parseLong(bundleId);
        }
        catch (NumberFormatException ex)
        {
            return -1;
        }
    }

    /**
     * Converts a module identifier to a bundle identifier. Module IDs
     * are typically <tt>&lt;bundle-id&gt;.&lt;revision&gt;</tt>; this
     * method returns only the portion corresponding to the revision.
    **/
    public static int getModuleRevisionFromModuleId(String id)
    {
        try
        {
            int index = id.indexOf('.');
            if (index >= 0)
            {
                return Integer.parseInt(id.substring(index + 1));
            }
        }
        catch (NumberFormatException ex)
        {
        }
        return -1;
    }

    public static String getClassName(String className)
    {
        if (className == null)
        {
            className = "";
        }
        return (className.lastIndexOf('.') < 0)
            ? "" : className.substring(className.lastIndexOf('.') + 1);
    }

    public static String getClassPackage(String className)
    {
        if (className == null)
        {
            className = "";
        }
        return (className.lastIndexOf('.') < 0)
            ? "" : className.substring(0, className.lastIndexOf('.'));
    }

    public static String getResourcePackage(String resource)
    {
        if (resource == null)
        {
            resource = "";
        }
        // NOTE: The package of a resource is tricky to determine since
        // resources do not follow the same naming conventions as classes.
        // This code is pessimistic and assumes that the package of a
        // resource is everything up to the last '/' character. By making
        // this choice, it will not be possible to load resources from
        // imports using relative resource names. For example, if a
        // bundle exports "foo" and an importer of "foo" tries to load
        // "/foo/bar/myresource.txt", this will not be found in the exporter
        // because the following algorithm assumes the package name is
        // "foo.bar", not just "foo". This only affects imported resources,
        // local resources will work as expected.
        String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource;
        pkgName = (pkgName.lastIndexOf('/') < 0)
            ? "" : pkgName.substring(0, pkgName.lastIndexOf('/'));
        pkgName = pkgName.replace('/', '.');
        return pkgName;
    }

    /**
     * <p>
     * This is a simple utility class that attempts to load the named
     * class using the class loader of the supplied class or
     * the class loader of one of its super classes or their implemented
     * interfaces. This is necessary during service registration to test
     * whether a given service object implements its declared service
     * interfaces.
     * </p>
     * <p>
     * To perform this test, the framework must try to load
     * the classes associated with the declared service interfaces, so
     * it must choose a class loader. The class loader of the registering
     * bundle cannot be used, since this disallows third parties to
     * register service on behalf of another bundle. Consequently, the
     * class loader of the service object must be used. However, this is
     * also not sufficient since the class loader of the service object
     * may not have direct access to the class in question.
     * </p>
     * <p>
     * The service object's class loader may not have direct access to
     * its service interface if it extends a super class from another
     * bundle which implements the service interface from an imported
     * bundle or if it implements an extension of the service interface
     * from another bundle which imports the base interface from another
     * bundle. In these cases, the service object's class loader only has
     * access to the super class's class or the extended service interface,
     * respectively, but not to the actual service interface.
     * </p>
     * <p>
     * Thus, it is necessary to not only try to load the service interface
     * class from the service object's class loader, but from the class
     * loaders of any interfaces it implements and the class loaders of
     * all super classes.
     * </p>
     * @param clazz the class that is the root of the search.
     * @param name the name of the class to load.
     * @return the loaded class or <tt>null</tt> if it could not be
     *         loaded.
    **/
    public static Class loadClassUsingClass(Class clazz, String name, SecureAction action)
    {
        Class loadedClass = null;

        while (clazz != null)
        {
            // Get the class loader of the current class object.
            ClassLoader loader = action.getClassLoader(clazz);
            // A null class loader represents the system class loader.
            loader = (loader == null) ? action.getSystemClassLoader() : loader;
            try
            {
                return loader.loadClass(name);
            }
            catch (ClassNotFoundException ex)
            {
                // Ignore and try interface class loaders.
            }

            // Try to see if we can load the class from
            // one of the class's implemented interface
            // class loaders.
            Class[] ifcs = clazz.getInterfaces();
            for (int i = 0; i < ifcs.length; i++)
            {
                loadedClass = loadClassUsingClass(ifcs[i], name, action);
                if (loadedClass != null)
                {
                    return loadedClass;
                }
            }

            // Try to see if we can load the class from
            // the super class class loader.
            clazz = clazz.getSuperclass();
        }

        return null;
    }

    /**
     * This method determines if the requesting bundle is able to cast
     * the specified service reference based on class visibility rules
     * of the underlying modules.
     * @param requester The bundle requesting the service.
     * @param ref The service in question.
     * @return <tt>true</tt> if the requesting bundle is able to case
     *         the service object to a known type.
    **/
    public static boolean isServiceAssignable(Bundle requester, ServiceReference ref)
    {
        // Boolean flag.
        boolean allow = true;
        // Get the service's objectClass property.
        String[] objectClass = (String[]) ref.getProperty(FelixConstants.OBJECTCLASS);

        // The the service reference is not assignable when the requesting
        // bundle is wired to a different version of the service object.
        // NOTE: We are pessimistic here, if any class in the service's
        // objectClass is not usable by the requesting bundle, then we
        // disallow the service reference.
        for (int classIdx = 0; (allow) && (classIdx < objectClass.length); classIdx++)
        {
            if (!ref.isAssignableTo(requester, objectClass[classIdx]))
            {
                allow = false;
            }
        }
        return allow;
    }

    public static List<BundleRequirement> getDynamicRequirements(
        List<BundleRequirement> reqs)
    {
        List<BundleRequirement> result = null;
        if (reqs != null)
        {
            for (BundleRequirement req : reqs)
            {
                String resolution = req.getDirectives().get(Constants.RESOLUTION_DIRECTIVE);
                if ((resolution != null) && resolution.equals("dynamic"))
                {
                    if (result == null)
                    {
                        result = new ArrayList<BundleRequirement>();
                    }
                    result.add(req);
                }
            }
        }
        return result;
    }

    public static BundleWire getWire(BundleRevision br, String name)
    {
        if (br.getWiring() != null)
        {
            List<BundleWire> wires = br.getWiring().getRequiredWires(null);
            if (wires != null)
            {
                for (BundleWire w : wires)
                {
                    if (w.getCapability().getNamespace()
                            .equals(BundleRevision.PACKAGE_NAMESPACE) &&
                            w.getCapability().getAttributes()
                                    .get(BundleRevision.PACKAGE_NAMESPACE).equals(name))
                    {
                        return w;
                    }
                }
            }
        }
        return null;
    }

    public static BundleCapability getPackageCapability(BundleRevision br, String name)
    {
        if (br.getWiring() != null)
        {
            List<BundleCapability> capabilities = br.getWiring().getCapabilities(null);
            if (capabilities != null)
            {
                for (BundleCapability c : capabilities)
                {
                    if (c.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)
                        && c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(name))
                    {
                        return c;
                    }
                }
            }
        }
        return null;
    }

    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
        0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
        0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
        0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31,
        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f };

    private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,
        -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
        -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
        30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        48, 49, 50, 51, -1, -1, -1, -1, -1 };

    public static String base64Encode(String s) throws IOException
    {
        return encode(s.getBytes(), 0);
    }

    /**
     * Encode a raw byte array to a Base64 String.
     *
     * @param in Byte array to encode.
     * @param len Length of Base64 lines. 0 means no line breaks.
    **/
    public static String encode(byte[] in, int len) throws IOException
    {
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream bais = null;
        try
        {
            baos = new ByteArrayOutputStream();
            bais = new ByteArrayInputStream(in);
            encode(bais, baos, len);
            // ASCII byte array to String
            return (new String(baos.toByteArray()));
        }
        finally
        {
            if (baos != null)
            {
                baos.close();
            }
            if (bais != null)
            {
                bais.close();
            }
        }
    }

    public static void encode(InputStream in, OutputStream out, int len)
        throws IOException
    {

        // Check that length is a multiple of 4 bytes
        if (len % 4 != 0)
        {
            throw new IllegalArgumentException("Length must be a multiple of 4");
        }

        // Read input stream until end of file
        int bits = 0;
        int nbits = 0;
        int nbytes = 0;
        int b;

        while ((b = in.read()) != -1)
        {
            bits = (bits << 8) | b;
            nbits += 8;
            while (nbits >= 6)
            {
                nbits -= 6;
                out.write(encTab[0x3f & (bits >> nbits)]);
                nbytes++;
                // New line
                if (len != 0 && nbytes >= len)
                {
                    out.write(0x0d);
                    out.write(0x0a);
                    nbytes -= len;
                }
            }
        }

        switch (nbits)
        {
            case 2:
                out.write(encTab[0x3f & (bits << 4)]);
                out.write(0x3d); // 0x3d = '='
                out.write(0x3d);
                break;
            case 4:
                out.write(encTab[0x3f & (bits << 2)]);
                out.write(0x3d);
                break;
        }

        if (len != 0)
        {
            if (nbytes != 0)
            {
                out.write(0x0d);
                out.write(0x0a);
            }
            out.write(0x0d);
            out.write(0x0a);
        }
    }


    private static final String DELIM_START = "${";
    private static final String DELIM_STOP  = "}";

    /**
     * <p>
     * This method performs property variable substitution on the
     * specified value. If the specified value contains the syntax
     * <tt>${&lt;prop-name&gt;}</tt>, where <tt>&lt;prop-name&gt;</tt>
     * refers to either a configuration property or a system property,
     * then the corresponding property value is substituted for the variable
     * placeholder. Multiple variable placeholders may exist in the
     * specified value as well as nested variable placeholders, which
     * are substituted from inner most to outer most. Configuration
     * properties override system properties.
     * </p>
     * @param val The string on which to perform property substitution.
     * @param currentKey The key of the property being evaluated used to
     *        detect cycles.
     * @param cycleMap Map of variable references used to detect nested cycles.
     * @param configProps Set of configuration properties.
     * @return The value of the specified string after system property substitution.
     * @throws IllegalArgumentException If there was a syntax error in the
     *         property placeholder syntax or a recursive variable reference.
    **/
    public static String substVars(String val, String currentKey,
        Map cycleMap, Properties configProps)
        throws IllegalArgumentException
    {
        // If there is currently no cycle map, then create
        // one for detecting cycles for this invocation.
        if (cycleMap == null)
        {
            cycleMap = new HashMap();
        }

        // Put the current key in the cycle map.
        cycleMap.put(currentKey, currentKey);

        // Assume we have a value that is something like:
        // "leading ${foo.${bar}} middle ${baz} trailing"

        // Find the first ending '}' variable delimiter, which
        // will correspond to the first deepest nested variable
        // placeholder.
        int stopDelim = -1;
        int startDelim = -1;

        do
        {
            stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1);
            // If there is no stopping delimiter, then just return
            // the value since there is no variable declared.
            if (stopDelim < 0)
            {
                return val;
            }
            // Try to find the matching start delimiter by
            // looping until we find a start delimiter that is
            // greater than the stop delimiter we have found.
            startDelim = val.indexOf(DELIM_START);
            // If there is no starting delimiter, then just return
            // the value since there is no variable declared.
            if (startDelim < 0)
            {
                return val;
            }
            while (stopDelim >= 0)
            {
                int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
                if ((idx < 0) || (idx > stopDelim))
                {
                    break;
                }
                else if (idx < stopDelim)
                {
                    startDelim = idx;
                }
            }
        }
        while ((startDelim > stopDelim) && (stopDelim >= 0));

        // At this point, we have found a variable placeholder so
        // we must perform a variable substitution on it.
        // Using the start and stop delimiter indices, extract
        // the first, deepest nested variable placeholder.
        String variable =
            val.substring(startDelim + DELIM_START.length(), stopDelim);

        // Verify that this is not a recursive variable reference.
        if (cycleMap.get(variable) != null)
        {
            throw new IllegalArgumentException(
                "recursive variable reference: " + variable);
        }

        // Get the value of the deepest nested variable placeholder.
        // Try to configuration properties first.
        String substValue = (configProps != null)
            ? configProps.getProperty(variable, null)
            : null;
        if (substValue == null)
        {
            // Ignore unknown property values.
            substValue = System.getProperty(variable, "");
        }

        // Remove the found variable from the cycle map, since
        // it may appear more than once in the value and we don't
        // want such situations to appear as a recursive reference.
        cycleMap.remove(variable);

        // Append the leading characters, the substituted value of
        // the variable, and the trailing characters to get the new
        // value.
        val = val.substring(0, startDelim)
            + substValue
            + val.substring(stopDelim + DELIM_STOP.length(), val.length());

        // Now perform substitution again, since there could still
        // be substitutions to make.
        val = substVars(val, currentKey, cycleMap, configProps);

        // Return the value.
        return val;
    }

    /**
     * Returns true if the specified bundle revision is a singleton
     * (i.e., directive singleton:=true in Bundle-SymbolicName).
     *
     * @param revision the revision to check for singleton status.
     * @return true if the revision is a singleton, false otherwise.
    **/
    public static boolean isSingleton(BundleRevision revision)
    {
        final List<BundleCapability> caps = revision.getDeclaredCapabilities(null);
        for (BundleCapability cap : caps)
        {
            // Find the bundle capability and check its directives.
            if (cap.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE))
            {
                for (Entry<String, String> entry : cap.getDirectives().entrySet())
                {
                    if (entry.getKey().equalsIgnoreCase(Constants.SINGLETON_DIRECTIVE))
                    {
                        return Boolean.valueOf(entry.getValue());
                    }
                }
                // Can only have one bundle capability, so break.
                break;
            }
        }
        return false;
    }

    /**
     * Checks if the provided module definition declares a fragment host.
     *
     * @param revision the module to check
     * @return <code>true</code> if the module declares a fragment host, <code>false</code>
     *      otherwise.
     */
    public static boolean isFragment(BundleRevision revision)
    {
        return ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) > 0);
    }

    public static boolean isFragment(Resource resource)
    {
        if (resource instanceof BundleRevision)
            return isFragment((BundleRevision) resource);
        else
            return false;
    }

    public static List<BundleRevision> getFragments(BundleWiring wiring)
    {
        List<BundleRevision> fragments = Collections.EMPTY_LIST;
        if (wiring != null)
        {
            List<BundleWire> wires = wiring.getProvidedWires(null);
            if (wires != null)
            {
                for (BundleWire w : wires)
                {
                    if (w.getCapability().getNamespace()
                        .equals(BundleRevision.HOST_NAMESPACE))
                    {
                        // Create array list if needed.
                        if (fragments.isEmpty())
                        {
                            fragments = new ArrayList<BundleRevision>();
                        }
                        fragments.add(w.getRequirerWiring().getRevision());
                    }
                }
            }
        }
        return fragments;
    }

    //
    // UUID code copied from Apache Harmony java.util.UUID
    //

    /**
     * <p>
     * Generates a variant 2, version 4 (randomly generated number) UUID as per
     * <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
     *
     * @return an UUID instance.
     */
    public static String randomUUID(boolean secure) {
        byte[] data = new byte[16];
        if (secure)
        {
            SecureRandom rng = new SecureRandom();
            rng.nextBytes(data);
        }
        else
        {
            Random rng = new Random();
            rng.nextBytes(data);
        }
        long mostSigBits = (data[0] & 0xFFL) << 56;
        mostSigBits |= (data[1] & 0xFFL) << 48;
        mostSigBits |= (data[2] & 0xFFL) << 40;
        mostSigBits |= (data[3] & 0xFFL) << 32;
        mostSigBits |= (data[4] & 0xFFL) << 24;
        mostSigBits |= (data[5] & 0xFFL) << 16;
        mostSigBits |= (data[6] & 0x0FL) << 8;
        mostSigBits |= (0x4L << 12); // set the version to 4
        mostSigBits |= (data[7] & 0xFFL);

        long leastSigBits = (data[8] & 0x3FL) << 56;
        leastSigBits |= (0x2L << 62); // set the variant to bits 01
        leastSigBits |= (data[9] & 0xFFL) << 48;
        leastSigBits |= (data[10] & 0xFFL) << 40;
        leastSigBits |= (data[11] & 0xFFL) << 32;
        leastSigBits |= (data[12] & 0xFFL) << 24;
        leastSigBits |= (data[13] & 0xFFL) << 16;
        leastSigBits |= (data[14] & 0xFFL) << 8;
        leastSigBits |= (data[15] & 0xFFL);

        //
        // UUID.init()
        //

        int variant;
        int version;
        long timestamp;
        int clockSequence;
        long node;
        int hash;

        // setup hash field
        int msbHash = (int) (mostSigBits ^ (mostSigBits >>> 32));
        int lsbHash = (int) (leastSigBits ^ (leastSigBits >>> 32));
        hash = msbHash ^ lsbHash;

        // setup variant field
        if ((leastSigBits & 0x8000000000000000L) == 0) {
            // MSB0 not set, NCS backwards compatibility variant
            variant = 0;
        } else if ((leastSigBits & 0x4000000000000000L) != 0) {
            // MSB1 set, either MS reserved or future reserved
            variant = (int) ((leastSigBits & 0xE000000000000000L) >>> 61);
        } else {
            // MSB1 not set, RFC 4122 variant
            variant = 2;
        }

        // setup version field
        version = (int) ((mostSigBits & 0x000000000000F000) >>> 12);

        if (!(variant != 2 && version != 1)) {
            // setup timestamp field
            long timeLow = (mostSigBits & 0xFFFFFFFF00000000L) >>> 32;
            long timeMid = (mostSigBits & 0x00000000FFFF0000L) << 16;
            long timeHigh = (mostSigBits & 0x0000000000000FFFL) << 48;
            timestamp = timeLow | timeMid | timeHigh;

            // setup clock sequence field
            clockSequence = (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);

            // setup node field
            node = (leastSigBits & 0x0000FFFFFFFFFFFFL);
        }

        //
        // UUID.toString()
        //

        StringBuilder builder = new StringBuilder(36);
        String msbStr = Long.toHexString(mostSigBits);
        if (msbStr.length() < 16) {
            int diff = 16 - msbStr.length();
            for (int i = 0; i < diff; i++) {
                builder.append('0');
            }
        }
        builder.append(msbStr);
        builder.insert(8, '-');
        builder.insert(13, '-');
        builder.append('-');
        String lsbStr = Long.toHexString(leastSigBits);
        if (lsbStr.length() < 16) {
            int diff = 16 - lsbStr.length();
            for (int i = 0; i < diff; i++) {
                builder.append('0');
            }
        }
        builder.append(lsbStr);
        builder.insert(23, '-');
        return builder.toString();
    }

    public static <K,V> V putIfAbsentAndReturn(ConcurrentHashMap<K,V> map, K key, V value)
    {
        V result = map.putIfAbsent(key, value);
        return result != null ? result : value;
    }

    public static String getFrameworkUUIDFromURL(String host)
    {
        if (host != null)
        {
            int idx = host.indexOf('_');
            if (idx > 0)
            {
                return host.substring(0, idx);
            }
        }
        return null;
    }

    public static String getRevisionIdFromURL(String host)
    {
        if (host != null)
        {
            int idx = host.indexOf('_');
            if (idx > 0 && idx < host.length())
            {
                return host.substring(idx + 1);
            }
            else
            {
                return host;
            }
        }
        return null;
    }

    public static Map<String, Object> getMultiReleaseAwareManifestHeaders(String version, BundleArchiveRevision revision) throws Exception
    {
        Map<String, Object> manifest = revision.getManifestHeader();
        if (manifest == null)
        {
            throw new FileNotFoundException("META-INF/MANIFEST.MF");
        }
        if ("true".equals(manifest.get("Multi-Release")))
        {
            for (int major = Version.parseVersion(version).getMajor(); major >= 9; major--)
            {
                byte[] versionManifestInput = revision.getContent()
                    .getEntryAsBytes("META-INF/versions/" + major + "/OSGI-INF/MANIFEST.MF");

                if (versionManifestInput != null)
                {
                    Map<String, Object> versionManifest = BundleCache.getMainAttributes(
                        new StringMap(), new ByteArrayInputStream(versionManifestInput), versionManifestInput.length);

                    if (versionManifest.get(Constants.IMPORT_PACKAGE) != null)
                    {
                        manifest.put(Constants.IMPORT_PACKAGE, versionManifest.get(Constants.IMPORT_PACKAGE));
                    }
                    if (versionManifest.get(Constants.REQUIRE_CAPABILITY) != null)
                    {
                        manifest.put(Constants.REQUIRE_CAPABILITY, versionManifest.get(Constants.REQUIRE_CAPABILITY));
                    }
                    break;
                }
            }
        }
        return manifest;
    }

    private static final List EMPTY_LIST = Collections.unmodifiableList(Collections.EMPTY_LIST);
    private static final Map EMPTY_MAP = Collections.unmodifiableMap(Collections.EMPTY_MAP);

    public static <T> List<T> newImmutableList(List<T> list)
    {
        return list == null || list.isEmpty() ? EMPTY_LIST : Collections.unmodifiableList(list);
    }

    public static <K,V> Map<K,V> newImmutableMap(Map<K,V> map)
    {
        return map == null || map.isEmpty() ? EMPTY_MAP : Collections.unmodifiableMap(map);
    }
}