| /* |
| * 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.jbi.msgmap; |
| |
| import java.util.Collection; |
| |
| import javax.jbi.messaging.MessagingException; |
| import javax.jbi.messaging.NormalizedMessage; |
| import javax.wsdl.Fault; |
| import javax.wsdl.Message; |
| import javax.wsdl.Operation; |
| import javax.wsdl.Part; |
| import javax.xml.namespace.QName; |
| import javax.xml.transform.dom.DOMSource; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| import org.apache.ode.utils.DOMUtils; |
| |
| /** |
| * Mapper to handle messages that are single-part docliteral (WSDL2.0 style). |
| */ |
| public class DocLitMapper extends BaseXmlMapper implements Mapper { |
| |
| public Recognized isRecognized(NormalizedMessage nmsMsg, Operation op) { |
| Message in = op.getInput() == null ? null : op.getInput().getMessage(); |
| Message out = op.getOutput() == null ? null : op.getOutput().getMessage(); |
| |
| // First we check if the signature of the operation makes this mapper |
| // a possibility. |
| if (!checkMessageDef(in) || !checkMessageDef(out)) |
| return Recognized.FALSE; |
| |
| // Ok, if it is possible, then we have to check the content of the |
| // input message to see if it matches doc lit style, if the input |
| // message is empty, then we have an ambiguous match |
| if (in == null) |
| return Recognized.UNSURE; |
| |
| Part inpart = (Part) in.getParts().values().iterator().next(); |
| assert inpart != null; |
| assert inpart.getElementName() != null; |
| |
| Element msg; |
| try { |
| msg = parse(nmsMsg.getContent()); |
| } catch (MessageTranslationException e) { |
| __log.debug("Failed to parse NMS message: " + nmsMsg, e); |
| return Recognized.FALSE; |
| } |
| |
| QName elName = DOMUtils.getElementQName(msg); |
| |
| // If the message element matches the single part element, then |
| // we are using doc-lit style messaging. |
| return inpart.getElementName().equals(elName) ? Recognized.TRUE : Recognized.FALSE; |
| } |
| |
| public void toNMS(NormalizedMessage nmsMsg, |
| org.apache.ode.bpel.iapi.Message odeMsg, Message msgdef, QName fault) |
| throws MessagingException, MessageTranslationException { |
| |
| // If this is an unkown fault, just return an empty element |
| // built with the fault name |
| if (msgdef == null && fault != null) { |
| Document doc = newDocument(); |
| Element content = doc.createElementNS(fault.getNamespaceURI(), fault.getLocalPart()); |
| doc.appendChild(content); |
| nmsMsg.setContent(new DOMSource(doc)); |
| return; |
| } |
| |
| // For empty messages there is nothing to do. |
| if (msgdef == null || msgdef.getParts().size() == 0) |
| return; |
| |
| // The assertions assume isRecognized was called! |
| assert msgdef.getParts().size() == 1 : "multi part!"; |
| Part partdef = (Part) msgdef.getParts().values().iterator().next(); |
| assert partdef.getElementName() != null : "non-element part!"; |
| |
| if (odeMsg.getMessage() == null) { |
| String errmsg = "Unknown fault: " + odeMsg.getType(); |
| __log.debug(errmsg); |
| throw new MessageTranslationException(errmsg); |
| } |
| |
| Element part = DOMUtils.findChildByName(odeMsg.getMessage(),new QName(null, partdef.getName())); |
| if (part == null) { |
| String errmsg = "ODE message did not contain expected part: " + partdef.getName(); |
| __log.debug(errmsg); |
| throw new MessageTranslationException(errmsg); |
| } |
| |
| Element content = DOMUtils.findChildByName(part, partdef.getElementName()); |
| if (content == null) { |
| String errmsg = "ODE message did not contain element " + partdef.getElementName() + " in part: " + partdef.getName(); |
| __log.debug(errmsg); |
| throw new MessageTranslationException(errmsg); |
| } |
| |
| nmsMsg.setContent(new DOMSource(content)); |
| } |
| |
| public void toODE(org.apache.ode.bpel.iapi.Message odeMsg, |
| NormalizedMessage nmsMsg, Message msgdef) |
| throws MessageTranslationException { |
| |
| // The assertions assume isRecognized was called! |
| assert msgdef.getParts().size() == 1 : "multi part!"; |
| Part partdef = (Part) msgdef.getParts().values().iterator().next(); |
| assert partdef.getElementName() != null : "non-element part!"; |
| |
| Element el = parse(nmsMsg.getContent()); |
| if (!DOMUtils.getElementQName(el).equals(partdef.getElementName())) { |
| String errmsg = "NMS message did not contain element " + partdef.getElementName(); |
| __log.debug(errmsg); |
| throw new MessageTranslationException(errmsg); |
| } |
| |
| |
| Document doc = newDocument(); |
| Element msgel = doc.createElement("message"); |
| doc.appendChild(msgel); |
| Element pel = doc.createElement(partdef.getName()); |
| msgel.appendChild(pel); |
| pel.appendChild(doc.importNode(el,true)); |
| odeMsg.setMessage(msgel); |
| |
| } |
| |
| |
| public Fault toFaultType(javax.jbi.messaging.Fault jbiFlt, Collection<Fault> faults) throws MessageTranslationException { |
| Element el = parse(jbiFlt.getContent()); |
| QName elQname = new QName(el.getNamespaceURI(),el.getLocalName()); |
| for (Fault f : faults) { |
| if (f.getMessage() == null || f.getMessage().getParts().size() != 1) |
| continue; |
| javax.wsdl.Part pdef = (Part) f.getMessage().getParts().values().iterator().next(); |
| if (pdef.getElementName() == null) |
| continue; |
| if (pdef.getElementName().equals(elQname)) |
| return f; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Check if a message definition is compatible with doc-lit mapping. For |
| * WSDL1.1 this means that the message definition needs to have exactly one |
| * element part. |
| * |
| * @param msg |
| * message definition to check |
| * @return true if compatible, false otherwise |
| */ |
| private boolean checkMessageDef(Message msg) { |
| // Null messages are acceptable. |
| if (msg == null) |
| return true; |
| |
| // If we are non-empty, we need to have exactly one part. |
| if (msg.getParts().size() != 1) |
| return false; |
| |
| // The single part must also be an "element" typed part. |
| if (((Part) msg.getParts().values().iterator().next()).getElementName() == null) |
| return false; |
| |
| return true; |
| |
| } |
| |
| } |