/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.riftsaw.engine.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.iapi.BpelEngineException;
import org.apache.ode.bpel.iapi.ContextException;
import org.apache.ode.bpel.iapi.Message;
import org.apache.ode.bpel.iapi.MessageExchange;
import org.apache.ode.bpel.iapi.MessageExchangeContext;
import org.apache.ode.bpel.iapi.MyRoleMessageExchange;
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
import org.riftsaw.engine.Fault;
import org.riftsaw.engine.Service;
import org.riftsaw.engine.ServiceLocator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Implementation of the ODE {@link org.apache.ode.bpel.iapi.MessageExchangeContext}
* interface. This class is used by the ODE engine to make invocation of external
* services using Axis.
*/
public class MessageExchangeContextImpl implements MessageExchangeContext {
private ServiceLocator _locator=null;
private static final Log LOG = LogFactory.getLog(MessageExchangeContextImpl.class);
/**
* This is the constructor.
*
* @param locator The service locator
*/
public MessageExchangeContextImpl(ServiceLocator locator) {
_locator = locator;
}
/**
* {@inheritDoc}
*/
public void invokePartnerUnreliable(PartnerRoleMessageExchange partnerRoleMessageExchange)
throws ContextException {
if (LOG.isDebugEnabled()) {
LOG.debug("Invoking a partner operation: " + partnerRoleMessageExchange.getOperationName());
}
PartnerRoleChannelImpl channel=(PartnerRoleChannelImpl)
partnerRoleMessageExchange.getChannel();
Service service=_locator.getService(partnerRoleMessageExchange.getCaller(),
channel.getEndpoint().serviceName,
channel.getEndpoint().portName);
if (service != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Invoke service="+service);
}
try {
Map<String, Node> headerParts = partnerRoleMessageExchange.getRequest().getHeaderParts();
Map<String, Object> transferedHeaderParts = new HashMap<String, Object>();
Set<String> keys = headerParts.keySet();
for (String key : keys) {
Element e = (Element)partnerRoleMessageExchange.getRequest().getHeaderPart(key).getFirstChild();
String k;
if (e.getNamespaceURI() == null || e.getNamespaceURI().isEmpty()) {
k = e.getLocalName();
} else {
k = "{"+e.getNamespaceURI()+"}" + e.getLocalName();
}
transferedHeaderParts.put(k, e);
}
Element resp=service.invoke(partnerRoleMessageExchange.getOperationName(),
partnerRoleMessageExchange.getRequest().getMessage(),
transferedHeaderParts);
if (partnerRoleMessageExchange.getMessageExchangePattern()
== MessageExchange.MessageExchangePattern.REQUEST_RESPONSE) {
Message responseMessage = partnerRoleMessageExchange.createMessage(
partnerRoleMessageExchange.getOperation().getOutput().getMessage().getQName());
responseMessage.setMessage(resp);
// Associate header values with response message
for (String key : transferedHeaderParts.keySet()) {
QName qname=QName.valueOf(key);
if (transferedHeaderParts.get(key) instanceof Element) {
responseMessage.setHeaderPart(qname.getLocalPart(),
(Element)transferedHeaderParts.get(key));
} else {
LOG.warn("Header part for '"+key+"' was not an Element");
}
}
partnerRoleMessageExchange.reply(responseMessage);
}
} catch (Fault f) {
QName faultName=f.getFaultName();
javax.wsdl.Fault fault=null;
if (faultName != null) {
fault = partnerRoleMessageExchange.getOperation().getFault(faultName.getLocalPart());
}
QName faultType=null;
if (fault == null) {
faultType = new QName(f.getFaultMessage().getNamespaceURI(),
f.getFaultMessage().getLocalName());
if (LOG.isTraceEnabled()) {
LOG.trace("Fault type from element = "+faultType);
}
} else {
faultType = fault.getMessage().getQName();
if (LOG.isTraceEnabled()) {
LOG.trace("Fault type from message QName = "+faultType);
}
}
Message faultMessage = partnerRoleMessageExchange.createMessage(
faultType);
faultMessage.setMessage(f.getFaultMessage());
partnerRoleMessageExchange.replyWithFault(faultName, faultMessage);
} catch (Exception e) {
throw new ContextException("Failed to invoke external service", e);
}
}
}
/**
* {@inheritDoc}
*/
public void invokePartnerReliable(PartnerRoleMessageExchange mex) throws ContextException {
// TODO: tie in to WS-RELIABLE* stack.
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
public void invokePartnerTransacted(PartnerRoleMessageExchange mex) throws ContextException {
// TODO: should we check if the partner actually supports transactions?
invokePartnerUnreliable(mex);
}
/**
* {@inheritDoc}
*/
public void onMyRoleMessageExchangeStateChanged(MyRoleMessageExchange myRoleMessageExchange) throws BpelEngineException {
// Add code here to handle MEXs that we've "forgotten" about due to system failure etc.. mostly
// useful for RELIABLE, but nice to have with ASYNC/BLOCKING as well.
}
/**
* {@inheritDoc}
*/
public void cancel(PartnerRoleMessageExchange mex) throws ContextException {
}
/**
* {@inheritDoc}
*/
public void invokePartner(PartnerRoleMessageExchange mex)
throws ContextException {
if (LOG.isDebugEnabled()) {
LOG.debug("Invoking a partner operation: " + mex.getOperationName());
}
invokePartnerUnreliable(mex);
}
/**
* {@inheritDoc}
*/
public void onAsyncReply(MyRoleMessageExchange mex)
throws BpelEngineException {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing an async reply from service " + mex.getServiceName());
}
// Nothing to do, no callback is necessary, the client just synchornizes itself with the
// mex reply when invoking the engine.
}
}