/*
 * 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.lang.reflect.Method;
import java.net.ContentHandler;
import java.net.ContentHandlerFactory;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import static org.apache.felix.framework.util.Util.putIfAbsentAndReturn;

import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.SecureAction;
import org.apache.felix.framework.util.SecurityManagerEx;
import org.osgi.framework.Constants;
import org.osgi.service.url.URLStreamHandlerService;

/**
 * <p>
 * This class is a singleton and implements the stream and content handler
 * factories for all framework instances executing within the JVM. Any
 * calls to retrieve stream or content handlers is routed through this class
 * and it acts as a multiplexer for all framework instances. To achieve this,
 * all framework instances register with this class when they are created so
 * that it can maintain a centralized registry of instances.
 * </p>
 * <p>
 * When this class receives a request for a stream or content handler, it
 * always returns a proxy handler instead of only returning a proxy if a
 * handler currently exists. This approach is used for three reasons:
 * </p>
 * <ol>
 *   <li>Potential caching behavior by the JVM of stream handlers does not give
 *       you a second chance to provide a handler.
 *   </li>
 *   <li>Due to the dynamic nature of OSGi services, handlers may appear at
 *       any time, so always creating a proxy makes sense.
 *   </li>
 *   <li>Since these handler factories service all framework instances,
 *       some instances may have handlers and others may not, so returning
 *       a proxy is the only answer that makes sense.
 *   </li>
 * </ol>
 * <p>
 * It is possible to disable the URL Handlers service by setting the
 * <tt>framework.service.urlhandlers</tt> configuration property to <tt>false</tt>.
 * When multiple framework instances are in use, if no framework instances enable
 * the URL Handlers service, then the singleton stream and content factories will
 * never be set (i.e., <tt>URL.setURLStreamHandlerFactory()</tt> and
 * <tt>URLConnection.setContentHandlerFactory()</tt>). However, if one instance
 * enables URL Handlers service, then the factory methods will be invoked. In
 * that case, framework instances that disable the URL Handlers service will
 * simply not provide that services to their contained bundles, while framework
 * instances with the service enabled will.
 * </p>
**/
class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
{
    private static final Class[] CLASS_TYPE = new Class[]{Class.class};

    private static final Class URLHANDLERS_CLASS = URLHandlers.class;

    private static final SecureAction m_secureAction = new SecureAction();

    private static volatile SecurityManagerEx m_sm = null;
    private static volatile URLHandlers m_handler = null;

    // This maps classloaders of URLHandlers in other classloaders to lists of
    // their frameworks.
    private final static ConcurrentHashMap<ClassLoader, List<Object>> m_classloaderToFrameworkLists = new ConcurrentHashMap<ClassLoader, List<Object>>();

    // The list to hold all enabled frameworks registered with this handlers
    private static final CopyOnWriteArrayList<Felix> m_frameworks = new CopyOnWriteArrayList<Felix>();
    private static volatile int m_counter = 0;

    private static final ConcurrentHashMap<String, ContentHandler> m_contentHandlerCache = new ConcurrentHashMap<String, ContentHandler>();
    private static final ConcurrentHashMap<String, URLStreamHandler> m_streamHandlerCache = new ConcurrentHashMap<String, URLStreamHandler>();
    private static final ConcurrentHashMap<String, URL> m_protocolToURL = new ConcurrentHashMap<String, URL>();

    private static volatile URLStreamHandlerFactory m_streamHandlerFactory;
    private static volatile ContentHandlerFactory m_contentHandlerFactory;
    private static final String STREAM_HANDLER_PACKAGE_PROP = "java.protocol.handler.pkgs";
    private static final String DEFAULT_STREAM_HANDLER_PACKAGE = "sun.net.www.protocol|com.ibm.oti.net.www.protocol|gnu.java.net.protocol|wonka.net|com.acunia.wonka.net|org.apache.harmony.luni.internal.net.www.protocol|weblogic.utils|weblogic.net|javax.net.ssl|COM.newmonics.www.protocols";
    private static volatile Object m_rootURLHandlers;

    private static final String m_streamPkgs;
    private static final ConcurrentHashMap<String, URLStreamHandler> m_builtIn = new ConcurrentHashMap<String, URLStreamHandler>();
    private static final boolean m_loaded;

    static
    {
        String pkgs = new SecureAction().getSystemProperty(STREAM_HANDLER_PACKAGE_PROP, "");
        m_streamPkgs = (pkgs.equals(""))
            ? DEFAULT_STREAM_HANDLER_PACKAGE
            : pkgs + "|" + DEFAULT_STREAM_HANDLER_PACKAGE;
        m_loaded = (null != URLHandlersStreamHandlerProxy.class) &&
            (null != URLHandlersContentHandlerProxy.class) && (null != URLStreamHandlerService.class);
    }

    private void init(String protocol, URLStreamHandlerFactory factory)
    {
        try
        {
            URLStreamHandler handler = getBuiltInStreamHandler(protocol, factory);
            if (handler != null)
            {
                URL url = new URL(protocol, null, -1, "", handler);
                addToCache(m_protocolToURL, protocol, url);
            }
        }
        catch (Throwable ex)
        {
            // Ignore, this is a best effort (maybe log it or something).
        }
    }

    /**
     * <p>
     * Only one instance of this class is created per classloader
     * and that one instance is registered as the stream and content handler
     * factories for the JVM. Unless, we already register one from a different
     * classloader. In this case we attach to this root.
     * </p>
    **/
    private URLHandlers()
    {
        m_sm = new SecurityManagerEx();
        synchronized (URL.class)
        {
            URLStreamHandlerFactory currentFactory = null;
            try
            {
                currentFactory = (URLStreamHandlerFactory) m_secureAction.swapStaticFieldIfNotClass(URL.class,
                    URLStreamHandlerFactory.class, URLHANDLERS_CLASS, "streamHandlerLock");
            }
            catch (Throwable ex)
            {
                // Ignore, this is a best effort (maybe log it or something)
            }

            init("file", currentFactory);
            init("ftp", currentFactory);
            init("http", currentFactory);
            init("https", currentFactory);
            try
            {
                getBuiltInStreamHandler("jar", currentFactory);
            }
            catch (Throwable ex)
            {
                // Ignore, this is a best effort (maybe log it or something)
            }

            // Try to preload the jrt handler as we need it from the jvm on java > 8
            if (getFromCache(m_builtIn, "jrt") == null)
            {
                try
                {
                    // Try to get it directly from the URL class to if possible
                    Method getURLStreamHandler = m_secureAction.getDeclaredMethod(URL.class,"getURLStreamHandler", new Class[]{String.class});
                    URLStreamHandler handler = (URLStreamHandler) m_secureAction.invoke(getURLStreamHandler, null, new Object[]{"jrt"});
                    addToCache(m_builtIn, "jrt", handler);
                }
                catch (Throwable ex)
                {
                    // Ignore, this is a best effort and try to load the normal way
                    try
                    {
                        getBuiltInStreamHandler("jrt", currentFactory);
                    }
                    catch (Throwable ex2)
                    {
                        // Ignore, this is a best efforts
                    }
                }
            }

            if (currentFactory != null)
            {
                try
                {
                    URL.setURLStreamHandlerFactory(currentFactory);
                }
                catch (Throwable ex)
                {
                    // Ignore, this is a best effort (maybe log it or something)
                }
            }

            try
            {
                URL.setURLStreamHandlerFactory(this);
                m_streamHandlerFactory = this;
                m_rootURLHandlers = this;
                // try to flush the cache (gnu/classpath doesn't do it itself)
                try
                {
                    m_secureAction.flush(URL.class, URL.class);
                }
                catch (Throwable t)
                {
                    // Not much we can do
                }
            }
            catch (Error err)
            {
                try
                {
                    // there already is a factory set so try to swap it with ours.
                    m_streamHandlerFactory = (URLStreamHandlerFactory)
                        m_secureAction.swapStaticFieldIfNotClass(URL.class,
                        URLStreamHandlerFactory.class, URLHANDLERS_CLASS, "streamHandlerLock");

                    if (m_streamHandlerFactory == null)
                    {
                        throw err;
                    }
                    if (!m_streamHandlerFactory.getClass().getName().equals(URLHANDLERS_CLASS.getName()))
                    {
                        URL.setURLStreamHandlerFactory(this);
                        m_rootURLHandlers = this;
                    }
                    else if (URLHANDLERS_CLASS != m_streamHandlerFactory.getClass())
                    {
                        try
                        {
                            m_secureAction.invoke(
                                m_secureAction.getDeclaredMethod(m_streamHandlerFactory.getClass(),
                                "registerFrameworkListsForContextSearch",
                                new Class[]{ClassLoader.class, List.class}),
                                m_streamHandlerFactory, new Object[]{ URLHANDLERS_CLASS.getClassLoader(),
                                    m_frameworks });
                            m_rootURLHandlers = m_streamHandlerFactory;
                        }
                        catch (Exception ex)
                        {
                            throw new RuntimeException(ex.getMessage());
                        }
                    }
                }
                catch (Exception e)
                {
                    throw err;
                }
            }

            try
            {
                URLConnection.setContentHandlerFactory(this);
                m_contentHandlerFactory = this;
                // try to flush the cache (gnu/classpath doesn't do it itself)
                try
                {
                    m_secureAction.flush(URLConnection.class, URLConnection.class);
                }
                catch (Throwable t)
                {
                    // Not much we can do
                }
            }
            catch (Error err)
            {
                // there already is a factory set so try to swap it with ours.
                try
                {
                    m_contentHandlerFactory = (ContentHandlerFactory)
                        m_secureAction.swapStaticFieldIfNotClass(
                            URLConnection.class, ContentHandlerFactory.class,
                            URLHANDLERS_CLASS, null);
                    if (m_contentHandlerFactory == null)
                    {
                        throw err;
                    }
                    if (!m_contentHandlerFactory.getClass().getName().equals(
                        URLHANDLERS_CLASS.getName()))
                    {
                        URLConnection.setContentHandlerFactory(this);
                    }
                }
                catch (Exception ex)
                {
                    throw err;
                }
            }
        }
        // are we not the new root?
        if (!((m_streamHandlerFactory == this) || !URLHANDLERS_CLASS.getName().equals(
            m_streamHandlerFactory.getClass().getName())))
        {
            m_sm = null;
            m_protocolToURL.clear();
            m_builtIn.clear();
        }
    }

    static void registerFrameworkListsForContextSearch(ClassLoader index,
        List frameworkLists)
    {
        synchronized (URL.class)
        {
            synchronized (m_classloaderToFrameworkLists)
            {
                m_classloaderToFrameworkLists.put(index, frameworkLists);
            }
        }
    }

    static void unregisterFrameworkListsForContextSearch(ClassLoader index)
    {
        synchronized (URL.class)
        {
            synchronized (m_classloaderToFrameworkLists)
            {
                m_classloaderToFrameworkLists.remove(index);
                if (m_classloaderToFrameworkLists.isEmpty() )
                {
                    synchronized (m_frameworks)
                    {
                        if (m_frameworks.isEmpty())
                        {
                            try
                            {
                                m_secureAction.swapStaticFieldIfNotClass(URL.class,
                                    URLStreamHandlerFactory.class, null, "streamHandlerLock");
                            }
                            catch (Exception ex)
                            {
                                // TODO log this
                                ex.printStackTrace();
                            }

                            if (m_streamHandlerFactory.getClass() != URLHANDLERS_CLASS)
                            {
                                URL.setURLStreamHandlerFactory(m_streamHandlerFactory);
                            }
                            try
                            {
                                m_secureAction.swapStaticFieldIfNotClass(
                                    URLConnection.class, ContentHandlerFactory.class,
                                    null, null);
                            }
                            catch (Exception ex)
                            {
                                // TODO log this
                                ex.printStackTrace();
                            }

                            if (m_contentHandlerFactory.getClass() != URLHANDLERS_CLASS)
                            {
                                URLConnection.setContentHandlerFactory(m_contentHandlerFactory);
                            }
                        }
                    }
                }
            }
        }
    }

    private URLStreamHandler getBuiltInStreamHandler(String protocol, URLStreamHandlerFactory factory)
    {
        URLStreamHandler handler = getFromCache(m_builtIn, protocol);

        if (handler != null)
        {
            return handler;
        }

        if (factory != null)
        {
            handler = factory.createURLStreamHandler(protocol);
        }

        if (handler == null)
        {
            // Check for built-in handlers for the mime type.
            // Iterate over built-in packages.
            handler = loadBuiltInStreamHandler(protocol, null);
        }

        if (handler == null)
        {
            handler = loadBuiltInStreamHandler(protocol, ClassLoader.getSystemClassLoader());
        }

        return addToCache(m_builtIn, protocol, handler);
    }

    private URLStreamHandler loadBuiltInStreamHandler(String protocol, ClassLoader classLoader) {
        StringTokenizer pkgTok = new StringTokenizer(m_streamPkgs, "| ");
        while (pkgTok.hasMoreTokens())
        {
            String pkg = pkgTok.nextToken().trim();
            String className = pkg + "." + protocol + ".Handler";
            try
            {
                // If a built-in handler is found then cache and return it
                Class handler = m_secureAction.forName(className, classLoader);
                if (handler != null)
                {
                    return (URLStreamHandler) handler.newInstance();
                }
            }
            catch (Throwable ex)
            {
                // This could be a class not found exception or an
                // instantiation exception, not much we can do in either
                // case other than ignore it.
            }
        }
        // This is a workaround for android - Starting with 4.1 the built-in core handler
        // are not following the normal naming nore package schema :-(
        String androidHandler = null;
        if ("file".equalsIgnoreCase(protocol))
        {
            androidHandler = "libcore.net.url.FileHandler";
        }
        else if ("ftp".equalsIgnoreCase(protocol))
        {
            androidHandler = "libcore.net.url.FtpHandler";
        }
        else if ("http".equalsIgnoreCase(protocol))
        {
            androidHandler = "libcore.net.http.HttpHandler";
        }
        else if ("https".equalsIgnoreCase(protocol))
        {
            androidHandler = "libcore.net.http.HttpsHandler";
        }
        else if ("jar".equalsIgnoreCase(protocol))
        {
            androidHandler = "libcore.net.url.JarHandler";
        }
        if (androidHandler != null)
        {
            try
            {
                // If a built-in handler is found then cache and return it
                Class handler = m_secureAction.forName(androidHandler, classLoader);
                if (handler != null)
                {
                    return (URLStreamHandler) handler.newInstance();
                }
            }
            catch (Throwable ex)
            {
                // This could be a class not found exception or an
                // instantiation exception, not much we can do in either
                // case other than ignore it.
            }
        }
        return null;
    }

    /**
     * <p>
     * This is a method implementation for the <tt>URLStreamHandlerFactory</tt>
     * interface. It simply creates a stream handler proxy object for the
     * specified protocol. It caches the returned proxy; therefore, subsequent
     * requests for the same protocol will receive the same handler proxy.
     * </p>
     * @param protocol the protocol for which a stream handler should be returned.
     * @return a stream handler proxy for the specified protocol.
    **/
    public URLStreamHandler createURLStreamHandler(String protocol)
    {
        // See if there is a cached stream handler.
        // IMPLEMENTATION NOTE: Caching is not strictly necessary for
        // stream handlers since the Java runtime caches them. Caching is
        // performed for code consistency between stream and content
        // handlers and also because caching behavior may not be guaranteed
        // across different JRE implementations.
        URLStreamHandler handler = getFromCache(m_streamHandlerCache, protocol);

        if (handler != null)
        {
            return handler;
        }
        // If this is the framework's "bundle:" protocol, then return
        // a handler for that immediately, since no one else can be
        // allowed to deal with it.
        if (protocol.equals(FelixConstants.BUNDLE_URL_PROTOCOL))
        {
            return new URLHandlersBundleStreamHandler(getFrameworkFromContext(), m_secureAction);
        }

        handler = getBuiltInStreamHandler(protocol,
            (m_streamHandlerFactory != this) ? m_streamHandlerFactory : null);

        // If built-in content handler, then create a proxy handler.
        return addToCache(m_streamHandlerCache, protocol,
            new URLHandlersStreamHandlerProxy(protocol, m_secureAction,
                handler, getFromCache(m_protocolToURL, protocol)));
    }

    /**
     * <p>
     * This is a method implementation for the <tt>ContentHandlerFactory</tt>
     * interface. It simply creates a content handler proxy object for the
     * specified mime type. It caches the returned proxy; therefore, subsequent
     * requests for the same content type will receive the same handler proxy.
     * </p>
     * @param mimeType the mime type for which a content handler should be returned.
     * @return a content handler proxy for the specified mime type.
    **/
    public ContentHandler createContentHandler(String mimeType)
    {
        // See if there is a cached stream handler.
        // IMPLEMENTATION NOTE: Caching is not strictly necessary for
        // stream handlers since the Java runtime caches them. Caching is
        // performed for code consistency between stream and content
        // handlers and also because caching behavior may not be guaranteed
        // across different JRE implementations.
        ContentHandler handler = getFromCache(m_contentHandlerCache, mimeType);

        if (handler != null)
        {
            return handler;
        }

        return addToCache(m_contentHandlerCache, mimeType,
            new URLHandlersContentHandlerProxy(mimeType, m_secureAction,
            (m_contentHandlerFactory != this) ? m_contentHandlerFactory : null));
    }

    private static <K,V> V addToCache(ConcurrentHashMap<K,V> cache, K key, V value)
    {
        return key != null && value != null ? putIfAbsentAndReturn(cache, key, value) : null;
    }

    private static <K,V> V getFromCache(ConcurrentHashMap<K,V> cache, K key)
    {
        return key != null ? cache.get(key) : null;
    }

    /**
     * <p>
     * Static method that adds a framework instance to the centralized
     * instance registry.
     * </p>
     * @param framework the framework instance to be added to the instance
     *        registry.
     * @param enable a flag indicating whether or not the framework wants to
     *        enable the URL Handlers service.
    **/
    public static void registerFrameworkInstance(Felix framework, boolean enable)
    {
        boolean register = false;
        synchronized (m_frameworks)
        {
            // If the URL Handlers service is not going to be enabled,
            // then return immediately.
            if (enable)
            {
                // We need to create an instance if this is the first
                // time this method is called, which will set the handler
                // factories.
                if (m_handler == null )
                {
                    register = true;
                }
                else
                {
                    m_frameworks.add(framework);
                    m_counter++;
                }
            }
            else
            {
                m_counter++;
            }
        }
        if (register)
        {
            synchronized (URL.class)
            {
                synchronized (m_classloaderToFrameworkLists)
                {
                    synchronized (m_frameworks)
                    {
                        if (m_handler == null )
                        {
                            m_handler = new URLHandlers();
                        }
                        m_frameworks.add(framework);
                        m_counter++;
                    }
                }
            }
        }
    }

    /**
     * <p>
     * Static method that removes a framework instance from the centralized
     * instance registry.
     * </p>
     * @param framework the framework instance to be removed from the instance
     *        registry.
    **/
    public static void unregisterFrameworkInstance(Object framework)
    {
        boolean unregister = false;
        synchronized (m_frameworks)
        {
            if (m_frameworks.contains(framework))
            {
                if (m_frameworks.size() == 1 && m_handler != null)
                {
                    unregister = true;
                }
                else
                {
                    m_frameworks.remove(framework);
                    m_counter--;
                }
            }
            else
            {
                m_counter--;
            }
        }
        if (unregister)
        {
            synchronized (URL.class)
            {
                synchronized (m_classloaderToFrameworkLists)
                {
                    synchronized (m_frameworks)
                    {
                        m_frameworks.remove(framework);
                        m_counter--;
                        if (m_frameworks.isEmpty() && m_handler != null)
                        {

                            m_handler = null;
                            try
                            {
                                m_secureAction.invoke(m_secureAction.getDeclaredMethod(
                                    m_rootURLHandlers.getClass(),
                                    "unregisterFrameworkListsForContextSearch",
                                    new Class[]{ ClassLoader.class}),
                                    m_rootURLHandlers,
                                    new Object[] {URLHANDLERS_CLASS.getClassLoader()});
                            }
                            catch (Exception e)
                            {
                                // This should not happen
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * <p>
     * This method returns the system bundle context for the caller.
     * It determines the appropriate system bundle by retrieving the
     * class call stack and find the first class that is loaded from
     * a bundle. It then checks to see which of the registered framework
     * instances owns the class and returns its system bundle context.
     * </p>
     * @return the system bundle context associated with the caller or
     *         <tt>null</tt> if no associated framework was found.
    **/
    public static Object getFrameworkFromContext()
    {
        // This is a hack. The idea is to return the only registered framework quickly
        int attempts = 0;
        while (m_classloaderToFrameworkLists.isEmpty() && (m_counter == 1) && (m_frameworks.size() == 1))
        {
            Object framework = m_frameworks.get(0);

            if (framework != null)
            {
                return framework;
            }
            else if (attempts++ > 3)
            {
                break;
            }
        }

        // get the current class call stack.
        Class[] stack = m_sm.getClassContext();
        // Find the first class that is loaded from a bundle.
        Class targetClass = null;
        ClassLoader targetClassLoader = null;
        for (int i = 0; i < stack.length; i++)
        {
            ClassLoader classLoader = m_secureAction.getClassLoader(stack[i]);
			if (classLoader != null)
            {
                String name = classLoader.getClass().getName();
                if (name.startsWith("org.apache.felix.framework.ModuleImpl$ModuleClassLoader")
                    || name.equals("org.apache.felix.framework.searchpolicy.ContentClassLoader")
                    || name.startsWith("org.apache.felix.framework.BundleWiringImpl$BundleClassLoader"))
                {
                    targetClass = stack[i];
                    targetClassLoader = classLoader;
                    break;
                }
            }
        }

        // If we found a class loaded from a bundle, then iterate
        // over the framework instances and see which framework owns
        // the bundle that loaded the class.
        if (targetClass != null)
        {
            ClassLoader index = m_secureAction.getClassLoader(targetClassLoader.getClass());

            List frameworks = (List) m_classloaderToFrameworkLists.get(index);

            if ((frameworks == null) && (index == URLHANDLERS_CLASS.getClassLoader()))
            {
                frameworks = m_frameworks;
            }
            if (frameworks != null)
            {
                // Check the registry of framework instances
                for (Object framework : frameworks)
                {
                    try
                    {
                        if (m_secureAction.invoke(
                            m_secureAction.getDeclaredMethod(framework.getClass(),
                            "getBundle", CLASS_TYPE),
                            framework, new Object[]{targetClass}) != null)
                        {
                            return framework;
                        }
                    }
                    catch (Exception ex)
                    {
                        // This should not happen but if it does there is
                        // not much we can do other then ignore it.
                        // Maybe log this or something.
                        ex.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    public static Object getFrameworkFromContext(String uuid)
    {
        if (uuid != null)
        {
            for (Felix framework : m_frameworks)
            {
                if (uuid.equals(framework._getProperty(Constants.FRAMEWORK_UUID)))
                {
                    return framework;
                }
            }
            for (List frameworks : m_classloaderToFrameworkLists.values())
            {
                for (Object framework : frameworks)
                {
                    try
                    {
                        if (uuid.equals(
                                m_secureAction.invoke(
                                        m_secureAction.getDeclaredMethod(framework.getClass(),"getProperty", new Class[]{String.class}),
                                        framework, new Object[]{Constants.FRAMEWORK_UUID})))
                        {
                            return framework;
                        }
                    }
                    catch (Exception ex)
                    {
                        // This should not happen but if it does there is
                        // not much we can do other then ignore it.
                        // Maybe log this or something.
                        ex.printStackTrace();
                    }
                }
            }
        }
        return getFrameworkFromContext();
    }
}
