org.wso2.carbon.bpel.analytics.publisher.AnalyticsPublisherExtensionOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.bpel.analytics.publisher.AnalyticsPublisherExtensionOperation.java

Source

/*
 * Copyright (c) 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.analytics.publisher;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.common.FaultException;
import org.apache.ode.bpel.elang.xpath20.o.OXPath20ExpressionBPEL20;
import org.apache.ode.bpel.explang.ConfigurationException;
import org.apache.ode.bpel.explang.EvaluationException;
import org.apache.ode.bpel.o.OExpressionLanguage;
import org.apache.ode.bpel.runtime.ExprEvaluationContextImpl;
import org.apache.ode.bpel.runtime.ExtensionContextImpl;
import org.apache.ode.bpel.runtime.ScopeFrame;
import org.apache.ode.bpel.runtime.extension.AbstractSyncExtensionOperation;
import org.apache.ode.bpel.runtime.extension.ExtensionContext;
import org.apache.ode.store.DeploymentUnitDir;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wso2.carbon.bpel.analytics.publisher.internal.AnalyticsPublisherServiceComponent;
import org.wso2.carbon.bpel.core.ode.integration.config.analytics.AnalyticsKey;
import org.wso2.carbon.bpel.core.ode.integration.config.analytics.AnalyticsServerProfile;
import org.wso2.carbon.bpel.core.ode.integration.config.analytics.AnalyticsStreamConfiguration;
import org.wso2.carbon.bpel.core.ode.integration.store.TenantProcessStore;
import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAuthenticationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointException;
import org.wso2.carbon.databridge.commons.Event;
import org.wso2.carbon.databridge.commons.exception.*;
import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils;

import javax.xml.namespace.QName;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class AnalyticsPublisherExtensionOperation extends AbstractSyncExtensionOperation {
    private static final Log log = LogFactory.getLog(AnalyticsPublisherExtensionOperation.class);

    @Override
    protected void runSync(ExtensionContext extensionContext, Element element) throws FaultException {
        String analyticsServerProfileName = element.getAttribute("analyticsServerProfile");
        String streamName = element.getAttribute(AnalyticsPublisherConstants.STREAM_NAME_ATTR);
        String streamVersion = element.getAttribute(AnalyticsPublisherConstants.STREAM_VERSION);
        Integer tenantId = getTenantId(extensionContext);
        AnalyticsStreamConfiguration stream = getEventStream(tenantId, analyticsServerProfileName, streamName,
                streamVersion);

        if (stream == null) {
            log.debug("Stream configuration is invalid");
            return;
        }
        DataPublisher dataPublisher = getDataPublisher(extensionContext, tenantId, analyticsServerProfileName);
        if (dataPublisher == null) {
            String msg = "Error while creating data publisher";
            handleException(msg);
        }
        String streamId = DataBridgeCommonsUtils.generateStreamId(stream.getName(), stream.getVersion());

        dataPublisher.tryPublish(streamId, createMetadata(stream, extensionContext, element),
                createCorrelationData(stream, extensionContext, element),
                createPayloadData(stream, extensionContext, element));
    }

    private Integer getTenantId(ExtensionContext context) {
        DeploymentUnitDir du = new DeploymentUnitDir(new File(context.getDUDir()));
        QName processIdQname = new QName(context.getProcessModel().getQName().getNamespaceURI(),
                context.getProcessModel().getQName().getLocalPart() + "-" + du.getStaticVersion());
        return AnalyticsPublisherServiceComponent.getBPELServer().getMultiTenantProcessStore()
                .getTenantId(processIdQname);
    }

    private AnalyticsServerProfile getAnalyticsServerProfile(int tenantId, String analyticsServerProfileName) {
        TenantProcessStore tenantsProcessStore = AnalyticsPublisherServiceComponent.getBPELServer()
                .getMultiTenantProcessStore().getTenantsProcessStore(tenantId);
        return tenantsProcessStore.getAnalyticsServerProfile(analyticsServerProfileName);
    }

    private AnalyticsStreamConfiguration getEventStream(int tenantId, String analyticsServerProfileName,
            String streamName, String streamVersion) {
        AnalyticsServerProfile analyticsServerProfile = getAnalyticsServerProfile(tenantId,
                analyticsServerProfileName);
        if (null == analyticsServerProfile) {
            String errMsg = "AnalyticsServerProfile not found for stream name and version " + streamName + " "
                    + streamVersion;
            log.error(errMsg);
            return null;
        }
        return analyticsServerProfile.getAnalyticsStreamConfiguration(streamName, streamVersion);
    }

    private void handleException(String errMsg, Throwable t) throws FaultException {
        log.error(errMsg, t);
        throw new FaultException(AnalyticsPublisherConstants.ANALYTICS_FAULT, errMsg, t);
    }

    private void handleException(String errMsg) throws FaultException {
        log.error(errMsg);
        throw new FaultException(AnalyticsPublisherConstants.ANALYTICS_FAULT, errMsg);
    }

    private Object[] createCorrelationData(AnalyticsStreamConfiguration stream, ExtensionContext context,
            Element element) throws FaultException {
        List<AnalyticsKey> correlationAnalyticsKeyList = stream.getCorrelationAnalyticsKeyList();
        int objectListSize = correlationAnalyticsKeyList.size();
        Object[] dataArray = new Object[objectListSize];
        int startIndex = 0;
        fillDataArray(dataArray, correlationAnalyticsKeyList, startIndex, context, element);
        return dataArray;
    }

    private Object[] createMetadata(AnalyticsStreamConfiguration stream, ExtensionContext context, Element element)
            throws FaultException {
        List<AnalyticsKey> metaAnalyticsKeyList = stream.getMetaAnalyticsKeyList();
        int objectListSize = metaAnalyticsKeyList.size();
        Object[] dataArray = new Object[objectListSize];
        int startIndex = 0;
        fillDataArray(dataArray, metaAnalyticsKeyList, startIndex, context, element);
        return dataArray;
    }

    private Object[] createPayloadData(AnalyticsStreamConfiguration stream, ExtensionContext context,
            Element element) throws FaultException {
        List<AnalyticsKey> payloadAnalyticsKeyList = stream.getPayloadAnalyticsKeyList();
        int objectListSize = payloadAnalyticsKeyList.size();
        Object[] dataArray = new Object[objectListSize];
        int startIndex = 0;
        fillDataArray(dataArray, payloadAnalyticsKeyList, startIndex, context, element);
        return dataArray;
    }

    private void fillDataArray(Object[] dataArray, List<AnalyticsKey> payloadAnalyticsKeyList, int startIndex,
            ExtensionContext context, Element element) throws FaultException {
        for (int i = 0; i < payloadAnalyticsKeyList.size(); i++) {
            AnalyticsKey analyticsKey = payloadAnalyticsKeyList.get(i);
            if (analyticsKey.getExpression() != null) {
                String expression = evaluateXPathExpression(context, analyticsKey.getExpression(), element);
                convertDataType(dataArray, (i + startIndex), analyticsKey, expression);

            } else if (analyticsKey.getVariable() != null && analyticsKey.getPart() == null) {
                if (analyticsKey.getQuery() == null) {
                    String variable = context.readVariable(analyticsKey.getVariable()).getTextContent();

                    convertDataType(dataArray, (i + startIndex), analyticsKey, variable);
                    /* simple types should be specified for here */

                } else {
                    String errMsg = "This functionality is currently not supported";
                    log.error(errMsg);
                    handleException(errMsg);
                }
            } else if (analyticsKey.getVariable() != null && analyticsKey.getPart() != null) {
                NodeList childNodes = context.readVariable(analyticsKey.getVariable()).getChildNodes();
                String result = null;
                String part = analyticsKey.getPart();
                for (int j = 0; j < childNodes.getLength(); j++) {
                    Node item = childNodes.item(j);
                    if (item != null && item.getNodeType() == Node.ELEMENT_NODE
                            && item.getLocalName().equals(part)) {
                        /* remove the payload part */
                        result = DOMUtils.domToString(DOMUtils.getFirstChildElement(item));
                    }
                }
                convertDataType(dataArray, (i + startIndex), analyticsKey, result);
                dataArray[i + startIndex] = result;
            }
        }
    }

    private String evaluateXPathExpression(ExtensionContext context, String xpath, Element element)
            throws FaultException {
        String result = "";
        QName qnVariableData = new QName(Namespaces.BPEL11_NS, "getVariableData");
        QName qnGetVariableProperty = new QName(Namespaces.BPEL11_NS, "getVariableProperty");
        QName qnGetLinkStatus = new QName(Namespaces.BPEL11_NS, "getLinkStatus");
        QName qnDoXslTransform = new QName(Namespaces.BPEL11_NS, "getDoXslTransform");

        OXPath20ExpressionBPEL20 oexpr = new OXPath20ExpressionBPEL20(
                context.getInternalInstance().getProcessModel().getOwner(), qnVariableData, qnGetVariableProperty,
                qnGetLinkStatus, qnDoXslTransform, false);

        OExpressionLanguage oExpressionLanguage = new OExpressionLanguage(context.getProcessModel().getOwner(),
                null);
        oExpressionLanguage.expressionLanguageUri = "urn:oasis:names:tc:wsbpel:2.0:sublang:xpath2.0";
        oexpr.expressionLanguage = oExpressionLanguage;

        oExpressionLanguage.properties.put("runtime-class",
                "org.apache.ode.bpel.elang.xpath20.runtime.XPath20ExpressionRuntime");

        try {
            context.getInternalInstance().getExpLangRuntime().registerRuntime(oExpressionLanguage);
        } catch (ConfigurationException ex) {
            String errMsg = "Error when trying to register xpath runtime";
            log.error(errMsg, ex);
            handleException(errMsg, ex);
        }
        oexpr.insertMissingData = true;
        ScopeFrame scopeFrame = ((ExtensionContextImpl) context).getScopeFrame();
        ExprEvaluationContextImpl exprEvaluationContext = new ExprEvaluationContextImpl(scopeFrame,
                context.getInternalInstance());

        oexpr.vars = (HashMap) context.getVisibleVariables();

        oexpr.namespaceCtx = context.getProcessModel().namespaceContext;

        try {
            oexpr.xpath = xpath;
            List resultList = context.getInternalInstance().getExpLangRuntime().evaluate(oexpr,
                    exprEvaluationContext);
            if (result != null) {
                Iterator iterator = resultList.iterator();
                /** for analytics publishing to work, there should only be a single node here */
                while (iterator.hasNext()) {
                    Node node = ((Node) iterator.next());
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        result += node.getTextContent();
                    } else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
                        result += node.getNodeValue();
                    }
                }
            }
        } catch (EvaluationException e) {
            String errMsg = "Xpath evaluation failed";
            log.error(errMsg);
            handleException(errMsg, e);
        }
        return result;
    }

    private DataPublisher getDataPublisher(ExtensionContext context, int tenantId,
            String analyticsServerProfileName) throws FaultException {

        DataPublisher dataPublisher = null;
        TenantProcessStore tenantsProcessStore = AnalyticsPublisherServiceComponent.getBPELServer()
                .getMultiTenantProcessStore().getTenantsProcessStore(tenantId);

        String processName = context.getProcessModel().getName().toString();

        dataPublisher = (DataPublisher) tenantsProcessStore.getDataPublisher(processName);

        // Create new DataPublisher if not created already.
        if (dataPublisher == null) {
            AnalyticsServerProfile analyticsServerProfile = getAnalyticsServerProfile(tenantId,
                    analyticsServerProfileName);
            try {
                dataPublisher = new DataPublisher(analyticsServerProfile.getType(),
                        analyticsServerProfile.getReceiverURLSet(), analyticsServerProfile.getAuthURLSet(),
                        analyticsServerProfile.getUserName(), analyticsServerProfile.getPassword());
            } catch (TransportException e) {
                String errorMsg = "Transport layer problem.";
                handleException(errorMsg, e);
            } catch (DataEndpointAuthenticationException e) {
                String errorMsg = "Data endpoint authentication problem.";
                handleException(errorMsg, e);
            } catch (DataEndpointAgentConfigurationException e) {
                String errorMsg = "Data endpoint agent configuration problem.";
                handleException(errorMsg, e);
            } catch (DataEndpointException e) {
                String errorMsg = "Data endpoint problem.";
                handleException(errorMsg, e);
            } catch (DataEndpointConfigurationException e) {
                String errorMsg = "Data endpoint configuration problem.";
                handleException(errorMsg, e);
            }
            if (log.isDebugEnabled()) {
                log.debug("Data Publisher Created : " + analyticsServerProfile.toString());
            }
            if (dataPublisher != null) {
                tenantsProcessStore.addDataPublisher(processName, dataPublisher);
            }
        }
        return dataPublisher;
    }

    public void convertDataType(Object[] dataArray, int index, AnalyticsKey key, String value) {
        AnalyticsKey.AnalyticsKeyDataType dataType = key.getDataType();
        switch (dataType) {
        case INTEGER:
            dataArray[index] = Integer.valueOf(value);
            break;
        case LONG:
            dataArray[index] = Long.valueOf(value);
            break;
        case DOUBLE:
            dataArray[index] = Double.valueOf(value);
            break;
        case FLOAT:
            dataArray[index] = Float.valueOf(value);
            break;
        case BOOL:
            dataArray[index] = Boolean.valueOf(value);
            break;
        case STRING:
            dataArray[index] = String.valueOf(value);
            break;
        default:
            dataArray[index] = String.valueOf(value);
            break;
        }
    }
}