/*
 * 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.axis2.jaxws.handler;

import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.description.DescriptionFactory;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.ResolvedHandlersDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.description.impl.ResolvedHandlersDescriptionImpl;
import org.apache.axis2.jaxws.description.xml.handler.HandlerChainType;
import org.apache.axis2.jaxws.description.xml.handler.HandlerChainsType;
import org.apache.axis2.jaxws.description.xml.handler.HandlerType;
import org.apache.axis2.jaxws.handler.lifecycle.factory.HandlerLifecycleManager;
import org.apache.axis2.jaxws.handler.lifecycle.factory.HandlerLifecycleManagerFactory;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.axis2.jaxws.spi.handler.BaseHandlerResolver;
import org.apache.axis2.util.LoggingControl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/* 
 * This class should be created by the ServiceDelegate.
 * HandlerResolverImpl.getHandlerChain(PortInfo) will be called by the
 * InvocationContext, and the return value will be set on the Binding
 * under the BindingProvider.
 * 
 * HandlerResolverImpl.getHandlerChain(PortInfo) will be responsible for
 * starting each Handler's lifecycle according to JAX-WS spec 9.3.1
 */

public class HandlerResolverImpl extends BaseHandlerResolver {

    private static Log log = LogFactory.getLog(HandlerResolverImpl.class);
    /*
      * TODO:  is there any value/reason in caching the list we collect from the
      * ports?  It is a "live" list in the sense that we could possibly return
      * a List or ArrayList object to a service or client application, where
      * they could manipulate it.
      */

    private ServiceDescription serviceDesc;
    private Object serviceDelegateKey;
    
    public HandlerResolverImpl(ServiceDescription sd) {
        this(sd, null);
    }

    public HandlerResolverImpl(ServiceDescription sd, Object serviceDelegateKey) { 
        this.serviceDesc = sd;
        this.serviceDelegateKey = serviceDelegateKey;
    }
    
    private ResolvedHandlersDescription getResolvedHandlersDescription(PortInfo portInfo) {
        ResolvedHandlersDescription resolvedHandlersDesc = null;
        // On the client the handler information can be changed via service-delegate-specific
        // deployment information.  So, only look into the service-side cache only if the 
        // service delegate key is null.
        if (serviceDelegateKey == null) {
            resolvedHandlersDesc = serviceDesc.getResolvedHandlersDescription(portInfo);
        }
        return resolvedHandlersDesc;
    }
    private ResolvedHandlersDescription getOrCreateResolvedHandlersDescription(PortInfo portInfo) {
        ResolvedHandlersDescription resolvedHandlersDesc = null;
        // On the client the handler information can be changed via service-delegate-specific
        // deployment information.  So, only look into the service-side cache only if the 
        // service delegate key is null.
        if (serviceDelegateKey == null) {
            resolvedHandlersDesc = serviceDesc.getResolvedHandlersDescription(portInfo);
            if (resolvedHandlersDesc == null) {
                resolvedHandlersDesc = DescriptionFactory.createResolvedHandlersDescription();
            }
        }
        return resolvedHandlersDesc;
    }
    private List<Class> geCachedResolvedHandlersClasses(PortInfo portInfo) {
        List<Class> cachedHandlerClasses = null;
        ResolvedHandlersDescription resolvedHandlersDesc = getResolvedHandlersDescription(portInfo);
        if (resolvedHandlersDesc != null) {
            cachedHandlerClasses = resolvedHandlersDesc.getHandlerClasses();
        }
        return cachedHandlerClasses;
    }
    
    private void cacheResolvedHandlersInfo(PortInfo portInfo, 
                                              List<Class> handlerClasses,
                                              List<String> roles) {
        ResolvedHandlersDescription resolvedHandlersDesc = getOrCreateResolvedHandlersDescription(portInfo);
        if (resolvedHandlersDesc != null) {
            resolvedHandlersDesc.setHandlerClasses(handlerClasses);
            resolvedHandlersDesc.setRoles(roles);
            serviceDesc.setResolvedHandlersDescription(portInfo, resolvedHandlersDesc);
        }
    }

    private List<Class> getHandlerClasses(PortInfo portInfo) {
        List<Class> handlerClasses = geCachedResolvedHandlersClasses(portInfo);
        if (handlerClasses == null) {
            List<String> resolveRoles = new ArrayList<String>();
            handlerClasses = resolveHandlers(portInfo, resolveRoles);
            cacheResolvedHandlersInfo(portInfo, handlerClasses, resolveRoles);
        }
        return handlerClasses;
    }
    private List<String> getHandlerRoles(PortInfo portInfo) {
        List<String> resolveRoles = getCachedResolvedHandlersRoles(portInfo);
        if (resolveRoles == null) {
            resolveRoles = new ArrayList<String>();
            List<Class> resolveClasses = resolveHandlers(portInfo, resolveRoles);
            cacheResolvedHandlersInfo(portInfo, resolveClasses, resolveRoles);
        }
        return resolveRoles;
    }
    private List<String> getCachedResolvedHandlersRoles(PortInfo portInfo) {
        List<String> cachedHandlerRoles = null;
        ResolvedHandlersDescription resolvedHandlersDesc = getResolvedHandlersDescription(portInfo);
        if (resolvedHandlersDesc != null) {
            cachedHandlerRoles = resolvedHandlersDesc.getRoles();
        }
        return cachedHandlerRoles;
    }

    public List<Handler> getHandlerChain(PortInfo portInfo) {
        List<Class> handlerClasses = getHandlerClasses(portInfo);

        if (handlerClasses.size() == 0) {
            return new ArrayList<Handler>();
        }

        ArrayList<Handler> handlers = new ArrayList<Handler>();
        // Create temporary MessageContext to pass information to HandlerLifecycleManager
        MessageContext ctx = new MessageContext();
        ctx.setEndpointDescription(serviceDesc.getEndpointDescription(portInfo.getPortName()));

        HandlerLifecycleManager hlm = createHandlerlifecycleManager();

        for (Iterator<Class> iterator = handlerClasses.iterator(); iterator.hasNext();) {
            Class aClass = iterator.next();
            //  instantiate portHandler class 
            try {
                handlers.add(hlm.createHandlerInstance(ctx, aClass));
            } catch (Exception e) {
                // TODO: should we just ignore this problem?
                throw ExceptionFactory.makeWebServiceException(e);
            }
            if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
                log.debug("Successfully instantiated the class: " + aClass);
            }

        }
        return handlers;
    }

    public List<String> getRoles(PortInfo portInfo) {
        List<String> handlerRoles = getHandlerRoles(portInfo);
        return handlerRoles;
    }
    /*
      * The list of handlers (rather, list of class names) is already
      * available per port.  Ports are stored under the ServiceDelegate
      * as PortData objects.
      *
	 * The resolveHandlers method is responsible for instantiating each Handler,
	 * running the annotated PostConstruct method, resolving the list,
	 * and returning it.  We do not sort here.
      */
    /**
     * Resolve the handlers and roles for the given port.  This will process the handler configuration
     * information, which can be specified either in a file on a HandlerChain annotaiton or via a
     * deployment descriptor.  The handler classes and the SOAP roles played will be resolved and
     * returned.
     * 
     * @param portinfo  Information describing the port for which the handlers and roles are to be
     *     resolved
     * @param handlerRoles  OUTPUT PARAMETER!  The List that is passed in will be updated with the
     *     roles relevant to the specfied port.
     * @return List of handler classes relevant to the specified port.
     * @throws WebServiceException
     */
    private ArrayList<Class> resolveHandlers(PortInfo portinfo, List<String> handlerRoles) throws WebServiceException {
        /*
            A sample XML file for the handler-chains:
            
            <jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">
                <jws:handler-chain>
                    <jws:protocol-bindings>##XML_HTTP</jws:protocol-bindings>
                    <jws:handler>
                        <jws:handler-name>MyHandler</jws:handler-name>
                        <jws:handler-class>org.apache.axis2.jaxws.MyHandler</jws:handler-class>
                    </jws:handler>
                </jws:handler-chain>
                <jws:handler-chain>
                    <jws:port-name-pattern>jws:Foo*</jws:port-name-pattern>
                    <jws:handler>
                        <jws:handler-name>MyHandler</jws:handler-name>
                        <jws:handler-class>org.apache.axis2.jaxws.MyHandler</jws:handler-class>
                        <jws:soap-role>http://org/apache/axis2/jaxws/MyRole</jws:soap-role>
                    </jws:handler>
                </jws:handler-chain>
                <jws:handler-chain>
                    <jws:service-name-pattern>jws:Bar</jws:service-name-pattern>
                    <jws:handler>
                        <jws:handler-name>MyHandler</jws:handler-name>
                        <jws:handler-class>org.apache.axis2.jaxws.MyHandler</jws:handler-class>
                    </jws:handler>
                </jws:handler-chain>
            </jws:handler-chains>
            
            Couple of things I'm not sure about...
            1)  if the protocol-binding, port-name-pattern, and service-name-pattern all
                match the PortInfo object, does MyHandler get added three times?  Probably would get added 3 times.
            2)  I assume the asterisk "*" is a wildcard.  Can the asterisk only occur on the local part of the qname?
            3)  Can there be more than one service-name-pattern or port-name-pattern, just like for protocol-bindings?
            4)  How many protocol-bindings are there?  ##XML_HTTP ##SOAP11_HTTP ##SOAP12_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP_MTOM
                They are separated by spaces
         */

        // our implementation already has a reference to the EndpointDescription,
        // which is where one might get the portinfo object.  We still have the 
        // passed-in variable, however, due to the spec

        ArrayList<Class> handlers = new ArrayList<Class>();

        /*
         * TODO: do a better job checking that the return value matches up
         * with the PortInfo object before we add it to the chain.
         */

        // The HandlerChain annotation can be specified on:
        // - a service implementation (per JSR-181) which is on the service-provider side
        // - an SEI (per JSR-181), which can be on both the service-provider and 
        //   service-requester sides
        // - a generated Service (per JSR-224), which is on the service-requester side
        //
        // The order of precedence here is a bit counter intuitive if the HandlerChain annotation
        // is present on more than one class.  
        // - For the service-provider, JSR-181 [p. 25, Section 4.6.1]
        //   states that the service implementation's HandlerChain takes is used if it is present
        //   on both the implementation and the SEI.
        // - Following that same pattern, we conclude that a generated service HandlerChain should
        //   take precedence if the annotation is on both the Service and the SEI.
        //
        // The reasoning for this is (probably) that the SEI can be used by multiple endpoints 
        // and / or multiple Service requesters, so the endpoint implementation and the Service
        // should have the final say in what handlers are run, rather than the SEI.
        //
        // Adding Deployment Descriptors complicates this further.  A DD should have the absolute 
        // final say (such as a JSR-109 client DD).  Given that, on a service-requester if the
        // Service has a HandlerChain and the SEI has a HandlerChain and the DD specifies a 
        // HandlerChain for a port, then the DD should win.  Since DDs are implented as information
        // in a sparse composite, then that means the sparse composite wins.
        
        // Get the HandlerChains specified on the Endpoint (service-provider) or on the Service
        // (service-requester).
        handlerChainsType = serviceDesc.getHandlerChain(serviceDelegateKey);  

        // HandlerChains apply to specific Port Compoments (service-provider) or Ports (
        // (service-requesters) so find the appropriate one.
        EndpointDescription ed = null;
        if(portinfo !=null){
             ed = serviceDesc.getEndpointDescription(portinfo.getPortName());
        }
        
        // Get the HandlerChain information, if any, off the SEI (service-provider or 
        // service-requster) and check for any DD overrides.
        if (ed != null) {
            // If there was no handler chains information specifed on the endpoint (service-
            // provider) or the Service (service-requester)
            // -- OR -- 
            // If the handler chains associated with a particular instance of a service delegate
            // DOES NOT match the handler chains across all service delegates, then there was
            // sparse composite information specified for this service delegate.  Sparse composite
            // information is how Deployment Descriptor information is specified, and that 
            // overrides the annotations as described in the long-winded comment above.
            // -- THEN --
            // Use this handler chains information
            HandlerChainsType hct_includingComposite = ed.getHandlerChain(serviceDelegateKey);
            HandlerChainsType hct_noComposite = ed.getHandlerChain();
            if (handlerChainsType == null || (hct_includingComposite != hct_noComposite)) {
                handlerChainsType = hct_includingComposite;
            } 
        } else {
            // There is no EndpointDescription that matches the portInfo specified so 
            // return the empty list of handlers since there are no ports that match
            if (log.isDebugEnabled()) {
                log.debug("The PortInfo object did not match any ports; returning an empty list of handlers." 
                        + "  PortInfo QName: " + portinfo.getPortName());
            }
            return handlers;
        }

        Iterator it = handlerChainsType == null ? null : handlerChainsType.getHandlerChain().iterator();

        while ((it != null) && (it.hasNext())) {
            HandlerChainType handlerChainType = ((HandlerChainType)it.next());
            
            // if !match, continue (to next chain)
            if (!(chainResolvesToPort(handlerChainType, portinfo)))
                continue;
            
            List<HandlerType> handlerTypeList = handlerChainType.getHandler();
            Iterator ht = handlerTypeList.iterator();
            while (ht.hasNext()) {
                HandlerType handlerType = (HandlerType) ht.next();
                // TODO must do better job comparing the handlerType with the PortInfo param
                // to see if the current iterator handler is intended for this service.
                // TODO review: need to check for null getHandlerClass() return?
                // or will schema not allow it?
                String portHandler = handlerType.getHandlerClass().getValue();
                Class aClass;
                try {
                    aClass = loadClass(portHandler);
                } catch (Exception e) {
                    // TODO: should we just ignore this problem?
                    throw ExceptionFactory.makeWebServiceException(e);
                }

                // 9.2.1.2 sort them by Logical, then SOAP
                if (LogicalHandler.class.isAssignableFrom(aClass))
                    handlers.add(aClass);
                else if (SOAPHandler.class.isAssignableFrom(aClass))
                    // instanceof ProtocolHandler
                    handlers.add(aClass);
                else if (Handler.class.isAssignableFrom(aClass)) {
                    throw ExceptionFactory.makeWebServiceException(Messages
                            .getMessage("handlerChainErr1", aClass.getName()));
                } else {
                    throw ExceptionFactory.makeWebServiceException(Messages
                            .getMessage("handlerChainErr2", aClass.getName()));
                }
                // If a role was specified, add it to the roles played
                if (handlerRoles != null) {
                    List<org.apache.axis2.jaxws.description.xml.handler.String> soapRolesList = 
                        handlerType.getSoapRole();
                    Iterator<org.apache.axis2.jaxws.description.xml.handler.String> 
                        soapRolesIterator = soapRolesList.iterator();
                    while (soapRolesIterator.hasNext()) {
                        org.apache.axis2.jaxws.description.xml.handler.String soapRoleElement =
                            soapRolesIterator.next();
                        String addSoapRole = soapRoleElement.getValue();
                        handlerRoles.add(addSoapRole);
                        if (log.isDebugEnabled()) {
                            log.debug("Adding soap role " + addSoapRole);
                        }
                    }
                }
            }
        }

        return handlers;
    }

    private HandlerLifecycleManager createHandlerlifecycleManager() {
        HandlerLifecycleManagerFactory elmf = (HandlerLifecycleManagerFactory)FactoryRegistry
                .getFactory(HandlerLifecycleManagerFactory.class);
        return elmf.createHandlerLifecycleManager();
    }
}
