001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)WrapperParserImpl.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.wsdl11wrapper.impl;
030:
031: import com.sun.jbi.wsdl11wrapper.util.WrapperUtil;
032: import com.sun.jbi.wsdl11wrapper.WrapperParser;
033: import com.sun.jbi.wsdl11wrapper.WrapperProcessingException;
034:
035: import java.util.Map;
036: import java.util.HashMap;
037: import java.util.ArrayList;
038: import java.util.List;
039: import javax.wsdl.Message;
040: import javax.wsdl.Definition;
041: import javax.xml.namespace.QName;
042: import org.w3c.dom.Element;
043: import org.w3c.dom.Node;
044: import org.w3c.dom.NodeList;
045: import org.w3c.dom.Document;
046:
047: /**
048: * Assists in processing the WSDL 1.1 wrapper for normalized messages specified by JBI
049: *
050: * @author aegloff
051: */
052: public class WrapperParserImpl implements WrapperParser {
053:
054: QName messageType;
055: String messageName;
056: Map wrappedParts = new HashMap();
057: List partsOrder;
058:
059: /** Creates a new instance */
060: public WrapperParserImpl() {
061: }
062:
063: /**
064: * Parse a normalized message document in JBI WSDL 1.1 wrapper format
065: * @param wrappedDoc the wrapped normalized message document
066: * @param wsdlDefinition the full wsdl definition, including the definition for the normalized message
067: * @throws WrapperProcessingException if there is an issue parsing the normalized message,
068: * e.g. if the normalized message could not be found in the WSDL
069: */
070: public void parse(Document wrappedDoc, Definition wsdlDefinition)
071: throws WrapperProcessingException {
072: QName wrapperMessageType = extractMessageType(wrappedDoc,
073: wsdlDefinition);
074: Message wsdlMessageDefinition = wsdlDefinition
075: .getMessage(wrapperMessageType);
076: if (wsdlMessageDefinition == null) {
077: throw new WrapperProcessingException(
078: "The WSDL definition provided does not contain a definition for the normalized message "
079: + wrapperMessageType.toString());
080: }
081: parse(wrappedDoc, wsdlMessageDefinition);
082: }
083:
084: /**
085: * Parse a normalized message document in JBI WSDL 1.1 wrapper format
086: * @param wrappedDoc the wrapped normalized message document
087: * @param wsdlMessageDefinition the wsdl message definition for the normalized message
088: * @throws WrapperProcessingException if there is an issue parsing the normalized message,
089: * e.g. if the normalized message does not match the WSDL description
090: */
091: public void parse(Document wrappedDoc, Message wsdlMessageDefinition)
092: throws WrapperProcessingException {
093:
094: // Re-set all internal state
095: wrappedParts.clear();
096:
097: // Get the jbi message wrapper element
098: Element jbiMessageWrapper = wrappedDoc.getDocumentElement();
099: QName unresolvedMessageType = extractMessageType(wrappedDoc,
100: null);
101: // Check that wsdl def passed is for this wrapped message
102: QName passedInDefQName = wsdlMessageDefinition.getQName();
103: if (!passedInDefQName.getLocalPart().equals(
104: unresolvedMessageType.getLocalPart())) {
105: throw new WrapperProcessingException(
106: "The WSDL message definition "
107: + passedInDefQName.getLocalPart()
108: + " does not match the name of the message wrapper of the normalized message ("
109: + unresolvedMessageType.getLocalPart()
110: + ")");
111: } else {
112: messageType = passedInDefQName;
113: }
114: messageName = extractMessageName(wrappedDoc);
115:
116: // Get the order of parts
117: WSDLInfo info = WSDLInfo.getInstance(wsdlMessageDefinition);
118: partsOrder = info.getPartsOrder();
119:
120: // The JBI wsdl 1.1 wrapper does not contain part names, but all parts
121: // have to appear in the exact order defined in the WSDL
122: NodeList childNodes = jbiMessageWrapper.getChildNodes();
123:
124: // Extract all JBI part wrapped elements
125: for (int childCount = 0; childCount < childNodes.getLength(); childCount++) {
126: Node currNode = childNodes.item(childCount);
127: if (currNode.getNodeType() == Node.ELEMENT_NODE) {
128: Element jbiPartWrapper = (Element) currNode;
129: int partPos = wrappedParts.size();
130: if (partPos >= partsOrder.size()) {
131: throw new WrapperProcessingException(
132: "The normalized message contains more parts than are defined in the WSDL message definition");
133: }
134: String partName = (String) partsOrder.get(partPos);
135: wrappedParts.put(partName, jbiPartWrapper);
136: }
137: }
138:
139: if (partsOrder.size() > wrappedParts.size()) {
140: throw new WrapperProcessingException(
141: "The normalized message contains less parts than are defined in the WSDL message definition");
142: }
143:
144: }
145:
146: /**
147: * Note that the spec mandates that all parts present in the WSDL message definition
148: * have to appear in the wrapped normalized message - as such this method has limited usefulness
149: *
150: * @param partName the name of the part to check
151: * @return true if the parsed document contains an entry for the given part - even if the part payload itself is empty.
152: * false if the part is not present
153: */
154: public boolean hasPart(String partName) {
155: return wrappedParts.containsKey(partName);
156: }
157:
158: /**
159: * Returns only the first Element inside the part wrapper
160: * Legally, the jbi:part may contain multiple Elements, or text - but
161: * in many cases the WSDL will limit this to one element.
162: *
163: * (a jbi:part element may legally contain multiple Elements, or text)
164: * @param partName the name of the part
165: * @return the first Element in the normalized message part, null if no element is present
166: * @throws WrapperProcessingException if the part could not be returned
167: */
168: //TODO: is this really needed/useful?
169: /*
170: public Element getPartElement(String partName) throws WrapperProcessingException {
171: Element firstNode = null;
172: NodeList allNodes = getPartNodes(partName);
173: if (allNodes != null && allNodes.size() > 0) {
174: if (aNode.getNodeType() == Node.ELEMENT_NODE || aNode.getNodeType() == Node.TEXT_NODE) {
175:
176: firstNode = (Element) allElements.get(0);
177: }
178: return firstNode;
179: }
180: */
181:
182: /**
183: * Returns all Element inside the part wrapper
184: * (a jbi:part element may legally contain multiple Elements, or text)
185: * @param partName the name of the part
186: * @return all Elements in the normalized message part
187: * @throws WrapperProcessingException if the part could not be returned
188: */
189: /*
190: public List getPartElements(String partName) throws WrapperProcessingException {
191: Element wrappedPart = (Element) wrappedParts.get(partName);
192: if (wrappedPart == null) {
193: throw new WrapperProcessingException("The parsed message does not contain part " + partName);
194: }
195: List allElements = removeJBIPartWrapper(wrappedPart);
196: return allElements;
197: }
198: */
199: /**
200: * Returns all Nodes inside the part wrapper
201: * (a jbi:part element may legally contain multiple Elements, or text)
202: * @param partName the name of the part
203: * @return all Elements in the normalized message part
204: * @throws WrapperProcessingException if the part could not be returned
205: */
206: public NodeList getPartNodes(String partName)
207: throws WrapperProcessingException {
208: Element wrappedPart = (Element) wrappedParts.get(partName);
209: if (wrappedPart == null) {
210: throw new WrapperProcessingException(
211: "The parsed message does not contain part "
212: + partName);
213: }
214: NodeList allElements = removeJBIPartWrapper(wrappedPart);
215: return allElements;
216: }
217:
218: /**
219: * Returns the part, including the <jbi:part> part wrapper element around
220: * the part 'payload'
221: *
222: * (a jbi:part element may legally contain multiple Elements, or text)
223: * @param partName the name of the part
224: * @return the wrapped normalized message part
225: * @throws WrapperProcessingException if the part could not be returned
226: */
227: public Element getWrappedPart(String partName)
228: throws WrapperProcessingException {
229: Element wrappedPart = (Element) wrappedParts.get(partName);
230: if (wrappedPart == null) {
231: throw new WrapperProcessingException(
232: "The parsed message does not contain part "
233: + partName);
234: }
235: return wrappedPart;
236: }
237:
238: /**
239: * @return the number of parts in the normalized message
240: */
241: public int getNoOfParts() {
242: return wrappedParts.size();
243: }
244:
245: /**
246: * @return the names of the parts in the normalized message
247: */
248: public String[] getPartNames() {
249: return (String[]) partsOrder.toArray(new String[0]);
250: }
251:
252: /**
253: * Given the element for a jbi part wrapper, removes the wrapper element
254: * and returns the part payload
255: * @param wrappedPart the Element representing the JBI part wrapper
256: * @return the part payload as a List of Element s
257: */
258: public static NodeList removeJBIPartWrapper(Element wrappedPart) {
259: List elements = new ArrayList();
260: NodeList childNodes = wrappedPart.getChildNodes();
261:
262: /*
263: for (int childCount = 0; childCount < childNodes.getLength(); childCount++) {
264: Node aNode = (Node) childNodes.item(childCount);
265: if (aNode != null) {
266: if (aNode.getNodeType() == Node.ELEMENT_NODE || aNode.getNodeType() == Node.TEXT_NODE) {
267: elements.add(aNode);
268: }
269: }
270: }
271: */
272:
273: return childNodes;
274: }
275:
276: /**
277: * Get the message type of the message wrapper in the wrapped document.
278: * @return the message type as QName
279: */
280: public QName getMessageType() throws WrapperProcessingException {
281: return messageType;
282: }
283:
284: /**
285: * Get the optional message "name" defined in the wrapped document.
286: * This is the logical name defined in the operation binding, not the type name.
287: * @return the message name
288: */
289: public String getMessageName() throws WrapperProcessingException {
290: return messageName;
291: }
292:
293: /**
294: * Get the message type of the message wrapper in the wrapped document.
295: * If the wsdlDefinition passed in does not contain a namespace definition for the
296: * type prefix present int the message wrapper the QName namespace will be null
297: * @param wrappedDoc the wrapped normalized message
298: * @param wsdlDefinition the wsdl definition containing the definition for the normalized message.
299: * @return the message type as QName
300: */
301: public static QName extractMessageType(Document wrappedDoc,
302: Definition wsdlDefinition)
303: throws WrapperProcessingException {
304: QName msgTypeQName = null;
305: // Get the jbi message wrapper element
306: Element jbiMessageWrapper = wrappedDoc.getDocumentElement();
307: if (jbiMessageWrapper == null) {
308: throw new WrapperProcessingException(
309: "Could not get the wrapper message type, no message wrapper element is defined.");
310: } else {
311: String msgType = jbiMessageWrapper
312: .getAttribute(WrapperUtil.WRAPPER_ATTRIBUTE_TYPE);
313: if (msgType == null || msgType.equals("")) {
314: throw new WrapperProcessingException(
315: "Failed to obtain type from JBI Message Wrapper.");
316: }
317:
318: int colonPos = msgType.indexOf(':');
319: String localName = msgType;
320: String prefix = null;
321: String namespace = null;
322: if (colonPos > -1) {
323: prefix = msgType.substring(0, colonPos);
324: localName = msgType.substring(colonPos + 1);
325: if (prefix.equals("msgns")) {
326: namespace = jbiMessageWrapper.getAttribute("xmlns:"
327: + "msgns");
328: ;
329: } else if (wsdlDefinition != null) {
330: namespace = wsdlDefinition.getNamespace(prefix);
331: }
332: }
333: msgTypeQName = new QName(namespace, localName, prefix);
334:
335: }
336: return msgTypeQName;
337: }
338:
339: /**
340: * Get the optional message "name" defined in the wrapped document.
341: * This is the logical name defined in the operation binding, not the type name.
342: * @param wrappedDoc the wrapped normalized message
343: * @return the message name
344: */
345: public static String extractMessageName(Document wrappedDoc)
346: throws WrapperProcessingException {
347: String messageName = null;
348: // Get the jbi message wrapper element
349: Element jbiMessageWrapper = wrappedDoc.getDocumentElement();
350: if (jbiMessageWrapper == null) {
351: throw new WrapperProcessingException(
352: "Could not get the wrapper message name, no message wrapper element is defined.");
353: } else {
354: messageName = jbiMessageWrapper
355: .getAttribute(WrapperUtil.WRAPPER_ATTRIBUTE_NAME);
356: }
357: return messageName;
358: }
359: }
|