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 }