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

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.xml.namespace.QName;

import org.apache.axis2.AxisFault;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfigurator;
import org.apache.commons.collections.map.MultiKeyMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.agents.memory.SizingAgent;
import org.apache.ode.axis2.hooks.ODEAxisService;
import org.apache.ode.axis2.hooks.ODEMessageReceiver;
import org.apache.ode.axis2.httpbinding.HttpExternalService;
import org.apache.ode.bpel.iapi.BindingContext;
import org.apache.ode.bpel.iapi.ContextException;
import org.apache.ode.bpel.iapi.Endpoint;
import org.apache.ode.bpel.iapi.EndpointReference;
import org.apache.ode.bpel.iapi.PartnerRoleChannel;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.apache.ode.utils.wsdl.WsdlUtils;

/**
 * AXIS2 implementation of the {@link org.apache.ode.bpel.iapi.BindingContext}
 * interface. Deals with the activation of endpoints.
 *
 * @author Maciej Szefler - m s z e f l e r @ g m a i l . c o m
 *
 */
public class BindingContextImpl implements BindingContext {
    protected final Logger __log = LoggerFactory.getLogger(getClass());

    private ODEServer _server;
    private MultiKeyMap _services = new MultiKeyMap();
    private Map<ODEService, EndpointReference> _serviceEprMap = new HashMap<ODEService, EndpointReference>();

    public BindingContextImpl(ODEServer server) {
        _server = server;
    }

    public EndpointReference activateMyRoleEndpoint(QName processId, Endpoint myRoleEndpoint) {
        try {
            ProcessConf pconf = _server._store.getProcessConfiguration(processId);
            Definition wsdl = pconf.getDefinitionForService(myRoleEndpoint.serviceName);
            if (wsdl == null)
                throw new ContextException("Unable to access WSDL definition to activate MyRole endpoint for service " + myRoleEndpoint.serviceName
                        + " and port " + myRoleEndpoint.portName);
            ODEService svc = createService(pconf, myRoleEndpoint.serviceName, myRoleEndpoint.portName);
            EndpointReference epr = svc.getMyServiceRef();
            _serviceEprMap.put(svc, epr);
            return epr;
        } catch (AxisFault axisFault) {
            throw new ContextException("Could not activate endpoint for service " + myRoleEndpoint.serviceName
                    + " and port " + myRoleEndpoint.portName, axisFault);
        }
    }

    public void deactivateMyRoleEndpoint(Endpoint myRoleEndpoint) {
        ODEService service = destroyService(myRoleEndpoint.serviceName, myRoleEndpoint.portName);
        if (service != null) {
            _serviceEprMap.remove(service);
        }
    }

    public PartnerRoleChannel createPartnerRoleChannel(QName processId, PortType portType,
                                                       Endpoint initialPartnerEndpoint) {
        // NOTE: This implementation assumes that the initial value of the
        // partner role determines the binding.
        ProcessConf pconf = _server._store.getProcessConfiguration(processId);
        Definition wsdl = pconf.getDefinitionForService(initialPartnerEndpoint.serviceName);
        if (wsdl == null) {
            throw new ContextException("Cannot find definition for service " + initialPartnerEndpoint.serviceName
                                       + " in the context of process "+processId);
        }
        return createExternalService(pconf, initialPartnerEndpoint.serviceName, initialPartnerEndpoint.portName);
    }

    public long calculateSizeofService(EndpointReference epr) {
        if (_server._odeConfig.isProcessSizeThrottled()) {
            for (ODEService service : _serviceEprMap.keySet()) {
                if (epr.equals(_serviceEprMap.get(epr))) {
                    return SizingAgent.deepSizeOf(service);
                }
            }
        }
        return 0;
    }

    protected ODEService createService(ProcessConf pconf, QName serviceName, String portName) throws AxisFault {
        AxisService axisService = ODEAxisService.createService(_server._configContext.getAxisConfiguration(), pconf, serviceName, portName);
        ODEService odeService = new ODEService(axisService, pconf, serviceName, portName, _server._bpelServer, _server._txMgr);

        destroyService(serviceName, portName);

        _services.put(serviceName, portName, odeService);

        // Setting our new service on the ODE receiver
        Iterator operationIterator = axisService.getOperations();
        while (operationIterator.hasNext()) {
            AxisOperation op = (AxisOperation) operationIterator.next();
            if (op.getMessageReceiver() instanceof ODEMessageReceiver) {
                ((ODEMessageReceiver) op.getMessageReceiver()).setService(odeService);
                break;
            }
        }

        // We're public!
        _server._configContext.getAxisConfiguration().addService(axisService);
        if (__log.isDebugEnabled()) {
            __log.debug("Created Axis2 service " + serviceName);
        }
        return odeService;
    }

    protected ODEService destroyService(QName serviceName, String portName) {
        if (__log.isDebugEnabled()) {
            __log.debug("Destroying service " + serviceName + " port " + portName);
        }
        ODEService service = (ODEService) _services.remove(serviceName, portName);
        if (service != null) {
            // try to clean up the service after itself
            try {
                String axisServiceName = service.getAxisService().getName();
                AxisService axisService = _server._configContext.getAxisConfiguration().getService(axisServiceName);

                //axisService might be null if it could not be properly activated before. 
                if (axisService != null) {
                    // first, de-allocate its schemas
                    axisService.releaseSchemaList();
                    // then, de-allocate its parameters
                    // the service's wsdl object model is stored as one of its parameters!
                    // can't stress strongly enough how important it is to clean this up.
                    ArrayList<Parameter> parameters = (ArrayList<Parameter>) axisService.getParameters();
                    for (Parameter parameter : parameters) {
                        axisService.removeParameter(parameter);
                    }
                }
                // now, stop the service
                _server._configContext.getAxisConfiguration().stopService(axisServiceName);
                // if only this method did a good job of cleaning up after itself
                _server._configContext.getAxisConfiguration().removeService(service.getName());
                completeCleanup(axisService);

                //ODE-994: commenting the cleanup on axisConfig as it cleansup everything on axis2 1.6
                //_server._axisConfig.cleanup();
                //For backward compatibility with older versions of axis2 that is below 1.6
                AxisConfigurator configurator = _server._configContext.getAxisConfiguration().getConfigurator();
                if(configurator != null)
                    configurator.cleanup();

            } catch (AxisFault axisFault) {
                __log.error("Couldn't destroy service " + serviceName);
            }
        } else {
            if (__log.isDebugEnabled()) {
                __log.debug("Couldn't find service " + serviceName + " port " + portName + " to destroy.");
            }
        }
        return service;
    }

    /**
     * /!\ Monkey patching to remove references to the service:
     * Manually & externally & really really horribly fix for ODE-580/AXIS2-3870
     * The exception handling is for locked down environment where reflection would not be allowed...
     *
     * This patch is needed for Axis2 1.3 and 1.4.1
     * @param service
     * @throws AxisFault
     */
    private void completeCleanup(AxisService service) {
        try {
            Field field= _server._configContext.getAxisConfiguration().getClass().getDeclaredField("allEndpoints");
            field.setAccessible(true);
            synchronized (_server._configContext.getAxisConfiguration()) {
                //removes the endpoints to this service
                Map allEndpoints = (Map) field.get(_server._configContext.getAxisConfiguration());

                //removes the service endpoints
                for (Iterator<String> iter = service.getEndpoints().keySet().iterator(); iter.hasNext();) {
                    allEndpoints.remove(service.getName() + "." + iter.next());
                }
            }
        } catch(Exception e) {
            __log.error("Workaround for ODE-580/AXIS2-3870 failed. AxisConfig clean up might be incomplete.",  e);
        }
    }

    protected ExternalService createExternalService(ProcessConf pconf, QName serviceName, String portName) throws ContextException {
        ExternalService extService = null;

        Definition def = pconf.getDefinitionForService(serviceName);
        try {
            if (WsdlUtils.useHTTPBinding(def, serviceName, portName)) {
                if (__log.isDebugEnabled()) __log.debug("Creating HTTP-bound external service " + serviceName);
                extService = new HttpExternalService(pconf, serviceName, portName, _server._executorService, _server._scheduler, _server._bpelServer, _server.httpConnectionManager, _server._clusterUrlTransformer);
            } else if (WsdlUtils.useSOAPBinding(def, serviceName, portName)) {
                if (__log.isDebugEnabled()) __log.debug("Creating SOAP-bound external service " + serviceName);
                extService = new SoapExternalService(pconf, serviceName, portName, _server._executorService, _server._configContext, _server._scheduler, _server._bpelServer, _server.httpConnectionManager, _server._clusterUrlTransformer);
            }
        } catch (Exception ex) {
            __log.error("Could not create external service.", ex);
            throw new ContextException("Error creating external service! name:" + serviceName + ", port:" + portName, ex);
        }

        // if not SOAP nor HTTP binding
        if (extService == null) {
            throw new ContextException("Only SOAP and HTTP binding supported!");
        }

        if (__log.isDebugEnabled()) {
            __log.debug("Created external service " + serviceName);
        }
        return extService;
    }

}
