001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.support;
014:
015: import java.util.ArrayList;
016: import java.util.Iterator;
017: import java.util.List;
018: import java.util.Map;
019:
020: import javax.wsdl.Binding;
021: import javax.wsdl.BindingOperation;
022: import javax.wsdl.Part;
023: import javax.wsdl.Port;
024: import javax.wsdl.Service;
025: import javax.xml.namespace.QName;
026:
027: import org.apache.log4j.Logger;
028: import org.apache.xmlbeans.SchemaGlobalElement;
029: import org.apache.xmlbeans.SchemaType;
030: import org.apache.xmlbeans.XmlException;
031: import org.apache.xmlbeans.XmlObject;
032:
033: import com.eviware.soapui.impl.wsdl.WsdlInterface;
034: import com.eviware.soapui.impl.wsdl.WsdlOperation;
035: import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
036: import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
037: import com.eviware.soapui.model.iface.Operation;
038:
039: /**
040: * XmlObject based wrapper for manipulation, etc..
041: *
042: * @author Ole.Matzura
043: */
044:
045: public class MessageXmlObject {
046: private XmlObject messageObj;
047: private WsdlContext wsdlContext;
048: private List<MessageXmlPart> messageParts = new ArrayList<MessageXmlPart>();
049:
050: private final static Logger log = Logger
051: .getLogger(MessageXmlObject.class);
052: private final String messageContent;
053: private Operation operation;
054: private final boolean isRequest;
055:
056: public MessageXmlObject(WsdlOperation operation,
057: String messageContent, boolean isRequest) {
058: this .messageContent = messageContent;
059: this .operation = operation;
060: this .isRequest = isRequest;
061: wsdlContext = ((WsdlInterface) operation.getInterface())
062: .getWsdlContext();
063: }
064:
065: public String getMessageContent() {
066: if (messageObj == null) {
067: return messageContent;
068: } else {
069: for (int c = 0; c < messageParts.size(); c++)
070: messageParts.get(c).update();
071:
072: return messageObj.xmlText();
073: }
074: }
075:
076: public XmlObject getMessageObj() throws XmlException {
077: if (messageObj == null) {
078: messageObj = XmlObject.Factory.parse(getMessageContent());
079: }
080:
081: return messageObj;
082: }
083:
084: public MessageXmlPart[] getMessageParts() throws Exception {
085: String operationName = operation.getName();
086: BindingOperation bindingOperation = findBindingOperation(operationName);
087: if (bindingOperation == null) {
088: throw new Exception("Missing operation [" + operationName
089: + "] in wsdl definition");
090: }
091:
092: if (!wsdlContext.hasSchemaTypes()) {
093: throw new Exception("Missing schema types for message");
094: }
095:
096: XmlObject msgXml = getMessageObj();
097: Part[] inputParts = WsdlUtils.getInputParts(bindingOperation);
098: messageParts.clear();
099:
100: if (WsdlUtils.isRpc(wsdlContext.getDefinition(),
101: bindingOperation)) {
102: // get root element
103: XmlObject[] paths = msgXml
104: .selectPath("declare namespace env='"
105: + wsdlContext.getSoapVersion()
106: .getEnvelopeNamespace()
107: + "';"
108: + "declare namespace ns='"
109: + wsdlContext.getDefinition()
110: .getTargetNamespace() + "';"
111: + "$this/env:Envelope/env:Body/ns:"
112: + bindingOperation.getName());
113:
114: if (paths.length != 1) {
115: throw new Exception("Missing message wrapper element ["
116: + wsdlContext.getDefinition()
117: .getTargetNamespace() + "@"
118: + bindingOperation.getName());
119: } else {
120: XmlObject wrapper = paths[0];
121:
122: for (int i = 0; i < inputParts.length; i++) {
123: Part part = inputParts[i];
124:
125: QName partName = part.getElementName();
126: if (partName == null)
127: partName = new QName(part.getName());
128:
129: XmlObject[] children = wrapper
130: .selectChildren(partName);
131:
132: // attachment part?
133: if (WsdlUtils.isAttachmentInputPart(part,
134: bindingOperation)) {
135: // not required
136: if (children.length == 1) {
137: QName typeName = part.getTypeName();
138: SchemaType type = typeName == null ? null
139: : wsdlContext.getSchemaTypeLoader()
140: .findType(typeName);
141: messageParts.add(new MessageXmlPart(
142: children[0], type, part,
143: bindingOperation, isRequest));
144: }
145: } else if (children.length != 1) {
146: log.error("Missing message part ["
147: + part.getName() + "]");
148: } else {
149: QName typeName = part.getTypeName();
150: if (typeName == null) {
151: typeName = partName;
152: SchemaGlobalElement type = wsdlContext
153: .getSchemaTypeLoader().findElement(
154: typeName);
155:
156: if (type != null) {
157: messageParts.add(new MessageXmlPart(
158: children[0], type.getType(),
159: part, bindingOperation,
160: isRequest));
161: } else
162: log
163: .error("Missing element ["
164: + typeName
165: + "] in associated schema for part ["
166: + part.getName() + "]");
167: } else {
168: SchemaType type = wsdlContext
169: .getSchemaTypeLoader().findType(
170: typeName);
171: if (type != null) {
172: messageParts.add(new MessageXmlPart(
173: children[0], type, part,
174: bindingOperation, isRequest));
175: } else
176: log
177: .error("Missing type ["
178: + typeName
179: + "] in associated schema for part ["
180: + part.getName() + "]");
181: }
182: }
183: }
184: }
185: } else {
186: Part part = inputParts[0];
187: QName elementName = part.getElementName();
188: if (elementName != null) {
189: // just check for correct message element, other elements are avoided (should create an error)
190: XmlObject[] paths = msgXml
191: .selectPath("declare namespace env='"
192: + wsdlContext.getSoapVersion()
193: .getEnvelopeNamespace() + "';"
194: + "declare namespace ns='"
195: + elementName.getNamespaceURI() + "';"
196: + "$this/env:Envelope/env:Body/ns:"
197: + elementName.getLocalPart());
198:
199: if (paths.length == 1) {
200: SchemaGlobalElement elm = wsdlContext
201: .getSchemaTypeLoader().findElement(
202: elementName);
203: if (elm != null) {
204: messageParts.add(new MessageXmlPart(paths[0],
205: elm.getType(), part, bindingOperation,
206: isRequest));
207: } else
208: throw new Exception(
209: "Missing part type in associated schema");
210: } else
211: throw new Exception(
212: "Missing message part with name ["
213: + elementName + "]");
214: }
215: }
216:
217: return messageParts.toArray(new MessageXmlPart[messageParts
218: .size()]);
219: }
220:
221: private BindingOperation findBindingOperation(String operationName)
222: throws Exception {
223: Map services = wsdlContext.getDefinition().getAllServices();
224: Iterator i = services.keySet().iterator();
225: while (i.hasNext()) {
226: Service service = (Service) wsdlContext.getDefinition()
227: .getService((QName) i.next());
228: Map ports = service.getPorts();
229:
230: Iterator iterator = ports.keySet().iterator();
231: while (iterator.hasNext()) {
232: Port port = (Port) service.getPort((String) iterator
233: .next());
234: BindingOperation bindingOperation = port.getBinding()
235: .getBindingOperation(operationName, null, null);
236: if (bindingOperation != null)
237: return bindingOperation;
238: }
239: }
240:
241: Map bindings = wsdlContext.getDefinition().getAllBindings();
242: i = bindings.keySet().iterator();
243: while (i.hasNext()) {
244: Binding binding = (Binding) bindings.get(i.next());
245: BindingOperation bindingOperation = binding
246: .getBindingOperation(operationName, null, null);
247: if (bindingOperation != null)
248: return bindingOperation;
249: }
250:
251: return null;
252: }
253: }
|