Package org.apache.ode.bpel.engine

Source Code of org.apache.ode.bpel.engine.PartnerLinkMyRoleImpl

/*
* 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.bpel.engine;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.common.CorrelationKey;
import org.apache.ode.bpel.common.FaultException;
import org.apache.ode.bpel.common.InvalidMessageException;
import org.apache.ode.bpel.dao.CorrelatorDAO;
import org.apache.ode.bpel.dao.MessageRouteDAO;
import org.apache.ode.bpel.dao.ProcessDAO;
import org.apache.ode.bpel.dao.ProcessInstanceDAO;
import org.apache.ode.bpel.evt.CorrelationMatchEvent;
import org.apache.ode.bpel.evt.CorrelationNoMatchEvent;
import org.apache.ode.bpel.evt.NewProcessInstanceEvent;
import org.apache.ode.bpel.iapi.Endpoint;
import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.MyRoleMessageExchange;
import org.apache.ode.bpel.iapi.ProcessState;
import org.apache.ode.bpel.intercept.InterceptorInvoker;
import org.apache.ode.bpel.o.OMessageVarType;
import org.apache.ode.bpel.o.OPartnerLink;
import org.apache.ode.bpel.o.OProcess;
import org.apache.ode.bpel.o.OScope;
import org.apache.ode.bpel.runtime.InvalidProcessException;
import org.apache.ode.bpel.runtime.PROCESS;
import org.apache.ode.utils.ArrayUtils;
import org.apache.ode.utils.ObjectPrinter;
import org.apache.ode.utils.msg.MessageBundle;
import org.w3c.dom.Element;

import javax.wsdl.Operation;
import javax.xml.namespace.QName;
import java.util.*;

/**
* @author Matthieu Riou <mriou at apache dot org>
*/
class PartnerLinkMyRoleImpl extends PartnerLinkRoleImpl {
    private static final Log __log = LogFactory.getLog(BpelProcess.class);
    private static final Messages __msgs = MessageBundle.getMessages(Messages.class);

    /** The local endpoint for this "myrole". */
    public Endpoint _endpoint;

    PartnerLinkMyRoleImpl(BpelProcess process, OPartnerLink plink, Endpoint endpoint) {
        super(process, plink);
        _endpoint = endpoint;
    }

    public String toString() {
        StringBuffer buf = new StringBuffer("{PartnerLinkRole-");
        buf.append(_plinkDef.name);
        buf.append('.');
        buf.append(_plinkDef.myRoleName);
        buf.append(" on ");
        buf.append(_endpoint);
        buf.append('}');

        return buf.toString();
    }

    /**
     * Called when an input message has been received.
     *
     * @param mex
     *            exchange to which the message is related
     */
    public void invokeMyRole(MyRoleMessageExchangeImpl mex) {
        if (__log.isTraceEnabled()) {
            __log.trace(ObjectPrinter.stringifyMethodEnter(this + ":inputMsgRcvd", new Object[] {
                    "messageExchange", mex }));
        }

        Operation operation = getMyRoleOperation(mex.getOperationName());
        if (operation == null) {
            __log.error(__msgs.msgUnknownOperation(mex.getOperationName(), _plinkDef.myRolePortType.getQName()));
            mex.setFailure(MessageExchange.FailureType.UNKNOWN_OPERATION, mex.getOperationName(), null);
            return;
        }

        mex.getDAO().setPartnerLinkModelId(_plinkDef.getId());
        mex.setPortOp(_plinkDef.myRolePortType, operation);
        mex.setPattern(operation.getOutput() == null ? MessageExchange.MessageExchangePattern.REQUEST_ONLY
                : MessageExchange.MessageExchangePattern.REQUEST_RESPONSE);

        // Is this a /possible/ createInstance Operation?
        boolean isCreateInstnace = _plinkDef.isCreateInstanceOperation(operation);

        // now, the tricks begin: when a message arrives we have to see if
        // there
        // is anyone waiting for it.
        // Get the correlator, a persisted communnication-reduction data
        // structure
        // supporting correlation correlationKey matching!
        String correlatorId = BpelProcess.genCorrelatorId(_plinkDef, operation.getName());

        CorrelatorDAO correlator = _process.getProcessDAO().getCorrelator(correlatorId);

        CorrelationKey[] keys;
        MessageRouteDAO messageRoute = null;

        // We need to compute the correlation keys (based on the operation
        // we can  infer which correlation keys to compute - this is merely a set
        // consisting of each correlationKey used in each correlation sets
        // that is ever referenced in an <receive>/<onMessage> on this
        // partnerlink/operation.
        try {
            keys = computeCorrelationKeys(mex);
        } catch (InvalidMessageException ime) {
            // We'd like to do a graceful exit here, no sense in rolling back due to a
            // a message format problem.
            __log.debug("Unable to evaluate correlation keys, invalid message format. ",ime);
            mex.setFailure(MessageExchange.FailureType.FORMAT_ERROR, ime.getMessage(), null);
            return;
        }

        String mySessionId = mex.getProperty(MessageExchange.PROPERTY_SEP_MYROLE_SESSIONID);
        String partnerSessionId = mex.getProperty(MessageExchange.PROPERTY_SEP_PARTNERROLE_SESSIONID);
        if (__log.isDebugEnabled()) {
            __log.debug("INPUTMSG: " + correlatorId + ": MSG RCVD keys="
                    + ArrayUtils.makeCollection(HashSet.class, keys) + " mySessionId=" + mySessionId
                    + " partnerSessionId=" + partnerSessionId);
        }

        CorrelationKey matchedKey = null;

        // Try to find a route for one of our keys.
        for (CorrelationKey key : keys) {
            messageRoute = correlator.findRoute(key);
            if (messageRoute != null) {
                if (__log.isDebugEnabled()) {
                    __log.debug("INPUTMSG: " + correlatorId + ": ckey " + key + " route is to " + messageRoute);
                }
                matchedKey = key;
                break;
            }
        }

        // TODO - ODE-58

        // If no luck, and this operation qualifies for create-instance
        // treatment, then create a new process
        // instance.
        if (messageRoute == null && isCreateInstnace) {
            if (__log.isDebugEnabled()) {
                __log.debug("INPUTMSG: " + correlatorId + ": routing failed, CREATING NEW INSTANCE");
            }
            ProcessDAO processDAO = _process.getProcessDAO();

            if (_process._pconf.getState() == ProcessState.RETIRED) {
                throw new InvalidProcessException("Process is retired.", InvalidProcessException.RETIRED_CAUSE_CODE);
            }

            if (!_process.processInterceptors(mex, InterceptorInvoker.__onNewInstanceInvoked)) {
                __log.debug("Not creating a new instance for mex " + mex + "; interceptor prevented!");
                return;
            }

            ProcessInstanceDAO newInstance = processDAO.createInstance(correlator);

            BpelRuntimeContextImpl instance = _process
                    .createRuntimeContext(newInstance, new PROCESS(_process.getOProcess()), mex);

            // send process instance event
            NewProcessInstanceEvent evt = new NewProcessInstanceEvent(new QName(_process.getOProcess().targetNamespace,
                    _process.getOProcess().getName()), _process.getProcessDAO().getProcessId(), newInstance.getInstanceId());
            evt.setPortType(mex.getPortType().getQName());
            evt.setOperation(operation.getName());
            evt.setMexId(mex.getMessageExchangeId());
            _process._debugger.onEvent(evt);
            _process.saveEvent(evt, newInstance);
            mex.setCorrelationStatus(MyRoleMessageExchange.CorrelationStatus.CREATE_INSTANCE);
            mex.getDAO().setInstance(newInstance);

            instance.execute();
        } else if (messageRoute != null) {
            if (__log.isDebugEnabled()) {
                __log.debug("INPUTMSG: " + correlatorId + ": ROUTING to instance "
                        + messageRoute.getTargetInstance().getInstanceId());
            }

            ProcessInstanceDAO instanceDao = messageRoute.getTargetInstance();

            // Reload process instance for DAO.
            BpelRuntimeContextImpl instance = _process.createRuntimeContext(instanceDao, null, null);
            instance.inputMsgMatch(messageRoute.getGroupId(), messageRoute.getIndex(), mex);

            // Kill the route so some new message does not get routed to
            // same process instance.
            correlator.removeRoutes(messageRoute.getGroupId(), instanceDao);

            // send process instance event
            CorrelationMatchEvent evt = new CorrelationMatchEvent(new QName(_process.getOProcess().targetNamespace,
                    _process.getOProcess().getName()), _process.getProcessDAO().getProcessId(),
                    instanceDao.getInstanceId(), matchedKey);
            evt.setPortType(mex.getPortType().getQName());
            evt.setOperation(operation.getName());
            evt.setMexId(mex.getMessageExchangeId());

            _process._debugger.onEvent(evt);
            // store event
            _process.saveEvent(evt, instanceDao);

            // EXPERIMENTAL -- LOCK
            // instanceDao.lock();

            mex.setCorrelationStatus(MyRoleMessageExchange.CorrelationStatus.MATCHED);
            mex.getDAO().setInstance(messageRoute.getTargetInstance());
            instance.execute();
        } else {
            if (__log.isDebugEnabled()) {
                __log.debug("INPUTMSG: " + correlatorId + ": SAVING to DB (no match) ");
            }

            if (!mex.isAsynchronous()) {
                mex.setFailure(MessageExchange.FailureType.NOMATCH, "No process instance matching correlation keys.", null);

            } else {
                // send event
                CorrelationNoMatchEvent evt = new CorrelationNoMatchEvent(mex.getPortType().getQName(), mex
                        .getOperation().getName(), mex.getMessageExchangeId(), keys);

                evt.setProcessId(_process.getProcessDAO().getProcessId());
                evt.setProcessName(new QName(_process.getOProcess().targetNamespace, _process.getOProcess().getName()));
                _process._debugger.onEvent(evt);

                mex.setCorrelationStatus(MyRoleMessageExchange.CorrelationStatus.QUEUED);

                // No match, means we add message exchange to the queue.
                correlator.enqueueMessage(mex.getDAO(), keys);

            }
        }

        // Now we have to update our message exchange status. If the <reply>
        // was not hit during the
        // invocation, then we will be in the "REQUEST" phase which means
        // that either this was a one-way
        // or a two-way that needs to delivery the reply asynchronously.
        if (mex.getStatus() == MessageExchange.Status.REQUEST) {
            mex.setStatus(MessageExchange.Status.ASYNC);
        }
    }

    @SuppressWarnings("unchecked")
    private Operation getMyRoleOperation(String operationName) {
        Operation op = _plinkDef.getMyRoleOperation(operationName);
        return op;
    }

    private CorrelationKey[] computeCorrelationKeys(MyRoleMessageExchangeImpl mex) {
        Operation operation = mex.getOperation();
        Element msg = mex.getRequest().getMessage();
        javax.wsdl.Message msgDescription = operation.getInput().getMessage();
        List<CorrelationKey> keys = new ArrayList<CorrelationKey>();

        Set<OScope.CorrelationSet> csets = _plinkDef.getCorrelationSetsForOperation(operation);

        for (OScope.CorrelationSet cset : csets) {
            CorrelationKey key = computeCorrelationKey(cset,
                    _process.getOProcess().messageTypes.get(msgDescription.getQName()), msg);
            keys.add(key);
        }

        // Let's creata a key based on the sessionId
        String mySessionId = mex.getProperty(MessageExchange.PROPERTY_SEP_MYROLE_SESSIONID);
        if (mySessionId != null)
            keys.add(new CorrelationKey(-1, new String[] { mySessionId }));

        return keys.toArray(new CorrelationKey[keys.size()]);
    }

    private CorrelationKey computeCorrelationKey(OScope.CorrelationSet cset, OMessageVarType messagetype,
            Element msg) {
        String[] values = new String[cset.properties.size()];

        int jIdx = 0;
        for (Iterator j = cset.properties.iterator(); j.hasNext(); ++jIdx) {
            OProcess.OProperty property = (OProcess.OProperty) j.next();
            OProcess.OPropertyAlias alias = property.getAlias(messagetype);

            if (alias == null) {
                // TODO: Throw a real exception! And catch this at compile
                // time.
                throw new IllegalArgumentException("No alias matching property '" + property.name
                        + "' with message type '" + messagetype + "'");
            }

            String value;
            try {
                value = _process.extractProperty(msg, alias, msg.toString());
            } catch (FaultException fe) {
                String emsg = __msgs.msgPropertyAliasDerefFailedOnMessage(alias.getDescription(), fe.getMessage());
                __log.error(emsg, fe);
                throw new InvalidMessageException(emsg, fe);
            }
            values[jIdx] = value;
        }

        CorrelationKey key = new CorrelationKey(cset.getId(), values);
        return key;
    }

}
TOP

Related Classes of org.apache.ode.bpel.engine.PartnerLinkMyRoleImpl

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.