Package org.wso2.carbon.bpel.ode.integration

Source Code of org.wso2.carbon.bpel.ode.integration.BPELBindingContextImpl

/*
* Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.wso2.carbon.bpel.ode.integration;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.AxisServiceGroup;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.collections.map.MultiKeyMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.agents.memory.SizingAgent;
import org.apache.ode.bpel.iapi.*;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.bpel.ode.integration.store.*;
import org.wso2.carbon.bpel.ode.integration.utils.AxisServiceUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.Map;

/**
* Axis2 implementation of the {@link org.apache.ode.bpel.iapi.BindingContext}
* interface. Deals with the activation of endpoints.
*/

public class BPELBindingContextImpl implements BindingContext {
    private static final Log log = LogFactory.getLog(BPELBindingContextImpl.class);
    private BPELServerImpl bpelServer;
    private MultiKeyMap services = new MultiKeyMap();
    private Map<BPELProcessProxy, EndpointReference> serviceEprMap =
            new HashMap<BPELProcessProxy, EndpointReference>();

    public BPELBindingContextImpl(BPELServerImpl bpelServer) {
        this.bpelServer = bpelServer;
    }

    public EndpointReference activateMyRoleEndpoint(QName processId, Endpoint myRoleEndpoint) {
        try {

            ProcessConf processConfiguration = ((ProcessStore) bpelServer.
                    getMultiTenantProcessStore()).getProcessConfiguration(processId);

            BPELProcessProxy processProxy = publishAxisService(processConfiguration,
                    myRoleEndpoint.serviceName,
                    myRoleEndpoint.portName);
            serviceEprMap.put(processProxy, processProxy.getServiceReference());
            updateServiceList(getTenantId(processId), myRoleEndpoint, STATE.ADD);
            return processProxy.getServiceReference();
        } catch (AxisFault af) {
            final String errMsg = "Could not activate endpoint for service " +
                    myRoleEndpoint.serviceName + " and port " +
                    myRoleEndpoint.portName;
            log.error(errMsg, af);
            throw new ContextException(errMsg, af);
        }
    }

    public void deactivateMyRoleEndpoint(QName processID, Endpoint endpoint) {
        if (log.isDebugEnabled()) {
            log.debug("Deactivating my role endpoint for service: " + endpoint.serviceName + " and port: "
                    + endpoint.portName);
        }

        Integer tenantId = ((MultiTenantProcessStore) bpelServer.
                    getMultiTenantProcessStore()).getTenantId(processID);

        BPELProcessProxy processProxy = getBPELProcessProxy(tenantId.toString(), endpoint.serviceName, endpoint.portName);
        if (processProxy != null) {
            ProcessConfigurationImpl processConf =
                    (ProcessConfigurationImpl) processProxy.getProcessConfiguration();
            if (processConf.isUndeploying()) {
                AxisService service = processProxy.getAxisService();
                Parameter param = service.getParameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM);
                param.setValue("false");
            }

            removeBPELProcessProxyAndAxisService(tenantId.toString(), endpoint.serviceName, endpoint.portName);

            updateServiceList(
                    ((ProcessConfigurationImpl) processProxy.getProcessConfiguration()).getTenantId(),
                    endpoint,
                    STATE.REMOVE);
            serviceEprMap.remove(processProxy);
            if (processConf.isUndeploying()) {
                bpelServer.getMultiTenantProcessStore().removeFromProcessToTenantMap(processID);
            }
        }  // else this method also get called for the retired processes where there could be an
        // active version of the same process type. Since there is only one service for a
        // particular process type, processProxy will be null for all the endpoints except for 1.

    }

    public PartnerRoleChannel createPartnerRoleChannel(QName processId, PortType portType,
                                                       Endpoint initialPartnerEndpoint) {
        ProcessConf processConfiguration = ((ProcessStore) bpelServer.getMultiTenantProcessStore())
                .getProcessConfiguration(processId);
        Definition wsdl = processConfiguration.getDefinitionForService(
                initialPartnerEndpoint.serviceName);
        if (wsdl == null) {
            throw new ContextException("Cannot find definition for service " +
                    initialPartnerEndpoint.serviceName
                    + " in the context of process " + processId);
        }
        return createPartnerService(processConfiguration,
                initialPartnerEndpoint.serviceName,
                initialPartnerEndpoint.portName);
    }

    public long calculateSizeofService(EndpointReference endpointReference) {
        if (bpelServer.getOdeConfigurationProperties().isProcessSizeThrottled()) {
            for (Map.Entry<BPELProcessProxy, EndpointReference> entry : serviceEprMap.entrySet()) {
                if (endpointReference.equals(entry.getValue())) {
                    return SizingAgent.deepSizeOf(entry.getKey());
                }
            }
        }
        return 0;
    }

    private Integer getTenantId(QName processId) {
        ProcessConf processConfiguration = ((ProcessStore) bpelServer.
                getMultiTenantProcessStore()).getProcessConfiguration(processId);
        return MultitenantUtils
                .getTenantId(((MultiTenantProcessConfiguration) processConfiguration).getTenantConfigurationContext());
    }

    private PartnerService createPartnerService(ProcessConf pConf, QName serviceName,
                                                String portName)
            throws ContextException {
        PartnerService partnerService;

        Definition def = pConf.getDefinitionForService(serviceName);
        try {
            if (log.isDebugEnabled()) {
                log.debug("Creating external service " + serviceName);
            }
            partnerService = new PartnerService(def, serviceName, portName,
                    getConfigurationContextFromProcessConfiguration(pConf),
                    pConf, bpelServer.getHttpConnectionManager());

        } 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 (partnerService == null) {
            throw new ContextException("Only SOAP and HTTP binding supported!");
        }

        log.debug("Created external service " + serviceName);
        return partnerService;
    }

    private BPELProcessProxy publishAxisService(ProcessConf processConfiguration, QName serviceName,
                                                String portName)
            throws AxisFault {
        // TODO: Need to fix this to suite multi-tenant environment
        // TODO: There is a problem in this, in this manner we can't have two axis services with
        // same QName
        BPELProcessProxy processProxy = new BPELProcessProxy(processConfiguration, bpelServer,
                serviceName, portName);
        ConfigurationContext tenantConfigCtx =
                getConfigurationContextFromProcessConfiguration(processConfiguration);

        AxisService axisService;
        try {
            axisService = AxisServiceUtils.createAxisService(tenantConfigCtx.getAxisConfiguration(),
                    processProxy);
        } catch (AxisFault e) {
            log.error("Error occurred creating the axis service " + serviceName.toString());

            int tenantId = bpelServer.getMultiTenantProcessStore().
                    getTenantId(processConfiguration.getProcessId());
            TenantProcessStoreImpl pStore = (TenantProcessStoreImpl) bpelServer.
                    getMultiTenantProcessStore().getTenantsProcessStore(tenantId);
            pStore.removeProcessConfiguration(processConfiguration.getProcessId());
            throw new DeploymentException("BPEL Package undeployment failed.", e);
        }

        processProxy.setAxisService(axisService);
        removeBPELProcessProxyAndAxisService(processConfiguration.getDeployer(), serviceName, portName);
        services.put(processConfiguration.getDeployer(), serviceName, portName, processProxy);

        tenantConfigCtx.getAxisConfiguration().addServiceGroup(
                createServiceGroupForService(axisService));

        if (log.isDebugEnabled()) {
            log.debug("BPELProcessProxy created for process " + processConfiguration.getProcessId());
            log.debug("AxisService " + serviceName + " created for BPEL process " +
                    processConfiguration.getProcessId());
        }

        return processProxy;
    }

    private AxisServiceGroup createServiceGroupForService(AxisService svc) throws AxisFault {
        AxisServiceGroup svcGroup = new AxisServiceGroup();
        svcGroup.setServiceGroupName(svc.getName());
        svcGroup.addService(svc);
        // Checking configured using files param is not a good solution. We must figure out a way to handle this
        // at Carbon persistence manager layer.
        if (svc.getParameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM) != null &&
                svc.getParameter(BPELConstants.CONFIGURED_USING_BPEL_PKG_CONFIG_FILES) == null) {
            svcGroup.addParameter(new Parameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM, "true"));
        }

        return svcGroup;
    }

    private BPELProcessProxy getBPELProcessProxy(String processDeployer, QName serviceName, String portName) {
        return (BPELProcessProxy) services.get(processDeployer, serviceName, portName);
    }

    private void removeBPELProcessProxyAndAxisService(
            String processDeployer,
            QName serviceName,
            String portName) {

        if (log.isDebugEnabled()) {
            log.debug("Removing service " + serviceName.toString() + " port " + portName);
        }
        BPELProcessProxy processProxy = (BPELProcessProxy) services.remove(processDeployer, serviceName, portName);
        if (processProxy != null) {
            try {
                String axisServiceName = processProxy.getAxisService().getName();
                AxisConfiguration axisConfig = processProxy.getAxisService().getAxisConfiguration();
                ///////////////////////////////////////////////////////////////////////////////////////////////////////
                // There is a issue in this code due to tenant unloading and loading. When we unload a tenant we don't
                // undeploy the process. So BPELBindingContextImpl#deactivateMyRoleEndpoint will not get invoked and
                // BPELProcessProxy instance will be there in the BPELBindingContextImpl#services map. So at the
                // time we load the tenant again, axisService returned from axisConfig will be null even though we
                // have a BPELProcessProxy instance in service map. This is because teant unloading logic cleans the
                // axis configuration. So if the axisService is null, we ignore the other steps after this.
                ///////////////////////////////////////////////////////////////////////////////////////////////////////
                AxisService axisService = axisConfig.getService(axisServiceName);
                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) {
//                    if (!parameter.getName().equals(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM) && !BPELProcessStoreImpl.isUndeploying) {
//                        axisService.removeParameter(parameter);
//                    }
//                }
//
//                if (RegistryBasedProcessStoreImpl.isUndeploying) {
//                    BPSServerImpl.getAxisConfig().getServiceGroup(axisServiceName).removeParameter(
//                            new Parameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM, "true"));
//                }
//
//                if (RegistryBasedProcessStoreImpl.isUpdatingBPELPackage) {
//                    axisService.addParameter(new Parameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM, "true"));
//                    axisService.getAxisServiceGroup().addParameter(new Parameter(CarbonConstants.PRESERVE_SERVICE_HISTORY_PARAM, "true"));
//                }
                    // now, stop the service
                    axisConfig.stopService(axisServiceName);
                    // calling removeServiceGroup() is workaround to AXIS2-4314.
                    //  It happens that Axis2 creates one group per service you add with AxisConfiguration.addService().
                    // See this.createService()
                    // Once this issue is fixed (hopully in Axis2-1.5), we can use removeService() again.
                    axisConfig.removeServiceGroup(axisServiceName);
                    // This must not done. This will cause axis configuration to cleanup deployment schedular
                    // and it'll throw exception when it tries to reschedule deployer after undeplying.
                    //_server._axisConfig.cleanup();
                }
            } catch (AxisFault axisFault) {
                log.error("Couldn't remove service " + serviceName);
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Couldn't find service " + serviceName + " port " + portName + " to remove.");
            }
        }
    }

    private ConfigurationContext getConfigurationContextFromProcessConfiguration(ProcessConf processConf) {
        if (processConf instanceof ProcessConfigurationImpl) {
            return ((ProcessConfigurationImpl) processConf)
                    .getTenantConfigurationContext();
        }
        throw new RuntimeException("ProcessConf implementatoin type mismatch. " +
                "ProcessConf implentation should be a instance of" +
                " org.wso2.carbon.bpel.ode.integration.store.ProcessConfigurationImpl.");
    }

    private void updateServiceList(int tenantId, Endpoint myRoleEndpoint, STATE state) {
        TenantProcessStore tenantProcessStore = bpelServer.getMultiTenantProcessStore().
                getTenantsProcessStore(tenantId);
        if (tenantProcessStore == null) {
            throw new RuntimeException("TenantProcessStore null for tenant " + tenantId + ".");
        }
        switch (state) {
            case ADD:
                if (log.isDebugEnabled()) {
                    log.debug("Adding published service information for service: " + myRoleEndpoint.serviceName);
                }
                tenantProcessStore.getDeployedServices().put(myRoleEndpoint.serviceName, new Object());
                break;
            case REMOVE:
                if (log.isDebugEnabled()) {
                    log.debug("Removing published service information for service: " + myRoleEndpoint.serviceName);
                }
                tenantProcessStore.getDeployedServices().remove(myRoleEndpoint.serviceName);
                break;
        }

    }

    private static enum STATE {
        ADD,
        REMOVE
    }
}
TOP

Related Classes of org.wso2.carbon.bpel.ode.integration.BPELBindingContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.