View Javadoc
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 &lt;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 &lt;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 &lt;ReplyTo> or &lt;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 }