View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.xml.internal.ws.wsdl.parser;
27  
28  import com.sun.istack.internal.NotNull;
29  import com.sun.istack.internal.Nullable;
30  import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
31  import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
32  import com.sun.xml.internal.stream.buffer.XMLStreamBufferMark;
33  import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferCreator;
34  import com.sun.xml.internal.ws.api.BindingID;
35  import com.sun.xml.internal.ws.api.BindingIDFactory;
36  import com.sun.xml.internal.ws.api.SOAPVersion;
37  import com.sun.xml.internal.ws.api.EndpointAddress;
38  import com.sun.xml.internal.ws.api.WSDLLocator;
39  import com.sun.xml.internal.ws.api.policy.PolicyResolver;
40  import com.sun.xml.internal.ws.api.policy.PolicyResolverFactory;
41  import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
42  import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
43  import com.sun.xml.internal.ws.api.model.ParameterBinding;
44  import com.sun.xml.internal.ws.api.model.wsdl.WSDLDescriptorKind;
45  import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel;
46  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundFault;
47  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundOperation;
48  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundPortType;
49  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLFault;
50  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLInput;
51  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLMessage;
52  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLModel;
53  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOperation;
54  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOutput;
55  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPart;
56  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPort;
57  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPortType;
58  import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLService;
59  import com.sun.xml.internal.ws.api.server.Container;
60  import com.sun.xml.internal.ws.api.server.ContainerResolver;
61  import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
62  import com.sun.xml.internal.ws.api.wsdl.parser.MetaDataResolver;
63  import com.sun.xml.internal.ws.api.wsdl.parser.MetadataResolverFactory;
64  import com.sun.xml.internal.ws.api.wsdl.parser.ServiceDescriptor;
65  import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension;
66  import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver;
67  import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser;
68  import com.sun.xml.internal.ws.model.wsdl.*;
69  import com.sun.xml.internal.ws.resources.ClientMessages;
70  import com.sun.xml.internal.ws.resources.WsdlmodelMessages;
71  import com.sun.xml.internal.ws.streaming.SourceReaderFactory;
72  import com.sun.xml.internal.ws.streaming.TidyXMLStreamReader;
73  import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
74  import com.sun.xml.internal.ws.util.ServiceFinder;
75  import com.sun.xml.internal.ws.util.xml.XmlUtil;
76  import com.sun.xml.internal.ws.policy.jaxws.PolicyWSDLParserExtension;
77  
78  import org.xml.sax.EntityResolver;
79  import org.xml.sax.SAXException;
80  
81  import javax.jws.soap.SOAPBinding.Style;
82  import javax.xml.namespace.QName;
83  import javax.xml.stream.*;
84  import javax.xml.transform.Source;
85  import javax.xml.transform.stream.StreamSource;
86  import javax.xml.ws.Service;
87  import javax.xml.ws.WebServiceException;
88  
89  import java.io.IOException;
90  import java.io.InputStream;
91  import java.io.FilterInputStream;
92  import java.net.URISyntaxException;
93  import java.net.URL;
94  import java.util.*;
95  import java.util.logging.Logger;
96  
97  /**
98   * Parses WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}.
99   *
100  * @author Vivek Pandey
101  * @author Rama Pulavarthi
102  */
103 public class RuntimeWSDLParser {
104 
105     private final EditableWSDLModel wsdlDoc;
106     /**
107      * Target namespace URI of the WSDL that we are currently parsing.
108      */
109     private String targetNamespace;
110     /**
111      * System IDs of WSDLs that are already read.
112      */
113     private final Set<String> importedWSDLs = new HashSet<String>();
114     /**
115      * Must not be null.
116      */
117     private final XMLEntityResolver resolver;
118 
119     private final PolicyResolver policyResolver;
120 
121     /**
122      * The {@link WSDLParserExtension}. Always non-null.
123      */
124     private final WSDLParserExtension extensionFacade;
125 
126     private final WSDLParserExtensionContextImpl context;
127 
128     List<WSDLParserExtension> extensions;
129 
130     //Capture namespaces declared on the ancestors of wsa:EndpointReference, so that valid XmlStreamBuffer is created
131     // from the EndpointReference fragment.
132     Map<String, String> wsdldef_nsdecl = new HashMap<String, String>();
133     Map<String, String> service_nsdecl = new HashMap<String, String>();
134     Map<String, String> port_nsdecl = new HashMap<String, String>();
135 
136     /**
137      * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
138      * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
139      * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
140      *
141      * @param wsdlLoc
142      *      Either this or <tt>wsdl</tt> parameter must be given.
143      *      Null location means the system won't be able to resolve relative references in the WSDL,
144      */
145     public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver,
146                                       boolean isClientSide, Container container,
147                                       WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
148         return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, Service.class, PolicyResolverFactory.create(),extensions);
149     }
150 
151     /**
152      * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
153      * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
154      * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
155      *
156      * @param wsdlLoc
157      *      Either this or <tt>wsdl</tt> parameter must be given.
158      *      Null location means the system won't be able to resolve relative references in the WSDL,
159      */
160     public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver,
161                                       boolean isClientSide, Container container, Class serviceClass,
162                                       WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
163         return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, serviceClass, PolicyResolverFactory.create(),extensions);
164     }
165 
166     /**
167      * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
168      * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
169      * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
170      *
171      * @param wsdlLoc
172      *      Either this or <tt>wsdl</tt> parameter must be given.
173      *      Null location means the system won't be able to resolve relative references in the WSDL,
174      */
175     public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver,
176                                       boolean isClientSide, Container container, @NotNull PolicyResolver policyResolver,
177                                       WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
178         return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, Service.class, policyResolver, extensions);
179     }
180 
181     /**
182      * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
183      * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
184      * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
185      *
186      * @param wsdlLoc
187      *      Either this or <tt>wsdl</tt> parameter must be given.
188      *      Null location means the system won't be able to resolve relative references in the WSDL,
189      */
190     public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver,
191                                       boolean isClientSide, Container container, Class serviceClass,
192                                       @NotNull PolicyResolver policyResolver,
193                                       WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
194         return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, serviceClass, policyResolver, false, extensions);
195     }
196 
197     /**
198      * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL
199      * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found
200      * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'.
201      *
202      * @param wsdlLoc
203      *      Either this or <tt>wsdl</tt> parameter must be given.
204      *      Null location means the system won't be able to resolve relative references in the WSDL,
205      */
206     public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver,
207                                       boolean isClientSide, Container container, Class serviceClass,
208                                       @NotNull PolicyResolver policyResolver,
209                                       boolean isUseStreamFromEntityResolverWrapper,
210                                       WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
211         assert resolver != null;
212 
213         RuntimeWSDLParser wsdlParser = new RuntimeWSDLParser(wsdlSource.getSystemId(), new EntityResolverWrapper(resolver, isUseStreamFromEntityResolverWrapper), isClientSide, container, policyResolver, extensions);
214         Parser parser;
215         try{
216             parser = wsdlParser.resolveWSDL(wsdlLoc, wsdlSource, serviceClass);
217             if(!hasWSDLDefinitions(parser.parser)){
218                 throw new XMLStreamException(ClientMessages.RUNTIME_WSDLPARSER_INVALID_WSDL(parser.systemId,
219                         WSDLConstants.QNAME_DEFINITIONS, parser.parser.getName(), parser.parser.getLocation()));
220             }
221         }catch(XMLStreamException e){
222             //Try MEX if there is WSDLLoc available
223             if(wsdlLoc == null)
224                 throw e;
225             return tryWithMex(wsdlParser, wsdlLoc, resolver, isClientSide, container, e, serviceClass, policyResolver, extensions);
226 
227         }catch(IOException e){
228             //Try MEX if there is WSDLLoc available
229             if(wsdlLoc == null)
230                 throw e;
231             return tryWithMex(wsdlParser, wsdlLoc, resolver, isClientSide, container, e, serviceClass, policyResolver, extensions);
232         }
233         wsdlParser.extensionFacade.start(wsdlParser.context);
234         wsdlParser.parseWSDL(parser, false);
235         wsdlParser.wsdlDoc.freeze();
236         wsdlParser.extensionFacade.finished(wsdlParser.context);
237         wsdlParser.extensionFacade.postFinished(wsdlParser.context);
238 
239         if(wsdlParser.wsdlDoc.getServices().isEmpty())
240             throw new WebServiceException(ClientMessages.WSDL_CONTAINS_NO_SERVICE(wsdlLoc));
241 
242         return wsdlParser.wsdlDoc;
243     }
244 
245     private static WSDLModel tryWithMex(@NotNull RuntimeWSDLParser wsdlParser, @NotNull URL wsdlLoc, @NotNull EntityResolver resolver, boolean isClientSide, Container container, Throwable e, Class serviceClass, PolicyResolver policyResolver, WSDLParserExtension... extensions) throws SAXException, XMLStreamException {
246         ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
247         try {
248             WSDLModel wsdlModel = wsdlParser.parseUsingMex(wsdlLoc, resolver, isClientSide, container, serviceClass, policyResolver,extensions);
249             if(wsdlModel == null){
250                 throw new WebServiceException(ClientMessages.FAILED_TO_PARSE(wsdlLoc.toExternalForm(), e.getMessage()), e);
251             }
252             return wsdlModel;
253         } catch (URISyntaxException e1) {
254             exceptions.add(e);
255             exceptions.add(e1);
256         } catch(IOException e1){
257             exceptions.add(e);
258             exceptions.add(e1);
259         }
260         throw new InaccessibleWSDLException(exceptions);
261     }
262 
263     private WSDLModel parseUsingMex(@NotNull URL wsdlLoc, @NotNull EntityResolver resolver, boolean isClientSide, Container container, Class serviceClass, PolicyResolver policyResolver, WSDLParserExtension[] extensions) throws IOException, SAXException, XMLStreamException, URISyntaxException {
264         //try MEX
265         MetaDataResolver mdResolver = null;
266         ServiceDescriptor serviceDescriptor = null;
267         RuntimeWSDLParser wsdlParser = null;
268 
269         //Currently we try the first available MetadataResolverFactory that gives us a WSDL document
270         for (MetadataResolverFactory resolverFactory : ServiceFinder.find(MetadataResolverFactory.class)) {
271             mdResolver = resolverFactory.metadataResolver(resolver);
272             serviceDescriptor = mdResolver.resolve(wsdlLoc.toURI());
273             //we got the ServiceDescriptor, now break
274             if (serviceDescriptor != null)
275                 break;
276         }
277         if (serviceDescriptor != null) {
278             List<? extends Source> wsdls = serviceDescriptor.getWSDLs();
279             wsdlParser = new RuntimeWSDLParser(wsdlLoc.toExternalForm(), new MexEntityResolver(wsdls), isClientSide, container, policyResolver, extensions);
280             wsdlParser.extensionFacade.start(wsdlParser.context);
281 
282             for(Source src: wsdls ) {
283                 String systemId = src.getSystemId();
284                 Parser parser = wsdlParser.resolver.resolveEntity(null, systemId);
285                 wsdlParser.parseWSDL(parser, false);
286             }
287         }
288         //Incase that mex is not present or it couldn't get the metadata, try by appending ?wsdl and give
289         // it a last shot else fail
290         if ((mdResolver == null || serviceDescriptor == null) && (wsdlLoc.getProtocol().equals("http") || wsdlLoc.getProtocol().equals("https")) && (wsdlLoc.getQuery() == null)) {
291             String urlString = wsdlLoc.toExternalForm();
292             urlString += "?wsdl";
293             wsdlLoc = new URL(urlString);
294             wsdlParser = new RuntimeWSDLParser(wsdlLoc.toExternalForm(),new EntityResolverWrapper(resolver), isClientSide, container, policyResolver, extensions);
295             wsdlParser.extensionFacade.start(wsdlParser.context);
296             Parser parser = resolveWSDL(wsdlLoc, new StreamSource(wsdlLoc.toExternalForm()), serviceClass);
297             wsdlParser.parseWSDL(parser, false);
298         }
299 
300         if(wsdlParser == null)
301             return null;
302 
303         wsdlParser.wsdlDoc.freeze();
304         wsdlParser.extensionFacade.finished(wsdlParser.context);
305         wsdlParser.extensionFacade.postFinished(wsdlParser.context);
306         return wsdlParser.wsdlDoc;
307     }
308 
309     private static boolean hasWSDLDefinitions(XMLStreamReader reader) {
310         XMLStreamReaderUtil.nextElementContent(reader);
311         return reader.getName().equals(WSDLConstants.QNAME_DEFINITIONS);
312     }
313 
314     public static WSDLModel parse(XMLEntityResolver.Parser wsdl, XMLEntityResolver resolver, boolean isClientSide, Container container, PolicyResolver policyResolver, WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
315         assert resolver != null;
316         RuntimeWSDLParser parser = new RuntimeWSDLParser( wsdl.systemId.toExternalForm(), resolver, isClientSide, container, policyResolver, extensions);
317         parser.extensionFacade.start(parser.context);
318         parser.parseWSDL(wsdl, false);
319         parser.wsdlDoc.freeze();
320         parser.extensionFacade.finished(parser.context);
321         parser.extensionFacade.postFinished(parser.context);
322         return parser.wsdlDoc;
323     }
324 
325     public static WSDLModel parse(XMLEntityResolver.Parser wsdl, XMLEntityResolver resolver, boolean isClientSide, Container container, WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException {
326         assert resolver != null;
327         RuntimeWSDLParser parser = new RuntimeWSDLParser( wsdl.systemId.toExternalForm(), resolver, isClientSide, container, PolicyResolverFactory.create(), extensions);
328         parser.extensionFacade.start(parser.context);
329         parser.parseWSDL(wsdl, false);
330         parser.wsdlDoc.freeze();
331         parser.extensionFacade.finished(parser.context);
332         parser.extensionFacade.postFinished(parser.context);
333         return parser.wsdlDoc;
334     }
335 
336     private RuntimeWSDLParser(@NotNull String sourceLocation, XMLEntityResolver resolver, boolean isClientSide, Container container, PolicyResolver policyResolver, WSDLParserExtension... extensions) {
337         this.wsdlDoc = sourceLocation!=null ? new WSDLModelImpl(sourceLocation) : new WSDLModelImpl();
338         this.resolver = resolver;
339         this.policyResolver = policyResolver;
340         this.extensions = new ArrayList<WSDLParserExtension>();
341         this.context = new WSDLParserExtensionContextImpl(wsdlDoc, isClientSide, container, policyResolver);
342 
343         boolean isPolicyExtensionFound = false;
344         for (WSDLParserExtension e : extensions) {
345                 if (e instanceof com.sun.xml.internal.ws.api.wsdl.parser.PolicyWSDLParserExtension)
346                         isPolicyExtensionFound = true;
347             register(e);
348         }
349 
350         // register handlers for default extensions
351         if (!isPolicyExtensionFound)
352                 register(new PolicyWSDLParserExtension());
353         register(new MemberSubmissionAddressingWSDLParserExtension());
354         register(new W3CAddressingWSDLParserExtension());
355         register(new W3CAddressingMetadataWSDLParserExtension());
356 
357         this.extensionFacade =  new WSDLParserExtensionFacade(this.extensions.toArray(new WSDLParserExtension[0]));
358     }
359 
360     private Parser resolveWSDL(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, Class serviceClass) throws IOException, SAXException, XMLStreamException {
361         String systemId = wsdlSource.getSystemId();
362 
363         XMLEntityResolver.Parser parser = resolver.resolveEntity(null, systemId);
364         if (parser == null && wsdlLoc != null) {
365                 String exForm = wsdlLoc.toExternalForm();
366             parser = resolver.resolveEntity(null, exForm);
367 
368             if (parser == null && serviceClass != null) {
369                 URL ru = serviceClass.getResource(".");
370                 if (ru != null) {
371                         String ruExForm = ru.toExternalForm();
372                         if (exForm.startsWith(ruExForm)) {
373                                 parser = resolver.resolveEntity(null, exForm.substring(ruExForm.length()));
374                         }
375                 }
376             }
377         }
378         if (parser == null) {
379             //If a WSDL source is provided that is known to be readable, then
380             //prioritize that over the URL - this avoids going over the network
381             //an additional time if a valid WSDL Source is provided - Deva Sagar 09/20/2011
382             if (isKnownReadableSource(wsdlSource)) {
383                 parser = new Parser(wsdlLoc, createReader(wsdlSource));
384             } else if (wsdlLoc != null) {
385                 parser = new Parser(wsdlLoc, createReader(wsdlLoc, serviceClass));
386             }
387 
388             //parser could still be null if isKnownReadableSource returns
389             //false and wsdlLoc is also null. Fall back to using Source based
390             //parser since Source is not null
391             if (parser == null) {
392                 parser = new Parser(wsdlLoc, createReader(wsdlSource));
393             }
394         }
395         return parser;
396     }
397 
398     private boolean isKnownReadableSource(Source wsdlSource) {
399                 if (wsdlSource instanceof StreamSource) {
400                         return (((StreamSource) wsdlSource).getInputStream() != null ||
401                                         ((StreamSource) wsdlSource).getReader() != null);
402                 } else {
403                         return false;
404                 }
405         }
406 
407     private XMLStreamReader createReader(@NotNull Source src) throws XMLStreamException {
408         return new TidyXMLStreamReader(SourceReaderFactory.createSourceReader(src, true), null);
409     }
410 
411     private void parseImport(@NotNull URL wsdlLoc) throws XMLStreamException, IOException, SAXException {
412         String systemId = wsdlLoc.toExternalForm();
413         XMLEntityResolver.Parser parser = resolver.resolveEntity(null, systemId);
414         if (parser == null) {
415             parser = new Parser(wsdlLoc, createReader(wsdlLoc));
416         }
417         parseWSDL(parser, true);
418     }
419 
420     private void parseWSDL(Parser parser, boolean imported) throws XMLStreamException, IOException, SAXException {
421         XMLStreamReader reader = parser.parser;
422         try {
423             // avoid processing the same WSDL twice.
424             // if no system ID is given, the check won't work
425             if (parser.systemId != null && !importedWSDLs.add(parser.systemId.toExternalForm()))
426                 return;
427 
428             if(reader.getEventType() == XMLStreamConstants.START_DOCUMENT)
429                 XMLStreamReaderUtil.nextElementContent(reader);
430             if (WSDLConstants.QNAME_DEFINITIONS.equals(reader.getName())) {
431                 readNSDecl(wsdldef_nsdecl, reader);
432             }
433             if (reader.getEventType()!= XMLStreamConstants.END_DOCUMENT && reader.getName().equals(WSDLConstants.QNAME_SCHEMA)) {
434                 if (imported) {
435                     // wsdl:import could be a schema. Relaxing BP R2001 requirement.
436                     LOGGER.warning(WsdlmodelMessages.WSDL_IMPORT_SHOULD_BE_WSDL(parser.systemId));
437                     return;
438                 }
439             }
440 
441             //get the targetNamespace of the service
442             String tns = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_TNS);
443 
444             final String oldTargetNamespace = targetNamespace;
445             targetNamespace = tns;
446 
447             while (XMLStreamReaderUtil.nextElementContent(reader) !=
448                     XMLStreamConstants.END_ELEMENT) {
449                 if (reader.getEventType() == XMLStreamConstants.END_DOCUMENT)
450                     break;
451 
452                 QName name = reader.getName();
453                 if (WSDLConstants.QNAME_IMPORT.equals(name)) {
454                     parseImport(parser.systemId, reader);
455                 } else if (WSDLConstants.QNAME_MESSAGE.equals(name)) {
456                     parseMessage(reader);
457                 } else if (WSDLConstants.QNAME_PORT_TYPE.equals(name)) {
458                     parsePortType(reader);
459                 } else if (WSDLConstants.QNAME_BINDING.equals(name)) {
460                     parseBinding(reader);
461                 } else if (WSDLConstants.QNAME_SERVICE.equals(name)) {
462                     parseService(reader);
463                 } else {
464                     extensionFacade.definitionsElements(reader);
465                 }
466             }
467             targetNamespace = oldTargetNamespace;
468         } finally {
469             this.wsdldef_nsdecl = new HashMap<String,String>();
470             reader.close();
471         }
472     }
473 
474     private void parseService(XMLStreamReader reader) {
475         service_nsdecl.putAll(wsdldef_nsdecl);
476         readNSDecl(service_nsdecl,reader);
477 
478         String serviceName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
479         EditableWSDLService service = new WSDLServiceImpl(reader,wsdlDoc,new QName(targetNamespace, serviceName));
480         extensionFacade.serviceAttributes(service, reader);
481         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
482             QName name = reader.getName();
483             if (WSDLConstants.QNAME_PORT.equals(name)) {
484                 parsePort(reader, service);
485                 if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) {
486                     XMLStreamReaderUtil.next(reader);
487                 }
488             } else {
489                 extensionFacade.serviceElements(service, reader);
490             }
491         }
492         wsdlDoc.addService(service);
493         service_nsdecl =  new HashMap<String, String>();
494     }
495 
496     private void parsePort(XMLStreamReader reader, EditableWSDLService service) {
497         port_nsdecl.putAll(service_nsdecl);
498         readNSDecl(port_nsdecl,reader);
499 
500         String portName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
501         String binding = ParserUtil.getMandatoryNonEmptyAttribute(reader, "binding");
502 
503         QName bindingName = ParserUtil.getQName(reader, binding);
504         QName portQName = new QName(service.getName().getNamespaceURI(), portName);
505         EditableWSDLPort port = new WSDLPortImpl(reader,service, portQName, bindingName);
506 
507         extensionFacade.portAttributes(port, reader);
508 
509         String location;
510         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
511             QName name = reader.getName();
512             if (SOAPConstants.QNAME_ADDRESS.equals(name) || SOAPConstants.QNAME_SOAP12ADDRESS.equals(name)) {
513                 location = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_LOCATION);
514                 if (location != null) {
515                     try {
516                         port.setAddress(new EndpointAddress(location));
517                     } catch (URISyntaxException e) {
518                         //Lets not throw any exception, latter on it should be thrown when invocation happens. At this
519                         // time user has option to set the endopint address using request contexxt property.
520                     }
521                 }
522                 XMLStreamReaderUtil.next(reader);
523             } else if (AddressingVersion.W3C.nsUri.equals(name.getNamespaceURI()) &&
524                     "EndpointReference".equals(name.getLocalPart())) {
525                 try {
526                     StreamReaderBufferCreator creator = new StreamReaderBufferCreator(new MutableXMLStreamBuffer());
527                     XMLStreamBuffer eprbuffer = new XMLStreamBufferMark(port_nsdecl, creator);
528                     creator.createElementFragment(reader, false);
529 
530                     WSEndpointReference wsepr = new WSEndpointReference(eprbuffer, AddressingVersion.W3C);
531                     //wsepr.toSpec().writeTo(new StreamResult(System.out));
532                     port.setEPR(wsepr);
533                     /** XMLStreamBuffer.createNewBufferFromXMLStreamReader(reader) called from inside WSEndpointReference()
534                      *  consumes the complete EPR infoset and moves to the next element. This breaks the normal wsdl parser
535                      *  processing where it expects anyone reading the infoset to move to the end of the element that its reading
536                      *  and not to the next element.
537                      */
538                     if(reader.getEventType() == XMLStreamConstants.END_ELEMENT && reader.getName().equals(WSDLConstants.QNAME_PORT))
539                         break;
540                 } catch (XMLStreamException e) {
541                     throw new WebServiceException(e);
542                 }
543             } else {
544 
545                 extensionFacade.portElements(port, reader);
546             }
547         }
548         if (port.getAddress() == null) {
549             try {
550                 port.setAddress(new EndpointAddress(""));
551             } catch (URISyntaxException e) {
552                 //Lets not throw any exception, latter on it should be thrown when invocation happens. At this
553                 //time user has option to set the endopint address using request contexxt property.
554             }
555         }
556         service.put(portQName, port);
557         port_nsdecl =new HashMap<String, String>();
558     }
559 
560     private void parseBinding(XMLStreamReader reader) {
561         String bindingName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name");
562         String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "type");
563         if ((bindingName == null) || (portTypeName == null)) {
564             //TODO: throw exception?
565             //
566             //  wsdl:binding element for now
567             XMLStreamReaderUtil.skipElement(reader);
568             return;
569         }
570         EditableWSDLBoundPortType binding = new WSDLBoundPortTypeImpl(reader,wsdlDoc, new QName(targetNamespace, bindingName),
571                 ParserUtil.getQName(reader, portTypeName));
572         extensionFacade.bindingAttributes(binding, reader);
573 
574         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
575             QName name = reader.getName();
576             if (WSDLConstants.NS_SOAP_BINDING.equals(name)) {
577                 String transport = reader.getAttributeValue(null, WSDLConstants.ATTR_TRANSPORT);
578                 binding.setBindingId(createBindingId(transport, SOAPVersion.SOAP_11));
579 
580                 String style = reader.getAttributeValue(null, "style");
581 
582                 if ((style != null) && (style.equals("rpc"))) {
583                     binding.setStyle(Style.RPC);
584                 } else {
585                     binding.setStyle(Style.DOCUMENT);
586                 }
587                 goToEnd(reader);
588             } else if (WSDLConstants.NS_SOAP12_BINDING.equals(name)) {
589                 String transport = reader.getAttributeValue(null, WSDLConstants.ATTR_TRANSPORT);
590                 binding.setBindingId(createBindingId(transport, SOAPVersion.SOAP_12));
591 
592                 String style = reader.getAttributeValue(null, "style");
593                 if ((style != null) && (style.equals("rpc"))) {
594                     binding.setStyle(Style.RPC);
595                 } else {
596                     binding.setStyle(Style.DOCUMENT);
597                 }
598                 goToEnd(reader);
599             } else if (WSDLConstants.QNAME_OPERATION.equals(name)) {
600                 parseBindingOperation(reader, binding);
601             } else {
602                 extensionFacade.bindingElements(binding, reader);
603             }
604         }
605     }
606 
607     private static BindingID createBindingId(String transport, SOAPVersion soapVersion) {
608         if (!transport.equals(SOAPConstants.URI_SOAP_TRANSPORT_HTTP)) {
609             for( BindingIDFactory f : ServiceFinder.find(BindingIDFactory.class) ) {
610                 BindingID bindingId = f.create(transport, soapVersion);
611                 if(bindingId!=null) {
612                     return bindingId;
613                 }
614             }
615         }
616         return soapVersion.equals(SOAPVersion.SOAP_11)?BindingID.SOAP11_HTTP:BindingID.SOAP12_HTTP;
617     }
618 
619 
620     private void parseBindingOperation(XMLStreamReader reader, EditableWSDLBoundPortType binding) {
621         String bindingOpName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name");
622         if (bindingOpName == null) {
623             //TODO: throw exception?
624             //skip wsdl:binding element for now
625             XMLStreamReaderUtil.skipElement(reader);
626             return;
627         }
628 
629         QName opName = new QName(binding.getPortTypeName().getNamespaceURI(), bindingOpName);
630         EditableWSDLBoundOperation bindingOp = new WSDLBoundOperationImpl(reader,binding, opName);
631         binding.put(opName, bindingOp);
632         extensionFacade.bindingOperationAttributes(bindingOp, reader);
633 
634         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
635             QName name = reader.getName();
636             String style = null;
637             if (WSDLConstants.QNAME_INPUT.equals(name)) {
638                 parseInputBinding(reader, bindingOp);
639             } else if (WSDLConstants.QNAME_OUTPUT.equals(name)) {
640                 parseOutputBinding(reader, bindingOp);
641             } else if (WSDLConstants.QNAME_FAULT.equals(name)) {
642                 parseFaultBinding(reader, bindingOp);
643             } else if (SOAPConstants.QNAME_OPERATION.equals(name) ||
644                     SOAPConstants.QNAME_SOAP12OPERATION.equals(name)) {
645                 style = reader.getAttributeValue(null, "style");
646                 String soapAction = reader.getAttributeValue(null, "soapAction");
647 
648                 if (soapAction != null)
649                     bindingOp.setSoapAction(soapAction);
650 
651                 goToEnd(reader);
652             } else {
653                 extensionFacade.bindingOperationElements(bindingOp, reader);
654             }
655             /**
656              *  If style attribute is present set it otherwise set the style as defined
657              *  on the <soap:binding> element
658              */
659             if (style != null) {
660                 if (style.equals("rpc"))
661                     bindingOp.setStyle(Style.RPC);
662                 else
663                     bindingOp.setStyle(Style.DOCUMENT);
664             } else {
665                 bindingOp.setStyle(binding.getStyle());
666             }
667         }
668     }
669 
670     private void parseInputBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) {
671         boolean bodyFound = false;
672         extensionFacade.bindingOperationInputAttributes(bindingOp, reader);
673         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
674             QName name = reader.getName();
675             if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY.equals(name)) && !bodyFound) {
676                 bodyFound = true;
677                 bindingOp.setInputExplicitBodyParts(parseSOAPBodyBinding(reader, bindingOp, BindingMode.INPUT));
678                 goToEnd(reader);
679             } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER.equals(name))) {
680                 parseSOAPHeaderBinding(reader, bindingOp.getInputParts());
681             } else if (MIMEConstants.QNAME_MULTIPART_RELATED.equals(name)) {
682                 parseMimeMultipartBinding(reader, bindingOp, BindingMode.INPUT);
683             } else {
684                 extensionFacade.bindingOperationInputElements(bindingOp, reader);
685             }
686         }
687     }
688 
689     private void parseOutputBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) {
690         boolean bodyFound = false;
691         extensionFacade.bindingOperationOutputAttributes(bindingOp, reader);
692         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
693             QName name = reader.getName();
694             if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY.equals(name)) && !bodyFound) {
695                 bodyFound = true;
696                 bindingOp.setOutputExplicitBodyParts(parseSOAPBodyBinding(reader, bindingOp, BindingMode.OUTPUT));
697                 goToEnd(reader);
698             } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER.equals(name))) {
699                 parseSOAPHeaderBinding(reader, bindingOp.getOutputParts());
700             } else if (MIMEConstants.QNAME_MULTIPART_RELATED.equals(name)) {
701                 parseMimeMultipartBinding(reader, bindingOp, BindingMode.OUTPUT);
702             } else {
703                 extensionFacade.bindingOperationOutputElements(bindingOp, reader);
704             }
705         }
706     }
707 
708     private void parseFaultBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) {
709         String faultName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name");
710         EditableWSDLBoundFault wsdlBoundFault = new WSDLBoundFaultImpl(reader, faultName, bindingOp);
711         bindingOp.addFault(wsdlBoundFault);
712 
713         extensionFacade.bindingOperationFaultAttributes(wsdlBoundFault, reader);
714 
715         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
716             extensionFacade.bindingOperationFaultElements(wsdlBoundFault, reader);
717         }
718     }
719 
720     private enum BindingMode {
721         INPUT, OUTPUT, FAULT}
722 
723     private static boolean parseSOAPBodyBinding(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) {
724         String namespace = reader.getAttributeValue(null, "namespace");
725         if (mode == BindingMode.INPUT) {
726             op.setRequestNamespace(namespace);
727             return parseSOAPBodyBinding(reader, op.getInputParts());
728         }
729         //resp
730         op.setResponseNamespace(namespace);
731         return parseSOAPBodyBinding(reader, op.getOutputParts());
732     }
733 
734     /**
735      * Returns true if body has explicit parts declaration
736      */
737     private static boolean parseSOAPBodyBinding(XMLStreamReader reader, Map<String, ParameterBinding> parts) {
738         String partsString = reader.getAttributeValue(null, "parts");
739         if (partsString != null) {
740             List<String> partsList = XmlUtil.parseTokenList(partsString);
741             if (partsList.isEmpty()) {
742                 parts.put(" ", ParameterBinding.BODY);
743             } else {
744                 for (String part : partsList) {
745                     parts.put(part, ParameterBinding.BODY);
746                 }
747             }
748             return true;
749         }
750         return false;
751     }
752 
753     private static void parseSOAPHeaderBinding(XMLStreamReader reader, Map<String, ParameterBinding> parts) {
754         String part = reader.getAttributeValue(null, "part");
755         //if(part == null| part.equals("")||message == null || message.equals("")){
756         if (part == null || part.equals("")) {
757             return;
758         }
759 
760         //lets not worry about message attribute for now, probably additional headers wont be there
761         //String message = reader.getAttributeValue(null, "message");
762         //QName msgName = ParserUtil.getQName(reader, message);
763         parts.put(part, ParameterBinding.HEADER);
764         goToEnd(reader);
765     }
766 
767 
768     private static void parseMimeMultipartBinding(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) {
769         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
770             QName name = reader.getName();
771             if (MIMEConstants.QNAME_PART.equals(name)) {
772                 parseMIMEPart(reader, op, mode);
773             } else {
774                 XMLStreamReaderUtil.skipElement(reader);
775             }
776         }
777     }
778 
779     private static void parseMIMEPart(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) {
780         boolean bodyFound = false;
781         Map<String, ParameterBinding> parts = null;
782         if (mode == BindingMode.INPUT) {
783             parts = op.getInputParts();
784         } else if (mode == BindingMode.OUTPUT) {
785             parts = op.getOutputParts();
786         } else if (mode == BindingMode.FAULT) {
787             parts = op.getFaultParts();
788         }
789         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
790             QName name = reader.getName();
791             if (SOAPConstants.QNAME_BODY.equals(name) && !bodyFound) {
792                 bodyFound = true;
793                 parseSOAPBodyBinding(reader, op, mode);
794                 XMLStreamReaderUtil.next(reader);
795             } else if (SOAPConstants.QNAME_HEADER.equals(name)) {
796                 bodyFound = true;
797                 parseSOAPHeaderBinding(reader, parts);
798                 XMLStreamReaderUtil.next(reader);
799             } else if (MIMEConstants.QNAME_CONTENT.equals(name)) {
800                 String part = reader.getAttributeValue(null, "part");
801                 String type = reader.getAttributeValue(null, "type");
802                 if ((part == null) || (type == null)) {
803                     XMLStreamReaderUtil.skipElement(reader);
804                     continue;
805                 }
806                 ParameterBinding sb = ParameterBinding.createAttachment(type);
807                 if (parts != null && sb != null && part != null)
808                     parts.put(part, sb);
809                 XMLStreamReaderUtil.next(reader);
810             } else {
811                 XMLStreamReaderUtil.skipElement(reader);
812             }
813         }
814     }
815 
816     protected void parseImport(@Nullable URL baseURL, XMLStreamReader reader) throws IOException, SAXException, XMLStreamException {
817         // expand to the absolute URL of the imported WSDL.
818         String importLocation =
819                 ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_LOCATION);
820         URL importURL;
821         if(baseURL!=null)
822             importURL = new URL(baseURL, importLocation);
823         else // no base URL. this better be absolute
824             importURL = new URL(importLocation);
825         parseImport(importURL);
826         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
827             XMLStreamReaderUtil.skipElement(reader);
828         }
829     }
830 
831     private void parsePortType(XMLStreamReader reader) {
832         String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
833         if (portTypeName == null) {
834             //TODO: throw exception?
835             //skip wsdl:portType element for now
836             XMLStreamReaderUtil.skipElement(reader);
837             return;
838         }
839         EditableWSDLPortType portType = new WSDLPortTypeImpl(reader,wsdlDoc, new QName(targetNamespace, portTypeName));
840         extensionFacade.portTypeAttributes(portType, reader);
841         wsdlDoc.addPortType(portType);
842         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
843             QName name = reader.getName();
844             if (WSDLConstants.QNAME_OPERATION.equals(name)) {
845                 parsePortTypeOperation(reader, portType);
846             } else {
847                 extensionFacade.portTypeElements(portType, reader);
848             }
849         }
850     }
851 
852 
853     private void parsePortTypeOperation(XMLStreamReader reader, EditableWSDLPortType portType) {
854         String operationName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
855         if (operationName == null) {
856             //TODO: throw exception?
857             //skip wsdl:portType element for now
858             XMLStreamReaderUtil.skipElement(reader);
859             return;
860         }
861 
862         QName operationQName = new QName(portType.getName().getNamespaceURI(), operationName);
863         EditableWSDLOperation operation = new WSDLOperationImpl(reader,portType, operationQName);
864         extensionFacade.portTypeOperationAttributes(operation, reader);
865         String parameterOrder = ParserUtil.getAttribute(reader, "parameterOrder");
866         operation.setParameterOrder(parameterOrder);
867         portType.put(operationName, operation);
868         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
869             QName name = reader.getName();
870             if (name.equals(WSDLConstants.QNAME_INPUT)) {
871                 parsePortTypeOperationInput(reader, operation);
872             } else if (name.equals(WSDLConstants.QNAME_OUTPUT)) {
873                 parsePortTypeOperationOutput(reader, operation);
874             } else if (name.equals(WSDLConstants.QNAME_FAULT)) {
875                 parsePortTypeOperationFault(reader, operation);
876             } else {
877                 extensionFacade.portTypeOperationElements(operation, reader);
878             }
879         }
880     }
881 
882 
883     private void parsePortTypeOperationFault(XMLStreamReader reader, EditableWSDLOperation operation) {
884         String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader, "message");
885         QName msgName = ParserUtil.getQName(reader, msg);
886         String name = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name");
887         EditableWSDLFault fault = new WSDLFaultImpl(reader,name, msgName, operation);
888         operation.addFault(fault);
889         extensionFacade.portTypeOperationFaultAttributes(fault, reader);
890         extensionFacade.portTypeOperationFault(operation, reader);
891         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
892             extensionFacade.portTypeOperationFaultElements(fault, reader);
893         }
894     }
895 
896     private void parsePortTypeOperationInput(XMLStreamReader reader, EditableWSDLOperation operation) {
897         String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader, "message");
898         QName msgName = ParserUtil.getQName(reader, msg);
899         String name = ParserUtil.getAttribute(reader, "name");
900         EditableWSDLInput input = new WSDLInputImpl(reader, name, msgName, operation);
901         operation.setInput(input);
902         extensionFacade.portTypeOperationInputAttributes(input, reader);
903         extensionFacade.portTypeOperationInput(operation, reader);
904         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
905             extensionFacade.portTypeOperationInputElements(input, reader);
906         }
907     }
908 
909     private void parsePortTypeOperationOutput(XMLStreamReader reader, EditableWSDLOperation operation) {
910         String msg = ParserUtil.getAttribute(reader, "message");
911         QName msgName = ParserUtil.getQName(reader, msg);
912         String name = ParserUtil.getAttribute(reader, "name");
913         EditableWSDLOutput output = new WSDLOutputImpl(reader,name, msgName, operation);
914         operation.setOutput(output);
915         extensionFacade.portTypeOperationOutputAttributes(output, reader);
916         extensionFacade.portTypeOperationOutput(operation, reader);
917         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
918             extensionFacade.portTypeOperationOutputElements(output, reader);
919         }
920     }
921 
922     private void parseMessage(XMLStreamReader reader) {
923         String msgName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
924         EditableWSDLMessage msg = new WSDLMessageImpl(reader,new QName(targetNamespace, msgName));
925         extensionFacade.messageAttributes(msg, reader);
926         int partIndex = 0;
927         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
928             QName name = reader.getName();
929             if (WSDLConstants.QNAME_PART.equals(name)) {
930                 String part = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME);
931                 String desc = null;
932                 int index = reader.getAttributeCount();
933                 WSDLDescriptorKind kind = WSDLDescriptorKind.ELEMENT;
934                 for (int i = 0; i < index; i++) {
935                     QName descName = reader.getAttributeName(i);
936                     if (descName.getLocalPart().equals("element"))
937                         kind = WSDLDescriptorKind.ELEMENT;
938                     else if (descName.getLocalPart().equals("type"))
939                         kind = WSDLDescriptorKind.TYPE;
940 
941                     if (descName.getLocalPart().equals("element") || descName.getLocalPart().equals("type")) {
942                         desc = reader.getAttributeValue(i);
943                         break;
944                     }
945                 }
946                 if (desc != null) {
947                     EditableWSDLPart wsdlPart = new WSDLPartImpl(reader, part, partIndex, new WSDLPartDescriptorImpl(reader,ParserUtil.getQName(reader, desc), kind));
948                     msg.add(wsdlPart);
949                 }
950                 if (reader.getEventType() != XMLStreamConstants.END_ELEMENT)
951                     goToEnd(reader);
952             } else {
953                 extensionFacade.messageElements(msg, reader);
954             }
955         }
956         wsdlDoc.addMessage(msg);
957         if (reader.getEventType() != XMLStreamConstants.END_ELEMENT)
958             goToEnd(reader);
959     }
960 
961     private static void goToEnd(XMLStreamReader reader) {
962         while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) {
963             XMLStreamReaderUtil.skipElement(reader);
964         }
965     }
966 
967     /**
968      * Make sure to return a "fresh" reader each time it is called because
969      * more than one active reader may be needed within a single thread
970      * to parse a WSDL file.
971      */
972     private static XMLStreamReader createReader(URL wsdlLoc) throws IOException, XMLStreamException {
973         return createReader(wsdlLoc, null);
974     }
975 
976     /**
977      * Make sure to return a "fresh" reader each time it is called because
978      * more than one active reader may be needed within a single thread
979      * to parse a WSDL file.
980      */
981     private static XMLStreamReader createReader(URL wsdlLoc, Class<Service> serviceClass) throws IOException, XMLStreamException {
982         InputStream stream;
983         try {
984                 stream = wsdlLoc.openStream();
985         } catch (IOException io) {
986                 out:
987                 do {
988                         if (serviceClass != null) {
989                                 WSDLLocator locator = ContainerResolver.getInstance().getContainer().getSPI(WSDLLocator.class);
990                                 if (locator != null) {
991                                   String exForm = wsdlLoc.toExternalForm();
992                                   URL ru = serviceClass.getResource(".");
993                                   String loc = wsdlLoc.getPath();
994                                   if (ru != null) {
995                                     String ruExForm = ru.toExternalForm();
996                                     if (exForm.startsWith(ruExForm)) {
997                                       loc = exForm.substring(ruExForm.length());
998                                     }
999                                   }
1000                                   wsdlLoc = locator.locateWSDL(serviceClass, loc);
1001                                   if (wsdlLoc != null) {
1002                                                 stream = new FilterInputStream(wsdlLoc.openStream()) {
1003                                                     boolean closed;
1004 
1005                                                     @Override
1006                                                     public void close() throws IOException {
1007                                                         if (!closed) {
1008                                                             closed = true;
1009                                                             byte[] buf = new byte[8192];
1010                                                             while(read(buf) != -1);
1011                                                             super.close();
1012                                                         }
1013                                                     }
1014                                                 };
1015                                           break out;
1016                                   }
1017                                 }
1018                         }
1019                         throw io;
1020                 } while(true);
1021         }
1022 
1023         return new TidyXMLStreamReader(XMLStreamReaderFactory.create(wsdlLoc.toExternalForm(), stream, false), stream);
1024     }
1025 
1026     private void register(WSDLParserExtension e) {
1027         // protect JAX-WS RI from broken parser extension
1028         extensions.add(new FoolProofParserExtension(e));
1029     }
1030 
1031     /**
1032      * Reads the namespace declarations from the reader's current position in to the map. The reader is expected to be
1033      * on the start element.
1034      *
1035      * @param ns_map
1036      * @param reader
1037      */
1038     private static void readNSDecl(Map<String, String> ns_map, XMLStreamReader reader) {
1039         if (reader.getNamespaceCount() > 0) {
1040             for (int i = 0; i < reader.getNamespaceCount(); i++) {
1041                 ns_map.put(reader.getNamespacePrefix(i), reader.getNamespaceURI(i));
1042             }
1043         }
1044     }
1045 
1046     private static final Logger LOGGER = Logger.getLogger(RuntimeWSDLParser.class.getName());
1047 }