/*
 * 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 flex.messaging.services.remoting.adapters;

import flex.management.runtime.messaging.services.remoting.adapters.JavaAdapterControl;
import flex.messaging.FlexComponent;
import flex.messaging.Destination;
import flex.messaging.FactoryInstance;
import flex.messaging.FlexFactory;
import flex.messaging.MessageException;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.ConfigurationConstants;
import flex.messaging.config.ConfigurationException;
import flex.messaging.config.SecurityConstraint;
import flex.messaging.messages.Message;
import flex.messaging.messages.RemotingMessage;
import flex.messaging.security.SecurityException;
import flex.messaging.services.ServiceAdapter;
import flex.messaging.services.remoting.RemotingDestination;
import flex.messaging.util.MethodMatcher;
import flex.messaging.util.MethodMatcher.Match;
import flex.messaging.util.ExceptionUtil;
import flex.messaging.util.StringUtils;

import flex.messaging.log.LogCategories;
import flex.messaging.log.Log;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class JavaAdapter extends ServiceAdapter {
    static final String LOG_CATEGORY = LogCategories.MESSAGE_REMOTING;

    public static final String[] PROTECTED_PACKAGES = new String[]{"jrun", "jrunx", "macromedia",
            "flex", "flex2", "coldfusion",
            "allaire", "com.allaire", "com.macromedia"};

    private static final int REMOTING_METHOD_NULL_NAME_ERRMSG = 10658;
    private static final int REMOTING_METHOD_REFS_UNDEFINED_CONSTRAINT_ERRMSG = 10659;
    private static final int REMOTING_METHOD_NOT_DEFINED_ERRMSG = 10660;

    private static final String PROPERTY_INCLUDE_METHODS = "include-methods";
    private static final String PROPERTY_EXCLUDE_METHODS = "exclude-methods";
    private static final String METHOD_ELEMENT = "method";
    private static final String NAME_ELEMENT = "name";

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs an unmanaged <code>JavaAdapter</code> instance.
     */
    public JavaAdapter() {
        this(false);
    }

    /**
     * Constructs a <code>JavaAdapter</code> instance.
     *
     * @param enableManagement <code>true</code> if the <code>JavaAdapter</code> has a
     *                         corresponding MBean control for management; otherwise <code>false</code>.
     */
    public JavaAdapter(boolean enableManagement) {
        super(enableManagement);
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * The MBean control for this adapter.
     */
    private JavaAdapterControl controller;

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  destination
    //----------------------------------

    /**
     * Casts the <code>Destination</code> into <code>RemotingDestination</code>
     * and calls super.setDestination.
     *
     * @param destination remoting destination to associate with this adapter
     */
    @Override
    public void setDestination(Destination destination) {
        Destination dest = (RemotingDestination) destination;
        super.setDestination(dest);
    }

    //----------------------------------
    //  excludeMethods
    //----------------------------------

    private Map excludeMethods;

    /**
     * Returns an <tt>Iterator</tt> over the currently registered exclude methods.
     *
     * @return an <tt>Iterator</tt> over the currently registered exclude methods
     */
    public Iterator getExcludeMethodIterator() {
        return excludeMethods == null ? Collections.EMPTY_LIST.iterator() : excludeMethods.values().iterator();
    }

    /**
     * Adds a method to the list of excluded methods for the adapter.
     * Invocations of excluded methods are blocked.
     *
     * @param value method to exclude
     */
    public void addExcludeMethod(RemotingMethod value) {
        String name = value.getName();
        if (name == null) {
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(REMOTING_METHOD_NULL_NAME_ERRMSG, new Object[]{getDestination().getId()});
            throw ce;
        }

        // Validate that a method with this name is defined on the source class.
        if (!isMethodDefinedBySource(name)) {
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(REMOTING_METHOD_NOT_DEFINED_ERRMSG, new Object[]{name, getDestination().getId()});
            throw ce;
        }

        if (excludeMethods == null) {
            excludeMethods = new HashMap();
            excludeMethods.put(name, value);
        } else if (!excludeMethods.containsKey(name)) {
            excludeMethods.put(name, value);
        }
    }

    /**
     * Removes a method from the list of excluded methods for the adapter.
     *
     * @param value method to remove from exlcuded methods list
     */
    public void removeExcludeMethod(RemotingMethod value) {
        excludeMethods.remove(value.getName());
    }

    //----------------------------------
    //  includeMethods
    //----------------------------------

    private Map includeMethods;

    /**
     * Returns an <tt>Iterator</tt> over the currently registered include methods.
     *
     * @return an <tt>Iterator</tt> over the currently registered include methods
     */
    public Iterator getIncludeMethodIterator() {
        return includeMethods == null ? Collections.EMPTY_LIST.iterator() : includeMethods.values().iterator();
    }

    /**
     * Adds a method to the list of included methods for the adapter.
     * Invocations of included methods are allowed, and invocations of any non-included methods will be blocked.
     *
     * @param value method to include
     */
    public void addIncludeMethod(RemotingMethod value) {
        String name = value.getName();
        if (name == null) {
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(REMOTING_METHOD_NULL_NAME_ERRMSG, new Object[]{getDestination().getId()});
            throw ce;
        }

        // Validate that a method with this name is defined on the source class.
        if (!isMethodDefinedBySource(name)) {
            ConfigurationException ce = new ConfigurationException();
            ce.setMessage(REMOTING_METHOD_NOT_DEFINED_ERRMSG, new Object[]{name, getDestination().getId()});
            throw ce;
        }

        if (includeMethods == null) {
            includeMethods = new HashMap();
            includeMethods.put(name, value);
        } else if (!includeMethods.containsKey(name)) {
            includeMethods.put(name, value);
        }
    }

    /**
     * Removes a method from the list of included methods for the adapter.
     *
     * @param value method to remove from the included methods list
     */
    public void removeIncludeMethod(RemotingMethod value) {
        includeMethods.remove(value.getName());
    }

    //--------------------------------------------------------------------------
    //
    // Initialize, validate, start, and stop methods.
    //
    //--------------------------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    @Override
    public void initialize(String id, ConfigMap properties) {
        ConfigMap methodsToInclude = properties.getPropertyAsMap(PROPERTY_INCLUDE_METHODS, null);
        if (methodsToInclude != null) {
            List methods = methodsToInclude.getPropertyAsList(METHOD_ELEMENT, null);
            if ((methods != null) && !methods.isEmpty()) {
                int n = methods.size();
                for (int i = 0; i < n; i++) {
                    ConfigMap methodSettings = (ConfigMap) methods.get(i);
                    String name = methodSettings.getPropertyAsString(NAME_ELEMENT, null);
                    RemotingMethod method = new RemotingMethod();
                    method.setName(name);
                    // Check for security constraint.
                    String constraintRef = methodSettings.getPropertyAsString(ConfigurationConstants.SECURITY_CONSTRAINT_ELEMENT, null);
                    if (constraintRef != null) {
                        try {
                            method.setSecurityConstraint(getDestination().getService().getMessageBroker().getSecurityConstraint(constraintRef));
                        } catch (SecurityException se) {
                            // Rethrow with a more descriptive message.
                            ConfigurationException ce = new ConfigurationException();
                            ce.setMessage(REMOTING_METHOD_REFS_UNDEFINED_CONSTRAINT_ERRMSG, new Object[]{name, getDestination().getId(), constraintRef});
                            throw ce;
                        }
                    }
                    addIncludeMethod(method);
                }
            }
        }
        ConfigMap methodsToExclude = properties.getPropertyAsMap(PROPERTY_EXCLUDE_METHODS, null);
        if (methodsToExclude != null) {
            // Warn that <exclude-properties> will be ignored.
            if (includeMethods != null) {
                RemotingDestination dest = (RemotingDestination) getDestination();
                if (Log.isWarn())
                    Log.getLogger(LogCategories.CONFIGURATION).warn("The remoting destination '" + dest.getId() + "' contains both <include-methods/> and <exclude-methods/> configuration. The <exclude-methods/> block will be ignored.");
            }
            // Excludes must be processed regardless of whether we add them or not to avoid 'Unused tags in <properties>' exceptions.
            List methods = methodsToExclude.getPropertyAsList(METHOD_ELEMENT, null);
            if ((methods != null) && !methods.isEmpty()) {
                int n = methods.size();
                for (int i = 0; i < n; i++) {
                    ConfigMap methodSettings = (ConfigMap) methods.get(i);
                    String name = methodSettings.getPropertyAsString(NAME_ELEMENT, null);
                    RemotingMethod method = new RemotingMethod();
                    method.setName(name);
                    // Check for security constraint.
                    String constraintRef = methodSettings.getPropertyAsString(ConfigurationConstants.SECURITY_CONSTRAINT_ELEMENT, null);
                    // Conditionally add, only if include methods are not defined.
                    if (includeMethods == null) {
                        if (constraintRef != null) {
                            RemotingDestination dest = (RemotingDestination) getDestination();
                            if (Log.isWarn())
                                Log.getLogger(LogCategories.CONFIGURATION).warn("The method '" + name + "' for remoting destination '" + dest.getId() + "' is configured to use a security constraint, but security constraints are not applicable for excluded methods.");
                        }
                        addExcludeMethod(method);
                    }
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void start() {
        if (isStarted()) {
            return;
        }
        super.start();
        validateInstanceSettings();

        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        if (FlexFactory.SCOPE_APPLICATION.equals(remotingDestination.getScope())) {
            FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();
            createInstance(factoryInstance.getInstanceClass());
        }
    }

    //--------------------------------------------------------------------------
    //
    // Other public APIs
    //
    //--------------------------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    @Override
    public Object invoke(Message message) {
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        RemotingMessage remotingMessage = (RemotingMessage) message;
        FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();

        // We don't allow the client to specify the source for
        // Java based services.
        String className = factoryInstance.getSource();
        remotingMessage.setSource(className);

        String methodName = remotingMessage.getOperation();
        List parameters = remotingMessage.getParameters();
        Object result = null;

        try {
            // Test that the target method may be invoked based upon include/exclude method settings.
            validateAgainstMethodFilters(methodName);

            // Lookup and invoke.
            Object instance = createInstance(factoryInstance.getInstanceClass());
            if (instance == null) {
                MessageException me = new MessageException("Null instance returned from: " + factoryInstance);
                me.setCode("Server.Processing");
                throw me;
            }
            Class c = instance.getClass();

            MethodMatcher methodMatcher = remotingDestination.getMethodMatcher();
            Method method = methodMatcher.getMethod(c, methodName, parameters);
            result = method.invoke(instance, parameters.toArray());

            saveInstance(instance);
        } catch (InvocationTargetException ex) {
            /*
             * If the invocation exception wraps a message exception, unwrap it and
             * rethrow the nested message exception. Otherwise, build and throw a new
             * message exception.
             */
            Throwable cause = ex.getCause();
            if ((cause != null) && (cause instanceof MessageException)) {
                throw (MessageException) cause;
            } else if (cause != null) {
                // Log a warning for this client's selector and continue
                if (Log.isError()) {
                    Log.getLogger(LOG_CATEGORY).error("Error processing remote invocation: " +
                            cause.toString() + StringUtils.NEWLINE +
                            "  incomingMessage: " + message + StringUtils.NEWLINE +
                            ExceptionUtil.toString(cause));
                }
                MessageException me = new MessageException(cause.getClass().getName() + " : " + cause.getMessage());
                me.setCode("Server.Processing");
                me.setRootCause(cause);
                throw me;
            } else {
                MessageException me = new MessageException(ex.getMessage());
                me.setCode("Server.Processing");
                throw me;
            }
        } catch (IllegalAccessException ex) {
            MessageException me = new MessageException(ex.getMessage());
            me.setCode("Server.Processing");
            throw me;
        }

        return result;
    }

    //--------------------------------------------------------------------------
    //
    // Protected/private APIs
    //
    //--------------------------------------------------------------------------

    /**
     * Checks if the method is allowed to be invoked, i.e., if it has been
     * explicitly excluded, or if inclusions have been specified and it is not
     * on the inclusion list.
     *
     * @throw MessageException if method is not allowed.
     */
    protected void validateAgainstMethodFilters(String methodName) {
        if (includeMethods != null) {
            RemotingMethod method = (RemotingMethod) includeMethods.get(methodName);
            if (method == null)
                MethodMatcher.methodNotFound(methodName, null, new Match(null));

            // Check method-level security constraint, if defined.
            SecurityConstraint constraint = method.getSecurityConstraint();
            if (constraint != null)
                getDestination().getService().getMessageBroker().getLoginManager().checkConstraint(constraint);
        } else if ((excludeMethods != null) && excludeMethods.containsKey(methodName))
            MethodMatcher.methodNotFound(methodName, null, new Match(null));
    }

    /**
     * This method returns the instance of the given class.  You can override this in
     * your subclass to control how the instance is constructed.  Note that you can
     * can more general control how components are created by implementing the
     * flex.messaging.FlexFactory interface.
     *
     * @see flex.messaging.FlexFactory
     */
    protected Object createInstance(Class cl) {
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        // Note: this breaks the admin console right now as we use this to call
        // mbean methods.  Might have performance impact as well?
        //assertAccess(cl.getName());
        FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();
        Object instance = factoryInstance.lookup();
        if (isStarted() && instance instanceof FlexComponent
                && !((FlexComponent) instance).isStarted()) {
            ((FlexComponent) instance).start();
        }
        return instance;
    }

    /**
     * This method is called by the adapter after the remote method has been invoked.
     * For session scoped components, by default FlexFactory provides an
     * operationComplete method to implement this operation.  For the JavaFactory,
     * this sets the attribute in the FlexSession to trigger sesison replication
     * for this attribute.
     */
    protected void saveInstance(Object instance) {
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();
        factoryInstance.operationComplete(instance);
    }

    protected void assertAccess(String serviceClass) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // if there is a SecurityManager, check for specific access privileges on this class
            if (serviceClass.indexOf('.') != -1) {
                StringBuffer permissionData = new StringBuffer("accessClassInPackage.");
                permissionData.append(serviceClass.substring(0, serviceClass.lastIndexOf('.')));
                RuntimePermission perm = new RuntimePermission(permissionData.toString());
                AccessController.checkPermission(perm);
            }
        } else {
            // even without a SecurityManager, protect server packages
            for (int i = 0; i < PROTECTED_PACKAGES.length; i++) {
                if (serviceClass.startsWith(PROTECTED_PACKAGES[i])) {
                    StringBuffer permissionData = new StringBuffer("accessClassInPackage.");
                    permissionData.append(PROTECTED_PACKAGES[i].substring(0, PROTECTED_PACKAGES[i].length()));
                    RuntimePermission perm = new RuntimePermission(permissionData.toString());
                    AccessController.checkPermission(perm);
                }
            }
        }
    }

    protected void validateInstanceSettings() {
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        // This will validate that we have a valid factory instance and accesses
        // any constructor properties needed for our factory so they do not give
        // startup warnings.
        remotingDestination.getFactoryInstance();
    }

    /**
     * Returns the log category of the <code>JavaAdapter</code>.
     *
     * @return The log category.
     */
    @Override
    protected String getLogCategory() {
        return LOG_CATEGORY;
    }

    /**
     * Invoked automatically to allow the <code>JavaAdapter</code> to setup its corresponding
     * MBean control.
     *
     * @param broker The <code>Destination</code> that manages this <code>JavaAdapter</code>.
     */
    @Override
    protected void setupAdapterControl(Destination destination) {
        controller = new JavaAdapterControl(this, destination.getControl());
        controller.register();
        setControl(controller);
    }

    /**
     * Tests whether the backing source class for this adapter defines a method with the specified name.
     *
     * @param methodName The method name.
     * @return <code>true</code> if the method is defined; otherwise <code>false</code>.
     */
    private boolean isMethodDefinedBySource(String methodName) {
        RemotingDestination remotingDestination = (RemotingDestination) getDestination();
        FactoryInstance factoryInstance = remotingDestination.getFactoryInstance();
        Class c = factoryInstance.getInstanceClass();
        if (c == null)
            return true; // No source class; ignore validation and generate an error at runtime.
        Method[] methods = c.getMethods();
        int n = methods.length;
        for (int i = 0; i < n; i++) {
            if (methods[i].getName().equals(methodName))
                return true;
        }
        return false;
    }
}
