/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.support;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
import com.eviware.soapui.support.xml.XmlUtils;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import javax.wsdl.BindingOperation;
import javax.wsdl.Part;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
/**
* XmlObject based wrapper for manipulation, etc..
*
* @author Ole.Matzura
*/
public class MessageXmlObject {
private XmlObject messageObj;
private WsdlContext wsdlContext;
private List<MessageXmlPart> messageParts = new ArrayList<MessageXmlPart>();
private final static Logger log = Logger.getLogger(MessageXmlObject.class);
private final String messageContent;
private WsdlOperation operation;
private final boolean isRequest;
public MessageXmlObject(WsdlOperation operation, String messageContent, boolean isRequest) {
this.messageContent = messageContent;
this.operation = operation;
this.isRequest = isRequest;
wsdlContext = operation.getInterface().getWsdlContext();
}
public String getMessageContent() {
if (messageObj == null) {
return messageContent;
} else {
for (int c = 0; c < messageParts.size(); c++) {
messageParts.get(c).update();
}
return messageObj.xmlText();
}
}
public XmlObject getMessageObj() throws XmlException {
if (messageObj == null) {
// messageObj = XmlObject.Factory.parse( getMessageContent() );
messageObj = XmlUtils.createXmlObject(getMessageContent(), XmlUtils.createDefaultXmlOptions());
}
return messageObj;
}
public MessageXmlPart[] getMessageParts() throws Exception {
String operationName = operation.getName();
BindingOperation bindingOperation = operation.getBindingOperation();
if (bindingOperation == null) {
throw new Exception("Missing operation [" + operationName + "] in wsdl definition");
}
if (!wsdlContext.hasSchemaTypes()) {
throw new Exception("Missing schema types for message");
}
XmlObject msgXml = getMessageObj();
Part[] inputParts = isRequest ? WsdlUtils.getInputParts(bindingOperation) : WsdlUtils
.getOutputParts(bindingOperation);
messageParts.clear();
if (WsdlUtils.isRpc(wsdlContext.getDefinition(), bindingOperation)) {
// get root element
XmlObject[] paths = msgXml.selectPath("declare namespace env='"
+ wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" + "declare namespace ns='"
+ WsdlUtils.getTargetNamespace(wsdlContext.getDefinition()) + "';" + "$this/env:Envelope/env:Body/ns:"
+ bindingOperation.getName());
if (paths.length != 1) {
throw new Exception("Missing message wrapper element ["
+ WsdlUtils.getTargetNamespace(wsdlContext.getDefinition()) + "@" + bindingOperation.getName());
} else {
XmlObject wrapper = paths[0];
for (int i = 0; i < inputParts.length; i++) {
Part part = inputParts[i];
QName partName = part.getElementName();
if (partName == null) {
partName = new QName(part.getName());
}
XmlObject[] children = wrapper.selectChildren(partName);
// attachment part?
if (WsdlUtils.isAttachmentInputPart(part, bindingOperation)) {
// not required
if (children.length == 1) {
QName typeName = part.getTypeName();
SchemaType type = typeName == null ? null : wsdlContext.getSchemaTypeLoader().findType(typeName);
messageParts.add(new MessageXmlPart(children[0], type, part, bindingOperation, isRequest));
}
} else if (children.length != 1) {
log.error("Missing message part [" + part.getName() + "]");
} else {
QName typeName = part.getTypeName();
if (typeName == null) {
typeName = partName;
SchemaGlobalElement type = wsdlContext.getSchemaTypeLoader().findElement(typeName);
if (type != null) {
messageParts.add(new MessageXmlPart(children[0], type.getType(), part, bindingOperation,
isRequest));
} else {
log.error("Missing element [" + typeName + "] in associated schema for part ["
+ part.getName() + "]");
}
} else {
SchemaType type = wsdlContext.getSchemaTypeLoader().findType(typeName);
if (type != null) {
messageParts.add(new MessageXmlPart(children[0], type, part, bindingOperation, isRequest));
} else {
log.error("Missing type [" + typeName + "] in associated schema for part [" + part.getName()
+ "]");
}
}
}
}
}
} else {
Part part = inputParts[0];
QName elementName = part.getElementName();
if (elementName != null) {
// just check for correct message element, other elements are
// avoided (should create an error)
XmlObject[] paths = msgXml.selectPath("declare namespace env='"
+ wsdlContext.getSoapVersion().getEnvelopeNamespace() + "';" + "declare namespace ns='"
+ elementName.getNamespaceURI() + "';" + "$this/env:Envelope/env:Body/ns:"
+ elementName.getLocalPart());
if (paths.length == 1) {
SchemaGlobalElement elm = wsdlContext.getSchemaTypeLoader().findElement(elementName);
if (elm != null) {
messageParts.add(new MessageXmlPart(paths[0], elm.getType(), part, bindingOperation, isRequest));
} else {
throw new Exception("Missing part type in associated schema");
}
} else {
throw new Exception("Missing message part with name [" + elementName + "]");
}
}
}
return messageParts.toArray(new MessageXmlPart[messageParts.size()]);
}
}