001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.wsdl.parser;
038:
039: import com.sun.istack.NotNull;
040: import com.sun.istack.Nullable;
041: import com.sun.xml.ws.api.BindingID;
042: import com.sun.xml.ws.api.EndpointAddress;
043: import com.sun.xml.ws.api.addressing.AddressingVersion;
044: import com.sun.xml.ws.api.addressing.WSEndpointReference;
045: import com.sun.xml.ws.api.model.ParameterBinding;
046: import com.sun.xml.ws.api.model.wsdl.WSDLDescriptorKind;
047: import com.sun.xml.ws.api.model.wsdl.WSDLModel;
048: import com.sun.xml.ws.api.streaming.XMLStreamReaderFactory;
049: import com.sun.xml.ws.api.wsdl.parser.MetaDataResolver;
050: import com.sun.xml.ws.api.wsdl.parser.MetadataResolverFactory;
051: import com.sun.xml.ws.api.wsdl.parser.ServiceDescriptor;
052: import com.sun.xml.ws.api.wsdl.parser.WSDLParserExtension;
053: import com.sun.xml.ws.api.wsdl.parser.XMLEntityResolver;
054: import com.sun.xml.ws.api.wsdl.parser.XMLEntityResolver.Parser;
055: import com.sun.xml.ws.model.wsdl.*;
056: import com.sun.xml.ws.resources.ClientMessages;
057: import com.sun.xml.ws.resources.WsdlmodelMessages;
058: import com.sun.xml.ws.streaming.SourceReaderFactory;
059: import com.sun.xml.ws.streaming.TidyXMLStreamReader;
060: import com.sun.xml.ws.streaming.XMLStreamReaderUtil;
061: import com.sun.xml.ws.util.ServiceFinder;
062: import com.sun.xml.ws.util.xml.XmlUtil;
063: import org.xml.sax.EntityResolver;
064: import org.xml.sax.SAXException;
065:
066: import javax.jws.soap.SOAPBinding.Style;
067: import javax.xml.namespace.QName;
068: import javax.xml.stream.XMLStreamConstants;
069: import javax.xml.stream.XMLStreamException;
070: import javax.xml.stream.XMLStreamReader;
071: import javax.xml.transform.Source;
072: import javax.xml.transform.stream.StreamSource;
073: import javax.xml.ws.WebServiceException;
074: import java.io.IOException;
075: import java.io.InputStream;
076: import java.net.URISyntaxException;
077: import java.net.URL;
078: import java.util.ArrayList;
079: import java.util.HashSet;
080: import java.util.List;
081: import java.util.Map;
082: import java.util.Set;
083: import java.util.logging.Logger;
084:
085: /**
086: * Parses WSDL and builds {@link WSDLModel}.
087: *
088: * @author Vivek Pandey
089: */
090: public class RuntimeWSDLParser {
091:
092: private final WSDLModelImpl wsdlDoc;
093: /**
094: * Target namespace URI of the WSDL that we are currently parsing.
095: */
096: private String targetNamespace;
097: /**
098: * System IDs of WSDLs that are already read.
099: */
100: private final Set<String> importedWSDLs = new HashSet<String>();
101: /**
102: * Must not be null.
103: */
104: private final XMLEntityResolver resolver;
105: /**
106: * The {@link WSDLParserExtension}. Always non-null.
107: */
108: private final WSDLParserExtension extensionFacade;
109:
110: private final WSDLParserExtensionContextImpl context;
111:
112: List<WSDLParserExtension> extensions;
113:
114: /**
115: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
116: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
117: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
118: *
119: * @param wsdlLoc
120: * Either this or <tt>wsdl</tt> parameter must be given.
121: * Null location means the system won't be able to resolve relative references in the WSDL,
122: */
123: public static WSDLModelImpl parse(@Nullable
124: URL wsdlLoc, @NotNull
125: Source wsdlSource, @NotNull
126: EntityResolver resolver, boolean isClientSide,
127: WSDLParserExtension... extensions) throws IOException,
128: XMLStreamException, SAXException {
129: assert resolver != null;
130:
131: RuntimeWSDLParser wsdlParser = new RuntimeWSDLParser(wsdlSource
132: .getSystemId(), new EntityResolverWrapper(resolver),
133: isClientSide, extensions);
134: Parser parser;
135: try {
136: parser = wsdlParser.resolveWSDL(wsdlLoc, wsdlSource);
137: if (!hasWSDLDefinitions(parser.parser)) {
138: throw new XMLStreamException(ClientMessages
139: .RUNTIME_WSDLPARSER_INVALID_WSDL(
140: parser.systemId,
141: WSDLConstants.QNAME_DEFINITIONS,
142: parser.parser.getName(), parser.parser
143: .getLocation()));
144: }
145: } catch (XMLStreamException e) {
146: //Try MEX if there is WSDLLoc available
147: if (wsdlLoc == null)
148: throw e;
149: return tryWithMex(wsdlParser, wsdlLoc, resolver,
150: isClientSide, e, extensions);
151:
152: } catch (IOException e) {
153: //Try MEX if there is WSDLLoc available
154: if (wsdlLoc == null)
155: throw e;
156: return tryWithMex(wsdlParser, wsdlLoc, resolver,
157: isClientSide, e, extensions);
158: }
159: wsdlParser.parseWSDL(parser, false);
160: wsdlParser.wsdlDoc.freeze();
161: wsdlParser.extensionFacade.finished(wsdlParser.context);
162: wsdlParser.extensionFacade.postFinished(wsdlParser.context);
163:
164: if (wsdlParser.wsdlDoc.getServices().isEmpty())
165: throw new WebServiceException(ClientMessages
166: .WSDL_CONTAINS_NO_SERVICE(wsdlLoc));
167:
168: return wsdlParser.wsdlDoc;
169: }
170:
171: private static WSDLModelImpl tryWithMex(@NotNull
172: RuntimeWSDLParser wsdlParser, @NotNull
173: URL wsdlLoc, @NotNull
174: EntityResolver resolver, boolean isClientSide, Throwable e,
175: WSDLParserExtension... extensions) throws SAXException,
176: XMLStreamException {
177: ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
178: try {
179: WSDLModelImpl wsdlModel = wsdlParser.parseUsingMex(wsdlLoc,
180: resolver, isClientSide, extensions);
181: if (wsdlModel == null) {
182: throw new WebServiceException(ClientMessages
183: .FAILED_TO_PARSE(wsdlLoc.toExternalForm(), e
184: .getMessage()), e);
185: }
186: return wsdlModel;
187: } catch (URISyntaxException e1) {
188: exceptions.add(e);
189: exceptions.add(e1);
190: } catch (IOException e1) {
191: exceptions.add(e);
192: exceptions.add(e1);
193: }
194: throw new InaccessibleWSDLException(exceptions);
195: }
196:
197: private WSDLModelImpl parseUsingMex(@NotNull
198: URL wsdlLoc, @NotNull
199: EntityResolver resolver, boolean isClientSide,
200: WSDLParserExtension[] extensions) throws IOException,
201: SAXException, XMLStreamException, URISyntaxException {
202: //try MEX
203: MetaDataResolver mdResolver = null;
204: ServiceDescriptor serviceDescriptor = null;
205: RuntimeWSDLParser wsdlParser = null;
206:
207: //Currently we try the first available MetadataResolverFactory that gives us a WSDL document
208: for (MetadataResolverFactory resolverFactory : ServiceFinder
209: .find(MetadataResolverFactory.class)) {
210: mdResolver = resolverFactory.metadataResolver(resolver);
211: serviceDescriptor = mdResolver.resolve(wsdlLoc.toURI());
212: //we got the ServiceDescriptor, now break
213: if (serviceDescriptor != null)
214: break;
215: }
216: if (serviceDescriptor != null) {
217: List<? extends Source> wsdls = serviceDescriptor.getWSDLs();
218: wsdlParser = new RuntimeWSDLParser(
219: wsdlLoc.toExternalForm(), new MexEntityResolver(
220: wsdls), isClientSide, extensions);
221:
222: for (Source src : wsdls) {
223: String systemId = src.getSystemId();
224: Parser parser = wsdlParser.resolver.resolveEntity(null,
225: systemId);
226: wsdlParser.parseWSDL(parser, false);
227: }
228: }
229: //Incase that mex is not present or it couldn't get the metadata, try by appending ?wsdl and give
230: // it a last shot else fail
231: if ((mdResolver == null || serviceDescriptor == null)
232: && (wsdlLoc.getProtocol().equals("http") || wsdlLoc
233: .getProtocol().equals("https"))
234: && (wsdlLoc.getQuery() == null)) {
235: String urlString = wsdlLoc.toExternalForm();
236: urlString += "?wsdl";
237: wsdlLoc = new URL(urlString);
238: wsdlParser = new RuntimeWSDLParser(
239: wsdlLoc.toExternalForm(),
240: new EntityResolverWrapper(resolver), isClientSide,
241: extensions);
242: Parser parser = resolveWSDL(wsdlLoc, new StreamSource(
243: wsdlLoc.toExternalForm()));
244: wsdlParser.parseWSDL(parser, false);
245: }
246:
247: if (wsdlParser == null)
248: return null;
249:
250: wsdlParser.wsdlDoc.freeze();
251: wsdlParser.extensionFacade.finished(wsdlParser.context);
252: wsdlParser.extensionFacade.postFinished(wsdlParser.context);
253: return wsdlParser.wsdlDoc;
254: }
255:
256: private static boolean hasWSDLDefinitions(XMLStreamReader reader) {
257: XMLStreamReaderUtil.nextElementContent(reader);
258: return reader.getName().equals(WSDLConstants.QNAME_DEFINITIONS);
259: }
260:
261: public static WSDLModelImpl parse(XMLEntityResolver.Parser wsdl,
262: XMLEntityResolver resolver, boolean isClientSide,
263: WSDLParserExtension... extensions) throws IOException,
264: XMLStreamException, SAXException {
265: assert resolver != null;
266: RuntimeWSDLParser parser = new RuntimeWSDLParser(wsdl.systemId
267: .toExternalForm(), resolver, isClientSide, extensions);
268: parser.parseWSDL(wsdl, false);
269: parser.wsdlDoc.freeze();
270: parser.extensionFacade.finished(parser.context);
271: parser.extensionFacade.postFinished(parser.context);
272: return parser.wsdlDoc;
273: }
274:
275: private RuntimeWSDLParser(@NotNull
276: String sourceLocation, XMLEntityResolver resolver,
277: boolean isClientSide, WSDLParserExtension... extensions) {
278: this .wsdlDoc = sourceLocation != null ? new WSDLModelImpl(
279: sourceLocation) : new WSDLModelImpl();
280: this .resolver = resolver;
281:
282: this .extensions = new ArrayList<WSDLParserExtension>();
283: this .context = new WSDLParserExtensionContextImpl(wsdlDoc,
284: isClientSide);
285:
286: // register handlers for default extensions
287: register(new MemberSubmissionAddressingWSDLParserExtension());
288: register(new W3CAddressingWSDLParserExtension());
289:
290: for (WSDLParserExtension e : extensions)
291: register(e);
292:
293: this .extensionFacade = new WSDLParserExtensionFacade(
294: this .extensions.toArray(new WSDLParserExtension[0]));
295: }
296:
297: private Parser resolveWSDL(@Nullable
298: URL wsdlLoc, @NotNull
299: Source wsdlSource) throws IOException, SAXException,
300: XMLStreamException {
301: String systemId = wsdlSource.getSystemId();
302:
303: XMLEntityResolver.Parser parser = resolver.resolveEntity(null,
304: systemId);
305: if (parser == null && wsdlLoc != null) {
306: parser = resolver.resolveEntity(null, wsdlLoc
307: .toExternalForm());
308:
309: }
310: if (parser == null) {
311: if (wsdlLoc != null)
312: parser = new Parser(wsdlLoc, createReader(wsdlLoc));
313: else
314: parser = new Parser(wsdlLoc, createReader(wsdlSource));
315: }
316: return parser;
317: }
318:
319: private XMLStreamReader createReader(@NotNull
320: Source src) throws XMLStreamException {
321: return new TidyXMLStreamReader(SourceReaderFactory
322: .createSourceReader(src, true), null);
323: }
324:
325: private void parseImport(@NotNull
326: URL wsdlLoc) throws XMLStreamException, IOException, SAXException {
327: String systemId = wsdlLoc.toExternalForm();
328: XMLEntityResolver.Parser parser = resolver.resolveEntity(null,
329: systemId);
330: if (parser == null) {
331: parser = new Parser(wsdlLoc, createReader(wsdlLoc));
332: }
333: parseWSDL(parser, true);
334: }
335:
336: private void parseWSDL(Parser parser, boolean imported)
337: throws XMLStreamException, IOException, SAXException {
338: XMLStreamReader reader = parser.parser;
339: try {
340: // avoid processing the same WSDL twice.
341: // if no system ID is given, the check won't work
342: if (parser.systemId != null
343: && !importedWSDLs.add(parser.systemId
344: .toExternalForm()))
345: return;
346:
347: if (reader.getEventType() == XMLStreamConstants.START_DOCUMENT)
348: XMLStreamReaderUtil.nextElementContent(reader);
349:
350: if (reader.getEventType() != XMLStreamConstants.END_DOCUMENT
351: && reader.getName().equals(
352: WSDLConstants.QNAME_SCHEMA)) {
353: if (imported) {
354: // wsdl:import could be a schema. Relaxing BP R2001 requirement.
355: LOGGER
356: .warning(WsdlmodelMessages
357: .WSDL_IMPORT_SHOULD_BE_WSDL(parser.systemId));
358: return;
359: }
360: }
361:
362: //get the targetNamespace of the service
363: String tns = ParserUtil.getMandatoryNonEmptyAttribute(
364: reader, WSDLConstants.ATTR_TNS);
365:
366: final String oldTargetNamespace = targetNamespace;
367: targetNamespace = tns;
368:
369: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
370: if (reader.getEventType() == XMLStreamConstants.END_DOCUMENT)
371: break;
372:
373: QName name = reader.getName();
374: if (WSDLConstants.QNAME_IMPORT.equals(name)) {
375: parseImport(parser.systemId, reader);
376: } else if (WSDLConstants.QNAME_MESSAGE.equals(name)) {
377: parseMessage(reader);
378: } else if (WSDLConstants.QNAME_PORT_TYPE.equals(name)) {
379: parsePortType(reader);
380: } else if (WSDLConstants.QNAME_BINDING.equals(name)) {
381: parseBinding(reader);
382: } else if (WSDLConstants.QNAME_SERVICE.equals(name)) {
383: parseService(reader);
384: } else {
385: extensionFacade.definitionsElements(reader);
386: }
387: }
388: targetNamespace = oldTargetNamespace;
389: } finally {
390: reader.close();
391: }
392: }
393:
394: private void parseService(XMLStreamReader reader) {
395: String serviceName = ParserUtil.getMandatoryNonEmptyAttribute(
396: reader, WSDLConstants.ATTR_NAME);
397: WSDLServiceImpl service = new WSDLServiceImpl(reader, wsdlDoc,
398: new QName(targetNamespace, serviceName));
399: extensionFacade.serviceAttributes(service, reader);
400: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
401: QName name = reader.getName();
402: if (WSDLConstants.QNAME_PORT.equals(name)) {
403: parsePort(reader, service);
404: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
405: XMLStreamReaderUtil.next(reader);
406: }
407: } else {
408: extensionFacade.serviceElements(service, reader);
409: }
410: }
411: wsdlDoc.addService(service);
412: }
413:
414: private void parsePort(XMLStreamReader reader,
415: WSDLServiceImpl service) {
416: String portName = ParserUtil.getMandatoryNonEmptyAttribute(
417: reader, WSDLConstants.ATTR_NAME);
418: String binding = ParserUtil.getMandatoryNonEmptyAttribute(
419: reader, "binding");
420:
421: QName bindingName = ParserUtil.getQName(reader, binding);
422: QName portQName = new QName(
423: service.getName().getNamespaceURI(), portName);
424: WSDLPortImpl port = new WSDLPortImpl(reader, service,
425: portQName, bindingName);
426:
427: extensionFacade.portAttributes(port, reader);
428:
429: String location;
430: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
431: QName name = reader.getName();
432: if (SOAPConstants.QNAME_ADDRESS.equals(name)
433: || SOAPConstants.QNAME_SOAP12ADDRESS.equals(name)) {
434: location = ParserUtil.getMandatoryNonEmptyAttribute(
435: reader, WSDLConstants.ATTR_LOCATION);
436: if (location != null) {
437: try {
438: port.setAddress(new EndpointAddress(location));
439: } catch (URISyntaxException e) {
440: //Lets not throw any exception, latter on it should be thrown when invocation happens. At this
441: // time user has option to set the endopint address using request contexxt property.
442: }
443: }
444: XMLStreamReaderUtil.next(reader);
445: } else if (AddressingVersion.W3C.nsUri.equals(name
446: .getNamespaceURI())
447: && "EndpointReference".equals(name.getLocalPart())) {
448: try {
449: WSEndpointReference wsepr = new WSEndpointReference(
450: reader, AddressingVersion.W3C);
451: port.setEPR(wsepr);
452: /** XMLStreamBuffer.createNewBufferFromXMLStreamReader(reader) called from inside WSEndpointReference()
453: * consumes the complete EPR infoset and moves to the next element. This breaks the normal wsdl parser
454: * processing where it expects anyone reading the infoset to move to the end of the element that its reading
455: * and not to the next element.
456: */
457: if (reader.getEventType() == XMLStreamConstants.END_ELEMENT
458: && reader.getName().equals(
459: WSDLConstants.QNAME_PORT))
460: break;
461: } catch (XMLStreamException e) {
462: throw new WebServiceException(e);
463: }
464: } else {
465:
466: extensionFacade.portElements(port, reader);
467: }
468: }
469: if (port.getAddress() == null) {
470: try {
471: port.setAddress(new EndpointAddress(""));
472: } catch (URISyntaxException e) {
473: //Lets not throw any exception, latter on it should be thrown when invocation happens. At this
474: //time user has option to set the endopint address using request contexxt property.
475: }
476: }
477: service.put(portQName, port);
478: }
479:
480: private void parseBinding(XMLStreamReader reader) {
481: String bindingName = ParserUtil.getMandatoryNonEmptyAttribute(
482: reader, "name");
483: String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(
484: reader, "type");
485: if ((bindingName == null) || (portTypeName == null)) {
486: //TODO: throw exception?
487: //
488: // wsdl:binding element for now
489: XMLStreamReaderUtil.skipElement(reader);
490: return;
491: }
492: WSDLBoundPortTypeImpl binding = new WSDLBoundPortTypeImpl(
493: reader, wsdlDoc,
494: new QName(targetNamespace, bindingName), ParserUtil
495: .getQName(reader, portTypeName));
496: extensionFacade.bindingAttributes(binding, reader);
497:
498: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
499: QName name = reader.getName();
500: if (WSDLConstants.NS_SOAP_BINDING.equals(name)) {
501: binding.setBindingId(BindingID.SOAP11_HTTP);
502: String style = reader.getAttributeValue(null, "style");
503:
504: if ((style != null) && (style.equals("rpc"))) {
505: binding.setStyle(Style.RPC);
506: } else {
507: binding.setStyle(Style.DOCUMENT);
508: }
509: XMLStreamReaderUtil.next(reader);
510: } else if (WSDLConstants.NS_SOAP12_BINDING.equals(name)) {
511: binding.setBindingId(BindingID.SOAP12_HTTP);
512: String style = reader.getAttributeValue(null, "style");
513: if ((style != null) && (style.equals("rpc"))) {
514: binding.setStyle(Style.RPC);
515: } else {
516: binding.setStyle(Style.DOCUMENT);
517: }
518: XMLStreamReaderUtil.next(reader);
519: } else if (WSDLConstants.QNAME_OPERATION.equals(name)) {
520: parseBindingOperation(reader, binding);
521: } else {
522: extensionFacade.bindingElements(binding, reader);
523: }
524: }
525: }
526:
527: private void parseBindingOperation(XMLStreamReader reader,
528: WSDLBoundPortTypeImpl binding) {
529: String bindingOpName = ParserUtil
530: .getMandatoryNonEmptyAttribute(reader, "name");
531: if (bindingOpName == null) {
532: //TODO: throw exception?
533: //skip wsdl:binding element for now
534: XMLStreamReaderUtil.skipElement(reader);
535: return;
536: }
537:
538: QName opName = new QName(binding.getPortTypeName()
539: .getNamespaceURI(), bindingOpName);
540: WSDLBoundOperationImpl bindingOp = new WSDLBoundOperationImpl(
541: reader, binding, opName);
542: binding.put(opName, bindingOp);
543: extensionFacade.bindingOperationAttributes(bindingOp, reader);
544:
545: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
546: QName name = reader.getName();
547: String style = null;
548: if (WSDLConstants.QNAME_INPUT.equals(name)) {
549: parseInputBinding(reader, bindingOp);
550: } else if (WSDLConstants.QNAME_OUTPUT.equals(name)) {
551: parseOutputBinding(reader, bindingOp);
552: } else if (WSDLConstants.QNAME_FAULT.equals(name)) {
553: parseFaultBinding(reader, bindingOp);
554: } else if (SOAPConstants.QNAME_OPERATION.equals(name)
555: || SOAPConstants.QNAME_SOAP12OPERATION.equals(name)) {
556: style = reader.getAttributeValue(null, "style");
557: String soapAction = reader.getAttributeValue(null,
558: "soapAction");
559:
560: if (soapAction != null)
561: bindingOp.setSoapAction(soapAction);
562:
563: XMLStreamReaderUtil.next(reader);
564: } else {
565: extensionFacade.bindingOperationElements(bindingOp,
566: reader);
567: }
568: /**
569: * If style attribute is present set it otherwise set the style as defined
570: * on the <soap:binding> element
571: */
572: if (style != null) {
573: if (style.equals("rpc"))
574: bindingOp.setStyle(Style.RPC);
575: else
576: bindingOp.setStyle(Style.DOCUMENT);
577: } else {
578: bindingOp.setStyle(binding.getStyle());
579: }
580: }
581: }
582:
583: private void parseInputBinding(XMLStreamReader reader,
584: WSDLBoundOperationImpl bindingOp) {
585: boolean bodyFound = false;
586: extensionFacade.bindingOperationInputAttributes(bindingOp,
587: reader);
588: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
589: QName name = reader.getName();
590: if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY
591: .equals(name))
592: && !bodyFound) {
593: bodyFound = true;
594: bindingOp
595: .setInputExplicitBodyParts(parseSOAPBodyBinding(
596: reader, bindingOp, BindingMode.INPUT));
597: goToEnd(reader);
598: } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER
599: .equals(name))) {
600: parseSOAPHeaderBinding(reader, bindingOp
601: .getInputParts());
602: } else if (MIMEConstants.QNAME_MULTIPART_RELATED
603: .equals(name)) {
604: parseMimeMultipartBinding(reader, bindingOp,
605: BindingMode.INPUT);
606: } else {
607: extensionFacade.bindingOperationInputElements(
608: bindingOp, reader);
609: }
610: }
611: }
612:
613: private void parseOutputBinding(XMLStreamReader reader,
614: WSDLBoundOperationImpl bindingOp) {
615: boolean bodyFound = false;
616: extensionFacade.bindingOperationOutputAttributes(bindingOp,
617: reader);
618: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
619: QName name = reader.getName();
620: if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY
621: .equals(name))
622: && !bodyFound) {
623: bodyFound = true;
624: bindingOp
625: .setOutputExplicitBodyParts(parseSOAPBodyBinding(
626: reader, bindingOp, BindingMode.OUTPUT));
627: goToEnd(reader);
628: } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER
629: .equals(name))) {
630: parseSOAPHeaderBinding(reader, bindingOp
631: .getOutputParts());
632: } else if (MIMEConstants.QNAME_MULTIPART_RELATED
633: .equals(name)) {
634: parseMimeMultipartBinding(reader, bindingOp,
635: BindingMode.OUTPUT);
636: } else {
637: extensionFacade.bindingOperationOutputElements(
638: bindingOp, reader);
639: }
640: }
641: }
642:
643: private void parseFaultBinding(XMLStreamReader reader,
644: WSDLBoundOperationImpl bindingOp) {
645: String faultName = ParserUtil.getMandatoryNonEmptyAttribute(
646: reader, "name");
647: WSDLBoundFaultImpl wsdlBoundFault = new WSDLBoundFaultImpl(
648: reader, faultName);
649: bindingOp.addFault(wsdlBoundFault);
650:
651: extensionFacade.bindingOperationFaultAttributes(wsdlBoundFault,
652: reader);
653:
654: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
655: extensionFacade.bindingOperationFaultElements(
656: wsdlBoundFault, reader);
657: }
658: }
659:
660: private enum BindingMode {
661: INPUT, OUTPUT, FAULT
662: }
663:
664: private static boolean parseSOAPBodyBinding(XMLStreamReader reader,
665: WSDLBoundOperationImpl op, BindingMode mode) {
666: String namespace = reader.getAttributeValue(null, "namespace");
667: if (mode == BindingMode.INPUT) {
668: op.setRequestNamespace(namespace);
669: return parseSOAPBodyBinding(reader, op.getInputParts());
670: }
671: //resp
672: op.setResponseNamespace(namespace);
673: return parseSOAPBodyBinding(reader, op.getOutputParts());
674: }
675:
676: /**
677: * Returns true if body has explicit parts declaration
678: */
679: private static boolean parseSOAPBodyBinding(XMLStreamReader reader,
680: Map<String, ParameterBinding> parts) {
681: String partsString = reader.getAttributeValue(null, "parts");
682: if (partsString != null) {
683: List<String> partsList = XmlUtil
684: .parseTokenList(partsString);
685: if (partsList.isEmpty()) {
686: parts.put(" ", ParameterBinding.BODY);
687: } else {
688: for (String part : partsList) {
689: parts.put(part, ParameterBinding.BODY);
690: }
691: }
692: return true;
693: }
694: return false;
695: }
696:
697: private static void parseSOAPHeaderBinding(XMLStreamReader reader,
698: Map<String, ParameterBinding> parts) {
699: String part = reader.getAttributeValue(null, "part");
700: //if(part == null| part.equals("")||message == null || message.equals("")){
701: if (part == null || part.equals("")) {
702: return;
703: }
704:
705: //lets not worry about message attribute for now, probably additional headers wont be there
706: //String message = reader.getAttributeValue(null, "message");
707: //QName msgName = ParserUtil.getQName(reader, message);
708: parts.put(part, ParameterBinding.HEADER);
709: goToEnd(reader);
710: }
711:
712: private static void parseMimeMultipartBinding(
713: XMLStreamReader reader, WSDLBoundOperationImpl op,
714: BindingMode mode) {
715: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
716: QName name = reader.getName();
717: if (MIMEConstants.QNAME_PART.equals(name)) {
718: parseMIMEPart(reader, op, mode);
719: } else {
720: XMLStreamReaderUtil.skipElement(reader);
721: }
722: }
723: }
724:
725: private static void parseMIMEPart(XMLStreamReader reader,
726: WSDLBoundOperationImpl op, BindingMode mode) {
727: boolean bodyFound = false;
728: Map<String, ParameterBinding> parts = null;
729: if (mode == BindingMode.INPUT) {
730: parts = op.getInputParts();
731: } else if (mode == BindingMode.OUTPUT) {
732: parts = op.getOutputParts();
733: } else if (mode == BindingMode.FAULT) {
734: parts = op.getFaultParts();
735: }
736: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
737: QName name = reader.getName();
738: if (SOAPConstants.QNAME_BODY.equals(name) && !bodyFound) {
739: bodyFound = true;
740: parseSOAPBodyBinding(reader, op, mode);
741: XMLStreamReaderUtil.next(reader);
742: } else if (SOAPConstants.QNAME_HEADER.equals(name)) {
743: bodyFound = true;
744: parseSOAPHeaderBinding(reader, parts);
745: XMLStreamReaderUtil.next(reader);
746: } else if (MIMEConstants.QNAME_CONTENT.equals(name)) {
747: String part = reader.getAttributeValue(null, "part");
748: String type = reader.getAttributeValue(null, "type");
749: if ((part == null) || (type == null)) {
750: XMLStreamReaderUtil.skipElement(reader);
751: continue;
752: }
753: ParameterBinding sb = ParameterBinding
754: .createAttachment(type);
755: if (parts != null && sb != null && part != null)
756: parts.put(part, sb);
757: XMLStreamReaderUtil.next(reader);
758: } else {
759: XMLStreamReaderUtil.skipElement(reader);
760: }
761: }
762: }
763:
764: protected void parseImport(@Nullable
765: URL baseURL, XMLStreamReader reader) throws IOException,
766: SAXException, XMLStreamException {
767: // expand to the absolute URL of the imported WSDL.
768: String importLocation = ParserUtil
769: .getMandatoryNonEmptyAttribute(reader,
770: WSDLConstants.ATTR_LOCATION);
771: URL importURL;
772: if (baseURL != null)
773: importURL = new URL(baseURL, importLocation);
774: else
775: // no base URL. this better be absolute
776: importURL = new URL(importLocation);
777: parseImport(importURL);
778: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
779: XMLStreamReaderUtil.skipElement(reader);
780: }
781: }
782:
783: private void parsePortType(XMLStreamReader reader) {
784: String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(
785: reader, WSDLConstants.ATTR_NAME);
786: if (portTypeName == null) {
787: //TODO: throw exception?
788: //skip wsdl:portType element for now
789: XMLStreamReaderUtil.skipElement(reader);
790: return;
791: }
792: WSDLPortTypeImpl portType = new WSDLPortTypeImpl(reader,
793: wsdlDoc, new QName(targetNamespace, portTypeName));
794: extensionFacade.portTypeAttributes(portType, reader);
795: wsdlDoc.addPortType(portType);
796: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
797: QName name = reader.getName();
798: if (WSDLConstants.QNAME_OPERATION.equals(name)) {
799: parsePortTypeOperation(reader, portType);
800: } else {
801: extensionFacade.portTypeElements(portType, reader);
802: }
803: }
804: }
805:
806: private void parsePortTypeOperation(XMLStreamReader reader,
807: WSDLPortTypeImpl portType) {
808: String operationName = ParserUtil
809: .getMandatoryNonEmptyAttribute(reader,
810: WSDLConstants.ATTR_NAME);
811: if (operationName == null) {
812: //TODO: throw exception?
813: //skip wsdl:portType element for now
814: XMLStreamReaderUtil.skipElement(reader);
815: return;
816: }
817:
818: QName operationQName = new QName(portType.getName()
819: .getNamespaceURI(), operationName);
820: WSDLOperationImpl operation = new WSDLOperationImpl(reader,
821: portType, operationQName);
822: extensionFacade.portTypeOperationAttributes(operation, reader);
823: String parameterOrder = ParserUtil.getAttribute(reader,
824: "parameterOrder");
825: operation.setParameterOrder(parameterOrder);
826: portType.put(operationName, operation);
827: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
828: QName name = reader.getName();
829: if (name.equals(WSDLConstants.QNAME_INPUT)) {
830: parsePortTypeOperationInput(reader, operation);
831: } else if (name.equals(WSDLConstants.QNAME_OUTPUT)) {
832: parsePortTypeOperationOutput(reader, operation);
833: } else if (name.equals(WSDLConstants.QNAME_FAULT)) {
834: parsePortTypeOperationFault(reader, operation);
835: } else {
836: extensionFacade.portTypeOperationElements(operation,
837: reader);
838: }
839: }
840: }
841:
842: private void parsePortTypeOperationFault(XMLStreamReader reader,
843: WSDLOperationImpl operation) {
844: String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader,
845: "message");
846: QName msgName = ParserUtil.getQName(reader, msg);
847: String name = ParserUtil.getMandatoryNonEmptyAttribute(reader,
848: "name");
849: WSDLFaultImpl fault = new WSDLFaultImpl(reader, name, msgName);
850: operation.addFault(fault);
851: extensionFacade.portTypeOperationFaultAttributes(fault, reader);
852: extensionFacade.portTypeOperationFault(operation, reader);
853: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
854: extensionFacade.portTypeOperationFaultElements(fault,
855: reader);
856: }
857: }
858:
859: private void parsePortTypeOperationInput(XMLStreamReader reader,
860: WSDLOperationImpl operation) {
861: String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader,
862: "message");
863: QName msgName = ParserUtil.getQName(reader, msg);
864: String name = ParserUtil.getAttribute(reader, "name");
865: WSDLInputImpl input = new WSDLInputImpl(reader, name, msgName,
866: operation);
867: operation.setInput(input);
868: extensionFacade.portTypeOperationInputAttributes(input, reader);
869: extensionFacade.portTypeOperationInput(operation, reader);
870: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
871: extensionFacade.portTypeOperationInputElements(input,
872: reader);
873: }
874: }
875:
876: private void parsePortTypeOperationOutput(XMLStreamReader reader,
877: WSDLOperationImpl operation) {
878: String msg = ParserUtil.getAttribute(reader, "message");
879: QName msgName = ParserUtil.getQName(reader, msg);
880: String name = ParserUtil.getAttribute(reader, "name");
881: WSDLOutputImpl output = new WSDLOutputImpl(reader, name,
882: msgName, operation);
883: operation.setOutput(output);
884: extensionFacade.portTypeOperationOutputAttributes(output,
885: reader);
886: extensionFacade.portTypeOperationOutput(operation, reader);
887: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
888: extensionFacade.portTypeOperationOutputElements(output,
889: reader);
890: }
891: }
892:
893: private void parseMessage(XMLStreamReader reader) {
894: String msgName = ParserUtil.getMandatoryNonEmptyAttribute(
895: reader, WSDLConstants.ATTR_NAME);
896: WSDLMessageImpl msg = new WSDLMessageImpl(reader, new QName(
897: targetNamespace, msgName));
898: extensionFacade.messageAttributes(msg, reader);
899: int partIndex = 0;
900: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
901: QName name = reader.getName();
902: if (WSDLConstants.QNAME_PART.equals(name)) {
903: String part = ParserUtil.getMandatoryNonEmptyAttribute(
904: reader, WSDLConstants.ATTR_NAME);
905: String desc = null;
906: int index = reader.getAttributeCount();
907: WSDLDescriptorKind kind = WSDLDescriptorKind.ELEMENT;
908: for (int i = 0; i < index; i++) {
909: QName descName = reader.getAttributeName(i);
910: if (descName.getLocalPart().equals("element"))
911: kind = WSDLDescriptorKind.ELEMENT;
912: else if (descName.getLocalPart().equals("TYPE"))
913: kind = WSDLDescriptorKind.TYPE;
914:
915: if (descName.getLocalPart().equals("element")
916: || descName.getLocalPart().equals("type")) {
917: desc = reader.getAttributeValue(i);
918: break;
919: }
920: }
921: if (desc == null)
922: continue;
923:
924: WSDLPartImpl wsdlPart = new WSDLPartImpl(reader, part,
925: partIndex,
926: new WSDLPartDescriptorImpl(reader, ParserUtil
927: .getQName(reader, desc), kind));
928: msg.add(wsdlPart);
929: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT)
930: goToEnd(reader);
931: } else {
932: extensionFacade.messageElements(msg, reader);
933: }
934: }
935: wsdlDoc.addMessage(msg);
936: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT)
937: goToEnd(reader);
938: }
939:
940: private static void goToEnd(XMLStreamReader reader) {
941: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
942: XMLStreamReaderUtil.skipElement(reader);
943: }
944: }
945:
946: /**
947: * Make sure to return a "fresh" reader each time it is called because
948: * more than one active reader may be needed within a single thread
949: * to parse a WSDL file.
950: */
951: private static XMLStreamReader createReader(URL wsdlLoc)
952: throws IOException, XMLStreamException {
953: InputStream stream = wsdlLoc.openStream();
954: return new TidyXMLStreamReader(XMLStreamReaderFactory.create(
955: wsdlLoc.toExternalForm(), stream, false), stream);
956: }
957:
958: private void register(WSDLParserExtension e) {
959: // protect JAX-WS RI from broken parser extension
960: extensions.add(new FoolProofParserExtension(e));
961: }
962:
963: private static final Logger LOGGER = Logger
964: .getLogger(RuntimeWSDLParser.class.getName());
965: }
|