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: * @(#)WsdlReader.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.wsdl2.impl;
030:
031: import com.sun.jbi.wsdl2.WsdlException;
032:
033: import java.io.File;
034: import java.io.IOException;
035: import java.io.StringBufferInputStream;
036: import java.io.StringWriter;
037:
038: import java.net.MalformedURLException;
039: import java.net.URL;
040:
041: import java.util.ArrayList;
042: import java.util.logging.Logger;
043:
044: import org.apache.xmlbeans.XmlError;
045: import org.apache.xmlbeans.XmlException;
046: import org.apache.xmlbeans.XmlOptions;
047:
048: import org.w3.ns.wsdl.DescriptionDocument;
049: import org.w3.ns.wsdl.DocumentationDocument;
050:
051: import javax.xml.parsers.DocumentBuilderFactory;
052: import javax.xml.parsers.DocumentBuilder;
053: import javax.xml.parsers.ParserConfigurationException;
054: import javax.xml.parsers.FactoryConfigurationError;
055: import javax.xml.transform.dom.DOMSource;
056: import javax.xml.transform.stream.StreamResult;
057: import javax.xml.transform.TransformerFactory;
058: import javax.xml.transform.Transformer;
059: import javax.xml.transform.TransformerConfigurationException;
060: import javax.xml.transform.TransformerException;
061: import org.w3c.dom.Node;
062: import org.w3c.dom.NodeList;
063: import org.w3c.dom.NamedNodeMap;
064: import org.w3c.dom.Document;
065: import org.w3c.dom.Element;
066:
067: import org.xml.sax.InputSource;
068:
069: /**
070: * This class provides the ability to read WSDL documents, converting them
071: * into <code>Description</code>.<p>
072: *
073: * This is loosely based on the WSDLReaderImpl in the JSR-110 RI, in order
074: * to preserve some sort of compatibility with 110-based code. The actual
075: * implementation is quite different.
076: *
077: * @author Sun Microsystems, Inc.
078: */
079: final class WsdlReader implements com.sun.jbi.wsdl2.WsdlReader {
080: /** This is for backward compatible with version of x2006.x01 */
081: private final String OLD_NS_STRING = "www.w3.org/2006/01/wsdl";
082: private final String NEW_NS_STRING = "www.w3.org/ns/wsdl";
083:
084: /** The logger to be used by this WSDL reader */
085: private final Logger mLogger = Logger
086: .getLogger(Constants.LOGGER_NAME);
087:
088: /**
089: * Get the logger used by this WSDL reader. <p> This avoids exposing our
090: * logger name, which may change.
091: *
092: * @return Logger used by WSDL readers.
093: */
094: public Logger getLogger() {
095: return this .mLogger;
096: }
097:
098: /**
099: * Read the given WSDL document, converting it into a <code>Description</code>
100: * object.
101: *
102: * @param wsdlUri A URI pointing to the WSDL XML document resource to read.
103: * @return Definition corresponding to the given WSDL document
104: * @exception WsdlException If the WSDL document contains errors.
105: * @exception MalformedURLException If the wsdlUri isn't a valid URL or file
106: * name.
107: * @exception IOException If an IO error occurs whilst reading the
108: * wsdlUri.
109: */
110: public com.sun.jbi.wsdl2.Description readDescription(String wsdlUri)
111: throws WsdlException, MalformedURLException, IOException {
112: return this .readDescription(null, wsdlUri);
113: }
114:
115: /**
116: * @deprecated - replaced by readDescription
117: */
118: public com.sun.jbi.wsdl2.Definitions readWsdl(String wsdlURI)
119: throws WsdlException, MalformedURLException, IOException {
120: return (com.sun.jbi.wsdl2.Definitions) readDescription(wsdlURI);
121: }
122:
123: /**
124: * Read the given WSDL2 document, in the given context URI, converting it into
125: * a <code>Description</code> object.
126: *
127: * @param contextUri The context to evaluate the <code>wsdlUri</code> in.
128: * @param wsdlUri A URI pointing to the WSDL XML document resource to
129: * read. This can be a URL or a filename.
130: * @return <code>Description</code> corresponding to the given WSDL document
131: * @exception WsdlException If the WSDL document contains errors.
132: * @exception MalformedURLException If one of the URIs given isn't a valid
133: * URL or file name.
134: * @exception IOException If an error occurs reading the
135: * resource given in <code>wsdlUri</code>.
136: */
137: public com.sun.jbi.wsdl2.Description readDescription(
138: String contextUri, String wsdlUri) throws WsdlException,
139: MalformedURLException, IOException {
140: Description result = null;
141: URL contextURL = contextUri != null ? getURL(null, contextUri)
142: : null;
143: URL wsdlURL = getURL(contextURL, wsdlUri);
144: DescriptionDocument defDoc = null;
145:
146: try {
147: try {
148: defDoc = DescriptionDocument.Factory.parse(wsdlURL);
149: } catch (Exception exp) {
150: mLogger
151: .info("May not be the final WSDL 2.0 version, let's try 2006.01");
152: DocumentBuilderFactory domFactory = DocumentBuilderFactory
153: .newInstance();
154: DocumentBuilder domBuilder = domFactory
155: .newDocumentBuilder();
156: Document doc = domBuilder.parse(wsdlURL.toString());
157: /* This is for backward compable (compatibble with 2006.01) */
158: recursivelyUpdate(doc);
159:
160: TransformerFactory transFactory = TransformerFactory
161: .newInstance();
162: Transformer trans = transFactory.newTransformer();
163: StringWriter strWriter = new StringWriter();
164: StreamResult resultStream = new StreamResult(strWriter);
165: trans.transform(new DOMSource(doc), resultStream);
166:
167: domFactory.setNamespaceAware(true);
168: DocumentBuilder domBuilder1 = domFactory
169: .newDocumentBuilder();
170: Document newDoc = domBuilder1
171: .parse(new StringBufferInputStream(strWriter
172: .getBuffer().toString()));
173: defDoc = DescriptionDocument.Factory.parse(newDoc);
174: strWriter.close();
175: }
176: validate(defDoc);
177: } catch (XmlException ex) {
178: throw new WsdlException(ex.getMessage());
179: } catch (org.xml.sax.SAXException exp) {
180: throw new WsdlException(exp.getMessage());
181: } catch (ParserConfigurationException exp) {
182: throw new WsdlException(exp.getMessage());
183: } catch (TransformerConfigurationException exp) {
184: throw new WsdlException(exp.getMessage());
185: } catch (TransformerException exp) {
186: throw new WsdlException(exp.getMessage());
187: }
188:
189: return DescriptionImpl.Factory.getInstance(defDoc, wsdlURL
190: .toExternalForm());
191: }
192:
193: /**
194: * @param doc the document which needs to be updated if necessary
195: */
196: private void recursivelyUpdate(Node theNode) {
197: NamedNodeMap attrs = theNode.getAttributes();
198: if (attrs != null) {
199: for (int i = 0; i < attrs.getLength(); ++i) {
200: Node attr = attrs.item(i);
201: String attrValue = "" + attr.getNodeValue();
202: attrValue = attrValue.replace(OLD_NS_STRING,
203: NEW_NS_STRING);
204: attr.setNodeValue(attrValue);
205: }
206: }
207:
208: NodeList nodeList = theNode.getChildNodes();
209: for (int i = 0; i < nodeList.getLength(); ++i) {
210: Node childNode = nodeList.item(i);
211: recursivelyUpdate(childNode);
212: }
213: }
214:
215: /**
216: * @deprecated use readDescription
217: */
218: public com.sun.jbi.wsdl2.Definitions readWsdl(String contextURI,
219: String wsdlURI) throws WsdlException,
220: MalformedURLException, IOException {
221: return (com.sun.jbi.wsdl2.Definitions) readDescription(
222: contextURI, wsdlURI);
223: }
224:
225: /**
226: * Validate the given document.
227: *
228: * @param defDoc The definitions document to be validated.
229: * @exception WsdlException if the document is invalid.
230: */
231: private static void validate(DescriptionDocument defDoc)
232: throws WsdlException {
233: XmlOptions validateOptions = new XmlOptions();
234: ArrayList errorList = new ArrayList();
235:
236: validateOptions.setErrorListener(errorList);
237:
238: boolean isValid = defDoc.validate(validateOptions);
239:
240: // If the XML isn't valid, loop through the listener's contents,
241: // constructing a suitable error message.
242: if (!isValid) {
243: StringBuffer sb = new StringBuffer();
244:
245: for (int i = 0; i < errorList.size(); i++) {
246: XmlError error = (XmlError) errorList.get(i);
247:
248: if (i > 0) {
249: sb.append("\n\n");
250: }
251: sb.append("Message: ");
252: sb.append(error.getMessage());
253: sb.append("\n");
254: sb.append("Location of invalid XML: ");
255: sb.append(error.getCursorLocation().xmlText());
256: sb.append("\n\n");
257: // Location by line / column not available by default
258: // with XmlBeans.
259: }
260:
261: throw new WsdlException(sb.toString());
262: }
263: }
264:
265: /**
266: * Read the given document (we assume it is WSDL 2.0) into a <code>
267: * Description</code> object.
268: *
269: * @param documentBaseUri The base url for the WSDL document
270: * @param document The WSDL document as a DOM tree.
271: * @return A WSDL Description component corresponding to the given
272: * WSDL 2.0 <code>document</code>.
273: * @exception WsdlException if an XML parsing error occurs.
274: */
275: public com.sun.jbi.wsdl2.Description readDescription(
276: String documentBaseUri, Document document)
277: throws WsdlException, IOException {
278: return readDescription(documentBaseUri, document
279: .getDocumentElement());
280: }
281:
282: /**
283: * @deprecated use readDescription
284: */
285: public com.sun.jbi.wsdl2.Definitions readWsdl(
286: String documentBaseURI, Document document)
287: throws WsdlException, MalformedURLException, IOException {
288: return (com.sun.jbi.wsdl2.Definitions) readDescription(
289: documentBaseURI, document);
290: }
291:
292: /**
293: * Read the given document (we assume it is WSDL 2.0) into a <code>
294: * Description</code> object.
295: *
296: * @param documentBaseUri The base url for the WSDL document
297: * @param element The <definitions> element for the WSDL instance.
298: * @return <code>Description</code> object representing the WSDL document read.
299: * @exception WsdlException If a parsing or processing error occurs.
300: */
301: public com.sun.jbi.wsdl2.Description readDescription(
302: String documentBaseUri, Element element)
303: throws WsdlException, IOException {
304: DescriptionDocument defDoc = null;
305:
306: try {
307: try {
308: defDoc = DescriptionDocument.Factory.parse(element);
309: } catch (Exception exp) {
310: mLogger
311: .info("May not be the final WSDL 2.0 version, let's try 2006.01");
312: /* This is for backward compable (compatibble with 2006.01) */
313:
314: DocumentBuilderFactory domFactory = DocumentBuilderFactory
315: .newInstance();
316: DocumentBuilder tmpBuilder = domFactory
317: .newDocumentBuilder();
318:
319: TransformerFactory transFactory = TransformerFactory
320: .newInstance();
321: Transformer trans = transFactory.newTransformer();
322: StringWriter strWriter = new StringWriter();
323: StreamResult tmpStream = new StreamResult(strWriter);
324: trans.transform(new DOMSource(element), tmpStream);
325:
326: // Load the doc with namespace as attribute for the 1st time
327: domFactory.setNamespaceAware(false);
328: Document tmpElement = tmpBuilder
329: .parse(new StringBufferInputStream(strWriter
330: .getBuffer().toString()));
331: strWriter.close();
332:
333: recursivelyUpdate(tmpElement);
334:
335: strWriter = new StringWriter();
336: StreamResult resultStream = new StreamResult(strWriter);
337: trans
338: .transform(new DOMSource(tmpElement),
339: resultStream);
340:
341: // Load the doc with namespace as namesapce for the 2nd time
342: domFactory.setNamespaceAware(true);
343: DocumentBuilder domBuilder = domFactory
344: .newDocumentBuilder();
345: Document newElement = domBuilder
346: .parse(new StringBufferInputStream(strWriter
347: .getBuffer().toString()));
348:
349: defDoc = DescriptionDocument.Factory.parse(newElement);
350: strWriter.close();
351: }
352: validate(defDoc);
353: } catch (XmlException ex) {
354: throw new WsdlException(ex.getMessage());
355: } catch (org.xml.sax.SAXException exp) {
356: throw new WsdlException(exp.getMessage());
357: } catch (ParserConfigurationException exp) {
358: throw new WsdlException(exp.getMessage());
359: } catch (TransformerConfigurationException exp) {
360: throw new WsdlException(exp.getMessage());
361: } catch (TransformerException exp) {
362: throw new WsdlException(exp.getMessage());
363: }
364:
365: return DescriptionImpl.Factory.getInstance(defDoc,
366: documentBaseUri);
367: }
368:
369: /**
370: * @deprecated use readDescription
371: */
372: public com.sun.jbi.wsdl2.Definitions readWsdl(
373: String documentBaseURI, Element definitionsElement)
374: throws WsdlException, MalformedURLException, IOException {
375: return (com.sun.jbi.wsdl2.Definitions) readDescription(
376: documentBaseURI, definitionsElement);
377: }
378:
379: /**
380: * Read a WSDL document into a WSDL definition.
381: *
382: * @param documentBaseURI The document base URI of the WSDL definition
383: * described by the document. Will be set as the
384: * documentBaseURI of the returned Definition.
385: * Can be null, in which case it will be ignored.
386: * @param inputSource An InputSource pointing to the WSDL document, an
387: * XML document obeying the WSDL schema.
388: * @return The WSDL document pointed to by the <code>inputSource</code>,
389: * as a Description component.
390: * @exception WsdlException if an XML parsing error occurs.
391: * @exception IOException if an error occurs reading
392: * <code>inputSource</code>.
393: */
394: public com.sun.jbi.wsdl2.Description readDescription(
395: String documentBaseURI, InputSource inputSource)
396: throws WsdlException, IOException {
397: return this .readDescription(documentBaseURI, DOMUtilities
398: .getDocument(documentBaseURI, inputSource));
399: }
400:
401: /**
402: * @deprecated use readDescription
403: */
404: public com.sun.jbi.wsdl2.Definitions readWsdl(
405: String documentBaseURI, InputSource inputSource)
406: throws WsdlException, MalformedURLException, IOException {
407: return (com.sun.jbi.wsdl2.Definitions) readDescription(
408: documentBaseURI, inputSource);
409: }
410:
411: /**
412: * Get the URL, based on the specification string and context URL (if any).
413: *
414: * @param contextURL The context in which to resolve the specification
415: * string.
416: * @param specification The URL specification string or filename.
417: * @return The URL corresponding the the given <code>specification</code>,
418: * in the given context <code>contextURL</code>(if not null).
419: * @exception MalformedURLException if the <code>specification</code>
420: * string is not a legal URL.
421: *
422: * This is based loosely on the JSR 110 RI StringUtil method of the same
423: * name.
424: */
425: static URL getURL(URL contextURL, String specification)
426: throws MalformedURLException {
427: if (contextURL != null) {
428: File tempFile = new File(specification);
429:
430: if (tempFile.isAbsolute()) {
431: return tempFile.toURL();
432: }
433: }
434:
435: try {
436: return new URL(contextURL, specification);
437: } catch (MalformedURLException e) {
438: if (contextURL == null) {
439: return new File(specification).toURL();
440: } else {
441: throw e;
442: }
443: }
444: }
445: }
|