src/share/jaxws_classes/com/sun/xml/internal/ws/api/addressing/WSEndpointReference.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
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 }

mercurial