/*
 * 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.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;

import org.apache.felix.framework.util.SecureAction;
import org.osgi.service.url.URLStreamHandlerService;
import org.osgi.service.url.URLStreamHandlerSetter;

/**
 * <p>
 * This class implements a stream handler proxy. When the stream handler
 * proxy instance is created, it is associated with a particular protocol
 * and will answer all future requests for handling of that stream type. It
 * does not directly handle the stream handler requests, but delegates the
 * requests to an underlying stream handler service.
 * </p>
 * <p>
 * The proxy instance for a particular protocol is used for all framework
 * instances that may contain their own stream handler services. When
 * performing a stream handler operation, the proxy retrieves the handler
 * service from the framework instance associated with the current call
 * stack and delegates the call to the handler service.
 * </p>
 * <p>
 * The proxy will create simple stream handler service trackers for each
 * framework instance. The trackers will listen to service events in its
 * respective framework instance to maintain a reference to the "best"
 * stream handler service at any given time.
 * </p>
**/
public class URLHandlersStreamHandlerProxy extends URLStreamHandler
    implements URLStreamHandlerSetter, InvocationHandler
{
    private static final Class[] URL_PROXY_CLASS;
    private static final Class[] STRING_TYPES = new Class[]{String.class};
    private static final Method EQUALS;
    private static final Method GET_DEFAULT_PORT;
    private static final Method GET_HOST_ADDRESS;
    private static final Method HASH_CODE;
    private static final Method HOSTS_EQUAL;
    private static final Method OPEN_CONNECTION;
    private static final Method OPEN_CONNECTION_PROXY;
    private static final Method SAME_FILE;
    private static final Method TO_EXTERNAL_FORM;

    static {
        SecureAction action = new SecureAction();
        try
        {
            EQUALS = URLStreamHandler.class.getDeclaredMethod("equals",
                new Class[]{URL.class, URL.class});
            action.setAccesssible(EQUALS);
            GET_DEFAULT_PORT = URLStreamHandler.class.getDeclaredMethod("getDefaultPort",
                (Class[]) null);
            action.setAccesssible(GET_DEFAULT_PORT);
            GET_HOST_ADDRESS = URLStreamHandler.class.getDeclaredMethod(
                    "getHostAddress", new Class[]{URL.class});
            action.setAccesssible(GET_HOST_ADDRESS);
            HASH_CODE = URLStreamHandler.class.getDeclaredMethod(
                    "hashCode", new Class[]{URL.class});
            action.setAccesssible(HASH_CODE);
            HOSTS_EQUAL = URLStreamHandler.class.getDeclaredMethod(
                    "hostsEqual", new Class[]{URL.class, URL.class});
            action.setAccesssible(HOSTS_EQUAL);
            OPEN_CONNECTION = URLStreamHandler.class.getDeclaredMethod(
                    "openConnection", new Class[]{URL.class});
            action.setAccesssible(OPEN_CONNECTION);
            SAME_FILE = URLStreamHandler.class.getDeclaredMethod(
                    "sameFile", new Class[]{URL.class, URL.class});
            action.setAccesssible(SAME_FILE);
            TO_EXTERNAL_FORM = URLStreamHandler.class.getDeclaredMethod(
                   "toExternalForm", new Class[]{URL.class});
            action.setAccesssible(TO_EXTERNAL_FORM);
        }
        catch (Exception ex)
        {
            throw new RuntimeException(ex.getMessage(), ex);
        }

        Method open_connection_proxy = null;
        Class[] url_proxy_class = null;
        try
        {
        	url_proxy_class = new Class[]{URL.class, java.net.Proxy.class};
            open_connection_proxy = URLStreamHandler.class.getDeclaredMethod(
                "openConnection", url_proxy_class);
            action.setAccesssible(open_connection_proxy);
        }
        catch (Throwable ex)
        {
           open_connection_proxy = null;
           url_proxy_class = null;
        }
        OPEN_CONNECTION_PROXY = open_connection_proxy;
        URL_PROXY_CLASS = url_proxy_class;
    }

    private final Object m_service;
    private final SecureAction m_action;
    private final URLStreamHandler m_builtIn;
    private final URL m_builtInURL;
    private final String m_protocol;

    public URLHandlersStreamHandlerProxy(String protocol,
        SecureAction action, URLStreamHandler builtIn, URL builtInURL)
    {
        m_protocol = protocol;
        m_service = null;
        m_action = action;
        m_builtIn = builtIn;
        m_builtInURL = builtInURL;
    }

    private URLHandlersStreamHandlerProxy(Object service, SecureAction action)
    {
        m_protocol = null;
        m_service = service;
        m_action = action;
        m_builtIn = null;
        m_builtInURL = null;
    }

    //
    // URLStreamHandler interface methods.
    //
    protected boolean equals(URL url1, URL url2)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url1.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).equals(url1, url2);
        }
        try
        {
            return ((Boolean) EQUALS.invoke(svc, new Object[]{url1, url2})).booleanValue();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected int getDefaultPort()
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException("Stream handler unavailable.");
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).getDefaultPort();
        }
        try
        {
            return ((Integer) GET_DEFAULT_PORT.invoke(svc, null)).intValue();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected InetAddress getHostAddress(URL url)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).getHostAddress(url);
        }
        try
        {
            return (InetAddress) GET_HOST_ADDRESS.invoke(svc, new Object[]{url});
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected int hashCode(URL url)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).hashCode(url);
        }
        try
        {
            return ((Integer) HASH_CODE.invoke(svc, new Object[]{url})).intValue();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected boolean hostsEqual(URL url1, URL url2)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url1.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).hostsEqual(url1, url2);
        }
        try
        {
            return ((Boolean) HOSTS_EQUAL.invoke(svc, new Object[]{url1, url2})).booleanValue();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected URLConnection openConnection(URL url) throws IOException
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new MalformedURLException("Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).openConnection(url);
        }
        try
        {
            if ("http".equals(url.getProtocol()) &&
                "felix.extensions".equals(url.getHost()) &&
                9 == url.getPort())
            {
                try
                {
                    Object handler =  m_action.getDeclaredField(
                        ExtensionManager.class, "m_extensionManager", null);

                    if (handler != null)
                    {
                        return (URLConnection) m_action.invoke(
                            m_action.getMethod(handler.getClass(),
                            "openConnection", new Class[]{URL.class}), handler,
                            new Object[]{url});
                    }

                    throw new IOException("Extensions not supported or ambiguous context.");
                }
                catch (IOException ex)
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    throw new IOException(ex.getMessage());
                }
            }
            return (URLConnection) OPEN_CONNECTION.invoke(svc, new Object[]{url});
        }
        catch (IOException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    protected URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new MalformedURLException("Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            Method method;
            try
            {
                method = svc.getClass().getMethod("openConnection", URL_PROXY_CLASS);
            }
            catch (NoSuchMethodException e)
            {
                RuntimeException rte = new UnsupportedOperationException(e.getMessage());
                rte.initCause(e);
                throw rte;
            }
            try
            {
                m_action.setAccesssible(method);
                return (URLConnection) method.invoke(svc, new Object[]{url, proxy});
            }
            catch (Exception e)
            {
                if (e instanceof IOException)
                {
                    throw (IOException) e;
                }
                throw new IOException(e.getMessage(), e);
            }
        }
        try
        {
            return (URLConnection) OPEN_CONNECTION_PROXY.invoke(svc, new Object[]{url, proxy});
        }
        catch (Exception ex)
        {
            if (ex instanceof IOException)
            {
                throw (IOException) ex;
            }
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    // We use this thread local to detect whether we have a reentrant entry to the parseURL
    // method. This can happen do to some difference between gnu/classpath and sun jvms
    // For more see inside the method.
    private static final ThreadLocal m_loopCheck = new ThreadLocal();
    protected void parseURL(URL url, String spec, int start, int limit)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            ((URLStreamHandlerService) svc).parseURL(this, url, spec, start, limit);
        }
        else
        {
            try
            {
                URL test = null;
                // In order to cater for built-in urls being over-writable we need to use a
                // somewhat strange hack. We use a hidden feature inside the jdk which passes
                // the handler of the url given as a context to a new URL to that URL as its
                // handler. This way, we can create a new URL which will use the given built-in
                // handler to parse the url. Subsequently, we can use the information from that
                // URL to call set with the correct values.
                if (m_builtInURL != null)
                {
                    // However, if we are on gnu/classpath we have to pass the handler directly
                    // because the hidden feature is not there. Funnily, the workaround to pass
                    // pass the handler directly doesn't work on sun as their handler detects
                    // that it is not the same as the one inside the url and throws an exception
                    // Luckily it doesn't do that on gnu/classpath. We detect that we need to
                    // pass the handler directly by using the m_loopCheck thread local to detect
                    // that we parseURL has been called inside a call to parseURL.
                    if (m_loopCheck.get() != null)
                    {
                        test = new URL(new URL(m_builtInURL, url.toExternalForm()), spec, (URLStreamHandler) svc);
                    }
                    else
                    {
                        // Set-up the thread local as we don't expect to be called again until we are
                        // done. Otherwise, we are on gnu/classpath
                        m_loopCheck.set(Thread.currentThread());
                        try
                        {
                            test = new URL(new URL(m_builtInURL, url.toExternalForm()), spec);
                        }
                        finally
                        {
                            m_loopCheck.set(null);
                        }
                    }
                }
                else
                {
                    // We don't have a url with a built-in handler for this but still want to create
                    // the url with the buil-in handler as we could find one now. This might not
                    // work for all handlers on sun but it is better then doing nothing.
                    test = m_action.createURL(url, spec, (URLStreamHandler) svc);
                }

                super.setURL(url, test.getProtocol(), test.getHost(), test.getPort(),test.getAuthority(),
                    test.getUserInfo(), test.getPath(), test.getQuery(), test.getRef());
            }
            catch (Exception ex)
            {
                throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
            }
        }
    }

    protected boolean sameFile(URL url1, URL url2)
    {
        Object svc = getStreamHandlerService();
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url1.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).sameFile(url1, url2);
        }
        try
        {
            return ((Boolean) SAME_FILE.invoke(
                svc, new Object[]{url1, url2})).booleanValue();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    public void setURL(
        URL url, String protocol, String host, int port, String authority,
        String userInfo, String path, String query, String ref)
    {
        super.setURL(url, protocol, host, port, authority, userInfo, path, query, ref);
    }

    public void setURL(
        URL url, String protocol, String host, int port, String file, String ref)
    {
        super.setURL(url, protocol, host, port, file, ref);
    }

    protected String toExternalForm(URL url)
    {
        return toExternalForm(url, getStreamHandlerService());
    }

    private String toExternalForm(URL url, Object svc)
    {
        if (svc == null)
        {
            throw new IllegalStateException(
                "Unknown protocol: " + url.getProtocol());
        }
        if (svc instanceof URLStreamHandlerService)
        {
            return ((URLStreamHandlerService) svc).toExternalForm(url);
        }
        try
        {
            try
            {
                String result = (String) TO_EXTERNAL_FORM.invoke(
                    svc, new Object[]{url});

                // mika does return an invalid format if we have a url with the
                // protocol only (<proto>://null) - we catch this case now
                if ((result != null) && (result.equals(url.getProtocol() + "://null")))
                {
                    result = url.getProtocol() + ":";
                }

                return result;
            }
            catch (InvocationTargetException ex)
            {
               Throwable t = ex.getTargetException();
               if (t instanceof Exception)
               {
                   throw (Exception) t;
               }
               else if (t instanceof Error)
               {
                   throw (Error) t;
               }
               else
               {
                   throw new IllegalStateException("Unknown throwable: " + t, t);
               }
            }
        }
        catch (NullPointerException ex)
        {
            // workaround for harmony and possibly J9. The issue is that
            // their implementation of URLStreamHandler.toExternalForm()
            // assumes that URL.getFile() doesn't return null but in our
            // case it can -- hence, we catch the NPE and do the work
            // ourselvs. The only difference is that we check whether the
            // URL.getFile() is null or not.
            StringBuilder answer = new StringBuilder();
            answer.append(url.getProtocol());
            answer.append(':');
            String authority = url.getAuthority();
            if ((authority != null) && (authority.length() > 0))
            {
                answer.append("//"); //$NON-NLS-1$
                answer.append(url.getAuthority());
            }

            String file = url.getFile();
            String ref = url.getRef();
            if (file != null)
            {
                answer.append(file);
            }
            if (ref != null)
            {
                answer.append('#');
                answer.append(ref);
            }
            return answer.toString();
        }
        catch (Exception ex)
        {
            throw new IllegalStateException("Stream handler unavailable due to: " + ex.getMessage(), ex);
        }
    }

    /**
     * <p>
     * Private method to retrieve the stream handler service from the
     * framework instance associated with the current call stack. A
     * simple service tracker is created and cached for the associated
     * framework instance when this method is called.
     * </p>
     * @return the stream handler service from the framework instance
     *         associated with the current call stack or <tt>null</tt>
     *         is no service is available.
    **/
    private Object getStreamHandlerService()
    {
        try
        {
            // Get the framework instance associated with call stack.
            Object framework = URLHandlers.getFrameworkFromContext();

            if (framework == null)
            {
                return m_builtIn;
            }


            Object service;
            if (framework instanceof Felix)
            {
                service = ((Felix) framework).getStreamHandlerService(m_protocol);
            }
            else
            {
                service = m_action.invoke(
                    m_action.getDeclaredMethod(framework.getClass(), "getStreamHandlerService", STRING_TYPES),
                    framework, new Object[]{m_protocol});
            }

            if (service == null)
            {
                return m_builtIn;
            }
            if (service instanceof URLStreamHandlerService)
            {
                return (URLStreamHandlerService) service;
            }
            
            return m_action.createProxy(
                    m_action.getClassLoader(URLStreamHandlerService.class), 
                    new Class[]{URLStreamHandlerService.class},
                    new URLHandlersStreamHandlerProxy(service, m_action));
        }
        catch (ThreadDeath td)
        {
            throw td;
        }
        catch (Throwable t)
        {
            // In case that we are inside tomcat - the problem is that the webapp classloader
            // creates a new url to load a class. This gets us to this method. Now, if we
            // trigger a classload while executing, tomcat is creating a new url and we end-up with
            // a loop which is cut short after two iterations (because of a circularclassload).
            // We catch this exception (and all others) and just return the built-in handler
            // (if we have any) as this way we at least eventually get started (this just means
            // that we don't use the potentially provided built-in handler overwrite).
            return m_builtIn;
        }
    }

    public Object invoke(Object obj, Method method, Object[] params)
        throws Throwable
    {
        Class[] types = method.getParameterTypes();
        if (m_service == null)
        {
            return m_action.invoke(m_action.getMethod(this.getClass(), method.getName(), types), this, params);
        }
        if ("parseURL".equals(method.getName()))
        {
            ClassLoader loader = m_action.getClassLoader(m_service.getClass());
            types[0] = loader.loadClass(URLStreamHandlerSetter.class.getName());
            params[0] = m_action.createProxy(loader, new Class[]{types[0]}, 
                    (URLHandlersStreamHandlerProxy) params[0]);
        }
        return m_action.invokeDirect(m_action.getDeclaredMethod(m_service.getClass(),
            method.getName(), types), m_service, params);
    }
}
