|
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 } |