ohair@286: /* alanb@368: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.xml.internal.ws.wsdl.parser; ohair@286: ohair@286: import com.sun.istack.internal.NotNull; ohair@286: import com.sun.istack.internal.Nullable; ohair@286: import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer; ohair@286: import com.sun.xml.internal.stream.buffer.XMLStreamBuffer; ohair@286: import com.sun.xml.internal.stream.buffer.XMLStreamBufferMark; ohair@286: import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferCreator; ohair@286: import com.sun.xml.internal.ws.api.BindingID; alanb@368: import com.sun.xml.internal.ws.api.BindingIDFactory; ohair@286: import com.sun.xml.internal.ws.api.SOAPVersion; ohair@286: import com.sun.xml.internal.ws.api.EndpointAddress; ohair@286: import com.sun.xml.internal.ws.api.WSDLLocator; ohair@286: import com.sun.xml.internal.ws.api.policy.PolicyResolver; ohair@286: import com.sun.xml.internal.ws.api.policy.PolicyResolverFactory; ohair@286: import com.sun.xml.internal.ws.api.addressing.AddressingVersion; ohair@286: import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; ohair@286: import com.sun.xml.internal.ws.api.model.ParameterBinding; ohair@286: import com.sun.xml.internal.ws.api.model.wsdl.WSDLDescriptorKind; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.WSDLModel; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundFault; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundOperation; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLBoundPortType; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLFault; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLInput; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLMessage; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLModel; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOperation; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLOutput; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPart; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPort; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLPortType; mkos@408: import com.sun.xml.internal.ws.api.model.wsdl.editable.EditableWSDLService; ohair@286: import com.sun.xml.internal.ws.api.server.Container; ohair@286: import com.sun.xml.internal.ws.api.server.ContainerResolver; ohair@286: import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.MetaDataResolver; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.MetadataResolverFactory; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.ServiceDescriptor; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver; ohair@286: import com.sun.xml.internal.ws.api.wsdl.parser.XMLEntityResolver.Parser; ohair@286: import com.sun.xml.internal.ws.model.wsdl.*; ohair@286: import com.sun.xml.internal.ws.resources.ClientMessages; ohair@286: import com.sun.xml.internal.ws.resources.WsdlmodelMessages; ohair@286: import com.sun.xml.internal.ws.streaming.SourceReaderFactory; ohair@286: import com.sun.xml.internal.ws.streaming.TidyXMLStreamReader; ohair@286: import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; ohair@286: import com.sun.xml.internal.ws.util.ServiceFinder; ohair@286: import com.sun.xml.internal.ws.util.xml.XmlUtil; ohair@286: import com.sun.xml.internal.ws.policy.jaxws.PolicyWSDLParserExtension; mkos@408: ohair@286: import org.xml.sax.EntityResolver; ohair@286: import org.xml.sax.SAXException; ohair@286: ohair@286: import javax.jws.soap.SOAPBinding.Style; ohair@286: import javax.xml.namespace.QName; ohair@286: import javax.xml.stream.*; ohair@286: import javax.xml.transform.Source; ohair@286: import javax.xml.transform.stream.StreamSource; ohair@286: import javax.xml.ws.Service; ohair@286: import javax.xml.ws.WebServiceException; mkos@408: ohair@286: import java.io.IOException; ohair@286: import java.io.InputStream; ohair@286: import java.io.FilterInputStream; ohair@286: import java.net.URISyntaxException; ohair@286: import java.net.URL; ohair@286: import java.util.*; ohair@286: import java.util.logging.Logger; ohair@286: ohair@286: /** ohair@286: * Parses WSDL and builds {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLModel}. ohair@286: * ohair@286: * @author Vivek Pandey ohair@286: * @author Rama Pulavarthi ohair@286: */ ohair@286: public class RuntimeWSDLParser { ohair@286: mkos@408: private final EditableWSDLModel wsdlDoc; ohair@286: /** ohair@286: * Target namespace URI of the WSDL that we are currently parsing. ohair@286: */ ohair@286: private String targetNamespace; ohair@286: /** ohair@286: * System IDs of WSDLs that are already read. ohair@286: */ ohair@286: private final Set importedWSDLs = new HashSet(); ohair@286: /** ohair@286: * Must not be null. ohair@286: */ ohair@286: private final XMLEntityResolver resolver; ohair@286: ohair@286: private final PolicyResolver policyResolver; alanb@368: ohair@286: /** ohair@286: * The {@link WSDLParserExtension}. Always non-null. ohair@286: */ ohair@286: private final WSDLParserExtension extensionFacade; ohair@286: ohair@286: private final WSDLParserExtensionContextImpl context; ohair@286: ohair@286: List extensions; ohair@286: ohair@286: //Capture namespaces declared on the ancestors of wsa:EndpointReference, so that valid XmlStreamBuffer is created ohair@286: // from the EndpointReference fragment. ohair@286: Map wsdldef_nsdecl = new HashMap(); ohair@286: Map service_nsdecl = new HashMap(); ohair@286: Map port_nsdecl = new HashMap(); ohair@286: ohair@286: /** ohair@286: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL ohair@286: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found ohair@286: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'. ohair@286: * ohair@286: * @param wsdlLoc ohair@286: * Either this or wsdl parameter must be given. ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL, ohair@286: */ mkos@408: public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver, ohair@286: boolean isClientSide, Container container, ohair@286: WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, Service.class, PolicyResolverFactory.create(),extensions); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL ohair@286: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found ohair@286: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'. ohair@286: * ohair@286: * @param wsdlLoc ohair@286: * Either this or wsdl parameter must be given. ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL, ohair@286: */ mkos@408: public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver, ohair@286: boolean isClientSide, Container container, Class serviceClass, ohair@286: WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, serviceClass, PolicyResolverFactory.create(),extensions); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL ohair@286: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found ohair@286: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'. ohair@286: * ohair@286: * @param wsdlLoc ohair@286: * Either this or wsdl parameter must be given. ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL, ohair@286: */ mkos@408: public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver, ohair@286: boolean isClientSide, Container container, @NotNull PolicyResolver policyResolver, ohair@286: WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, Service.class, policyResolver, extensions); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL ohair@286: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found ohair@286: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'. ohair@286: * ohair@286: * @param wsdlLoc ohair@286: * Either this or wsdl parameter must be given. ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL, ohair@286: */ mkos@408: public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver, ohair@286: boolean isClientSide, Container container, Class serviceClass, ohair@286: @NotNull PolicyResolver policyResolver, ohair@286: WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: return parse(wsdlLoc, wsdlSource, resolver, isClientSide, container, serviceClass, policyResolver, false, extensions); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses the WSDL and gives WSDLModel. If wsdl parameter is null, then wsdlLoc is used to get the WSDL. If the WSDL ohair@286: * document could not be obtained then {@link MetadataResolverFactory} is tried to get the WSDL document, if not found ohair@286: * then as last option, if the wsdlLoc has no '?wsdl' as query parameter then it is tried by appending '?wsdl'. ohair@286: * ohair@286: * @param wsdlLoc ohair@286: * Either this or wsdl parameter must be given. ohair@286: * Null location means the system won't be able to resolve relative references in the WSDL, ohair@286: */ mkos@408: public static WSDLModel parse(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, @NotNull EntityResolver resolver, ohair@286: boolean isClientSide, Container container, Class serviceClass, ohair@286: @NotNull PolicyResolver policyResolver, ohair@286: boolean isUseStreamFromEntityResolverWrapper, ohair@286: WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: assert resolver != null; ohair@286: ohair@286: RuntimeWSDLParser wsdlParser = new RuntimeWSDLParser(wsdlSource.getSystemId(), new EntityResolverWrapper(resolver, isUseStreamFromEntityResolverWrapper), isClientSide, container, policyResolver, extensions); ohair@286: Parser parser; ohair@286: try{ ohair@286: parser = wsdlParser.resolveWSDL(wsdlLoc, wsdlSource, serviceClass); ohair@286: if(!hasWSDLDefinitions(parser.parser)){ ohair@286: throw new XMLStreamException(ClientMessages.RUNTIME_WSDLPARSER_INVALID_WSDL(parser.systemId, ohair@286: WSDLConstants.QNAME_DEFINITIONS, parser.parser.getName(), parser.parser.getLocation())); ohair@286: } ohair@286: }catch(XMLStreamException e){ ohair@286: //Try MEX if there is WSDLLoc available ohair@286: if(wsdlLoc == null) ohair@286: throw e; ohair@286: return tryWithMex(wsdlParser, wsdlLoc, resolver, isClientSide, container, e, serviceClass, policyResolver, extensions); ohair@286: ohair@286: }catch(IOException e){ ohair@286: //Try MEX if there is WSDLLoc available ohair@286: if(wsdlLoc == null) ohair@286: throw e; ohair@286: return tryWithMex(wsdlParser, wsdlLoc, resolver, isClientSide, container, e, serviceClass, policyResolver, extensions); ohair@286: } ohair@286: wsdlParser.extensionFacade.start(wsdlParser.context); ohair@286: wsdlParser.parseWSDL(parser, false); ohair@286: wsdlParser.wsdlDoc.freeze(); ohair@286: wsdlParser.extensionFacade.finished(wsdlParser.context); ohair@286: wsdlParser.extensionFacade.postFinished(wsdlParser.context); ohair@286: ohair@286: if(wsdlParser.wsdlDoc.getServices().isEmpty()) ohair@286: throw new WebServiceException(ClientMessages.WSDL_CONTAINS_NO_SERVICE(wsdlLoc)); ohair@286: ohair@286: return wsdlParser.wsdlDoc; ohair@286: } ohair@286: mkos@408: 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 { ohair@286: ArrayList exceptions = new ArrayList(); ohair@286: try { mkos@408: WSDLModel wsdlModel = wsdlParser.parseUsingMex(wsdlLoc, resolver, isClientSide, container, serviceClass, policyResolver,extensions); ohair@286: if(wsdlModel == null){ ohair@286: throw new WebServiceException(ClientMessages.FAILED_TO_PARSE(wsdlLoc.toExternalForm(), e.getMessage()), e); ohair@286: } ohair@286: return wsdlModel; ohair@286: } catch (URISyntaxException e1) { ohair@286: exceptions.add(e); ohair@286: exceptions.add(e1); ohair@286: } catch(IOException e1){ ohair@286: exceptions.add(e); ohair@286: exceptions.add(e1); ohair@286: } ohair@286: throw new InaccessibleWSDLException(exceptions); ohair@286: } ohair@286: mkos@408: private WSDLModel parseUsingMex(@NotNull URL wsdlLoc, @NotNull EntityResolver resolver, boolean isClientSide, Container container, Class serviceClass, PolicyResolver policyResolver, WSDLParserExtension[] extensions) throws IOException, SAXException, XMLStreamException, URISyntaxException { ohair@286: //try MEX ohair@286: MetaDataResolver mdResolver = null; ohair@286: ServiceDescriptor serviceDescriptor = null; ohair@286: RuntimeWSDLParser wsdlParser = null; ohair@286: ohair@286: //Currently we try the first available MetadataResolverFactory that gives us a WSDL document ohair@286: for (MetadataResolverFactory resolverFactory : ServiceFinder.find(MetadataResolverFactory.class)) { ohair@286: mdResolver = resolverFactory.metadataResolver(resolver); ohair@286: serviceDescriptor = mdResolver.resolve(wsdlLoc.toURI()); ohair@286: //we got the ServiceDescriptor, now break ohair@286: if (serviceDescriptor != null) ohair@286: break; ohair@286: } ohair@286: if (serviceDescriptor != null) { ohair@286: List wsdls = serviceDescriptor.getWSDLs(); ohair@286: wsdlParser = new RuntimeWSDLParser(wsdlLoc.toExternalForm(), new MexEntityResolver(wsdls), isClientSide, container, policyResolver, extensions); ohair@286: wsdlParser.extensionFacade.start(wsdlParser.context); ohair@286: ohair@286: for(Source src: wsdls ) { ohair@286: String systemId = src.getSystemId(); ohair@286: Parser parser = wsdlParser.resolver.resolveEntity(null, systemId); ohair@286: wsdlParser.parseWSDL(parser, false); ohair@286: } ohair@286: } ohair@286: //Incase that mex is not present or it couldn't get the metadata, try by appending ?wsdl and give ohair@286: // it a last shot else fail ohair@286: if ((mdResolver == null || serviceDescriptor == null) && (wsdlLoc.getProtocol().equals("http") || wsdlLoc.getProtocol().equals("https")) && (wsdlLoc.getQuery() == null)) { ohair@286: String urlString = wsdlLoc.toExternalForm(); ohair@286: urlString += "?wsdl"; ohair@286: wsdlLoc = new URL(urlString); ohair@286: wsdlParser = new RuntimeWSDLParser(wsdlLoc.toExternalForm(),new EntityResolverWrapper(resolver), isClientSide, container, policyResolver, extensions); ohair@286: wsdlParser.extensionFacade.start(wsdlParser.context); ohair@286: Parser parser = resolveWSDL(wsdlLoc, new StreamSource(wsdlLoc.toExternalForm()), serviceClass); ohair@286: wsdlParser.parseWSDL(parser, false); ohair@286: } ohair@286: ohair@286: if(wsdlParser == null) ohair@286: return null; ohair@286: ohair@286: wsdlParser.wsdlDoc.freeze(); ohair@286: wsdlParser.extensionFacade.finished(wsdlParser.context); ohair@286: wsdlParser.extensionFacade.postFinished(wsdlParser.context); ohair@286: return wsdlParser.wsdlDoc; ohair@286: } ohair@286: ohair@286: private static boolean hasWSDLDefinitions(XMLStreamReader reader) { ohair@286: XMLStreamReaderUtil.nextElementContent(reader); ohair@286: return reader.getName().equals(WSDLConstants.QNAME_DEFINITIONS); ohair@286: } ohair@286: mkos@408: public static WSDLModel parse(XMLEntityResolver.Parser wsdl, XMLEntityResolver resolver, boolean isClientSide, Container container, PolicyResolver policyResolver, WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: assert resolver != null; ohair@286: RuntimeWSDLParser parser = new RuntimeWSDLParser( wsdl.systemId.toExternalForm(), resolver, isClientSide, container, policyResolver, extensions); ohair@286: parser.extensionFacade.start(parser.context); ohair@286: parser.parseWSDL(wsdl, false); ohair@286: parser.wsdlDoc.freeze(); ohair@286: parser.extensionFacade.finished(parser.context); ohair@286: parser.extensionFacade.postFinished(parser.context); ohair@286: return parser.wsdlDoc; ohair@286: } ohair@286: mkos@408: public static WSDLModel parse(XMLEntityResolver.Parser wsdl, XMLEntityResolver resolver, boolean isClientSide, Container container, WSDLParserExtension... extensions) throws IOException, XMLStreamException, SAXException { ohair@286: assert resolver != null; ohair@286: RuntimeWSDLParser parser = new RuntimeWSDLParser( wsdl.systemId.toExternalForm(), resolver, isClientSide, container, PolicyResolverFactory.create(), extensions); ohair@286: parser.extensionFacade.start(parser.context); ohair@286: parser.parseWSDL(wsdl, false); ohair@286: parser.wsdlDoc.freeze(); ohair@286: parser.extensionFacade.finished(parser.context); ohair@286: parser.extensionFacade.postFinished(parser.context); ohair@286: return parser.wsdlDoc; ohair@286: } ohair@286: ohair@286: private RuntimeWSDLParser(@NotNull String sourceLocation, XMLEntityResolver resolver, boolean isClientSide, Container container, PolicyResolver policyResolver, WSDLParserExtension... extensions) { ohair@286: this.wsdlDoc = sourceLocation!=null ? new WSDLModelImpl(sourceLocation) : new WSDLModelImpl(); ohair@286: this.resolver = resolver; ohair@286: this.policyResolver = policyResolver; ohair@286: this.extensions = new ArrayList(); ohair@286: this.context = new WSDLParserExtensionContextImpl(wsdlDoc, isClientSide, container, policyResolver); ohair@286: ohair@286: boolean isPolicyExtensionFound = false; ohair@286: for (WSDLParserExtension e : extensions) { ohair@286: if (e instanceof com.sun.xml.internal.ws.api.wsdl.parser.PolicyWSDLParserExtension) ohair@286: isPolicyExtensionFound = true; ohair@286: register(e); ohair@286: } ohair@286: ohair@286: // register handlers for default extensions ohair@286: if (!isPolicyExtensionFound) ohair@286: register(new PolicyWSDLParserExtension()); ohair@286: register(new MemberSubmissionAddressingWSDLParserExtension()); ohair@286: register(new W3CAddressingWSDLParserExtension()); ohair@286: register(new W3CAddressingMetadataWSDLParserExtension()); ohair@286: ohair@286: this.extensionFacade = new WSDLParserExtensionFacade(this.extensions.toArray(new WSDLParserExtension[0])); ohair@286: } ohair@286: ohair@286: private Parser resolveWSDL(@Nullable URL wsdlLoc, @NotNull Source wsdlSource, Class serviceClass) throws IOException, SAXException, XMLStreamException { ohair@286: String systemId = wsdlSource.getSystemId(); ohair@286: ohair@286: XMLEntityResolver.Parser parser = resolver.resolveEntity(null, systemId); ohair@286: if (parser == null && wsdlLoc != null) { ohair@286: String exForm = wsdlLoc.toExternalForm(); ohair@286: parser = resolver.resolveEntity(null, exForm); ohair@286: ohair@286: if (parser == null && serviceClass != null) { ohair@286: URL ru = serviceClass.getResource("."); ohair@286: if (ru != null) { ohair@286: String ruExForm = ru.toExternalForm(); ohair@286: if (exForm.startsWith(ruExForm)) { ohair@286: parser = resolver.resolveEntity(null, exForm.substring(ruExForm.length())); ohair@286: } ohair@286: } ohair@286: } ohair@286: } alanb@368: if (parser == null) { alanb@368: //If a WSDL source is provided that is known to be readable, then alanb@368: //prioritize that over the URL - this avoids going over the network alanb@368: //an additional time if a valid WSDL Source is provided - Deva Sagar 09/20/2011 alanb@368: if (isKnownReadableSource(wsdlSource)) { ohair@286: parser = new Parser(wsdlLoc, createReader(wsdlSource)); alanb@368: } else if (wsdlLoc != null) { alanb@368: parser = new Parser(wsdlLoc, createReader(wsdlLoc, serviceClass)); alanb@368: } ohair@286: alanb@368: //parser could still be null if isKnownReadableSource returns alanb@368: //false and wsdlLoc is also null. Fall back to using Source based alanb@368: //parser since Source is not null alanb@368: if (parser == null) { alanb@368: parser = new Parser(wsdlLoc, createReader(wsdlSource)); alanb@368: } ohair@286: } ohair@286: return parser; ohair@286: } ohair@286: ohair@286: private boolean isKnownReadableSource(Source wsdlSource) { ohair@286: if (wsdlSource instanceof StreamSource) { ohair@286: return (((StreamSource) wsdlSource).getInputStream() != null || ohair@286: ((StreamSource) wsdlSource).getReader() != null); ohair@286: } else { ohair@286: return false; ohair@286: } ohair@286: } ohair@286: ohair@286: private XMLStreamReader createReader(@NotNull Source src) throws XMLStreamException { ohair@286: return new TidyXMLStreamReader(SourceReaderFactory.createSourceReader(src, true), null); ohair@286: } ohair@286: ohair@286: private void parseImport(@NotNull URL wsdlLoc) throws XMLStreamException, IOException, SAXException { ohair@286: String systemId = wsdlLoc.toExternalForm(); ohair@286: XMLEntityResolver.Parser parser = resolver.resolveEntity(null, systemId); ohair@286: if (parser == null) { ohair@286: parser = new Parser(wsdlLoc, createReader(wsdlLoc)); ohair@286: } ohair@286: parseWSDL(parser, true); ohair@286: } ohair@286: ohair@286: private void parseWSDL(Parser parser, boolean imported) throws XMLStreamException, IOException, SAXException { ohair@286: XMLStreamReader reader = parser.parser; ohair@286: try { ohair@286: // avoid processing the same WSDL twice. ohair@286: // if no system ID is given, the check won't work ohair@286: if (parser.systemId != null && !importedWSDLs.add(parser.systemId.toExternalForm())) ohair@286: return; ohair@286: ohair@286: if(reader.getEventType() == XMLStreamConstants.START_DOCUMENT) ohair@286: XMLStreamReaderUtil.nextElementContent(reader); ohair@286: if (WSDLConstants.QNAME_DEFINITIONS.equals(reader.getName())) { ohair@286: readNSDecl(wsdldef_nsdecl, reader); ohair@286: } ohair@286: if (reader.getEventType()!= XMLStreamConstants.END_DOCUMENT && reader.getName().equals(WSDLConstants.QNAME_SCHEMA)) { ohair@286: if (imported) { ohair@286: // wsdl:import could be a schema. Relaxing BP R2001 requirement. ohair@286: LOGGER.warning(WsdlmodelMessages.WSDL_IMPORT_SHOULD_BE_WSDL(parser.systemId)); ohair@286: return; ohair@286: } ohair@286: } ohair@286: ohair@286: //get the targetNamespace of the service ohair@286: String tns = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_TNS); ohair@286: ohair@286: final String oldTargetNamespace = targetNamespace; ohair@286: targetNamespace = tns; ohair@286: ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != ohair@286: XMLStreamConstants.END_ELEMENT) { ohair@286: if (reader.getEventType() == XMLStreamConstants.END_DOCUMENT) ohair@286: break; ohair@286: ohair@286: QName name = reader.getName(); ohair@286: if (WSDLConstants.QNAME_IMPORT.equals(name)) { ohair@286: parseImport(parser.systemId, reader); ohair@286: } else if (WSDLConstants.QNAME_MESSAGE.equals(name)) { ohair@286: parseMessage(reader); ohair@286: } else if (WSDLConstants.QNAME_PORT_TYPE.equals(name)) { ohair@286: parsePortType(reader); ohair@286: } else if (WSDLConstants.QNAME_BINDING.equals(name)) { ohair@286: parseBinding(reader); ohair@286: } else if (WSDLConstants.QNAME_SERVICE.equals(name)) { ohair@286: parseService(reader); ohair@286: } else { ohair@286: extensionFacade.definitionsElements(reader); ohair@286: } ohair@286: } ohair@286: targetNamespace = oldTargetNamespace; ohair@286: } finally { ohair@286: this.wsdldef_nsdecl = new HashMap(); ohair@286: reader.close(); ohair@286: } ohair@286: } ohair@286: ohair@286: private void parseService(XMLStreamReader reader) { ohair@286: service_nsdecl.putAll(wsdldef_nsdecl); ohair@286: readNSDecl(service_nsdecl,reader); ohair@286: ohair@286: String serviceName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); mkos@408: EditableWSDLService service = new WSDLServiceImpl(reader,wsdlDoc,new QName(targetNamespace, serviceName)); ohair@286: extensionFacade.serviceAttributes(service, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (WSDLConstants.QNAME_PORT.equals(name)) { ohair@286: parsePort(reader, service); ohair@286: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) { ohair@286: XMLStreamReaderUtil.next(reader); ohair@286: } ohair@286: } else { ohair@286: extensionFacade.serviceElements(service, reader); ohair@286: } ohair@286: } ohair@286: wsdlDoc.addService(service); ohair@286: service_nsdecl = new HashMap(); ohair@286: } ohair@286: mkos@408: private void parsePort(XMLStreamReader reader, EditableWSDLService service) { ohair@286: port_nsdecl.putAll(service_nsdecl); ohair@286: readNSDecl(port_nsdecl,reader); ohair@286: ohair@286: String portName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); ohair@286: String binding = ParserUtil.getMandatoryNonEmptyAttribute(reader, "binding"); ohair@286: ohair@286: QName bindingName = ParserUtil.getQName(reader, binding); ohair@286: QName portQName = new QName(service.getName().getNamespaceURI(), portName); mkos@408: EditableWSDLPort port = new WSDLPortImpl(reader,service, portQName, bindingName); ohair@286: ohair@286: extensionFacade.portAttributes(port, reader); ohair@286: ohair@286: String location; ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (SOAPConstants.QNAME_ADDRESS.equals(name) || SOAPConstants.QNAME_SOAP12ADDRESS.equals(name)) { ohair@286: location = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_LOCATION); ohair@286: if (location != null) { ohair@286: try { ohair@286: port.setAddress(new EndpointAddress(location)); ohair@286: } catch (URISyntaxException e) { ohair@286: //Lets not throw any exception, latter on it should be thrown when invocation happens. At this ohair@286: // time user has option to set the endopint address using request contexxt property. ohair@286: } ohair@286: } ohair@286: XMLStreamReaderUtil.next(reader); ohair@286: } else if (AddressingVersion.W3C.nsUri.equals(name.getNamespaceURI()) && ohair@286: "EndpointReference".equals(name.getLocalPart())) { ohair@286: try { ohair@286: StreamReaderBufferCreator creator = new StreamReaderBufferCreator(new MutableXMLStreamBuffer()); ohair@286: XMLStreamBuffer eprbuffer = new XMLStreamBufferMark(port_nsdecl, creator); ohair@286: creator.createElementFragment(reader, false); ohair@286: ohair@286: WSEndpointReference wsepr = new WSEndpointReference(eprbuffer, AddressingVersion.W3C); ohair@286: //wsepr.toSpec().writeTo(new StreamResult(System.out)); ohair@286: port.setEPR(wsepr); ohair@286: /** XMLStreamBuffer.createNewBufferFromXMLStreamReader(reader) called from inside WSEndpointReference() ohair@286: * consumes the complete EPR infoset and moves to the next element. This breaks the normal wsdl parser ohair@286: * processing where it expects anyone reading the infoset to move to the end of the element that its reading ohair@286: * and not to the next element. ohair@286: */ ohair@286: if(reader.getEventType() == XMLStreamConstants.END_ELEMENT && reader.getName().equals(WSDLConstants.QNAME_PORT)) ohair@286: break; ohair@286: } catch (XMLStreamException e) { ohair@286: throw new WebServiceException(e); ohair@286: } ohair@286: } else { ohair@286: ohair@286: extensionFacade.portElements(port, reader); ohair@286: } ohair@286: } ohair@286: if (port.getAddress() == null) { ohair@286: try { ohair@286: port.setAddress(new EndpointAddress("")); ohair@286: } catch (URISyntaxException e) { ohair@286: //Lets not throw any exception, latter on it should be thrown when invocation happens. At this ohair@286: //time user has option to set the endopint address using request contexxt property. ohair@286: } ohair@286: } ohair@286: service.put(portQName, port); ohair@286: port_nsdecl =new HashMap(); ohair@286: } ohair@286: ohair@286: private void parseBinding(XMLStreamReader reader) { ohair@286: String bindingName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name"); ohair@286: String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "type"); ohair@286: if ((bindingName == null) || (portTypeName == null)) { ohair@286: //TODO: throw exception? ohair@286: // ohair@286: // wsdl:binding element for now ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: return; ohair@286: } mkos@408: EditableWSDLBoundPortType binding = new WSDLBoundPortTypeImpl(reader,wsdlDoc, new QName(targetNamespace, bindingName), ohair@286: ParserUtil.getQName(reader, portTypeName)); ohair@286: extensionFacade.bindingAttributes(binding, reader); ohair@286: ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (WSDLConstants.NS_SOAP_BINDING.equals(name)) { alanb@368: String transport = reader.getAttributeValue(null, WSDLConstants.ATTR_TRANSPORT); alanb@368: binding.setBindingId(createBindingId(transport, SOAPVersion.SOAP_11)); alanb@368: ohair@286: String style = reader.getAttributeValue(null, "style"); ohair@286: ohair@286: if ((style != null) && (style.equals("rpc"))) { ohair@286: binding.setStyle(Style.RPC); ohair@286: } else { ohair@286: binding.setStyle(Style.DOCUMENT); ohair@286: } ohair@286: goToEnd(reader); ohair@286: } else if (WSDLConstants.NS_SOAP12_BINDING.equals(name)) { alanb@368: String transport = reader.getAttributeValue(null, WSDLConstants.ATTR_TRANSPORT); alanb@368: binding.setBindingId(createBindingId(transport, SOAPVersion.SOAP_12)); alanb@368: ohair@286: String style = reader.getAttributeValue(null, "style"); ohair@286: if ((style != null) && (style.equals("rpc"))) { ohair@286: binding.setStyle(Style.RPC); ohair@286: } else { ohair@286: binding.setStyle(Style.DOCUMENT); ohair@286: } ohair@286: goToEnd(reader); ohair@286: } else if (WSDLConstants.QNAME_OPERATION.equals(name)) { ohair@286: parseBindingOperation(reader, binding); ohair@286: } else { ohair@286: extensionFacade.bindingElements(binding, reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: alanb@368: private static BindingID createBindingId(String transport, SOAPVersion soapVersion) { alanb@368: if (!transport.equals(SOAPConstants.URI_SOAP_TRANSPORT_HTTP)) { alanb@368: for( BindingIDFactory f : ServiceFinder.find(BindingIDFactory.class) ) { alanb@368: BindingID bindingId = f.create(transport, soapVersion); alanb@368: if(bindingId!=null) { alanb@368: return bindingId; alanb@368: } alanb@368: } alanb@368: } alanb@368: return soapVersion.equals(SOAPVersion.SOAP_11)?BindingID.SOAP11_HTTP:BindingID.SOAP12_HTTP; alanb@368: } alanb@368: ohair@286: mkos@408: private void parseBindingOperation(XMLStreamReader reader, EditableWSDLBoundPortType binding) { ohair@286: String bindingOpName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name"); ohair@286: if (bindingOpName == null) { ohair@286: //TODO: throw exception? ohair@286: //skip wsdl:binding element for now ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: return; ohair@286: } ohair@286: ohair@286: QName opName = new QName(binding.getPortTypeName().getNamespaceURI(), bindingOpName); mkos@408: EditableWSDLBoundOperation bindingOp = new WSDLBoundOperationImpl(reader,binding, opName); ohair@286: binding.put(opName, bindingOp); ohair@286: extensionFacade.bindingOperationAttributes(bindingOp, reader); ohair@286: ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: String style = null; ohair@286: if (WSDLConstants.QNAME_INPUT.equals(name)) { ohair@286: parseInputBinding(reader, bindingOp); ohair@286: } else if (WSDLConstants.QNAME_OUTPUT.equals(name)) { ohair@286: parseOutputBinding(reader, bindingOp); ohair@286: } else if (WSDLConstants.QNAME_FAULT.equals(name)) { ohair@286: parseFaultBinding(reader, bindingOp); ohair@286: } else if (SOAPConstants.QNAME_OPERATION.equals(name) || ohair@286: SOAPConstants.QNAME_SOAP12OPERATION.equals(name)) { ohair@286: style = reader.getAttributeValue(null, "style"); ohair@286: String soapAction = reader.getAttributeValue(null, "soapAction"); ohair@286: ohair@286: if (soapAction != null) ohair@286: bindingOp.setSoapAction(soapAction); ohair@286: ohair@286: goToEnd(reader); ohair@286: } else { ohair@286: extensionFacade.bindingOperationElements(bindingOp, reader); ohair@286: } ohair@286: /** ohair@286: * If style attribute is present set it otherwise set the style as defined ohair@286: * on the element ohair@286: */ ohair@286: if (style != null) { ohair@286: if (style.equals("rpc")) ohair@286: bindingOp.setStyle(Style.RPC); ohair@286: else ohair@286: bindingOp.setStyle(Style.DOCUMENT); ohair@286: } else { ohair@286: bindingOp.setStyle(binding.getStyle()); ohair@286: } ohair@286: } ohair@286: } ohair@286: mkos@408: private void parseInputBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) { ohair@286: boolean bodyFound = false; ohair@286: extensionFacade.bindingOperationInputAttributes(bindingOp, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY.equals(name)) && !bodyFound) { ohair@286: bodyFound = true; ohair@286: bindingOp.setInputExplicitBodyParts(parseSOAPBodyBinding(reader, bindingOp, BindingMode.INPUT)); ohair@286: goToEnd(reader); ohair@286: } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER.equals(name))) { ohair@286: parseSOAPHeaderBinding(reader, bindingOp.getInputParts()); ohair@286: } else if (MIMEConstants.QNAME_MULTIPART_RELATED.equals(name)) { ohair@286: parseMimeMultipartBinding(reader, bindingOp, BindingMode.INPUT); ohair@286: } else { ohair@286: extensionFacade.bindingOperationInputElements(bindingOp, reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: mkos@408: private void parseOutputBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) { ohair@286: boolean bodyFound = false; ohair@286: extensionFacade.bindingOperationOutputAttributes(bindingOp, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if ((SOAPConstants.QNAME_BODY.equals(name) || SOAPConstants.QNAME_SOAP12BODY.equals(name)) && !bodyFound) { ohair@286: bodyFound = true; ohair@286: bindingOp.setOutputExplicitBodyParts(parseSOAPBodyBinding(reader, bindingOp, BindingMode.OUTPUT)); ohair@286: goToEnd(reader); ohair@286: } else if ((SOAPConstants.QNAME_HEADER.equals(name) || SOAPConstants.QNAME_SOAP12HEADER.equals(name))) { ohair@286: parseSOAPHeaderBinding(reader, bindingOp.getOutputParts()); ohair@286: } else if (MIMEConstants.QNAME_MULTIPART_RELATED.equals(name)) { ohair@286: parseMimeMultipartBinding(reader, bindingOp, BindingMode.OUTPUT); ohair@286: } else { ohair@286: extensionFacade.bindingOperationOutputElements(bindingOp, reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: mkos@408: private void parseFaultBinding(XMLStreamReader reader, EditableWSDLBoundOperation bindingOp) { ohair@286: String faultName = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name"); mkos@408: EditableWSDLBoundFault wsdlBoundFault = new WSDLBoundFaultImpl(reader, faultName, bindingOp); ohair@286: bindingOp.addFault(wsdlBoundFault); ohair@286: ohair@286: extensionFacade.bindingOperationFaultAttributes(wsdlBoundFault, reader); ohair@286: ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: extensionFacade.bindingOperationFaultElements(wsdlBoundFault, reader); ohair@286: } ohair@286: } ohair@286: ohair@286: private enum BindingMode { ohair@286: INPUT, OUTPUT, FAULT} ohair@286: mkos@408: private static boolean parseSOAPBodyBinding(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) { ohair@286: String namespace = reader.getAttributeValue(null, "namespace"); ohair@286: if (mode == BindingMode.INPUT) { ohair@286: op.setRequestNamespace(namespace); ohair@286: return parseSOAPBodyBinding(reader, op.getInputParts()); ohair@286: } ohair@286: //resp ohair@286: op.setResponseNamespace(namespace); ohair@286: return parseSOAPBodyBinding(reader, op.getOutputParts()); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Returns true if body has explicit parts declaration ohair@286: */ ohair@286: private static boolean parseSOAPBodyBinding(XMLStreamReader reader, Map parts) { ohair@286: String partsString = reader.getAttributeValue(null, "parts"); ohair@286: if (partsString != null) { ohair@286: List partsList = XmlUtil.parseTokenList(partsString); ohair@286: if (partsList.isEmpty()) { ohair@286: parts.put(" ", ParameterBinding.BODY); ohair@286: } else { ohair@286: for (String part : partsList) { ohair@286: parts.put(part, ParameterBinding.BODY); ohair@286: } ohair@286: } ohair@286: return true; ohair@286: } ohair@286: return false; ohair@286: } ohair@286: ohair@286: private static void parseSOAPHeaderBinding(XMLStreamReader reader, Map parts) { ohair@286: String part = reader.getAttributeValue(null, "part"); ohair@286: //if(part == null| part.equals("")||message == null || message.equals("")){ ohair@286: if (part == null || part.equals("")) { ohair@286: return; ohair@286: } ohair@286: ohair@286: //lets not worry about message attribute for now, probably additional headers wont be there ohair@286: //String message = reader.getAttributeValue(null, "message"); ohair@286: //QName msgName = ParserUtil.getQName(reader, message); ohair@286: parts.put(part, ParameterBinding.HEADER); ohair@286: goToEnd(reader); ohair@286: } ohair@286: ohair@286: mkos@408: private static void parseMimeMultipartBinding(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) { ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (MIMEConstants.QNAME_PART.equals(name)) { ohair@286: parseMIMEPart(reader, op, mode); ohair@286: } else { ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: mkos@408: private static void parseMIMEPart(XMLStreamReader reader, EditableWSDLBoundOperation op, BindingMode mode) { ohair@286: boolean bodyFound = false; ohair@286: Map parts = null; ohair@286: if (mode == BindingMode.INPUT) { ohair@286: parts = op.getInputParts(); ohair@286: } else if (mode == BindingMode.OUTPUT) { ohair@286: parts = op.getOutputParts(); ohair@286: } else if (mode == BindingMode.FAULT) { ohair@286: parts = op.getFaultParts(); ohair@286: } ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (SOAPConstants.QNAME_BODY.equals(name) && !bodyFound) { ohair@286: bodyFound = true; ohair@286: parseSOAPBodyBinding(reader, op, mode); ohair@286: XMLStreamReaderUtil.next(reader); ohair@286: } else if (SOAPConstants.QNAME_HEADER.equals(name)) { ohair@286: bodyFound = true; ohair@286: parseSOAPHeaderBinding(reader, parts); ohair@286: XMLStreamReaderUtil.next(reader); ohair@286: } else if (MIMEConstants.QNAME_CONTENT.equals(name)) { ohair@286: String part = reader.getAttributeValue(null, "part"); ohair@286: String type = reader.getAttributeValue(null, "type"); ohair@286: if ((part == null) || (type == null)) { ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: continue; ohair@286: } ohair@286: ParameterBinding sb = ParameterBinding.createAttachment(type); ohair@286: if (parts != null && sb != null && part != null) ohair@286: parts.put(part, sb); ohair@286: XMLStreamReaderUtil.next(reader); ohair@286: } else { ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: protected void parseImport(@Nullable URL baseURL, XMLStreamReader reader) throws IOException, SAXException, XMLStreamException { ohair@286: // expand to the absolute URL of the imported WSDL. ohair@286: String importLocation = ohair@286: ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_LOCATION); ohair@286: URL importURL; ohair@286: if(baseURL!=null) ohair@286: importURL = new URL(baseURL, importLocation); ohair@286: else // no base URL. this better be absolute ohair@286: importURL = new URL(importLocation); ohair@286: parseImport(importURL); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: } ohair@286: } ohair@286: ohair@286: private void parsePortType(XMLStreamReader reader) { ohair@286: String portTypeName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); ohair@286: if (portTypeName == null) { ohair@286: //TODO: throw exception? ohair@286: //skip wsdl:portType element for now ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: return; ohair@286: } mkos@408: EditableWSDLPortType portType = new WSDLPortTypeImpl(reader,wsdlDoc, new QName(targetNamespace, portTypeName)); ohair@286: extensionFacade.portTypeAttributes(portType, reader); ohair@286: wsdlDoc.addPortType(portType); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (WSDLConstants.QNAME_OPERATION.equals(name)) { ohair@286: parsePortTypeOperation(reader, portType); ohair@286: } else { ohair@286: extensionFacade.portTypeElements(portType, reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: mkos@408: private void parsePortTypeOperation(XMLStreamReader reader, EditableWSDLPortType portType) { ohair@286: String operationName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); ohair@286: if (operationName == null) { ohair@286: //TODO: throw exception? ohair@286: //skip wsdl:portType element for now ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: return; ohair@286: } ohair@286: ohair@286: QName operationQName = new QName(portType.getName().getNamespaceURI(), operationName); mkos@408: EditableWSDLOperation operation = new WSDLOperationImpl(reader,portType, operationQName); ohair@286: extensionFacade.portTypeOperationAttributes(operation, reader); ohair@286: String parameterOrder = ParserUtil.getAttribute(reader, "parameterOrder"); ohair@286: operation.setParameterOrder(parameterOrder); ohair@286: portType.put(operationName, operation); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (name.equals(WSDLConstants.QNAME_INPUT)) { ohair@286: parsePortTypeOperationInput(reader, operation); ohair@286: } else if (name.equals(WSDLConstants.QNAME_OUTPUT)) { ohair@286: parsePortTypeOperationOutput(reader, operation); ohair@286: } else if (name.equals(WSDLConstants.QNAME_FAULT)) { ohair@286: parsePortTypeOperationFault(reader, operation); ohair@286: } else { ohair@286: extensionFacade.portTypeOperationElements(operation, reader); ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: mkos@408: private void parsePortTypeOperationFault(XMLStreamReader reader, EditableWSDLOperation operation) { ohair@286: String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader, "message"); ohair@286: QName msgName = ParserUtil.getQName(reader, msg); ohair@286: String name = ParserUtil.getMandatoryNonEmptyAttribute(reader, "name"); mkos@408: EditableWSDLFault fault = new WSDLFaultImpl(reader,name, msgName, operation); ohair@286: operation.addFault(fault); ohair@286: extensionFacade.portTypeOperationFaultAttributes(fault, reader); ohair@286: extensionFacade.portTypeOperationFault(operation, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: extensionFacade.portTypeOperationFaultElements(fault, reader); ohair@286: } ohair@286: } ohair@286: mkos@408: private void parsePortTypeOperationInput(XMLStreamReader reader, EditableWSDLOperation operation) { ohair@286: String msg = ParserUtil.getMandatoryNonEmptyAttribute(reader, "message"); ohair@286: QName msgName = ParserUtil.getQName(reader, msg); ohair@286: String name = ParserUtil.getAttribute(reader, "name"); mkos@408: EditableWSDLInput input = new WSDLInputImpl(reader, name, msgName, operation); ohair@286: operation.setInput(input); ohair@286: extensionFacade.portTypeOperationInputAttributes(input, reader); ohair@286: extensionFacade.portTypeOperationInput(operation, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: extensionFacade.portTypeOperationInputElements(input, reader); ohair@286: } ohair@286: } ohair@286: mkos@408: private void parsePortTypeOperationOutput(XMLStreamReader reader, EditableWSDLOperation operation) { ohair@286: String msg = ParserUtil.getAttribute(reader, "message"); ohair@286: QName msgName = ParserUtil.getQName(reader, msg); ohair@286: String name = ParserUtil.getAttribute(reader, "name"); mkos@408: EditableWSDLOutput output = new WSDLOutputImpl(reader,name, msgName, operation); ohair@286: operation.setOutput(output); ohair@286: extensionFacade.portTypeOperationOutputAttributes(output, reader); ohair@286: extensionFacade.portTypeOperationOutput(operation, reader); ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: extensionFacade.portTypeOperationOutputElements(output, reader); ohair@286: } ohair@286: } ohair@286: ohair@286: private void parseMessage(XMLStreamReader reader) { ohair@286: String msgName = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); mkos@408: EditableWSDLMessage msg = new WSDLMessageImpl(reader,new QName(targetNamespace, msgName)); ohair@286: extensionFacade.messageAttributes(msg, reader); ohair@286: int partIndex = 0; ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: QName name = reader.getName(); ohair@286: if (WSDLConstants.QNAME_PART.equals(name)) { ohair@286: String part = ParserUtil.getMandatoryNonEmptyAttribute(reader, WSDLConstants.ATTR_NAME); ohair@286: String desc = null; ohair@286: int index = reader.getAttributeCount(); ohair@286: WSDLDescriptorKind kind = WSDLDescriptorKind.ELEMENT; ohair@286: for (int i = 0; i < index; i++) { ohair@286: QName descName = reader.getAttributeName(i); ohair@286: if (descName.getLocalPart().equals("element")) ohair@286: kind = WSDLDescriptorKind.ELEMENT; alanb@368: else if (descName.getLocalPart().equals("type")) ohair@286: kind = WSDLDescriptorKind.TYPE; ohair@286: ohair@286: if (descName.getLocalPart().equals("element") || descName.getLocalPart().equals("type")) { ohair@286: desc = reader.getAttributeValue(i); ohair@286: break; ohair@286: } ohair@286: } ohair@286: if (desc != null) { mkos@408: EditableWSDLPart wsdlPart = new WSDLPartImpl(reader, part, partIndex, new WSDLPartDescriptorImpl(reader,ParserUtil.getQName(reader, desc), kind)); ohair@286: msg.add(wsdlPart); ohair@286: } ohair@286: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) ohair@286: goToEnd(reader); ohair@286: } else { ohair@286: extensionFacade.messageElements(msg, reader); ohair@286: } ohair@286: } ohair@286: wsdlDoc.addMessage(msg); ohair@286: if (reader.getEventType() != XMLStreamConstants.END_ELEMENT) ohair@286: goToEnd(reader); ohair@286: } ohair@286: ohair@286: private static void goToEnd(XMLStreamReader reader) { ohair@286: while (XMLStreamReaderUtil.nextElementContent(reader) != XMLStreamConstants.END_ELEMENT) { ohair@286: XMLStreamReaderUtil.skipElement(reader); ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * Make sure to return a "fresh" reader each time it is called because ohair@286: * more than one active reader may be needed within a single thread ohair@286: * to parse a WSDL file. ohair@286: */ ohair@286: private static XMLStreamReader createReader(URL wsdlLoc) throws IOException, XMLStreamException { ohair@286: return createReader(wsdlLoc, null); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Make sure to return a "fresh" reader each time it is called because ohair@286: * more than one active reader may be needed within a single thread ohair@286: * to parse a WSDL file. ohair@286: */ ohair@286: private static XMLStreamReader createReader(URL wsdlLoc, Class serviceClass) throws IOException, XMLStreamException { ohair@286: InputStream stream; ohair@286: try { ohair@286: stream = wsdlLoc.openStream(); ohair@286: } catch (IOException io) { ohair@286: out: ohair@286: do { ohair@286: if (serviceClass != null) { ohair@286: WSDLLocator locator = ContainerResolver.getInstance().getContainer().getSPI(WSDLLocator.class); ohair@286: if (locator != null) { ohair@286: String exForm = wsdlLoc.toExternalForm(); ohair@286: URL ru = serviceClass.getResource("."); ohair@286: String loc = wsdlLoc.getPath(); ohair@286: if (ru != null) { ohair@286: String ruExForm = ru.toExternalForm(); ohair@286: if (exForm.startsWith(ruExForm)) { ohair@286: loc = exForm.substring(ruExForm.length()); ohair@286: } ohair@286: } ohair@286: wsdlLoc = locator.locateWSDL(serviceClass, loc); ohair@286: if (wsdlLoc != null) { ohair@286: stream = new FilterInputStream(wsdlLoc.openStream()) { ohair@286: boolean closed; ohair@286: ohair@286: @Override ohair@286: public void close() throws IOException { ohair@286: if (!closed) { ohair@286: closed = true; ohair@286: byte[] buf = new byte[8192]; ohair@286: while(read(buf) != -1); ohair@286: super.close(); ohair@286: } ohair@286: } ohair@286: }; ohair@286: break out; ohair@286: } ohair@286: } ohair@286: } ohair@286: throw io; ohair@286: } while(true); ohair@286: } ohair@286: ohair@286: return new TidyXMLStreamReader(XMLStreamReaderFactory.create(wsdlLoc.toExternalForm(), stream, false), stream); ohair@286: } ohair@286: ohair@286: private void register(WSDLParserExtension e) { ohair@286: // protect JAX-WS RI from broken parser extension ohair@286: extensions.add(new FoolProofParserExtension(e)); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Reads the namespace declarations from the reader's current position in to the map. The reader is expected to be ohair@286: * on the start element. ohair@286: * ohair@286: * @param ns_map ohair@286: * @param reader ohair@286: */ ohair@286: private static void readNSDecl(Map ns_map, XMLStreamReader reader) { ohair@286: if (reader.getNamespaceCount() > 0) { ohair@286: for (int i = 0; i < reader.getNamespaceCount(); i++) { ohair@286: ns_map.put(reader.getNamespacePrefix(i), reader.getNamespaceURI(i)); ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: private static final Logger LOGGER = Logger.getLogger(RuntimeWSDLParser.class.getName()); ohair@286: }