/*
 * 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.scr.impl.inject.methods;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Map;

import org.apache.felix.scr.impl.inject.BaseParameter;
import org.apache.felix.scr.impl.inject.MethodResult;
import org.apache.felix.scr.impl.inject.internal.ClassUtils;
import org.apache.felix.scr.impl.logger.ComponentLogger;
import org.apache.felix.scr.impl.metadata.DSVersion;
import org.osgi.service.log.LogService;


/**
 * Component method to be invoked on service (un)binding.
 */
public abstract class BaseMethod<P extends BaseParameter, T>
{

    private final DSVersion dsVersion;
    private final boolean configurableServiceProperties;

    private final String m_methodName;
    private final Class<?> m_componentClass;

    private volatile Method m_method;

    private final boolean m_methodRequired;

    private volatile State m_state;

    protected BaseMethod( final String methodName,
            final boolean methodRequired,
            final Class<?> componentClass,
            final DSVersion dsVersion,
            final boolean configurableServiceProperties )
    {
        m_methodName = methodName;
        m_methodRequired = methodRequired;
        m_componentClass = componentClass;
        this.dsVersion = dsVersion;
        this.configurableServiceProperties = configurableServiceProperties;
        if ( m_methodName == null )
        {
            m_state = NotApplicable.INSTANCE;
        }
        else
        {
            m_state = NotResolved.INSTANCE;
        }
    }

    protected final DSVersion getDSVersion()
    {
        return dsVersion;
    }


    protected final boolean isDS12Felix()
    {
        return configurableServiceProperties;
    }


    protected final String getMethodName()
    {
        return m_methodName;
    }

    final Method getMethod()
    {
        return m_method;
    }

    protected final Class<?> getComponentClass()
    {
        return m_componentClass;
    }

    protected abstract void setTypes(T types);

    synchronized void setMethod(MethodInfo<T> methodInfo, ComponentLogger logger)
    {
        this.m_method = methodInfo == null ? null : methodInfo.getMethod();

        if (m_method != null)
        {
            setTypes(methodInfo.getTypes());
            m_state = Resolved.INSTANCE;
            logger.log( LogService.LOG_DEBUG, "Found {0} method: {1}", null,
                    getMethodNamePrefix(), m_method );
        }
        else if ( m_methodRequired )
        {
            m_state = NotFound.INSTANCE;
            logger.log(LogService.LOG_ERROR, "{0} method [{1}] not found; Component will fail",
                    null,
                    getMethodNamePrefix(), getMethodName());
        }
        else
        {
            // optional method not found, log as DEBUG and ignore
            logger.log( LogService.LOG_DEBUG, "{0} method [{1}] not found, ignoring", null,
                    getMethodNamePrefix(), getMethodName() );
            m_state = NotApplicable.INSTANCE;
        }
    }


    State getState()
    {
        return m_state;
    }


    /**
     * Finds the method named in the {@link #m_methodName} field in the given
     * <code>targetClass</code>. If the target class has no acceptable method
     * the class hierarchy is traversed until a method is found or the root
     * of the class hierarchy is reached without finding a method.
     *
     * @return The requested method or <code>null</code> if no acceptable method
     *      can be found in the target class or any super class.
     * @throws InvocationTargetException If an unexpected Throwable is caught
     *      trying to find the requested method.
     * @param logger
     */
    private MethodInfo<T> findMethod(final ComponentLogger logger) throws InvocationTargetException
    {
        boolean acceptPrivate = getDSVersion().isDS11();
        boolean acceptPackage = getDSVersion().isDS11();

        final Class<?> targetClass = getComponentClass();
        final ClassLoader targetClasslLoader = targetClass.getClassLoader();
        final String targetPackage = getPackageName( targetClass );
        Class<?> theClass = targetClass;

        while (true)
        {

            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
            {
                logger.log( LogService.LOG_DEBUG,
                        "Locating method " + getMethodName() + " in class " + theClass.getName(), null );
            }

            try
            {
                MethodInfo<T> method = doFindMethod(theClass, acceptPrivate,
                    acceptPackage,
                    logger);
                if ( method != null )
                {
                    return method;
                }
            }
            catch ( SuitableMethodNotAccessibleException ex )
            {
                // log and return null
                logger.log( LogService.LOG_ERROR,
                        "findMethod: Suitable but non-accessible method {0} found in class {1}, subclass of {2}", null,
                                getMethodName(), theClass.getName(), targetClass.getName() );
                break;
            }

            // if we get here, we have no method, so check the super class
            theClass = theClass.getSuperclass();
            if ( theClass == null )
            {
                break;
            }

            // super class method check ignores private methods and accepts
            // package methods only if in the same package and package
            // methods are (still) allowed
            acceptPackage &= targetClasslLoader == theClass.getClassLoader()
                    && targetPackage.equals( getPackageName( theClass ) );

            // private methods will not be accepted any more in super classes
            acceptPrivate = false;
        }

        // nothing found after all these years ...
        return null;
    }


    protected abstract MethodInfo<T> doFindMethod(Class<?> targetClass,
        boolean acceptPrivate,
        boolean acceptPackage,
        ComponentLogger logger ) throws SuitableMethodNotAccessibleException, InvocationTargetException;


    private String[] getParametersForLogging(final Object[] params) {
        if (params == null) {
            return null;
        }
        final String[] result = new String[params.length];
        for (int i = 0; i < params.length; i++) {
            result[i] = (params[i] == null ? null : params[i].getClass().getName());
        }
        return result;
    }

    private MethodResult invokeMethod(final Object componentInstance, final P rawParameter )
            throws InvocationTargetException
    {
        final ComponentLogger logger = rawParameter.getComponentContext().getLogger();
        try
        {
            if ( componentInstance != null )
            {
                final Object[] params = getParameters(m_method, rawParameter);
                if (logger.isLogEnabled(LogService.LOG_DEBUG)) {
                    logger.log(LogService.LOG_DEBUG, "invoking {0}: {1}: parameters {2}", null, getMethodNamePrefix(),
                            getMethodName(), Arrays.asList(getParametersForLogging(params)));
                }
                final Object result = m_method.invoke(componentInstance, params);
                logger.log(LogService.LOG_DEBUG, "invoked {0}: {1}", null,
                        getMethodNamePrefix(), getMethodName() );
                return new MethodResult((m_method.getReturnType() != Void.TYPE), (Map<String, Object>) result);
            }
            else
            {
                rawParameter.getComponentContext().getLogger().log( LogService.LOG_WARNING, "Method {0}: {1} cannot be called on null object",
                        null,
                                getMethodNamePrefix(), getMethodName() );
            }
        }
        catch ( IllegalStateException ise )
        {
            rawParameter.getComponentContext().getLogger().log( LogService.LOG_DEBUG, ise.getMessage(), null );
            return null;
        }
        catch ( IllegalAccessException ex )
        {
            // 112.3.1 If the method is not is not declared protected or
            // public, SCR must log an error message with the log service,
            // if present, and ignore the method
            rawParameter.getComponentContext().getLogger().log( LogService.LOG_DEBUG, "Method {0} cannot be called", ex,
                    getMethodName() );
        }
        catch ( InvocationTargetException ex )
        {
            throw ex;
        }
        catch ( Throwable t )
        {
            throw new InvocationTargetException( t );
        }

        // assume success (also if the method is not available or accessible)
        return MethodResult.VOID;
    }

    protected boolean returnValue()
    {
        // allow returning Map if declared as DS 1.2-Felix or newer
        return isDS12Felix();
    }

    /**
     * Returns the parameter array created from the <code>rawParameter</code>
     * using the actual parameter type list of the <code>method</code>.
     * @param method
     * @param rawParameter
     * @return
     * @throws IllegalStateException If the required parameters cannot be
     *      extracted from the <code>rawParameter</code>
     */
    protected abstract Object[] getParameters( Method method, P rawParameter );


    protected String getMethodNamePrefix()
    {
        return "";
    }


    //---------- Helpers

    /**
     * Finds the named public or protected method in the given class or any
     * super class. If such a method is found, its accessibility is enfored by
     * calling the <code>Method.setAccessible</code> method if required and
     * the method is returned. Enforcing accessibility is required to support
     * invocation of protected methods.
     *
     *
     * @param clazz The <code>Class</code> which provides the method.
     * @param name The name of the method.
     * @param parameterTypes The parameters to the method. Passing
     *      <code>null</code> is equivalent to using an empty array.
     *
     * @param logger
     * @return The named method with enforced accessibility or <code>null</code>
     *      if no such method exists in the class.
     *
     * @throws SuitableMethodNotAccessibleException If method with the given
     *      name taking the parameters is found in the class but the method
     *      is not accessible.
     * @throws InvocationTargetException If an unexpected Throwable is caught
     *      trying to access the desired method.
     */
    public /* static */ Method getMethod( Class<?> clazz,
            String name,
            Class[] parameterTypes,
            boolean acceptPrivate,
            boolean acceptPackage,
            ComponentLogger logger ) throws SuitableMethodNotAccessibleException,
    InvocationTargetException
    {
        try
        {
            // find the declared method in this class
            Method method = clazz.getDeclaredMethod( name, parameterTypes );

            // accept public and protected methods only and ensure accessibility
            if ( accept( method, acceptPrivate, acceptPackage, returnValue() ) )
            {
                return method;
            }

            // the method would fit the requirements but is not acceptable
            throw new SuitableMethodNotAccessibleException();
        }
        catch ( NoSuchMethodException nsme )
        {
            // thrown if no method is declared with the given name and
            // parameters
            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
            {
                String argList = ( parameterTypes != null ) ? Arrays.asList( parameterTypes ).toString() : "";
                logger.log( LogService.LOG_DEBUG, "Declared Method {0}.{1}({2}) not found", null,
                        clazz.getName(), name, argList );
            }
        }
        catch ( NoClassDefFoundError cdfe )
        {
            // may be thrown if a method would be found but the signature
            // contains throws declaration for an exception which cannot
            // be loaded
            if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
            {
                StringBuilder buf = new StringBuilder();
                buf.append( "Failure loooking up method " ).append( name ).append( '(' );
                for ( int i = 0; parameterTypes != null && i < parameterTypes.length; i++ )
                {
                    buf.append( parameterTypes[i].getName() );
                    if ( i > 0 )
                    {
                        buf.append( ", " );
                    }
                }
                buf.append( ") in class class " ).append( clazz.getName() ).append( ". Assuming no such method." );
                logger.log( LogService.LOG_WARNING, buf.toString(), cdfe );
            }
        }
        catch ( SuitableMethodNotAccessibleException e)
        {
            throw e;
        }
        catch ( Throwable throwable )
        {
            // unexpected problem accessing the method, don't let everything
            // blow up in this situation, just throw a declared exception
            throw new InvocationTargetException( throwable, "Unexpected problem trying to get method " + name );
        }

        // caught and ignored exception, assume no method and continue search
        return null;
    }


    /**
     * Returns <code>true</code> if the method is acceptable to be returned from the
     * {@link #getMethod(Class, String, Class[], boolean, boolean, ComponentLogger)} and also
     * makes the method accessible.
     * <p>
     * This method returns <code>true</code> iff:
     * <ul>
     * <li>The method has <code>void</code> return type</li>
     * <li>Is not static</li>
     * <li>Is public or protected</li>
     * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
     * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
     * </ul>
     * <p>
     * This method is package private for unit testing purposes. It is not
     * meant to be called from client code.
     *
     *
     * @param method The method to check
     * @param acceptPrivate Whether a private method is acceptable
     * @param acceptPackage Whether a package private method is acceptable
     * @param allowReturnValue whether the method can return a value (to update service registration properties)
     * @return whether the method is acceptable
     */
    protected static boolean accept( final Method method, boolean acceptPrivate, boolean acceptPackage, boolean allowReturnValue )
    {
        if (!(Void.TYPE == method.getReturnType() || (ClassUtils.MAP_CLASS == method.getReturnType() && allowReturnValue)))
        {
            return false;
        }

        // check modifiers now
        int mod = method.getModifiers();

        // no static method
        if ( Modifier.isStatic( mod ) )
        {
            return false;
        }

        // accept public and protected methods
        if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) )
        {
            setAccessible( method );
            return true;
        }

        // accept private if accepted
        if ( Modifier.isPrivate( mod ) )
        {
            if ( acceptPrivate )
            {
                setAccessible( method );
                return true;
            }

            return false;
        }

        // accept default (package)
        if ( acceptPackage )
        {
            setAccessible( method );
            return true;
        }

        // else don't accept
        return false;
    }


    private static void setAccessible(final Method method)
    {
        AccessController.doPrivileged( new PrivilegedAction<Object>()
        {
            @Override
            public Object run()
            {
                method.setAccessible( true );
                return null;
            }
        } );
    }


    /**
     * Returns the name of the package to which the class belongs or an
     * empty string if the class is in the default package.
     */
    public static String getPackageName( Class<?> clazz )
    {
        String name = clazz.getName();
        int dot = name.lastIndexOf( '.' );
        return ( dot > 0 ) ? name.substring( 0, dot ) : "";
    }


    //---------- State management  ------------------------------------

    /**
     * Calls the declared method on the given component with the provided
     * method call arguments.
     *
     *
     *
     *
     * @param componentInstance The component instance on which to call the
     *      method
     * @param rawParameter The parameter container providing the actual
     *      parameters to provide to the called method
     * @param methodCallFailureResult The result to return from this method if
     *      calling the method resulted in an exception.
     *
     * @param logger
     * @return <code>true</code> if the method was called successfully or the
     *      method was not found and was not required. <code>false</code> if
     *      the method was not found but required.
     *      <code>methodCallFailureResult</code> is returned if the method was
     *      found and called, but the method threw an exception.
     */
    public MethodResult invoke( final Object componentInstance, final P rawParameter,
            final MethodResult methodCallFailureResult )
    {
        try
        {
            return m_state.invoke( this, componentInstance, rawParameter );
        }
        catch ( InvocationTargetException ite )
        {
            rawParameter.getComponentContext().getLogger().log( LogService.LOG_ERROR, "The {0} method has thrown an exception", ite.getCause(),
                    getMethodName() );
            if ( methodCallFailureResult != null && methodCallFailureResult.getResult() != null )
            {
                methodCallFailureResult.getResult().put("exception", ite.getCause());
            }
        }

        return methodCallFailureResult;
    }


    public boolean methodExists( ComponentLogger logger )
    {
        return m_state.methodExists( this, logger );
    }

    protected static final class MethodInfo<T>
    {
        private final Method m_method;
        private final T m_types;

        public MethodInfo(Method m)
        {
            this(m, null);
        }

        public MethodInfo(Method m, T types)
        {
            m_method = m;
            m_types = types;
        }

        public Method getMethod()
        {
            return m_method;
        }

        public T getTypes()
        {
            return m_types;
        }
    }

    private static interface State
    {

        <P extends BaseParameter, T> MethodResult invoke( BaseMethod<P, T> baseMethod, Object componentInstance, P rawParameter )
                throws InvocationTargetException;


        <P extends BaseParameter, T> boolean methodExists( BaseMethod<P, T> baseMethod, ComponentLogger logger );
    }

    private static class NotApplicable implements State
    {

        private static final State INSTANCE = new NotApplicable();


        @Override
        public <P extends BaseParameter, T> MethodResult invoke( final BaseMethod<P, T> baseMethod, final Object componentInstance, final P rawParameter )
        {
            return MethodResult.VOID;
        }


        @Override
        public <P extends BaseParameter, T> boolean methodExists( final BaseMethod<P, T> baseMethod, ComponentLogger logger )
        {
            return true;
        }
    }

    private static class NotResolved implements State
    {
        private static final State INSTANCE = new NotResolved();


        private <P extends BaseParameter, T> void resolve( final BaseMethod<P, T> baseMethod, ComponentLogger logger )
        {
            logger.log( LogService.LOG_DEBUG, "getting {0}: {1}", null,
                    baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() );

            // resolve the method
            MethodInfo<T> method = null;
            try
            {
                method = baseMethod.findMethod( logger );
            }
            catch ( InvocationTargetException ex )
            {
                logger.log( LogService.LOG_WARNING, "{0} cannot be found", ex.getTargetException(),
                        baseMethod.getMethodName() );
            }

            baseMethod.setMethod( method, logger );
        }


        @Override
        public <P extends BaseParameter, T> MethodResult invoke( final BaseMethod<P, T> baseMethod, final Object componentInstance, final P rawParameter )
                throws InvocationTargetException
        {
            resolve( baseMethod, rawParameter.getComponentContext().getLogger() );
            return baseMethod.getState().invoke( baseMethod, componentInstance, rawParameter );
        }


        @Override
        public <P extends BaseParameter, T> boolean methodExists( final BaseMethod<P, T> baseMethod, ComponentLogger logger )
        {
            resolve( baseMethod, logger );
            return baseMethod.getState().methodExists( baseMethod, logger );
        }
    }

    private static class NotFound implements State
    {
        private static final State INSTANCE = new NotFound();


        @Override
        public <P extends BaseParameter, T> MethodResult invoke( final BaseMethod<P, T> baseMethod, final Object componentInstance, final P rawParameter )
        {
            // 112.3.1 If the method is not found , SCR must log an error
            // message with the log service, if present, and ignore the
            // method
            rawParameter.getComponentContext().getLogger().log( LogService.LOG_ERROR, "{0} method [{1}] not found", null,
                    baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() );
            return null;
        }


        @Override
        public <P extends BaseParameter, T> boolean methodExists( final BaseMethod<P, T> baseMethod, ComponentLogger logger )
        {
            return false;
        }
    }

    private static class Resolved implements State
    {
        private static final State INSTANCE = new Resolved();


        @Override
        public <P extends BaseParameter, T> MethodResult invoke( final BaseMethod<P, T> baseMethod, final Object componentInstance, final P rawParameter )
                throws InvocationTargetException
        {
            return baseMethod.invokeMethod( componentInstance, rawParameter );
        }


        @Override
        public <P extends BaseParameter, T> boolean methodExists( final BaseMethod<P, T> baseMethod, ComponentLogger logger )
        {
            return true;
        }
    }
}
