|
1 /* |
|
2 * Copyright (c) 1997, 2012, 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.api.addressing; |
|
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.XMLStreamBufferResult; |
|
33 import com.sun.xml.internal.stream.buffer.XMLStreamBufferSource; |
|
34 import com.sun.xml.internal.stream.buffer.sax.SAXBufferProcessor; |
|
35 import com.sun.xml.internal.stream.buffer.stax.StreamReaderBufferProcessor; |
|
36 import com.sun.xml.internal.stream.buffer.stax.StreamWriterBufferCreator; |
|
37 import com.sun.xml.internal.ws.addressing.EndpointReferenceUtil; |
|
38 import com.sun.xml.internal.ws.addressing.W3CAddressingMetadataConstants; |
|
39 import com.sun.xml.internal.ws.addressing.WSEPRExtension; |
|
40 import com.sun.xml.internal.ws.addressing.model.InvalidAddressingHeaderException; |
|
41 import com.sun.xml.internal.ws.addressing.v200408.MemberSubmissionAddressingConstants; |
|
42 import com.sun.xml.internal.ws.api.message.Header; |
|
43 import com.sun.xml.internal.ws.api.message.HeaderList; |
|
44 import com.sun.xml.internal.ws.api.message.Message; |
|
45 import com.sun.xml.internal.ws.api.message.MessageHeaders; |
|
46 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; |
|
47 import com.sun.xml.internal.ws.api.model.wsdl.WSDLExtension; |
|
48 import com.sun.xml.internal.ws.resources.AddressingMessages; |
|
49 import com.sun.xml.internal.ws.resources.ClientMessages; |
|
50 import com.sun.xml.internal.ws.spi.ProviderImpl; |
|
51 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; |
|
52 import com.sun.xml.internal.ws.util.DOMUtil; |
|
53 import com.sun.xml.internal.ws.util.xml.XMLStreamWriterFilter; |
|
54 import com.sun.xml.internal.ws.util.xml.XmlUtil; |
|
55 import com.sun.xml.internal.ws.util.xml.XMLStreamReaderToXMLStreamWriter; |
|
56 import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; |
|
57 import org.w3c.dom.Element; |
|
58 import org.xml.sax.*; |
|
59 import org.xml.sax.helpers.XMLFilterImpl; |
|
60 |
|
61 import javax.xml.bind.JAXBContext; |
|
62 import javax.xml.namespace.QName; |
|
63 import javax.xml.stream.XMLStreamException; |
|
64 import javax.xml.stream.XMLStreamReader; |
|
65 import javax.xml.stream.XMLStreamWriter; |
|
66 import javax.xml.transform.Source; |
|
67 import javax.xml.transform.TransformerException; |
|
68 import javax.xml.transform.sax.SAXSource; |
|
69 import javax.xml.transform.stream.StreamResult; |
|
70 import javax.xml.transform.stream.StreamSource; |
|
71 import javax.xml.ws.Dispatch; |
|
72 import javax.xml.ws.EndpointReference; |
|
73 import javax.xml.ws.Service; |
|
74 import javax.xml.ws.WebServiceException; |
|
75 import javax.xml.ws.WebServiceFeature; |
|
76 import java.io.InputStream; |
|
77 import java.io.StringWriter; |
|
78 import java.net.URI; |
|
79 import java.net.URL; |
|
80 import java.util.*; |
|
81 |
|
82 /** |
|
83 * Internal representation of the EPR. |
|
84 * |
|
85 * <p> |
|
86 * Instances of this class are immutable and thread-safe. |
|
87 * |
|
88 * @author Kohsuke Kawaguchi |
|
89 * @author Rama Pulavarthi |
|
90 * |
|
91 * @see AddressingVersion#anonymousEpr |
|
92 */ |
|
93 public final class WSEndpointReference implements WSDLExtension { |
|
94 private final XMLStreamBuffer infoset; |
|
95 /** |
|
96 * Version of the addressing spec. |
|
97 */ |
|
98 private final AddressingVersion version; |
|
99 |
|
100 /** |
|
101 * Marked Reference parameters inside this EPR. |
|
102 * |
|
103 * Parsed when the object is created. can be empty but never null. |
|
104 * @see #parse() |
|
105 */ |
|
106 private @NotNull Header[] referenceParameters; |
|
107 private @NotNull String address; |
|
108 |
|
109 private @NotNull QName rootElement; |
|
110 /** |
|
111 * Creates from the spec version of {@link EndpointReference}. |
|
112 * |
|
113 * <p> |
|
114 * This method performs the data conversion, so it's slow. |
|
115 * Do not use this method in a performance critical path. |
|
116 */ |
|
117 public WSEndpointReference(EndpointReference epr, AddressingVersion version) { |
|
118 try { |
|
119 MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer(); |
|
120 epr.writeTo(new XMLStreamBufferResult(xsb)); |
|
121 this.infoset = xsb; |
|
122 this.version = version; |
|
123 this.rootElement = new QName("EndpointReference", version.nsUri); |
|
124 parse(); |
|
125 } catch (XMLStreamException e) { |
|
126 throw new WebServiceException(ClientMessages.FAILED_TO_PARSE_EPR(epr),e); |
|
127 } |
|
128 } |
|
129 |
|
130 /** |
|
131 * Creates from the spec version of {@link EndpointReference}. |
|
132 * |
|
133 * <p> |
|
134 * This method performs the data conversion, so it's slow. |
|
135 * Do not use this method in a performance critical path. |
|
136 */ |
|
137 public WSEndpointReference(EndpointReference epr) { |
|
138 this(epr,AddressingVersion.fromSpecClass(epr.getClass())); |
|
139 } |
|
140 |
|
141 /** |
|
142 * Creates a {@link WSEndpointReference} that wraps a given infoset. |
|
143 */ |
|
144 public WSEndpointReference(XMLStreamBuffer infoset, AddressingVersion version) { |
|
145 try { |
|
146 this.infoset = infoset; |
|
147 this.version = version; |
|
148 this.rootElement = new QName("EndpointReference", version.nsUri); |
|
149 parse(); |
|
150 } catch (XMLStreamException e) { |
|
151 // this can never happen because XMLStreamBuffer never has underlying I/O error. |
|
152 throw new AssertionError(e); |
|
153 } |
|
154 } |
|
155 |
|
156 /** |
|
157 * Creates a {@link WSEndpointReference} by parsing an infoset. |
|
158 */ |
|
159 public WSEndpointReference(InputStream infoset, AddressingVersion version) throws XMLStreamException { |
|
160 this(XMLStreamReaderFactory.create(null,infoset,false),version); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Creates a {@link WSEndpointReference} from the given infoset. |
|
165 * The {@link XMLStreamReader} must point to either a document or an element. |
|
166 */ |
|
167 public WSEndpointReference(XMLStreamReader in, AddressingVersion version) throws XMLStreamException { |
|
168 this(XMLStreamBuffer.createNewBufferFromXMLStreamReader(in), version); |
|
169 } |
|
170 |
|
171 /** |
|
172 * @see #WSEndpointReference(String, AddressingVersion) |
|
173 */ |
|
174 public WSEndpointReference(URL address, AddressingVersion version) { |
|
175 this(address.toExternalForm(), version); |
|
176 } |
|
177 |
|
178 /** |
|
179 * @see #WSEndpointReference(String, AddressingVersion) |
|
180 */ |
|
181 public WSEndpointReference(URI address, AddressingVersion version) { |
|
182 this(address.toString(), version); |
|
183 } |
|
184 |
|
185 /** |
|
186 * Creates a {@link WSEndpointReference} that only has an address. |
|
187 */ |
|
188 public WSEndpointReference(String address, AddressingVersion version) { |
|
189 this.infoset = createBufferFromAddress(address,version); |
|
190 this.version = version; |
|
191 this.address = address; |
|
192 this.rootElement = new QName("EndpointReference", version.nsUri); |
|
193 this.referenceParameters = EMPTY_ARRAY; |
|
194 } |
|
195 |
|
196 private static XMLStreamBuffer createBufferFromAddress(String address, AddressingVersion version) { |
|
197 try { |
|
198 MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer(); |
|
199 StreamWriterBufferCreator w = new StreamWriterBufferCreator(xsb); |
|
200 w.writeStartDocument(); |
|
201 w.writeStartElement(version.getPrefix(), |
|
202 "EndpointReference", version.nsUri); |
|
203 w.writeNamespace(version.getPrefix(), version.nsUri); |
|
204 w.writeStartElement(version.getPrefix(),version.eprType.address, version.nsUri); |
|
205 w.writeCharacters(address); |
|
206 w.writeEndElement(); |
|
207 w.writeEndElement(); |
|
208 w.writeEndDocument(); |
|
209 w.close(); |
|
210 return xsb; |
|
211 } catch (XMLStreamException e) { |
|
212 // can never happen because we are writing to XSB |
|
213 throw new AssertionError(e); |
|
214 } |
|
215 } |
|
216 |
|
217 /** |
|
218 * Creates an EPR from individual components. |
|
219 * |
|
220 * <p> |
|
221 * This version takes various information about metadata, and creates an EPR that has |
|
222 * the necessary embedded WSDL. |
|
223 */ |
|
224 public WSEndpointReference(@NotNull AddressingVersion version, |
|
225 @NotNull String address, |
|
226 @Nullable QName service, |
|
227 @Nullable QName port, |
|
228 @Nullable QName portType, |
|
229 @Nullable List<Element> metadata, |
|
230 @Nullable String wsdlAddress, |
|
231 @Nullable List<Element> referenceParameters) { |
|
232 this(version, address, service, port, portType, metadata, wsdlAddress, null, referenceParameters, null, null); |
|
233 } |
|
234 |
|
235 /** |
|
236 * Creates an EPR from individual components. |
|
237 * |
|
238 * <p> |
|
239 * This version takes various information about metadata, and creates an EPR that has |
|
240 * the necessary embedded WSDL. |
|
241 */ |
|
242 public WSEndpointReference(@NotNull AddressingVersion version, |
|
243 @NotNull String address, |
|
244 @Nullable QName service, |
|
245 @Nullable QName port, |
|
246 @Nullable QName portType, |
|
247 @Nullable List<Element> metadata, |
|
248 @Nullable String wsdlAddress, |
|
249 @Nullable List<Element> referenceParameters, |
|
250 @Nullable Collection<EPRExtension> extns,@Nullable Map<QName, String> attributes) { |
|
251 this(createBufferFromData(version, address, referenceParameters, service, port, portType, metadata, wsdlAddress, null, extns, attributes), |
|
252 version ); |
|
253 } |
|
254 |
|
255 /** |
|
256 * Creates an EPR from individual components. |
|
257 * |
|
258 * <p> |
|
259 * This version takes various information about metadata, and creates an EPR that has |
|
260 * the necessary embedded WSDL. |
|
261 * @since JAX-WS 2.2 |
|
262 */ |
|
263 public WSEndpointReference(@NotNull AddressingVersion version, |
|
264 @NotNull String address, |
|
265 @Nullable QName service, |
|
266 @Nullable QName port, |
|
267 @Nullable QName portType, |
|
268 @Nullable List<Element> metadata, |
|
269 @Nullable String wsdlAddress, |
|
270 @Nullable String wsdlTargetNamepsace, |
|
271 @Nullable List<Element> referenceParameters, |
|
272 @Nullable List<Element> elements, @Nullable Map<QName, String> attributes) { |
|
273 this( |
|
274 createBufferFromData(version, address, referenceParameters, service, port, portType, metadata, wsdlAddress,wsdlTargetNamepsace, elements, attributes), |
|
275 version ); |
|
276 } |
|
277 |
|
278 private static XMLStreamBuffer createBufferFromData(AddressingVersion version, String address, List<Element> referenceParameters, QName service, QName port, QName portType, |
|
279 List<Element> metadata, String wsdlAddress, String wsdlTargetNamespace, @Nullable List<Element> elements, @Nullable Map<QName, String> attributes) { |
|
280 |
|
281 StreamWriterBufferCreator writer = new StreamWriterBufferCreator(); |
|
282 |
|
283 try { |
|
284 writer.writeStartDocument(); |
|
285 writer.writeStartElement(version.getPrefix(),"EndpointReference", version.nsUri); |
|
286 writer.writeNamespace(version.getPrefix(),version.nsUri); |
|
287 |
|
288 writePartialEPRInfoset(writer, version, address, referenceParameters, service, port, portType, |
|
289 metadata,wsdlAddress, wsdlTargetNamespace, attributes); |
|
290 |
|
291 //write extensibility elements in the EPR element |
|
292 if (elements != null) { |
|
293 for (Element e : elements) { |
|
294 DOMUtil.serializeNode(e, writer); |
|
295 } |
|
296 } |
|
297 |
|
298 writer.writeEndElement(); |
|
299 writer.writeEndDocument(); |
|
300 writer.flush(); |
|
301 |
|
302 return writer.getXMLStreamBuffer(); |
|
303 } catch (XMLStreamException e) { |
|
304 throw new WebServiceException(e); |
|
305 } |
|
306 } |
|
307 |
|
308 private static XMLStreamBuffer createBufferFromData(AddressingVersion version, String address, List<Element> referenceParameters, QName service, QName port, QName portType, |
|
309 List<Element> metadata, String wsdlAddress, String wsdlTargetNamespace, @Nullable Collection<EPRExtension> extns, @Nullable Map<QName, String> attributes) { |
|
310 |
|
311 StreamWriterBufferCreator writer = new StreamWriterBufferCreator(); |
|
312 |
|
313 try { |
|
314 writer.writeStartDocument(); |
|
315 writer.writeStartElement(version.getPrefix(),"EndpointReference", version.nsUri); |
|
316 writer.writeNamespace(version.getPrefix(),version.nsUri); |
|
317 |
|
318 writePartialEPRInfoset(writer, version, address, referenceParameters, service, port, portType, |
|
319 metadata,wsdlAddress, wsdlTargetNamespace, attributes); |
|
320 |
|
321 //write extensibility elements in the EPR element |
|
322 if (extns != null) { |
|
323 for (EPRExtension e : extns) { |
|
324 XMLStreamReaderToXMLStreamWriter c = new XMLStreamReaderToXMLStreamWriter(); |
|
325 XMLStreamReader r = e.readAsXMLStreamReader(); |
|
326 c.bridge(r, writer); |
|
327 XMLStreamReaderFactory.recycle(r); |
|
328 } |
|
329 } |
|
330 |
|
331 writer.writeEndElement(); |
|
332 writer.writeEndDocument(); |
|
333 writer.flush(); |
|
334 |
|
335 return writer.getXMLStreamBuffer(); |
|
336 } catch (XMLStreamException e) { |
|
337 throw new WebServiceException(e); |
|
338 } |
|
339 } |
|
340 |
|
341 private static void writePartialEPRInfoset(StreamWriterBufferCreator writer, AddressingVersion version, String address, List<Element> referenceParameters, QName service, QName port, QName portType, |
|
342 List<Element> metadata, String wsdlAddress, String wsdlTargetNamespace, @Nullable Map<QName, String> attributes) throws XMLStreamException { |
|
343 //add extensibile attributes on the EPR element |
|
344 if (attributes != null) { |
|
345 for (Map.Entry<QName, String> entry : attributes.entrySet()) { |
|
346 QName qname = entry.getKey(); |
|
347 writer.writeAttribute(qname.getPrefix(), qname.getNamespaceURI(), qname.getLocalPart(), entry.getValue()); |
|
348 } |
|
349 } |
|
350 |
|
351 writer.writeStartElement(version.getPrefix(), version.eprType.address, version.nsUri); |
|
352 writer.writeCharacters(address); |
|
353 writer.writeEndElement(); |
|
354 //When the size of ReferenceParametes is zero, the ReferenceParametes element will not be written. |
|
355 if(referenceParameters != null && referenceParameters.size() > 0) { |
|
356 writer.writeStartElement(version.getPrefix(), version.eprType.referenceParameters, version.nsUri); |
|
357 for (Element e : referenceParameters) { |
|
358 DOMUtil.serializeNode(e, writer); |
|
359 } |
|
360 writer.writeEndElement(); |
|
361 } |
|
362 |
|
363 switch (version) { |
|
364 case W3C: |
|
365 writeW3CMetaData(writer, service, port, portType, metadata, wsdlAddress, wsdlTargetNamespace); |
|
366 break; |
|
367 |
|
368 case MEMBER: |
|
369 writeMSMetaData(writer, service, port, portType, metadata); |
|
370 if (wsdlAddress != null) { |
|
371 //Inline the wsdl as extensibility element |
|
372 //Write mex:Metadata wrapper |
|
373 writer.writeStartElement(MemberSubmissionAddressingConstants.MEX_METADATA.getPrefix(), |
|
374 MemberSubmissionAddressingConstants.MEX_METADATA.getLocalPart(), |
|
375 MemberSubmissionAddressingConstants.MEX_METADATA.getNamespaceURI()); |
|
376 writer.writeStartElement(MemberSubmissionAddressingConstants.MEX_METADATA_SECTION.getPrefix(), |
|
377 MemberSubmissionAddressingConstants.MEX_METADATA_SECTION.getLocalPart(), |
|
378 MemberSubmissionAddressingConstants.MEX_METADATA_SECTION.getNamespaceURI()); |
|
379 writer.writeAttribute(MemberSubmissionAddressingConstants.MEX_METADATA_DIALECT_ATTRIBUTE, |
|
380 MemberSubmissionAddressingConstants.MEX_METADATA_DIALECT_VALUE); |
|
381 |
|
382 writeWsdl(writer, service, wsdlAddress); |
|
383 |
|
384 writer.writeEndElement(); |
|
385 writer.writeEndElement(); |
|
386 } |
|
387 |
|
388 break; |
|
389 } |
|
390 } |
|
391 |
|
392 private static boolean isEmty(QName qname) { |
|
393 return qname == null || qname.toString().trim().length()== 0; |
|
394 } |
|
395 |
|
396 private static void writeW3CMetaData(StreamWriterBufferCreator writer, |
|
397 QName service, |
|
398 QName port, |
|
399 QName portType, List<Element> metadata, |
|
400 String wsdlAddress, String wsdlTargetNamespace) throws XMLStreamException { |
|
401 |
|
402 |
|
403 //.NET treate empty metaData element as bad request. |
|
404 if (isEmty(service) && isEmty(port) && isEmty(portType) && metadata == null/* && wsdlAddress == null*/) { |
|
405 return; |
|
406 } |
|
407 |
|
408 writer.writeStartElement(AddressingVersion.W3C.getPrefix(), |
|
409 AddressingVersion.W3C.eprType.wsdlMetadata.getLocalPart(), AddressingVersion.W3C.nsUri); |
|
410 writer.writeNamespace(AddressingVersion.W3C.getWsdlPrefix(), |
|
411 AddressingVersion.W3C.wsdlNsUri); |
|
412 //write wsdliLication as defined in WS-Addressing 1.0 Metadata spec |
|
413 if(wsdlAddress != null) { |
|
414 writeWsdliLocation(writer, service, wsdlAddress, wsdlTargetNamespace); |
|
415 } |
|
416 |
|
417 //Write Interface info |
|
418 if (portType != null) { |
|
419 writer.writeStartElement(W3CAddressingMetadataConstants.WSAM_PREFIX_NAME, |
|
420 AddressingVersion.W3C.eprType.portTypeName, |
|
421 W3CAddressingMetadataConstants.WSAM_NAMESPACE_NAME); |
|
422 writer.writeNamespace(W3CAddressingMetadataConstants.WSAM_PREFIX_NAME, |
|
423 W3CAddressingMetadataConstants.WSAM_NAMESPACE_NAME); |
|
424 String portTypePrefix = portType.getPrefix(); |
|
425 if (portTypePrefix == null || portTypePrefix.equals("")) { |
|
426 //TODO check prefix again |
|
427 portTypePrefix = "wsns"; |
|
428 } |
|
429 writer.writeNamespace(portTypePrefix, portType.getNamespaceURI()); |
|
430 writer.writeCharacters(portTypePrefix + ":" + portType.getLocalPart()); |
|
431 writer.writeEndElement(); |
|
432 } |
|
433 if (service != null) { |
|
434 //Write service and Port info |
|
435 if (!(service.getNamespaceURI().equals("") || service.getLocalPart().equals(""))) { |
|
436 writer.writeStartElement(W3CAddressingMetadataConstants.WSAM_PREFIX_NAME, |
|
437 AddressingVersion.W3C.eprType.serviceName, |
|
438 W3CAddressingMetadataConstants.WSAM_NAMESPACE_NAME); |
|
439 writer.writeNamespace(W3CAddressingMetadataConstants.WSAM_PREFIX_NAME, |
|
440 W3CAddressingMetadataConstants.WSAM_NAMESPACE_NAME); |
|
441 String servicePrefix = service.getPrefix(); |
|
442 if (servicePrefix == null || servicePrefix.equals("")) { |
|
443 //TODO check prefix again |
|
444 servicePrefix = "wsns"; |
|
445 } |
|
446 writer.writeNamespace(servicePrefix, service.getNamespaceURI()); |
|
447 if (port != null) { |
|
448 writer.writeAttribute(AddressingVersion.W3C.eprType.portName, port.getLocalPart()); |
|
449 } |
|
450 writer.writeCharacters(servicePrefix + ":" + service.getLocalPart()); |
|
451 writer.writeEndElement(); |
|
452 } |
|
453 } |
|
454 /* |
|
455 //Inline the wsdl |
|
456 if (wsdlAddress != null) { |
|
457 writeWsdl(writer, service, wsdlAddress); |
|
458 } |
|
459 */ |
|
460 //Add the extra metadata Elements |
|
461 if (metadata != null) { |
|
462 for (Element e : metadata) { |
|
463 DOMUtil.serializeNode(e, writer); |
|
464 } |
|
465 } |
|
466 writer.writeEndElement(); |
|
467 |
|
468 } |
|
469 |
|
470 /** |
|
471 * @param writer the writer should be at the start of element. |
|
472 * @param service Namespace URI of servcie is used as targetNamespace of wsdl if wsdlTargetNamespace is not null |
|
473 * @param wsdlAddress wsdl location |
|
474 * @param wsdlTargetNamespace targetnamespace of wsdl to be put in wsdliLocation |
|
475 * |
|
476 */ |
|
477 private static void writeWsdliLocation(StreamWriterBufferCreator writer, QName service,String wsdlAddress,String wsdlTargetNamespace) throws XMLStreamException { |
|
478 String wsdliLocation = ""; |
|
479 if(wsdlTargetNamespace != null) { |
|
480 wsdliLocation = wsdlTargetNamespace + " "; |
|
481 } else if (service != null) { |
|
482 wsdliLocation = service.getNamespaceURI() + " "; |
|
483 } else { |
|
484 throw new WebServiceException("WSDL target Namespace cannot be resolved"); |
|
485 } |
|
486 wsdliLocation += wsdlAddress; |
|
487 writer.writeNamespace(W3CAddressingMetadataConstants.WSAM_WSDLI_ATTRIBUTE_PREFIX, |
|
488 W3CAddressingMetadataConstants.WSAM_WSDLI_ATTRIBUTE_NAMESPACE); |
|
489 writer.writeAttribute(W3CAddressingMetadataConstants.WSAM_WSDLI_ATTRIBUTE_PREFIX, |
|
490 W3CAddressingMetadataConstants.WSAM_WSDLI_ATTRIBUTE_NAMESPACE, |
|
491 W3CAddressingMetadataConstants.WSAM_WSDLI_ATTRIBUTE_LOCALNAME, |
|
492 wsdliLocation); |
|
493 |
|
494 } |
|
495 private static void writeMSMetaData(StreamWriterBufferCreator writer, |
|
496 QName service, |
|
497 QName port, |
|
498 QName portType, List<Element> metadata) throws XMLStreamException { |
|
499 // TODO: write ReferenceProperties |
|
500 //TODO: write ReferenceParameters |
|
501 if (portType != null) { |
|
502 //Write Interface info |
|
503 writer.writeStartElement(AddressingVersion.MEMBER.getPrefix(), |
|
504 AddressingVersion.MEMBER.eprType.portTypeName, |
|
505 AddressingVersion.MEMBER.nsUri); |
|
506 |
|
507 |
|
508 String portTypePrefix = portType.getPrefix(); |
|
509 if (portTypePrefix == null || portTypePrefix.equals("")) { |
|
510 //TODO check prefix again |
|
511 portTypePrefix = "wsns"; |
|
512 } |
|
513 writer.writeNamespace(portTypePrefix, portType.getNamespaceURI()); |
|
514 writer.writeCharacters(portTypePrefix + ":" + portType.getLocalPart()); |
|
515 writer.writeEndElement(); |
|
516 } |
|
517 //Write service and Port info |
|
518 if (service != null) { |
|
519 if (!(service.getNamespaceURI().equals("") || service.getLocalPart().equals(""))) { |
|
520 writer.writeStartElement(AddressingVersion.MEMBER.getPrefix(), |
|
521 AddressingVersion.MEMBER.eprType.serviceName, |
|
522 AddressingVersion.MEMBER.nsUri); |
|
523 String servicePrefix = service.getPrefix(); |
|
524 if (servicePrefix == null || servicePrefix.equals("")) { |
|
525 //TODO check prefix again |
|
526 servicePrefix = "wsns"; |
|
527 } |
|
528 writer.writeNamespace(servicePrefix, service.getNamespaceURI()); |
|
529 if (port != null) { |
|
530 writer.writeAttribute(AddressingVersion.MEMBER.eprType.portName, |
|
531 port.getLocalPart()); |
|
532 } |
|
533 writer.writeCharacters(servicePrefix + ":" + service.getLocalPart()); |
|
534 writer.writeEndElement(); |
|
535 } |
|
536 } |
|
537 } |
|
538 |
|
539 private static void writeWsdl(StreamWriterBufferCreator writer, QName service, String wsdlAddress) throws XMLStreamException { |
|
540 // Inline-wsdl |
|
541 writer.writeStartElement(WSDLConstants.PREFIX_NS_WSDL, |
|
542 WSDLConstants.QNAME_DEFINITIONS.getLocalPart(), |
|
543 WSDLConstants.NS_WSDL); |
|
544 writer.writeNamespace(WSDLConstants.PREFIX_NS_WSDL, WSDLConstants.NS_WSDL); |
|
545 writer.writeStartElement(WSDLConstants.PREFIX_NS_WSDL, |
|
546 WSDLConstants.QNAME_IMPORT.getLocalPart(), |
|
547 WSDLConstants.NS_WSDL); |
|
548 writer.writeAttribute("namespace", service.getNamespaceURI()); |
|
549 writer.writeAttribute("location", wsdlAddress); |
|
550 writer.writeEndElement(); |
|
551 writer.writeEndElement(); |
|
552 } |
|
553 |
|
554 |
|
555 |
|
556 /** |
|
557 * Converts from {@link EndpointReference}. |
|
558 * |
|
559 * This handles null {@link EndpointReference} correctly. |
|
560 * Call {@link #WSEndpointReference(EndpointReference)} directly |
|
561 * if you know it's not null. |
|
562 */ |
|
563 public static @Nullable |
|
564 WSEndpointReference create(@Nullable EndpointReference epr) { |
|
565 if (epr != null) { |
|
566 return new WSEndpointReference(epr); |
|
567 } else { |
|
568 return null; |
|
569 } |
|
570 } |
|
571 |
|
572 /** |
|
573 * @see #createWithAddress(String) |
|
574 */ |
|
575 public @NotNull WSEndpointReference createWithAddress(@NotNull URI newAddress) { |
|
576 return createWithAddress(newAddress.toString()); |
|
577 } |
|
578 |
|
579 /** |
|
580 * @see #createWithAddress(String) |
|
581 */ |
|
582 public @NotNull WSEndpointReference createWithAddress(@NotNull URL newAddress) { |
|
583 return createWithAddress(newAddress.toString()); |
|
584 } |
|
585 |
|
586 /** |
|
587 * Creates a new {@link WSEndpointReference} by replacing the address of this EPR |
|
588 * to the new one. |
|
589 * |
|
590 * <p> |
|
591 * The following example shows how you can use this to force an HTTPS EPR, |
|
592 * when the endpoint can serve both HTTP and HTTPS requests. |
|
593 * <pre> |
|
594 * if(epr.getAddress().startsWith("http:")) |
|
595 * epr = epr.createWithAddress("https:"+epr.getAddress().substring(5)); |
|
596 * </pre> |
|
597 * |
|
598 * @param newAddress |
|
599 * This is a complete URL to be written inside <Adress> element of the EPR, |
|
600 * such as "http://foo.bar/abc/def" |
|
601 */ |
|
602 public @NotNull WSEndpointReference createWithAddress(@NotNull final String newAddress) { |
|
603 MutableXMLStreamBuffer xsb = new MutableXMLStreamBuffer(); |
|
604 XMLFilterImpl filter = new XMLFilterImpl() { |
|
605 private boolean inAddress = false; |
|
606 @Override |
|
607 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { |
|
608 if (localName.equals("Address") && uri.equals(version.nsUri)) { |
|
609 inAddress = true; |
|
610 } |
|
611 super.startElement(uri,localName,qName,atts); |
|
612 } |
|
613 |
|
614 @Override |
|
615 public void characters(char ch[], int start, int length) throws SAXException { |
|
616 if (!inAddress) { |
|
617 super.characters(ch, start, length); |
|
618 } |
|
619 } |
|
620 |
|
621 @Override |
|
622 public void endElement(String uri, String localName, String qName) throws SAXException { |
|
623 if (inAddress) { |
|
624 super.characters(newAddress.toCharArray(),0,newAddress.length()); |
|
625 } |
|
626 inAddress = false; |
|
627 super.endElement(uri, localName, qName); |
|
628 } |
|
629 }; |
|
630 filter.setContentHandler(xsb.createFromSAXBufferCreator()); |
|
631 try { |
|
632 infoset.writeTo(filter,false); |
|
633 } catch (SAXException e) { |
|
634 throw new AssertionError(e); // impossible since we are writing from XSB to XSB. |
|
635 } |
|
636 |
|
637 return new WSEndpointReference(xsb,version); |
|
638 } |
|
639 |
|
640 /** |
|
641 * Convert the EPR to the spec version. The actual type of |
|
642 * {@link EndpointReference} to be returned depends on which version |
|
643 * of the addressing spec this EPR conforms to. |
|
644 * |
|
645 * @throws WebServiceException |
|
646 * if the conversion fails, which can happen if the EPR contains |
|
647 * invalid infoset (wrong namespace URI, etc.) |
|
648 */ |
|
649 public @NotNull EndpointReference toSpec() { |
|
650 return ProviderImpl.INSTANCE.readEndpointReference(asSource("EndpointReference")); |
|
651 } |
|
652 |
|
653 /** |
|
654 * Converts the EPR to the specified spec version. |
|
655 * |
|
656 * If the {@link #getVersion() the addressing version in use} and |
|
657 * the given class is different, then this may involve version conversion. |
|
658 */ |
|
659 public @NotNull <T extends EndpointReference> T toSpec(Class<T> clazz) { |
|
660 return EndpointReferenceUtil.transform(clazz,toSpec()); |
|
661 } |
|
662 |
|
663 /** |
|
664 * Creates a proxy that can be used to talk to this EPR. |
|
665 * |
|
666 * <p> |
|
667 * All the normal WS-Addressing processing happens automatically, |
|
668 * such as setting the endpoint address to {@link #getAddress() the address}, |
|
669 * and sending the reference parameters associated with this EPR as |
|
670 * headers, etc. |
|
671 */ |
|
672 public @NotNull <T> T getPort(@NotNull Service jaxwsService, |
|
673 @NotNull Class<T> serviceEndpointInterface, |
|
674 WebServiceFeature... features) { |
|
675 // TODO: implement it in a better way |
|
676 return jaxwsService.getPort(toSpec(),serviceEndpointInterface,features); |
|
677 } |
|
678 |
|
679 /** |
|
680 * Creates a {@link Dispatch} that can be used to talk to this EPR. |
|
681 * |
|
682 * <p> |
|
683 * All the normal WS-Addressing processing happens automatically, |
|
684 * such as setting the endpoint address to {@link #getAddress() the address}, |
|
685 * and sending the reference parameters associated with this EPR as |
|
686 * headers, etc. |
|
687 */ |
|
688 public @NotNull <T> Dispatch<T> createDispatch( |
|
689 @NotNull Service jaxwsService, |
|
690 @NotNull Class<T> type, |
|
691 @NotNull Service.Mode mode, |
|
692 WebServiceFeature... features) { |
|
693 |
|
694 // TODO: implement it in a better way |
|
695 return jaxwsService.createDispatch(toSpec(),type,mode,features); |
|
696 } |
|
697 |
|
698 /** |
|
699 * Creates a {@link Dispatch} that can be used to talk to this EPR. |
|
700 * |
|
701 * <p> |
|
702 * All the normal WS-Addressing processing happens automatically, |
|
703 * such as setting the endpoint address to {@link #getAddress() the address}, |
|
704 * and sending the reference parameters associated with this EPR as |
|
705 * headers, etc. |
|
706 */ |
|
707 public @NotNull Dispatch<Object> createDispatch( |
|
708 @NotNull Service jaxwsService, |
|
709 @NotNull JAXBContext context, |
|
710 @NotNull Service.Mode mode, |
|
711 WebServiceFeature... features) { |
|
712 |
|
713 // TODO: implement it in a better way |
|
714 return jaxwsService.createDispatch(toSpec(),context,mode,features); |
|
715 } |
|
716 |
|
717 /** |
|
718 * Gets the addressing version of this EPR. |
|
719 */ |
|
720 public @NotNull AddressingVersion getVersion() { |
|
721 return version; |
|
722 } |
|
723 |
|
724 /** |
|
725 * The value of the <wsa:address> header. |
|
726 */ |
|
727 public @NotNull String getAddress() { |
|
728 return address; |
|
729 } |
|
730 |
|
731 /** |
|
732 * Returns true if this has anonymous URI as the {@link #getAddress() address}. |
|
733 */ |
|
734 public boolean isAnonymous() { |
|
735 return address.equals(version.anonymousUri); |
|
736 } |
|
737 |
|
738 /** |
|
739 * Returns true if this has {@link AddressingVersion#noneUri none URI} |
|
740 * as the {@link #getAddress() address}. |
|
741 */ |
|
742 public boolean isNone() { |
|
743 return address.equals(version.noneUri); |
|
744 } |
|
745 |
|
746 /** |
|
747 * Parses inside EPR and mark all reference parameters. |
|
748 */ |
|
749 private void parse() throws XMLStreamException { |
|
750 // TODO: validate the EPR structure. |
|
751 // check for non-existent Address, that sort of things. |
|
752 |
|
753 StreamReaderBufferProcessor xsr = infoset.readAsXMLStreamReader(); |
|
754 |
|
755 // parser should be either at the start element or the start document |
|
756 if (xsr.getEventType()==XMLStreamReader.START_DOCUMENT) { |
|
757 xsr.nextTag(); |
|
758 } |
|
759 assert xsr.getEventType()==XMLStreamReader.START_ELEMENT; |
|
760 |
|
761 String rootLocalName = xsr.getLocalName(); |
|
762 if(!xsr.getNamespaceURI().equals(version.nsUri)) { |
|
763 throw new WebServiceException(AddressingMessages.WRONG_ADDRESSING_VERSION( |
|
764 version.nsUri, xsr.getNamespaceURI())); |
|
765 } |
|
766 |
|
767 this.rootElement = new QName(xsr.getNamespaceURI(), rootLocalName); |
|
768 |
|
769 // since often EPR doesn't have a reference parameter, create array lazily |
|
770 List<Header> marks=null; |
|
771 |
|
772 while(xsr.nextTag()==XMLStreamReader.START_ELEMENT) { |
|
773 String localName = xsr.getLocalName(); |
|
774 if(version.isReferenceParameter(localName)) { |
|
775 XMLStreamBuffer mark; |
|
776 while((mark = xsr.nextTagAndMark())!=null) { |
|
777 if (marks==null) { |
|
778 marks = new ArrayList<Header>(); |
|
779 } |
|
780 |
|
781 // TODO: need a different header for member submission version |
|
782 marks.add(version.createReferenceParameterHeader( |
|
783 mark, xsr.getNamespaceURI(), xsr.getLocalName())); |
|
784 XMLStreamReaderUtil.skipElement(xsr); |
|
785 } |
|
786 } else |
|
787 if(localName.equals("Address")) { |
|
788 if (address!=null) { |
|
789 throw new InvalidAddressingHeaderException(new QName(version.nsUri,rootLocalName),AddressingVersion.fault_duplicateAddressInEpr); |
|
790 } |
|
791 address = xsr.getElementText().trim(); |
|
792 } else { |
|
793 XMLStreamReaderUtil.skipElement(xsr); |
|
794 } |
|
795 } |
|
796 |
|
797 // hit to </EndpointReference> by now |
|
798 |
|
799 if (marks==null) { |
|
800 this.referenceParameters = EMPTY_ARRAY; |
|
801 } else { |
|
802 this.referenceParameters = marks.toArray(new Header[marks.size()]); |
|
803 } |
|
804 |
|
805 if (address==null) { |
|
806 throw new InvalidAddressingHeaderException(new QName(version.nsUri,rootLocalName),version.fault_missingAddressInEpr); |
|
807 } |
|
808 } |
|
809 |
|
810 |
|
811 /** |
|
812 * Reads this EPR as {@link XMLStreamReader}. |
|
813 * |
|
814 * @param localName |
|
815 * EPR uses a different root tag name depending on the context. |
|
816 * The returned {@link XMLStreamReader} will use the given local name |
|
817 * for the root element name. |
|
818 */ |
|
819 public XMLStreamReader read(final @NotNull String localName) throws XMLStreamException { |
|
820 return new StreamReaderBufferProcessor(infoset) { |
|
821 @Override |
|
822 protected void processElement(String prefix, String uri, String _localName, boolean inScope) { |
|
823 if (_depth == 0) { |
|
824 _localName = localName; |
|
825 } |
|
826 super.processElement(prefix, uri, _localName, isInscope(infoset,_depth)); |
|
827 } |
|
828 }; |
|
829 } |
|
830 |
|
831 private boolean isInscope(XMLStreamBuffer buffer, int depth) { |
|
832 return buffer.getInscopeNamespaces().size() > 0 && depth ==0; |
|
833 } |
|
834 |
|
835 /** |
|
836 * Returns a {@link Source} that represents this EPR. |
|
837 * |
|
838 * @param localName |
|
839 * EPR uses a different root tag name depending on the context. |
|
840 * The returned {@link Source} will use the given local name |
|
841 * for the root element name. |
|
842 */ |
|
843 public Source asSource(@NotNull String localName) { |
|
844 return new SAXSource(new SAXBufferProcessorImpl(localName),new InputSource()); |
|
845 } |
|
846 |
|
847 /** |
|
848 * Writes this EPR to the given {@link ContentHandler}. |
|
849 * |
|
850 * @param localName |
|
851 * EPR uses a different root tag name depending on the context. |
|
852 * The returned {@link Source} will use the given local name |
|
853 * for the root element name. |
|
854 * @param fragment |
|
855 * If true, generate a fragment SAX events without start/endDocument callbacks. |
|
856 * If false, generate a full XML document event. |
|
857 */ |
|
858 public void writeTo(@NotNull String localName, ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException { |
|
859 SAXBufferProcessorImpl p = new SAXBufferProcessorImpl(localName); |
|
860 p.setContentHandler(contentHandler); |
|
861 p.setErrorHandler(errorHandler); |
|
862 p.process(infoset,fragment); |
|
863 } |
|
864 |
|
865 /** |
|
866 * Writes this EPR into the given writer. |
|
867 * |
|
868 * @param localName |
|
869 * EPR uses a different root tag name depending on the context. |
|
870 * The returned {@link Source} will use the given local name |
|
871 */ |
|
872 public void writeTo(final @NotNull String localName, @NotNull XMLStreamWriter w) throws XMLStreamException { |
|
873 infoset.writeToXMLStreamWriter(new XMLStreamWriterFilter(w) { |
|
874 private boolean root=true; |
|
875 |
|
876 @Override |
|
877 public void writeStartDocument() throws XMLStreamException { |
|
878 } |
|
879 |
|
880 @Override |
|
881 public void writeStartDocument(String encoding, String version) throws XMLStreamException { |
|
882 } |
|
883 |
|
884 @Override |
|
885 public void writeStartDocument(String version) throws XMLStreamException { |
|
886 } |
|
887 |
|
888 @Override |
|
889 public void writeEndDocument() throws XMLStreamException { |
|
890 } |
|
891 |
|
892 private String override(String ln) { |
|
893 if(root) { |
|
894 root = false; |
|
895 return localName; |
|
896 } |
|
897 return ln; |
|
898 } |
|
899 |
|
900 @Override |
|
901 public void writeStartElement(String localName) throws XMLStreamException { |
|
902 super.writeStartElement(override(localName)); |
|
903 } |
|
904 |
|
905 @Override |
|
906 public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException { |
|
907 super.writeStartElement(namespaceURI, override(localName)); |
|
908 } |
|
909 |
|
910 @Override |
|
911 public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { |
|
912 super.writeStartElement(prefix, override(localName), namespaceURI); |
|
913 } |
|
914 },true/*write as fragment*/); |
|
915 } |
|
916 |
|
917 /** |
|
918 * Returns a {@link Header} that wraps this {@link WSEndpointReference}. |
|
919 * |
|
920 * <p> |
|
921 * The returned header is immutable too, and can be reused with |
|
922 * many {@link Message}s. |
|
923 * |
|
924 * @param rootTagName |
|
925 * The header tag name to be used, such as <ReplyTo> or <FaultTo>. |
|
926 * (It's bit ugly that this method takes {@link QName} and not just local name, |
|
927 * unlike other methods. If it's making the caller's life miserable, then |
|
928 * we can talk.) |
|
929 */ |
|
930 public Header createHeader(QName rootTagName) { |
|
931 return new EPRHeader(rootTagName,this); |
|
932 } |
|
933 |
|
934 /** |
|
935 * Copies all the reference parameters in this EPR as headers |
|
936 * to the given {@link HeaderList}. |
|
937 * @deprecated - use addReferenceParametersToList(MessageHeaders) |
|
938 */ |
|
939 @SuppressWarnings("ManualArrayToCollectionCopy") |
|
940 public void addReferenceParametersToList(HeaderList outbound) { |
|
941 // implemented through iteration because of unsupportedoperation exception thrown from addAll method on headerlist |
|
942 // do not change |
|
943 for (Header header : referenceParameters) { |
|
944 outbound.add(header); |
|
945 } |
|
946 } |
|
947 |
|
948 /** |
|
949 * Copies all the reference parameters in this EPR as headers |
|
950 * to the given {@link MessageHeaders}. |
|
951 */ |
|
952 public void addReferenceParametersToList(MessageHeaders outbound) { |
|
953 for (Header header : referenceParameters) { |
|
954 outbound.add(header); |
|
955 } |
|
956 } |
|
957 /** |
|
958 * Copies all the reference parameters from the given {@link HeaderList} |
|
959 * to this EPR |
|
960 */ |
|
961 public void addReferenceParameters(HeaderList headers) { |
|
962 if (headers != null) { |
|
963 Header[] hs = new Header[referenceParameters.length + headers.size()]; |
|
964 System.arraycopy(referenceParameters, 0, hs, 0, referenceParameters.length); |
|
965 int i = referenceParameters.length; |
|
966 for (Header h : headers) { |
|
967 hs[i++] = h; |
|
968 } |
|
969 referenceParameters = hs; |
|
970 } |
|
971 } |
|
972 |
|
973 /** |
|
974 * Dumps the EPR infoset in a human-readable string. |
|
975 */ |
|
976 @Override |
|
977 public String toString() { |
|
978 try { |
|
979 // debug convenience |
|
980 StringWriter sw = new StringWriter(); |
|
981 XmlUtil.newTransformer().transform(asSource("EndpointReference"),new StreamResult(sw)); |
|
982 return sw.toString(); |
|
983 } catch (TransformerException e) { |
|
984 return e.toString(); |
|
985 } |
|
986 } |
|
987 |
|
988 /** |
|
989 * Gets the QName of the EndpointReference element. |
|
990 * @return |
|
991 */ |
|
992 @Override |
|
993 public QName getName() { |
|
994 return rootElement; |
|
995 } |
|
996 |
|
997 /** |
|
998 * Filtering {@link SAXBufferProcessor} that replaces the root tag name. |
|
999 */ |
|
1000 class SAXBufferProcessorImpl extends SAXBufferProcessor { |
|
1001 private final String rootLocalName; |
|
1002 private boolean root=true; |
|
1003 |
|
1004 public SAXBufferProcessorImpl(String rootLocalName) { |
|
1005 super(infoset,false); |
|
1006 this.rootLocalName = rootLocalName; |
|
1007 } |
|
1008 |
|
1009 @Override |
|
1010 protected void processElement(String uri, String localName, String qName, boolean inscope) throws SAXException { |
|
1011 if(root) { |
|
1012 root = false; |
|
1013 |
|
1014 if(qName.equals(localName)) { |
|
1015 qName = localName = rootLocalName; |
|
1016 } else { |
|
1017 localName = rootLocalName; |
|
1018 int idx = qName.indexOf(':'); |
|
1019 qName = qName.substring(0,idx+1)+rootLocalName; |
|
1020 } |
|
1021 } |
|
1022 super.processElement(uri, localName, qName, inscope); |
|
1023 } |
|
1024 } |
|
1025 |
|
1026 private static final OutboundReferenceParameterHeader[] EMPTY_ARRAY = new OutboundReferenceParameterHeader[0]; |
|
1027 |
|
1028 private Map<QName, EPRExtension> rootEprExtensions; |
|
1029 |
|
1030 /** |
|
1031 * Represents an extensibility element inside an EndpointReference |
|
1032 */ |
|
1033 public static abstract class EPRExtension { |
|
1034 public abstract XMLStreamReader readAsXMLStreamReader() throws XMLStreamException; |
|
1035 |
|
1036 public abstract QName getQName(); |
|
1037 } |
|
1038 |
|
1039 /** |
|
1040 * Returns the first extensibility element inside EPR root element with input QName. |
|
1041 */ |
|
1042 public @Nullable |
|
1043 EPRExtension getEPRExtension(final QName extnQName) throws XMLStreamException { |
|
1044 if (rootEprExtensions == null) { |
|
1045 parseEPRExtensions(); |
|
1046 } |
|
1047 return rootEprExtensions.get(extnQName); |
|
1048 } |
|
1049 |
|
1050 public @NotNull Collection<EPRExtension> getEPRExtensions() throws XMLStreamException { |
|
1051 if (rootEprExtensions == null) { |
|
1052 parseEPRExtensions(); |
|
1053 } |
|
1054 return rootEprExtensions.values(); |
|
1055 } |
|
1056 |
|
1057 private void parseEPRExtensions() throws XMLStreamException { |
|
1058 |
|
1059 rootEprExtensions = new HashMap<QName, EPRExtension>(); |
|
1060 |
|
1061 |
|
1062 StreamReaderBufferProcessor xsr = infoset.readAsXMLStreamReader(); |
|
1063 |
|
1064 // parser should be either at the start element or the start document |
|
1065 if (xsr.getEventType() == XMLStreamReader.START_DOCUMENT) { |
|
1066 xsr.nextTag(); |
|
1067 } |
|
1068 assert xsr.getEventType() == XMLStreamReader.START_ELEMENT; |
|
1069 |
|
1070 if (!xsr.getNamespaceURI().equals(version.nsUri)) { |
|
1071 throw new WebServiceException(AddressingMessages.WRONG_ADDRESSING_VERSION( |
|
1072 version.nsUri, xsr.getNamespaceURI())); |
|
1073 } |
|
1074 |
|
1075 // since often EPR doesn't have extensions, create array lazily |
|
1076 XMLStreamBuffer mark; |
|
1077 String localName; |
|
1078 String ns; |
|
1079 while ((mark = xsr.nextTagAndMark()) != null) { |
|
1080 localName = xsr.getLocalName(); |
|
1081 ns = xsr.getNamespaceURI(); |
|
1082 if (version.nsUri.equals(ns)) { |
|
1083 //EPR extensions do not use the same namespace of the Addressing Version. |
|
1084 //Not an extension - SKIP |
|
1085 XMLStreamReaderUtil.skipElement(xsr); |
|
1086 } else { |
|
1087 QName qn = new QName(ns, localName); |
|
1088 rootEprExtensions.put(qn, new WSEPRExtension(mark,qn)); |
|
1089 XMLStreamReaderUtil.skipElement(xsr); |
|
1090 } |
|
1091 } |
|
1092 // hit to </EndpointReference> by now |
|
1093 } |
|
1094 |
|
1095 /** |
|
1096 * Parses the metadata inside this EPR and obtains it in a easy-to-process form. |
|
1097 * |
|
1098 * <p> |
|
1099 * See {@link Metadata} class for what's avaliable as "metadata". |
|
1100 */ |
|
1101 public @NotNull Metadata getMetaData() { |
|
1102 return new Metadata(); |
|
1103 } |
|
1104 |
|
1105 /** |
|
1106 * Parses the Metadata in an EPR and provides convenience methods to access |
|
1107 * the metadata. |
|
1108 * |
|
1109 */ |
|
1110 public class Metadata { |
|
1111 private @Nullable QName serviceName; |
|
1112 private @Nullable QName portName; |
|
1113 private @Nullable QName portTypeName; //interfaceName |
|
1114 private @Nullable Source wsdlSource; |
|
1115 private @Nullable String wsdliLocation; |
|
1116 |
|
1117 public @Nullable QName getServiceName(){ |
|
1118 return serviceName; |
|
1119 } |
|
1120 public @Nullable QName getPortName(){ |
|
1121 return portName; |
|
1122 } |
|
1123 public @Nullable QName getPortTypeName(){ |
|
1124 return portTypeName; |
|
1125 } |
|
1126 public @Nullable Source getWsdlSource(){ |
|
1127 return wsdlSource; |
|
1128 } |
|
1129 public @Nullable String getWsdliLocation(){ |
|
1130 return wsdliLocation; |
|
1131 } |
|
1132 |
|
1133 private Metadata() { |
|
1134 try { |
|
1135 parseMetaData(); |
|
1136 } catch (XMLStreamException e) { |
|
1137 throw new WebServiceException(e); |
|
1138 } |
|
1139 } |
|
1140 |
|
1141 /** |
|
1142 * Parses the Metadata section of the EPR. |
|
1143 */ |
|
1144 private void parseMetaData() throws XMLStreamException { |
|
1145 StreamReaderBufferProcessor xsr = infoset.readAsXMLStreamReader(); |
|
1146 |
|
1147 // parser should be either at the start element or the start document |
|
1148 if (xsr.getEventType() == XMLStreamReader.START_DOCUMENT) { |
|
1149 xsr.nextTag(); |
|
1150 } |
|
1151 assert xsr.getEventType() == XMLStreamReader.START_ELEMENT; |
|
1152 String rootElement = xsr.getLocalName(); |
|
1153 if (!xsr.getNamespaceURI().equals(version.nsUri)) { |
|
1154 throw new WebServiceException(AddressingMessages.WRONG_ADDRESSING_VERSION( |
|
1155 version.nsUri, xsr.getNamespaceURI())); |
|
1156 } |
|
1157 String localName; |
|
1158 String ns; |
|
1159 if (version == AddressingVersion.W3C) { |
|
1160 do { |
|
1161 //If the current element is metadata enclosure, look inside |
|
1162 if (xsr.getLocalName().equals(version.eprType.wsdlMetadata.getLocalPart())) { |
|
1163 String wsdlLoc = xsr.getAttributeValue("http://www.w3.org/ns/wsdl-instance","wsdlLocation"); |
|
1164 if (wsdlLoc != null) { |
|
1165 wsdliLocation = wsdlLoc.trim(); |
|
1166 } |
|
1167 XMLStreamBuffer mark; |
|
1168 while ((mark = xsr.nextTagAndMark()) != null) { |
|
1169 localName = xsr.getLocalName(); |
|
1170 ns = xsr.getNamespaceURI(); |
|
1171 if (localName.equals(version.eprType.serviceName)) { |
|
1172 String portStr = xsr.getAttributeValue(null, version.eprType.portName); |
|
1173 if (serviceName != null) { |
|
1174 throw new RuntimeException("More than one "+ version.eprType.serviceName +" element in EPR Metadata"); |
|
1175 } |
|
1176 serviceName = getElementTextAsQName(xsr); |
|
1177 if (serviceName != null && portStr != null) { |
|
1178 portName = new QName(serviceName.getNamespaceURI(), portStr); |
|
1179 } |
|
1180 } else if (localName.equals(version.eprType.portTypeName)) { |
|
1181 if (portTypeName != null) { |
|
1182 throw new RuntimeException("More than one "+ version.eprType.portTypeName +" element in EPR Metadata"); |
|
1183 } |
|
1184 portTypeName = getElementTextAsQName(xsr); |
|
1185 } else if (ns.equals(WSDLConstants.NS_WSDL) |
|
1186 && localName.equals(WSDLConstants.QNAME_DEFINITIONS.getLocalPart())) { |
|
1187 wsdlSource = new XMLStreamBufferSource(mark); |
|
1188 } else { |
|
1189 XMLStreamReaderUtil.skipElement(xsr); |
|
1190 } |
|
1191 } |
|
1192 } else { |
|
1193 //Skip is it is not root element |
|
1194 if (!xsr.getLocalName().equals(rootElement)) { |
|
1195 XMLStreamReaderUtil.skipElement(xsr); |
|
1196 } |
|
1197 } |
|
1198 } while (XMLStreamReaderUtil.nextElementContent(xsr) == XMLStreamReader.START_ELEMENT); |
|
1199 |
|
1200 if(wsdliLocation != null) { |
|
1201 String wsdlLocation = wsdliLocation.trim(); |
|
1202 wsdlLocation = wsdlLocation.substring(wsdliLocation.lastIndexOf(" ")); |
|
1203 wsdlSource = new StreamSource(wsdlLocation); |
|
1204 } |
|
1205 } else if (version == AddressingVersion.MEMBER) { |
|
1206 do { |
|
1207 localName = xsr.getLocalName(); |
|
1208 ns = xsr.getNamespaceURI(); |
|
1209 //If the current element is metadata enclosure, look inside |
|
1210 if (localName.equals(version.eprType.wsdlMetadata.getLocalPart()) && |
|
1211 ns.equals(version.eprType.wsdlMetadata.getNamespaceURI())) { |
|
1212 while (xsr.nextTag() == XMLStreamReader.START_ELEMENT) { |
|
1213 XMLStreamBuffer mark; |
|
1214 while ((mark = xsr.nextTagAndMark()) != null) { |
|
1215 localName = xsr.getLocalName(); |
|
1216 ns = xsr.getNamespaceURI(); |
|
1217 if (ns.equals(WSDLConstants.NS_WSDL) |
|
1218 && localName.equals(WSDLConstants.QNAME_DEFINITIONS.getLocalPart())) { |
|
1219 wsdlSource = new XMLStreamBufferSource(mark); |
|
1220 } else { |
|
1221 XMLStreamReaderUtil.skipElement(xsr); |
|
1222 } |
|
1223 } |
|
1224 } |
|
1225 } else if (localName.equals(version.eprType.serviceName)) { |
|
1226 String portStr = xsr.getAttributeValue(null, version.eprType.portName); |
|
1227 serviceName = getElementTextAsQName(xsr); |
|
1228 if (serviceName != null && portStr != null) { |
|
1229 portName = new QName(serviceName.getNamespaceURI(), portStr); |
|
1230 } |
|
1231 } else if (localName.equals(version.eprType.portTypeName)) { |
|
1232 portTypeName = getElementTextAsQName(xsr); |
|
1233 } else { |
|
1234 //Skip is it is not root element |
|
1235 if (!xsr.getLocalName().equals(rootElement)) { |
|
1236 XMLStreamReaderUtil.skipElement(xsr); |
|
1237 } |
|
1238 } |
|
1239 } while (XMLStreamReaderUtil.nextElementContent(xsr) == XMLStreamReader.START_ELEMENT); |
|
1240 } |
|
1241 } |
|
1242 |
|
1243 private QName getElementTextAsQName(StreamReaderBufferProcessor xsr) throws XMLStreamException { |
|
1244 String text = xsr.getElementText().trim(); |
|
1245 String prefix = XmlUtil.getPrefix(text); |
|
1246 String name = XmlUtil.getLocalPart(text); |
|
1247 if (name != null) { |
|
1248 if (prefix != null) { |
|
1249 String ns = xsr.getNamespaceURI(prefix); |
|
1250 if (ns != null) { |
|
1251 return new QName(ns, name, prefix); |
|
1252 } |
|
1253 } else { |
|
1254 return new QName(null, name); |
|
1255 } |
|
1256 } |
|
1257 return null; |
|
1258 } |
|
1259 } |
|
1260 } |