Moved Spring-WS to separate dir.

This commit is contained in:
Arjen Poutsma
2006-09-24 19:22:56 +00:00
commit 66d3aef26c
623 changed files with 44122 additions and 0 deletions

104
core/pom.xml Normal file
View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>spring-ws</artifactId>
<groupId>org.springframework.ws</groupId>
<version>1.0-m3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-ws-core</artifactId>
<packaging>jar</packaging>
<name>Spring WS Core</name>
<description>Spring Web Services Core package.</description>
<dependencies>
<!-- Spring-WS dependencies -->
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-xml</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-oxm</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
</dependency>
<!-- XML handling dependencies -->
<dependency>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>xom</groupId>
<artifactId>xom</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>woodstox</groupId>
<artifactId>wstx-asl</artifactId>
<scope>test</scope>
</dependency>
<!-- SOAP dependencies -->
<dependency>
<groupId>ws-commons</groupId>
<artifactId>axiom-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ws-commons</groupId>
<artifactId>axiom-impl</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
</dependency>
<!-- JEE dependencies -->
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>saaj-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,6 @@
log4j.rootCategory=INFO, stdout
log4j.logger.org.springframework.ws=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="http://www.springframework.org/spring-ws/test/validation" effDate="2006-01-01">
<size>20</size>
</product>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.springframework.org/spring-ws/test/validation"
xmlns:tns="http://www.springframework.org/spring-ws/test/validation" elementFormDefault="qualified">
<include schemaLocation="sizeSchema.xsd"/>
<element name="product" type="tns:ProductType"/>
<complexType name="ProductType">
<sequence>
<element name="number" type="integer"/>
<element name="size" type="tns:SizeType"/>
</sequence>
<attribute name="effDate" type="date"/>
</complexType>
</schema>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.springframework.org/spring-ws/test/validation"
xmlns:tns="http://www.springframework.org/spring-ws/test/validation" elementFormDefault="qualified">
<element name="product" type="tns:ProductType"/>
<complexType name="ProductType">
<sequence>
<element name="number" type="integer"/>
<element name="size" type="tns:SizeType"/>
</sequence>
<attribute name="effDate" type="date"/>
</complexType>
<simpleType name="SizeType">
<restriction base="integer">
<minInclusive value="2"/>
<maxInclusive value="18"/>
</restriction>
</simpleType>
</schema>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified"
targetNamespace="http://springws.cas.de" xmlns:tns="http://springws.cas.de">
<complexType name="CasDataType">
<sequence>
<element name="key" type="long" nillable="false" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
<complexType name="AddressDataType">
<complexContent>
<extension base="tns:CasDataType">
<sequence>
<element name="firstName" nillable="true" minOccurs="0" type="string"/>
<element name="lastName" nillable="true" minOccurs="0" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType name="ArrayOfCasDataTypes">
<sequence>
<element name="casDataType" type="tns:CasDataType" nillable="false" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
</complexType>
<element name="createDataTypesRequest" type="tns:ArrayOfCasDataTypes"/>
<element name="createDataTypesResponse" type="tns:ArrayOfCasDataTypes"/>
</schema>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.springframework.org/spring-ws/test/validation"
xmlns:tns="http://www.springframework.org/spring-ws/test/validation" elementFormDefault="qualified">
<simpleType name="SizeType">
<restriction base="integer">
<minInclusive value="2"/>
<maxInclusive value="18"/>
</restriction>
</simpleType>
</schema>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="http://www.springframework.org/spring-ws/test/transformation" effDate="2006-01-01">
<number>42</number>
<size>10</size>
</product>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="http://www.springframework.org/spring-ws/test/transformation">
<effectiveDate>2006-01-01</effectiveDate>
<number>42</number>
<size>10</size>
</product>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:prod="http://www.springframework.org/spring-ws/test/transformation">
<output method="xml" encoding="UTF-8"/>
<template match="/">
<prod:product>
<prod:effectiveDate>
<value-of select="prod:product/@effDate"/>
</prod:effectiveDate>
<prod:number>
<value-of select="prod:product/prod:number"/>
</prod:number>
<prod:size>
<value-of select="prod:product/prod:size"/>
</prod:size>
</prod:product>
</template>
</stylesheet>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="http://www.springframework.org/spring-ws/test/validation" effDate="2006-01-01">
<number>42</number>
<size>10</size>
</product>

View File

@@ -0,0 +1,12 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://springws.cas.de">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:createDataTypesResponse>
<ns2:casDataType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns2:AddressDataType">
<ns2:key>123</ns2:key>
<ns2:firstName>Fritz</ns2:firstName>
<ns2:lastName>Meier</ns2:lastName>
</ns2:casDataType>
</ns2:createDataTypesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,3 @@
<root xmlns="http://www.springframework.org/spring-ws" attribute="value">
<child xmlns="http://www.springframework.org/spring-ws/child"/>
</root>

View File

@@ -0,0 +1,8 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'
SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m='http://www.springframework.org/spring-ws'>
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,7 @@
<env:Envelope xmlns:env='http://www.w3.org/2003/05/soap-envelope'>
<env:Body>
<m:alert xmlns:m='http://example.org/alert'>
<m:msg>Pick up Mary at school at 2pm</m:msg>
</m:alert>
</env:Body>
</env:Envelope>

View File

@@ -0,0 +1,5 @@
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<tru:StockSymbol xmlns:tru="http://fabrikam123.com/payloads">QQQ</tru:StockSymbol>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

View File

@@ -0,0 +1,125 @@
<?xml version='1.0' encoding='UTF-8' ?>
<!-- Schema for the SOAP/1.1 envelope
Portions © 2001 DevelopMentor.
© 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.
This document is governed by the W3C Software License [1] as described in the FAQ [2].
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
Original W3C files; http://www.w3.org/2001/06/soap-envelope
Changes made:
- reverted namespace to http://schemas.xmlsoap.org/soap/envelope/
- reverted mustUnderstand to only allow 0 and 1 as lexical values
- made encodingStyle a global attribute 20020825
- removed default value from mustUnderstand attribute declaration
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/">
<!-- Envelope, header and body -->
<xs:element name="Envelope" type="tns:Envelope"/>
<xs:complexType name="Envelope">
<xs:sequence>
<xs:element ref="tns:Header" minOccurs="0"/>
<xs:element ref="tns:Body" minOccurs="1"/>
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<xs:element name="Header" type="tns:Header"/>
<xs:complexType name="Header">
<xs:sequence>
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<xs:element name="Body" type="tns:Body"/>
<xs:complexType name="Body">
<xs:sequence>
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="lax">
<xs:annotation>
<xs:documentation>
Prose in the spec does not specify that attributes are allowed on the Body
element</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
<!-- Global Attributes. The following attributes are intended to be usable via qualified attribute names on any complex type referencing them. -->
<xs:attribute name="mustUnderstand">
<xs:simpleType>
<xs:restriction base='xs:boolean'>
<xs:pattern value='0|1'/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="actor" type="xs:anyURI"/>
<xs:simpleType name="encodingStyle">
<xs:annotation>
<xs:documentation>
'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing
element. For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern
described in SOAP specification</xs:documentation>
</xs:annotation>
<xs:list itemType="xs:anyURI"/>
</xs:simpleType>
<xs:attribute name="encodingStyle" type="tns:encodingStyle"/>
<xs:attributeGroup name="encodingStyle">
<xs:attribute ref="tns:encodingStyle"/>
</xs:attributeGroup>
<xs:element name="Fault" type="tns:Fault"/>
<xs:complexType name="Fault" final="extension">
<xs:annotation>
<xs:documentation>
Fault reporting structure</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="faultcode" type="xs:QName"/>
<xs:element name="faultstring" type="xs:string"/>
<xs:element name="faultactor" type="xs:anyURI" minOccurs="0"/>
<xs:element name="detail" type="tns:detail" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="detail">
<xs:sequence>
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="lax"/>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?><!-- Schema defined in the SOAP Version 1.2 Part 1 specification
Proposed Recommendation:
http://www.w3.org/TR/2003/PR-soap12-part1-20030507/
$Id: soap-envelope.xsd,v 1.1 2003/04/17 14:23:23 ylafon Exp $
Copyright (C)2003 W3C(R) (MIT, ERCIM, Keio), All Rights Reserved.
W3C viability, trademark, document use and software licensing rules
apply.
http://www.w3.org/Consortium/Legal/
This document is governed by the W3C Software License [1] as
described in the FAQ [2].
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"
targetNamespace="http://www.w3.org/2003/05/soap-envelope" elementFormDefault="qualified">
<xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
<!-- Envelope, header and body -->
<xs:element name="Envelope" type="tns:Envelope"/>
<xs:complexType name="Envelope">
<xs:sequence>
<xs:element ref="tns:Header" minOccurs="0"/>
<xs:element ref="tns:Body" minOccurs="1"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<xs:element name="Header" type="tns:Header"/>
<xs:complexType name="Header">
<xs:annotation>
<xs:documentation>
Elements replacing the wildcard MUST be namespace qualified, but can be in the
targetNamespace</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<xs:element name="Body" type="tns:Body"/>
<xs:complexType name="Body">
<xs:sequence>
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<!-- Global Attributes. The following attributes are intended to be
usable via qualified attribute names on any complex type referencing
them. -->
<xs:attribute name="mustUnderstand" type="xs:boolean" default="0"/>
<xs:attribute name="relay" type="xs:boolean" default="0"/>
<xs:attribute name="role" type="xs:anyURI"/>
<!-- 'encodingStyle' indicates any canonicalization conventions
followed in the contents of the containing element. For example, the
value 'http://www.w3.org/2003/05/soap-encoding' indicates the pattern
described in the last call working draft of SOAP Version 1.2 Part 2:
Adjuncts -->
<xs:attribute name="encodingStyle" type="xs:anyURI"/>
<xs:element name="Fault" type="tns:Fault"/>
<xs:complexType name="Fault" final="extension">
<xs:annotation>
<xs:documentation>
Fault reporting structure</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Code" type="tns:faultcode"/>
<xs:element name="Reason" type="tns:faultreason"/>
<xs:element name="Node" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Role" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Detail" type="tns:detail" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="faultreason">
<xs:sequence>
<xs:element name="Text" type="tns:reasontext" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="reasontext">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="xml:lang" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="faultcode">
<xs:sequence>
<xs:element name="Value" type="tns:faultcodeEnum"/>
<xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="faultcodeEnum">
<xs:restriction base="xs:QName">
<xs:enumeration value="tns:DataEncodingUnknown"/>
<xs:enumeration value="tns:MustUnderstand"/>
<xs:enumeration value="tns:Receiver"/>
<xs:enumeration value="tns:Sender"/>
<xs:enumeration value="tns:VersionMismatch"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="subcode">
<xs:sequence>
<xs:element name="Value" type="xs:QName"/>
<xs:element name="Subcode" type="tns:subcode" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="detail">
<xs:sequence>
<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax"/>
</xs:complexType>
<!-- Global element declaration and complex type definition for header entry returned due to a mustUnderstand fault -->
<xs:element name="NotUnderstood" type="tns:NotUnderstoodType"/>
<xs:complexType name="NotUnderstoodType">
<xs:attribute name="qname" type="xs:QName" use="required"/>
</xs:complexType>
<!-- Global element and associated types for managing version transition as described in Appendix A of the SOAP Version 1.2 Part 1 Last Call Working Draft -->
<xs:complexType name="SupportedEnvType">
<xs:attribute name="qname" type="xs:QName" use="required"/>
</xs:complexType>
<xs:element name="Upgrade" type="tns:UpgradeType"/>
<xs:complexType name="UpgradeType">
<xs:sequence>
<xs:element name="SupportedEnvelope" type="tns:SupportedEnvType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,114 @@
<?xml version='1.0'?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xml:lang="en">
<xs:annotation>
<xs:documentation>
See http://www.w3.org/XML/1998/namespace.html and http://www.w3.org/TR/REC-xml for information about this
namespace.
This schema document describes the XML namespace, in a form suitable for import by other schema documents.
Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or
its subgroups. The following names are currently defined in this namespace and should not be used with
conflicting semantics by any Working Group, specification, or document instance:
base (as an attribute name): denotes an attribute whose value provides a URI to be used as the base for
interpreting any relative URIs in the scope of the element on which it appears; its value is inherited. This
name is reserved by virtue of its definition in the XML Base specification.
id (as an attribute name): denotes an attribute whose value should be interpreted as if declared to be of
type ID. The xml:id specification is not yet a W3C Recommendation, but this attribute is included here to
facilitate experimentation with the mechanisms it proposes. Note that it is _not_ included in the
specialAttrs attribute group.
lang (as an attribute name): denotes an attribute whose value is a language code for the natural language of
the content of any element; its value is inherited. This name is reserved by virtue of its definition in the
XML specification.
space (as an attribute name): denotes an attribute whose value is a keyword indicating what whitespace
processing discipline is intended for the content of the element; its value is inherited. This name is
reserved by virtue of its definition in the XML specification.
Father (in any context at all): denotes Jon Bosak, the chair of the original XML Working Group. This name is
reserved by the following decision of the W3C XML Plenary and XML Coordination groups:
In appreciation for his vision, leadership and dedication the W3C XML Plenary on this 10th day of February,
2000 reserves for Jon Bosak in perpetuity the XML name xml:Father</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>This schema defines attributes and an attribute group suitable for use by schemas wishing to
allow xml:base, xml:lang, xml:space or xml:id attributes on elements they define.
To enable this, such a schema must import this schema for the XML namespace, e.g. as follows: &lt;schema . .
.> . . . &lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
Subsequently, qualified reference to any of the attributes or the group defined below will have the desired
effect, e.g.
&lt;type . . .> . . . &lt;attributeGroup ref="xml:specialAttrs"/>
will define a type which will schema-validate an instance element with any of those
attributes</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>In keeping with the XML Schema WG's standard versioning policy, this schema document will
persist at http://www.w3.org/2005/08/xml.xsd. At the date of issue it can also be found at
http://www.w3.org/2001/xml.xsd. The schema document at that URI may however change in the future, in order
to remain compatible with the latest version of XML Schema itself, or with the XML namespace itself. In
other words, if the XML Schema or XML namespaces change, the version of this document at
http://www.w3.org/2001/xml.xsd will change accordingly; the version at http://www.w3.org/2005/08/xml.xsd
will not change.</xs:documentation>
</xs:annotation>
<xs:attribute name="lang">
<xs:annotation>
<xs:documentation>Attempting to install the relevant ISO 2- and 3-letter codes as the enumerated possible
values is probably never going to be a realistic possibility. See RFC 3066 at
http://www.ietf.org/rfc/rfc3066.txt and the IANA registry at
http://www.iana.org/assignments/lang-tag-apps.htm for further information.
The union allows for the 'un-declaration' of xml:lang with the empty string.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:union memberTypes="xs:language">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="space">
<xs:simpleType>
<xs:restriction base="xs:NCName">
<xs:enumeration value="default"/>
<xs:enumeration value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" type="xs:anyURI">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xmlbase/ for information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="id" type="xs:ID">
<xs:annotation>
<xs:documentation>See http://www.w3.org/TR/xml-id/ for information about this attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup name="specialAttrs">
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/>
<xs:attribute ref="xml:space"/>
</xs:attributeGroup>
</xs:schema>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.springframework.org/spring-ws/wsdl"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:element name="request" type="xsd:string"/>
<xsd:element name="response" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="responseMessage">
<wsdl:part name="body" element="tns:response"/>
</wsdl:message>
<wsdl:message name="requestMessage">
<wsdl:part name="body" element="tns:request"/>
</wsdl:message>
<wsdl:portType name="portType">
<wsdl:operation name="operation">
<wsdl:input message="tns:requestMessage" name="request"/>
<wsdl:output message="tns:responseMessage" name="response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="binding" type="tns:portType">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="operation">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="request">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="response">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="service">
<wsdl:port binding="tns:binding" name="port">
<wsdlsoap:address location="http://example.com:8080/context/service"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.springframework.org/spring-ws/wsdl"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:element name="request" type="xsd:string"/>
<xsd:element name="response" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="responseMessage">
<wsdl:part name="body" element="tns:response"/>
</wsdl:message>
<wsdl:message name="requestMessage">
<wsdl:part name="body" element="tns:request"/>
</wsdl:message>
<wsdl:portType name="portType">
<wsdl:operation name="operation">
<wsdl:input message="tns:requestMessage" name="request"/>
<wsdl:output message="tns:responseMessage" name="response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="binding" type="tns:portType">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="operation">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="request">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="response">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="service">
<wsdl:port binding="tns:binding" name="port">
<wsdlsoap:address location="http://localhost:8080/context/service"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.springframework.org/spring-ws/wsdl/definitions"
xmlns:xsd="http://www.springframework.org/spring-ws/wsdl/schemas"
targetNamespace="http://www.springframework.org/spring-ws/wsdl/definitions">
<import namespace="http://www.springframework.org/spring-ws/wsdl/schemas" location="types.xsd"/>
<message name="responseMessage">
<part name="body" element="tns:response"/>
</message>
<message name="requestMessage">
<part name="body" element="tns:request"/>
</message>
<portType name="portType">
<operation name="operation">
<input message="tns:requestMessage" name="request"/>
<output message="tns:responseMessage" name="response"/>
</operation>
</portType>
</definitions>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://www.springframework.org/spring-ws/wsdl"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://www.springframework.org/spring-ws/wsdl">
<xsd:element name="request" type="xsd:string"/>
<xsd:element name="response" type="xsd:string"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="responseMessage">
<wsdl:part name="body" element="tns:response"/>
</wsdl:message>
<wsdl:message name="requestMessage">
<wsdl:part name="body" element="tns:request"/>
</wsdl:message>
<wsdl:portType name="portType">
<wsdl:operation name="operation">
<wsdl:input message="tns:requestMessage" name="request"/>
<wsdl:output message="tns:responseMessage" name="response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="binding" type="tns:portType">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="operation">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="request">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="response">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="service">
<wsdl:port binding="tns:binding" name="port">
<wsdlsoap:address location="/services"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:defs="http://www.springframework.org/spring-ws/wsdl/definitions"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://www.springframework.org/spring-ws/wsdl/service">
<import namespace="http://www.springframework.org/spring-ws/wsdl/definitions" location="abstract.wsdl"/>
<binding name="binding" type="defs:portType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="operation">
<soap:operation soapAction=""/>
<input name="request">
<soap:body use="literal"/>
</input>
<output name="response">
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="service">
<port binding="defs:binding" name="port">
<soap:address location="http://www.springframework.org/spring-ws/wsdl"/>
</port>
</service>
</definitions>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://www.springframework.org/spring-ws/wsdl/schemas">
<element name="request" type="string"/>
<element name="response" type="string"/>
</schema>

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import org.springframework.ws.context.MessageContext;
/**
* Interface that must be implemented for each endpoint type to handle a message request. This interface is used to
* allow the <code>MessageDispatcher</code> to be indefintely extensible. It accesses all installed endpoints through
* this interface, meaning that is does not contain code specific to any endpoint type.
* <p/>
* This interface is not intended for application developers. It is available for those who want to develop their own
* message flow.
*
* @author Arjen Poutsma
* @see MessageDispatcher
*/
public interface EndpointAdapter {
/**
* Given an endpoint instance, return whether or not this <code>EndpointAdapter</code> can support it. Typical
* <code>EndpointAdapters</code> will base the decision on the endpoint type.
*
* @param endpoint endpoint object to check
* @return whether or not this adapter can adapt the given endpoint
*/
boolean supports(Object endpoint);
/**
* Use the given endpoint to handle the request.
*
* @param messageContext the current message context
* @param endpoint the endpoint to use. This object must have previously been passed to the
* <code>supports</code> method of this interface, which must have returned <code>true</code>
* @throws Exception in case of errors
*/
void invoke(MessageContext messageContext, Object endpoint) throws Exception;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import org.springframework.ws.context.MessageContext;
/**
* Defines the interface for objects than can resolve exceptions thrown during endpoint execution, resulting in SOAP
* messages.
*
* @author Arjen Poutsma
*/
public interface EndpointExceptionResolver {
/**
* Try to resolve the given exception that got thrown during on endpoint execution.
*
* @param messageContext current message context
* @param endpoint the executed endpoint, or null if none chosen at the time of the exception
* @param ex the exception that got thrown during endpoint execution
* @return <code>true</code> if resolved; <code>false</code> otherwise
*/
boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex);
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import org.springframework.ws.context.MessageContext;
/**
* Workflow interface that allows for customized endpoint invocation chains. Applications can register any number of
* existing or custom interceptors for certain groups of endpoints, to add common preprocessing behavior without needing
* to modify each endpoint implementation.
* <p/>
* A <code>EndpointInterceptor</code> gets called before the appropriate <code>EndpointAdapter</code> triggers the
* invocation of the endpoint itself. This mechanism can be used for a large field of preprocessing aspects, e.g. for
* authorization checks, or message header checks. Its main purpose is to allow for factoring out repetitive endpoint
* code.
* <p/>
* Typically an interceptor chain is defined per <code>EndpointMapping</code> bean, sharing its granularity. To be able
* to apply a certain interceptor chain to a group of handlers, one needs to map the desired handlers via one
* <code>EndpointMapping</code> bean.
*
* @author Arjen Poutsma
* @see EndpointInvocationChain#getInterceptors()
* @see org.springframework.ws.endpoint.interceptor.EndpointInterceptorAdapter
* @see org.springframework.ws.endpoint.mapping.AbstractEndpointMapping#setInterceptors(EndpointInterceptor[])
*/
public interface EndpointInterceptor {
/**
* Processes the incoming request message.
*
* @param messageContext contains the incoming request message
* @param endpoint chosen endpoint to invoke
* @return <code>true</code> to continue processing of the request interceptor chain; <code>false</code> to indicate
* blocking of the request handler chain, <em>without invoking the endpoint</em>
*/
boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception;
/**
* Processes the outgoing response message.
*
* @param messageContext contains both request and response messages
* @param endpoint chosen endpoint to invoke
* @return <code>true</code> to continue processing of the reponse interceptor chain; <code>false</code> to indicate
* blocking of the response handler chain.
*/
boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception;
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
/**
* Endpoint invocation chain, consisting of an endpoint object and any preprocessing interceptors.
*
* @author Arjen Poutsma
* @see EndpointInterceptor
*/
public class EndpointInvocationChain {
private Object endpoint;
private EndpointInterceptor[] interceptors;
/**
* Create new <code>EndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
*/
public EndpointInvocationChain(Object endpoint) {
this.endpoint = endpoint;
}
/**
* Create new <code>EndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
* @param interceptors the array of interceptors to apply
*/
public EndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors) {
this.endpoint = endpoint;
this.interceptors = interceptors;
}
/**
* Returns the endpoint object to invoke.
*
* @return the endpoint object
*/
public Object getEndpoint() {
return endpoint;
}
/**
* Returns the array of interceptors to apply before the handler executes.
*
* @return the array of interceptors
*/
public EndpointInterceptor[] getInterceptors() {
return interceptors;
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import org.springframework.ws.context.MessageContext;
/**
* Interface to be implemented by objects that define a mapping between message requests and endpoint objects.
* <p/>
* This class can be implemented by application developers, although this is not necessary, as
* <code>PayloadRootQNameEndpointMapping</code> and <code>SoapActionEndpointMapping</code> are included.
* <p/>
* HandlerMapping implementations can support mapped interceptors but do not have to. An endpoint will always be wrapped
* in a <code>EndpointExecutionChain</code> instance, optionally accompanied by some <code>EndpointInterceptor</code>
* instances. The <code>MessageDispacher</code> will first call each <code>EndpointInterceptor</code>'s
* <code>handlerRequest</code> method in the given order, finally invoking the endpoint itself if all
* <code>handlerRequest</code> methods have returned <code>true</code>.
*
* @author Arjen Poutsma
* @see org.springframework.ws.endpoint.mapping.AbstractEndpointMapping
* @see org.springframework.ws.endpoint.mapping.PayloadRootQNameEndpointMapping
* @see org.springframework.ws.soap.endpoint.mapping.SoapActionEndpointMapping
*/
public interface EndpointMapping {
/**
* Returns an endpoint and any interceptors for this message context. The choice may be made on message contents,
* transport request url, a routing table, or any factor the implementing class chooses.
* <p/>
* The returned <code>EndpointExecutionChain</code> contains an endpoint Object, rather than even a tag interface,
* so that endpoints are not constrained in any way. For example, a <code>EndpointAdapter</code> could be written to
* allow another framework's endpoint objects to be used.
* <p/>
* Returns <code>null</code> if no match was found. This is not an error. The <code>MessageDispatcher</code> will
* query all registered <code>EndpointMapping</code> beans to find a match, and only decide there is an error if
* none can find an endpoint.
*
* @return a HandlerExecutionChain instance containing endpoint object and any interceptors, or <code>null</code> if
* no mapping found
* @throws Exception if there is an internal error
*/
EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception;
}

View File

@@ -0,0 +1,398 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.endpoint.MessageEndpoint;
/**
* Central dispatcher for use withing Spring-WS. Dispatches SOAP messages to registered endoints.
* <p/>
* This dispatcher is quite similar to Spring MVCs <code>DispatcherServlet</code>. Just like it's counterpart, this
* dispatcher is very flexible. <ul> <li>It can use any <code>EndpointMapping</code> implementation - whether standard,
* or provided as part of an application - to control the routing of request messages to endpoint objects. Endpoint
* mappings can be registerd using the <code>endpointMappings</code> property.</li> <li>It can use any
* <code>EndpointAdapter</code>; this allows to use any endpoint interface or form. Default are
* <code>MessageEndpointAdapter</code> and <code>PayloadEndpointAdapter</code>, for <code>MessageEndpoint</code> and
* <code>PayloadEndpoint</code>, respectively. Additional endpoint adapters can be added through the
* <code>endpointAdapters</code> property.</li> <li>Its exception resolution strategy can be specified via a
* <code>EndpointExceptionResolver</code>, for example mapping certain exceptions to SOAP Faults. Default is none.
* Additional exception resolvers can be added through the <code>endpointExceptionResolvers</code> property.</li> </ul>
* A web application can use any number of <code>MessageDispatcher</code>s.</b> Since a <code>MessageDispatcher</code>
* also implements <code>MessageEndpoint</code>, it is also possible to chain them: one dispatcher can be registered as
* the endpoint of another.
*
* @author Arjen Poutsma
* @see EndpointMapping
* @see EndpointAdapter
* @see EndpointExceptionResolver
* @see org.springframework.web.servlet.DispatcherServlet
*/
public class MessageDispatcher extends ApplicationObjectSupport implements MessageEndpoint, BeanNameAware {
/**
* Name of the class path resource (relative to the MessageDispatcher class) that defines MessageDispatcher's
* default strategy names.
*/
private static final String DEFAULT_STRATEGIES_PATH = "MessageDispatcher.properties";
/**
* Log category to use when no mapped endpoint is found for a request.
*/
public static final String ENDPOINT_NOT_FOUND_LOG_CATEGORY = "org.springframework.ws.EndpointNotFound";
/**
* Additional logger to use when no mapped endpoint is found for a request.
*/
protected static final Log endpointNotFoundLogger = LogFactory.getLog(ENDPOINT_NOT_FOUND_LOG_CATEGORY);
private static final Properties defaultStrategies = new Properties();
static {
// Load default strategy implementations from properties file.
// This is currently strictly internal and not meant to be customized
// by application developers.
try {
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, MessageDispatcher.class);
InputStream is = resource.getInputStream();
try {
defaultStrategies.load(is);
}
finally {
is.close();
}
}
catch (IOException ex) {
throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
}
}
/**
* List of EndpointMappings used in this dispatcher
*/
private List endpointMappings;
/**
* List of EndpointAdapters used in this dispatcher
*/
private List endpointAdapters;
/**
* List of EndpointExceptionResolvers used in this dispatcher
*/
private List endpointExceptionResolvers;
/**
* The registered bean name for this dispatcher.
*/
private String beanName;
/**
* Initializes the dispatcher.
*/
public void initApplicationContext() throws BeansException {
initEndpointMappings();
initEndpointAdapters();
initEndpointExceptionResolvers();
}
/**
* Initialize the <code>EndpointMappings</code> used in this class.
*/
private void initEndpointMappings() {
// Ensure we have at least one EndpointMapping, by registering a default if not others are found
if (endpointMappings == null) {
endpointMappings = getDefaultStrategies(EndpointMapping.class);
logger.info("No EndpointMapping found: using default");
}
}
/**
* Initialize the <code>EndpointAdapters</code> used by this class.
*/
private void initEndpointAdapters() {
if (endpointAdapters == null) {
// Ensure we have at least some EndpointAdapters, by registereing a default if no others are found
endpointAdapters = getDefaultStrategies(EndpointAdapter.class);
logger.info("No EndpointAdapters found: using default");
}
}
/**
* Initialize the <code>EndpointExceptionResolvers</code> used in this class.
*/
private void initEndpointExceptionResolvers() {
if (endpointExceptionResolvers == null) {
// Ensure we have at least some EndpointExceptionResolvers, by registereing a default if no others are found
endpointAdapters = getDefaultStrategies(EndpointExceptionResolver.class);
logger.info("No EndpointExceptionResolver found: using default");
}
}
/**
* Create a List of default strategy objects for the given strategy interface. <p/> The default implementation uses
* the "MessageDispatcher.properties" file (in the same package as the MessageDispatcher class) to determine the
* class names. It instantiates the strategy objects and satisifies ApplicationContextAware and InitializingBean if
* necessary.
*
* @param strategyInterface the strategy interface
* @return the List of corresponding strategy objects
* @throws BeansException if initialization failed
*/
protected List getDefaultStrategies(Class strategyInterface) throws BeansException {
String key = strategyInterface.getName();
try {
List strategies = null;
String value = defaultStrategies.getProperty(key);
if (value != null) {
String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
strategies = new ArrayList(classNames.length);
for (int i = 0; i < classNames.length; i++) {
Class clazz = Class.forName(classNames[i], true, getClass().getClassLoader());
Object strategy = BeanUtils.instantiateClass(clazz);
if (strategy instanceof ApplicationContextAware) {
((ApplicationContextAware) strategy).setApplicationContext(getApplicationContext());
}
strategies.add(strategy);
}
}
else {
strategies = Collections.EMPTY_LIST;
}
return strategies;
}
catch (ClassNotFoundException ex) {
throw new BeanInitializationException(
"Could not find MessageDispatcher's default strategy class for interface [" + key + "]",
ex);
}
}
public void invoke(MessageContext messageContext) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("MessageDispatcher with name '" + beanName + "' received request [" +
messageContext.getRequest() + "]");
}
dispatch(messageContext);
if (logger.isDebugEnabled() && messageContext.hasResponse()) {
logger.debug("MessageDispatcher with name '" + beanName + "' sends response [" +
messageContext.getResponse() + "]");
}
}
/**
* Dispatches the request in the given MessageContext according to the configuration.
*
* @param messageContext the message context
* @throws NoEndpointFoundException thrown when an endpoint cannot be resolved for the incoming message
*/
protected final void dispatch(MessageContext messageContext) throws Exception {
EndpointInvocationChain mappedEndpoint = null;
int interceptorIndex = -1;
try {
// Determine endpoint for the current context
mappedEndpoint = getEndpoint(messageContext);
if (mappedEndpoint == null || mappedEndpoint.getEndpoint() == null) {
throw new NoEndpointFoundException(messageContext.getRequest());
}
if (!handleRequest(mappedEndpoint, messageContext)) {
return;
}
// Apply handleRequest of registered interceptors
if (!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
for (int i = 0; i < mappedEndpoint.getInterceptors().length; i++) {
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
interceptorIndex = i;
if (!interceptor.handleRequest(messageContext, mappedEndpoint.getEndpoint())) {
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
return;
}
}
}
// Acutally invoke the endpoint
EndpointAdapter endpointAdapter = getEndpointAdapter(mappedEndpoint.getEndpoint());
endpointAdapter.invoke(messageContext, mappedEndpoint.getEndpoint());
// Apply handleResponse methods of registered interceptors
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
}
catch (NoEndpointFoundException ex) {
// No triggering of interceptors if no endpoint is found
if (endpointNotFoundLogger.isWarnEnabled()) {
endpointNotFoundLogger.warn("No endpoint mapping found for [" + messageContext.getRequest() + "]");
}
throw ex;
}
catch (Exception ex) {
Object endpoint = mappedEndpoint != null ? mappedEndpoint.getEndpoint() : null;
processEndpointException(messageContext, endpoint, ex);
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
}
}
/**
* Callback for pre-processing of given invocation chain and message context. Gets called before invocation of
* <code>handleRequest</code> on the interceptors.
* <p/>
* Default implementation does nothing, and returns <code>true</code>.
*
* @param mappedEndpoint the mapped <code>EndpointInvocationChain</code>
* @param messageContext the message context
* @return <code>true</code> if processing should continue; <code>false</code> otherwise
*/
protected boolean handleRequest(EndpointInvocationChain mappedEndpoint, MessageContext messageContext) {
return true;
}
/**
* Trigger handleResponse or handleFault on the mapped EndpointInterceptors. Will just invoke said method on all
* interceptors whose handleRequest invocation returned <code>true</code>, in addition to the last interceptor who
* returned <code>false</code>.
*
* @param mappedEndpoint the mapped EndpointInvocationChain
* @param interceptorIndex index of last interceptor that was called
* @param messageContext the message context, whose request and response are filled
* @see EndpointInterceptor#handleResponse(MessageContext, Object)
*/
protected void triggerHandleResponse(EndpointInvocationChain mappedEndpoint,
int interceptorIndex,
MessageContext messageContext) throws Exception {
if (mappedEndpoint != null && messageContext.hasResponse() &&
!ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
boolean resume = true;
for (int i = interceptorIndex; resume && i >= 0; i--) {
EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
resume = interceptor.handleResponse(messageContext, mappedEndpoint.getEndpoint());
}
}
}
/**
* Returns the endpoint for this request. All endpoint mappings are tried, in order.
*
* @return the <code>EndpointInvocationChain</code>, or <code>null</code> if no endpoint could be found.
*/
protected EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
for (Iterator iterator = endpointMappings.iterator(); iterator.hasNext();) {
EndpointMapping endpointMapping = (EndpointMapping) iterator.next();
EndpointInvocationChain endpoint = endpointMapping.getEndpoint(messageContext);
if (endpoint != null) {
if (logger.isDebugEnabled()) {
logger.debug("Endpoint mapping [" + endpointMapping + "] maps request to endpoint [" +
endpoint.getEndpoint() + "]");
}
return endpoint;
}
else if (logger.isDebugEnabled()) {
logger.debug("Endpoint mapping [" + endpointMapping + "] has no mapping for request");
}
}
return null;
}
/**
* Returns the <code>EndpointAdapter</code> for the given endpoint.
*
* @param endpoint the endpoint to find an adapter for
* @return the adapter
*/
protected EndpointAdapter getEndpointAdapter(Object endpoint) {
for (Iterator iterator = endpointAdapters.iterator(); iterator.hasNext();) {
EndpointAdapter endpointAdapter = (EndpointAdapter) iterator.next();
if (logger.isDebugEnabled()) {
logger.debug("Testing endpoint adapter [" + endpointAdapter + "]");
}
if (endpointAdapter.supports(endpoint)) {
return endpointAdapter;
}
}
throw new IllegalStateException("No adapter for endpoint [" + endpoint + "]: Does your endpoint implement a " +
"supported interface like MessageHandler or PayloadEndpoint?");
}
/**
* Determine an error <code>SOAPMessage</code> respone via the registered <code>EndpointExceptionResolvers</code>.
* Most likely, the response contains a <code>SOAPFault</code>. If no suitable resolver was found, the exception is
* rethrown.
*
* @param messageContext current SOAPMessage request
* @param endpoint the executed endpoint, or null if none chosen at the time of the exception
* @param ex the exception that got thrown during handler execution
* @throws Exception if no suitable resolver is found
*/
protected void processEndpointException(MessageContext messageContext, Object endpoint, Exception ex)
throws Exception {
for (Iterator iterator = endpointExceptionResolvers.iterator(); iterator.hasNext();) {
EndpointExceptionResolver resolver = (EndpointExceptionResolver) iterator.next();
if (logger.isDebugEnabled()) {
logger.debug("Testing endpoint exception resolver [" + resolver + "]");
}
if (resolver.resolveException(messageContext, endpoint, ex)) {
logger.warn("Endpoint invocation resulted in exception - responding with SOAP Fault", ex);
return;
}
}
// exception not resolved
throw ex;
}
/**
* Sets the <code>EndpointMapping</code>s to use by this <code>MessageDispatcher</code>.
*/
public void setEndpointMappings(List endpointMappings) {
this.endpointMappings = endpointMappings;
}
/**
* Sets the <code>EndpointAdapter</code>s to use by this <code>MessageDispatcher</code>.
*/
public void setEndpointAdapters(List endpointAdapters) {
this.endpointAdapters = endpointAdapters;
}
/**
* Sets the <code>EndpointExceptionResolver</code>s to use by this <code>MessageDispatcher</code>.
*/
public void setEndpointExceptionResolvers(List endpointExceptionResolvers) {
this.endpointExceptionResolvers = endpointExceptionResolvers;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
/**
* Exception thrown when an endpoint cannot be resolved for an incoming message request.
*
* @author Arjen Poutsma
*/
public final class NoEndpointFoundException extends WebServiceException {
public NoEndpointFoundException(WebServiceMessage request) {
super("No endpoint can be found for request [" + request + "]");
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import java.io.Serializable;
import org.springframework.core.NestedRuntimeException;
/**
* Root of the hierarchy of Web Service exceptions.
*
* @author Arjen Poutsma
*/
public abstract class WebServiceException extends NestedRuntimeException implements Serializable {
/**
* Constructor for <code>WebServiceException</code>.
*/
public WebServiceException(String msg) {
super(msg);
}
/**
* Constructor for <code>WebServiceException</code>.
*/
public WebServiceException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
/**
* Represents a protocol agnostic XML message. Contains methods that provide access to the payload of the message.
*
* @author Arjen Poutsma
* @see org.springframework.ws.soap.SoapMessage
*/
public interface WebServiceMessage {
/**
* Returns the contents of the message as a <code>java.xml.transform.Source</code>. Depending on the implementation,
* this can be retrieved multiple times, or just a single time.
*
* @return the message contents
*/
Source getPayloadSource();
/**
* Returns the contents of the message as a <code>java.xml.transform.Result</code>. Some implementations are
* read-only, and may throws an <code>UnsupportedOperationException</code>.
*
* @return the messaage contents
* @throws UnsupportedOperationException if the message is read-only
*/
Result getPayloadResult();
/**
* Writes the entire message to the given output stream.
*
* @param outputStream the stream to write to
* @throws IOException if an I/O exception occurs
*/
void writeTo(OutputStream outputStream) throws IOException;
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws;
/**
* Base class for all web service message exceptions.
*
* @author Arjen Poutsma
*/
public abstract class WebServiceMessageException extends WebServiceException {
/**
* Constructor for <code>WebServiceMessageException</code>.
*/
public WebServiceMessageException(String msg) {
super(msg);
}
/**
* Constructor for <code>WebServiceMessageException</code>.
*/
public WebServiceMessageException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.context;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.TransportRequest;
/**
* Abstract implementation of the <code>MessageContext</code> interface. Contains functionality to set and remove
* properties.
*
* @author Arjen Poutsma
*/
public abstract class AbstractMessageContext implements MessageContext {
private WebServiceMessage request;
private WebServiceMessage response;
private final TransportRequest transportRequest;
/**
* Keys are <code>Strings</code>, values are <code>Objects</code>. Lazily initalized by
* <code>getProperties()</code>.
*/
private Map properties;
/**
* Construct a new instance of the <code>AbstractMessageContext</code> with the given request message and
* transportRequest.
*/
protected AbstractMessageContext(WebServiceMessage request, TransportRequest transportRequest) {
Assert.notNull(request, "No request given");
Assert.notNull(transportRequest, "No transport request given");
this.request = request;
this.transportRequest = transportRequest;
}
public final WebServiceMessage getRequest() {
return request;
}
/**
* Protected method that sets the request message directly.
*/
protected final void setRequest(WebServiceMessage request) {
Assert.notNull(request);
this.request = request;
}
public final WebServiceMessage getResponse() {
if (response == null) {
response = createResponseMessage();
}
return response;
}
public final boolean hasResponse() {
return response != null;
}
public final TransportRequest getTransportRequest() {
return transportRequest;
}
/**
* Protected method that sets the response message directly.
*/
protected final void setResponse(WebServiceMessage response) {
Assert.notNull(response);
this.response = response;
}
private Map getProperties() {
if (properties == null) {
properties = new HashMap();
}
return properties;
}
public boolean containsProperty(String name) {
return getProperties().containsKey(name);
}
public Object getProperty(String name) {
return getProperties().get(name);
}
public String[] getPropertyNames() {
return (String[]) getProperties().keySet().toArray(new String[getProperties().size()]);
}
public void removeProperty(String name) {
getProperties().remove(name);
}
public void setProperty(String name, Object value) {
getProperties().put(name, value);
}
/**
* Abstract template method that creates a new <code>WebServiceMessage</code>.
*/
protected abstract WebServiceMessage createResponseMessage();
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.context;
import java.io.IOException;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.transport.TransportRequest;
import org.springframework.ws.transport.TransportResponse;
/**
* Context holder for message requests. Contains both the message request as well as the response. Response message are
* usually lazily created.
* <p/>
* <code>MessageContext</code> implementations are constructed using a <code>MessageContextFactory</code>, taking a
* <code>TransportContext</code> as a parameter.
*
* @author Arjen Poutsma
* @see MessageContextFactory#createContext(org.springframework.ws.transport.TransportContext)
*/
public interface MessageContext {
/**
* Returns the request message.
*
* @return the request message
*/
WebServiceMessage getRequest();
/**
* Returns the response message. Creates a new response if no response is present.
*
* @return the response message
* @see #hasResponse()
*/
WebServiceMessage getResponse();
/**
* Indicates whether this context has a resonse.
*
* @return <code>true</code> if this context has a response; <code>false</code> otherwise
*/
boolean hasResponse();
/**
* Returns the transport request used to create this context. Call be used for URL-based message routing.
*
* @return the transport request
*/
TransportRequest getTransportRequest();
/**
* Sends the response to the given transport response.
*
* @param transportResponse the transport used for sending
* @throws IOException if an I/O exception occurs
*/
void sendResponse(TransportResponse transportResponse) throws IOException;
/**
* Sets the name and value of a property associated with the <code>MessageContext</code>. If the
* <code>MessageContext</code> contains a value of the same property, the old value is replaced.
*
* @param name name of the property associated with the value
* @param value value of the property
*/
void setProperty(String name, Object value);
/**
* Gets the value of a specific property from the <code>MessageContext</code>.
*
* @param name name of the property whose value is to be retrieved
* @return value of the property
*/
Object getProperty(String name);
/**
* Removes a property from the <code>MessageContext</code>.
*
* @param name name of the property to be removed
*/
void removeProperty(String name);
/**
* Check if this message context contains a property with the given name.
*
* @param name the name of the property to look fo
* @return <code>true</code> if the <code>MessageContext</code> contains the property; <code>false</code> otherwise
*/
boolean containsProperty(String name);
/**
* Return the names of all properties in this <code>MessageContext</code>.
*
* @return the names of all properties in this context, or an empty array if none defined
*/
String[] getPropertyNames();
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.context;
import java.io.IOException;
import org.springframework.ws.transport.TransportContext;
/**
* The <code>MessageContextFactory</code> serves as factory for <code>MessageContext</code>s. Allows creation of
* contexts based on <code>TransportRequest</code>.
*
* @author Arjen Poutsma
*/
public interface MessageContextFactory {
/**
* Creates a <code>MessageContext</code> based on the given transport context. Implementations use the context
* request's input stream to create a request message, and possibly copy the request headers to the message.
* <p/>
* Implementations are free to store the transport context for later reference. For instance, streaming
* implementations of <code>MessageContextFactory</code> might use the transport response to directly write a
* response message.
*
* @param transportContext the transport context which contains the request
* @return the created message context
* @throws IOException if an I/O exception occurs
*/
MessageContext createContext(TransportContext transportContext) throws IOException;
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains the <code>MessageContext</code>, and <code>MessageContextFactory</code> interfaces.
</body>
</html>

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;
/**
* Abstract base class for endpoints that handle the message payload as dom4j elements. Offers the message payload as a
* dom4j <code>Element</code>, and allows subclasses to create a response by returning an <code>Element</code>.
* <p/>
* An <code>AbstractDom4JPayloadEndpoint</code> only accept one payload element. Multiple payload elements are not in
* accordance with WS-I.
*
* @author Arjen Poutsma
* @see org.dom4j.Element
*/
public abstract class AbstractDom4jPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
public final Source invoke(Source request) throws Exception {
Transformer transformer = createTransformer();
DocumentResult dom4jResult = new DocumentResult();
transformer.transform(request, dom4jResult);
Element requestElement = dom4jResult.getDocument().getRootElement();
Document responseDocument = DocumentHelper.createDocument();
Element responseElement = invokeInternal(requestElement, responseDocument);
return responseElement != null ? new DocumentSource(responseElement) : null;
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a dom4j <code>Element</code>, and
* allows subclasses to return a response <code>Element</code>.
* <p/>
* The given dom4j <code>Document</code> is to be used for constructing a response element, by using
* <code>addElement</code>.
*
* @param requestElement the contents of the SOAP message as dom4j elements
* @param responseDocument a dom4j document to be used for constructing a response
* @return the response element. Can be <code>null</code> to specify no response.
*/
protected abstract Element invokeInternal(Element requestElement, Document responseDocument) throws Exception;
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Abstract base class for endpoints that handle the message payload as DOM elements. Offers the message payload as a
* DOM <code>Element</code>, and allows subclasses to create a response by returning an <code>Element</code>.
* <p/>
* An <code>AbstractDomPayloadEndpoint</code> only accept one payload element. Multiple payload elements are not in
* accordance with WS-I.
*
* @author Arjen Poutsma
* @author Alef Arendsen
* @see #invokeInternal(org.w3c.dom.Element, org.w3c.dom.Document)
*/
public abstract class AbstractDomPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
private DocumentBuilderFactory documentBuilderFactory;
private boolean validating = false;
private boolean namespaceAware = true;
/**
* Set whether or not the XML parser should be XML namespace aware. Default is <code>true</code>.
*/
public void setNamespaceAware(boolean namespaceAware) {
this.namespaceAware = namespaceAware;
}
/**
* Set if the XML parser should validate the document. Default is <code>false</code>.
*/
public void setValidating(boolean validating) {
this.validating = validating;
}
public final Source invoke(Source request) throws Exception {
Transformer transformer = createTransformer();
if (documentBuilderFactory == null) {
documentBuilderFactory = createDocumentBuilderFactory();
}
DocumentBuilder documentBuilder = createDocumentBuilder(documentBuilderFactory);
Document requestDocument = documentBuilder.newDocument();
DOMResult domResult = new DOMResult(requestDocument);
transformer.transform(request, domResult);
Element requestElement = (Element) requestDocument.getFirstChild();
Document resonseDocument = documentBuilder.newDocument();
Element responseElement = invokeInternal(requestElement, resonseDocument);
if (responseElement != null) {
return new DOMSource(responseElement);
}
else {
return null;
}
}
/**
* Create a <code>DocumentBuilder</code> that this endpoint will use for parsing XML documents. Can be overridden in
* subclasses, adding further initialization of the builder.
*
* @param factory the <code>DocumentBuilderFactory</code> that the DocumentBuilder should be created with
* @return the <code>DocumentBuilder</code>
* @throws ParserConfigurationException if thrown by JAXP methods
*/
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
throws ParserConfigurationException {
return factory.newDocumentBuilder();
}
/**
* Create a <code>DocumentBuilderFactory</code> that this endpoint will use for constructing XML documents. Can be
* overridden in subclasses, adding further initialization of the factory. The resulting
* <code>DocumentBuilderFactory</code> is cached, so this method will only be called once.
*
* @return the DocumentBuilderFactory
* @throws ParserConfigurationException if thrown by JAXP methods
*/
protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(this.validating);
factory.setNamespaceAware(this.namespaceAware);
return factory;
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a DOM <code>Element</code>, and
* allows subclasses to return a response <code>Element</code>.
* <p/>
* The given DOM <code>Document</code> is to be used for constructing <code>Node</code>s, by using the various
* <code>create</code> methods.
*
* @param requestElement the contents of the SOAP message as DOM elements
* @param responseDocument a DOM document to be used for constructing <code>Node</code>s
* @return the response element. Can be <code>null</code> to specify no response.
*/
protected abstract Element invokeInternal(Element requestElement, Document responseDocument) throws Exception;
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ws.EndpointExceptionResolver;
import org.springframework.ws.context.MessageContext;
/**
* Abstract base class for <code>ExceptionResolver</code>s. Provides a set of mapped endpoints that the resolver should
* map.
*
* @author Arjen Poutsma
*/
public abstract class AbstractEndpointExceptionResolver implements EndpointExceptionResolver {
protected final Log logger = LogFactory.getLog(getClass());
private Set mappedEndpoints;
/**
* Specify the set of endpoints that this exception resolver should map. The exception mappings and the default
* fault will only apply to the specified endpoints.
* <p/>
* If no endpoints set, both the exception mappings and the default fault will apply to all handlers. This means
* that a specified default fault will be used as fallback for all exceptions; any further
* <code>EndpointExceptionResolvers</code> in the chain will be ignored in this case.
*/
public void setMappedEndpoints(Set mappedEndpoints) {
this.mappedEndpoints = mappedEndpoints;
}
/**
* Default implementation. Checks whether the given endpoint is in the set of mapped endpoints. Calls
* <code>resolveExceptionInternal</code>.
*
* @see #resolveExceptionInternal(org.springframework.ws.context.MessageContext, Object, Exception)
*/
public final boolean resolveException(MessageContext messageContext, Object endpoint, Exception ex) {
if (this.mappedEndpoints != null && !this.mappedEndpoints.contains(endpoint)) {
return false;
}
return resolveExceptionInternal(messageContext, endpoint, ex);
}
/**
* Template method for resolving exceptions. Gets called after <code>resolveException</code>.
*
* @param messageContext current message context
* @param endpoint the executed endpoint, or null if none chosen at the time of the exception
* @param ex the exception that got thrown during endpoint execution
* @return <code>true</code> if resolved; <code>false</code> otherwise
* @see #resolveException(org.springframework.ws.context.MessageContext, Object, Exception)
*/
protected abstract boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex);
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import org.jdom.Element;
import org.jdom.transform.JDOMResult;
import org.jdom.transform.JDOMSource;
/**
* Abstract base class for endpoints that handle the message payload as JDOM elements. Offers the message payload as a
* JDOM <code>Element</code>, and allows subclasses to create a response by returning an <code>Element</code>.
* <p/>
* An <code>AbstractJDomPayloadEndpoint</code> only accept one payload element. Multiple payload elements are not in
* accordance with WS-I.
*
* @author Arjen Poutsma
* @see Element
*/
public abstract class AbstractJDomPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
public final Source invoke(Source request) throws Exception {
Transformer transformer = createTransformer();
JDOMResult jdomResult = new JDOMResult();
transformer.transform(request, jdomResult);
Element requestElement = jdomResult.getDocument().getRootElement();
Element responseElement = invokeInternal(requestElement);
return responseElement != null ? new JDOMSource(responseElement) : null;
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a JDOM <code>Element</code>, and
* allows subclasses to return a response <code>Element</code>.
*
* @param requestElement the contents of the SOAP message as JDOM element
* @return the response element. Can be <code>null</code> to specify no response.
*/
protected abstract Element invokeInternal(Element requestElement) throws Exception;
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import java.io.StringWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
/**
* Abstract base class for <code>EndpointInterceptor</code> instances that log a part of a
* <code>WebServiceMessage</code>. By default, both request and response messages are logged, but this behaviour can be
* changed using the <code>logRequest</code> and <code>logResponse</code> properties.
*
* @author Arjen Poutsma
*/
public abstract class AbstractLoggingInterceptor extends TransformerObjectSupport implements EndpointInterceptor {
private boolean logRequest = true;
private boolean logResponse = true;
/**
* Indicates whether the request should be logged. Default is <code>true</code>.
*/
public final void setLogRequest(boolean logRequest) {
this.logRequest = logRequest;
}
/**
* Indicates whether the response should be logged. Default is <code>true</code>.
*/
public final void setLogResponse(boolean logResponse) {
this.logResponse = logResponse;
}
/**
* Logs the request message payload. Logging only ocurs if <code>logRequest</code> is set to <code>true</code>,
* which is the default.
*
* @param messageContext the message context
* @return <code>true</code>
* @throws TransformerException when the payload cannot be transformed to a string
*/
public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws TransformerException {
if (logRequest && logger.isDebugEnabled()) {
logMessageSource("Request: ", getSource(messageContext.getRequest()));
}
return true;
}
/**
* Logs the response message payload. Logging only ocurs if <code>logResponse</code> is set to <code>true</code>,
* which is the default.
*
* @param messageContext the message context
* @return <code>true</code>
* @throws TransformerException when the payload cannot be transformed to a string
*/
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
if (logResponse && logger.isDebugEnabled()) {
logMessageSource("Response: ", getSource(messageContext.getResponse()));
}
return true;
}
private Transformer createNonIndentingTransformer() throws TransformerConfigurationException {
Transformer transformer = createTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "no");
return transformer;
}
protected void logMessageSource(String logMessage, Source source) throws TransformerException {
if (source != null) {
Transformer transformer = createNonIndentingTransformer();
StringWriter writer = new StringWriter();
transformer.transform(source, new StreamResult(writer));
logger.debug(logMessage + writer.toString());
}
}
/**
* Abstract template method that returns the <code>Source</code> for the given <code>WebServiceMessage</code>.
*
* @param message the message
* @return the source of the message
*/
protected abstract Source getSource(WebServiceMessage message);
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
/**
* Endpoint that unmarshals the request payload, and marshals the response object. This endpoint needs a
* <code>Marshaller</code> and <code>Unmarshaller</code>, both of which can be set using properties. An abstract
* template method is invoked using the request object as a parameter, and allows for a response object to be returned.
*
* @author Arjen Poutsma
* @see #setMarshaller(org.springframework.oxm.Marshaller)
* @see Marshaller
* @see #setUnmarshaller(org.springframework.oxm.Unmarshaller)
* @see Unmarshaller
* @see #invokeInternal(Object)
*/
public abstract class AbstractMarshallingPayloadEndpoint implements MessageEndpoint, InitializingBean {
/**
* Logger available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private Marshaller marshaller;
private Unmarshaller unmarshaller;
/**
* Returns the marshalling used for transforming objects into XML.
*/
public final Marshaller getMarshaller() {
return marshaller;
}
/**
* Sets the marshalling used for transforming objects into XML.
*/
public final void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
/**
* Returns the unmarshaller used for transforming XML into objects.
*/
public final Unmarshaller getUnmarshaller() {
return unmarshaller;
}
/**
* Sets the unmarshaller used for transforming XML into objects.
*/
public final void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}
public final void afterPropertiesSet() throws Exception {
Assert.notNull(marshaller, "marshaller is required");
Assert.notNull(unmarshaller, "unmarshaller is required");
afterMarshallerSet();
}
public final void invoke(MessageContext messageContext) throws Exception {
WebServiceMessage request = messageContext.getRequest();
Object requestObject = unmarshaller.unmarshal(request.getPayloadSource());
if (logger.isDebugEnabled()) {
logger.debug("Unmarshalled payload request to [" + requestObject + "]");
}
Object responseObject = invokeInternal(requestObject);
if (responseObject != null) {
if (logger.isDebugEnabled()) {
logger.debug("Marshalling [" + responseObject + "] to response payload");
}
WebServiceMessage response = messageContext.getResponse();
marshaller.marshal(responseObject, response.getPayloadResult());
}
}
/**
* Template method that gets called after the marshaller and unmarshaller have been set.
*/
public void afterMarshallerSet() throws Exception {
}
/**
* Template method. Subclasses must implement this. The unmarshaled request object is passed as a parameter, and an
* the returned object is marshalled to a response. If no response is required, return <code>null</code>.
*
* @param requestObject the unnmarshalled message payload as object
* @return the object to be marshalled as response, or <code>null</code> if a response is not required
*/
protected abstract Object invokeInternal(Object requestObject) throws Exception;
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXResult;
import org.xml.sax.ContentHandler;
/**
* Abstract base class for endpoints that handle the message payload with a SAX <code>ContentHandler</code>. Allows
* subclasses to create a response by returning a <code>Source</code>.
* <p/>
* Implementations of this class should create a new handler for each call of <code>createContentHandler</code>, because
* of thread safety. The handlers is later passed on to <code>createResponse</code>, so it can be used for holding
* request-specific state.
*
* @author Arjen Poutsma
* @see #createContentHandler()
* @see #getResponse(org.xml.sax.ContentHandler)
*/
public abstract class AbstractSaxPayloadEndpoint extends TransformerObjectSupport implements PayloadEndpoint {
/**
* Invokes the provided <code>ContentHandler</code> and <code>LexicalHandler</code> on the given request. After
* parsing has been done, the provided response is returned.
*
* @see #createContentHandler()
* @see #getResponse(org.xml.sax.ContentHandler)
*/
public final Source invoke(Source request) throws Exception {
Transformer transformer = createTransformer();
ContentHandler contentHandler = createContentHandler();
SAXResult result = new SAXResult(contentHandler);
transformer.transform(request, result);
return getResponse(contentHandler);
}
/**
* Returns the SAX <code>ContentHandler</code> used to parse the incoming request payload. A new instance should be
* created for each call, because of thread-safety. The content handler can be used to hold request-specific state.
*
* @return a SAX content handler to be used for parsing
*/
protected abstract ContentHandler createContentHandler();
/**
* Returns the response to be given, if any. This method is called after the request payload has been parse using
* the SAX <code>ContentHandler</code>. The passed <code>ContentHandler</code> is created by
* <code>createContentHandler</code>: it can be used to hold request-specific state.
*
* @param contentHandler the content handler used to parse the request
*/
protected abstract Source getResponse(ContentHandler contentHandler);
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.XMLEventConsumer;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.transform.StaxResult;
import org.springframework.xml.transform.StaxSource;
/**
* Abstract base class for endpoints that handle the message payload with event-based StAX. Allows subclasses to read
* the request with a <code>XMLEventReader</code>, and to create a response using a <code>XMLEventWriter</code>.
*
* @author Arjen Poutsma
* @see #invokeInternal(javax.xml.stream.XMLEventReader, javax.xml.stream.util.XMLEventConsumer,
* javax.xml.stream.XMLEventFactory)
* @see XMLEventReader
* @see XMLEventWriter
*/
public abstract class AbstractStaxEventPayloadEndpoint extends AbstractStaxPayloadEndpoint implements MessageEndpoint {
private XMLEventFactory eventFactory;
public final void invoke(MessageContext messageContext) throws Exception {
XMLEventReader eventReader = getEventReader(messageContext.getRequest().getPayloadSource());
XMLEventWriter streamWriter = new ResponseCreatingEventWriter(messageContext);
invokeInternal(eventReader, streamWriter, getEventFactory());
streamWriter.flush();
}
/**
* Create a <code>XMLEventFactory</code> that this endpoint will use to create <code>XMLEvent</code>s. Can be
* overridden in subclasses, adding further initialization of the factory. The resulting
* <code>XMLEventFactory</code> is cached, so this method will only be called once.
*
* @return the created <code>XMLEventFactory</code>
*/
protected XMLEventFactory createXmlEventFactory() {
return XMLEventFactory.newInstance();
}
/**
* Returns an <code>XMLEventFactory</code> to read XML from.
*/
private XMLEventFactory getEventFactory() {
if (eventFactory == null) {
eventFactory = createXmlEventFactory();
}
return eventFactory;
}
private XMLEventReader getEventReader(Source source) throws XMLStreamException, TransformerException {
XMLEventReader eventReader = null;
if (source instanceof StaxSource) {
StaxSource staxSource = (StaxSource) source;
eventReader = staxSource.getXMLEventReader();
if (eventReader == null && staxSource.getXMLStreamReader() != null) {
try {
eventReader = getInputFactory().createXMLEventReader(staxSource.getXMLStreamReader());
}
catch (XMLStreamException ex) {
// ignore
}
}
}
if (eventReader == null) {
try {
eventReader = getInputFactory().createXMLEventReader(source);
}
catch (XMLStreamException ex) {
// ignore
}
}
if (eventReader == null) {
// as a final resort, transform the source to a stream, and read from that
Transformer transformer = createTransformer();
ByteArrayOutputStream os = new ByteArrayOutputStream();
transformer.transform(source, new StreamResult(os));
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
eventReader = getInputFactory().createXMLEventReader(is);
}
return eventReader;
}
private XMLEventWriter getEventWriter(Result result) {
XMLEventWriter eventWriter = null;
if (result instanceof StaxResult) {
StaxResult staxResult = (StaxResult) result;
eventWriter = staxResult.getXMLEventWriter();
}
if (eventWriter == null) {
try {
eventWriter = getOutputFactory().createXMLEventWriter(result);
}
catch (XMLStreamException ex) {
// ignore
}
}
return eventWriter;
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a <code>XMLEventReader</code>, and
* a <code>XMLEventWriter</code> to write the response payload to.
*
* @param eventReader the reader to read the payload events from
* @param eventWriter the writer to write payload events to
* @param eventFactory an <code>XMLEventFactory</code> that can be used to create events
*/
protected abstract void invokeInternal(XMLEventReader eventReader,
XMLEventConsumer eventWriter,
XMLEventFactory eventFactory) throws Exception;
/**
* Implementation of the <code>XMLEventWriter</code> interface that creates a response
* <code>WebServiceMessage</code> as soon as any method is called, thus lazily creating the response.
*/
private class ResponseCreatingEventWriter implements XMLEventWriter {
private XMLEventWriter eventWriter;
private MessageContext messageContext;
private ByteArrayOutputStream os;
public ResponseCreatingEventWriter(MessageContext messageContext) {
this.messageContext = messageContext;
}
public NamespaceContext getNamespaceContext() {
return eventWriter.getNamespaceContext();
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
createEventWriter();
eventWriter.setNamespaceContext(context);
}
public void add(XMLEventReader reader) throws XMLStreamException {
createEventWriter();
while (reader.hasNext()) {
add(reader.nextEvent());
}
}
public void add(XMLEvent event) throws XMLStreamException {
createEventWriter();
eventWriter.add(event);
if (event.isEndDocument()) {
if (os != null) {
eventWriter.flush();
// if we used an output stream cache, we have to transform it to the response again
try {
Transformer transformer = createTransformer();
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
transformer.transform(new StreamSource(is), messageContext.getResponse().getPayloadResult());
}
catch (TransformerException ex) {
throw new XMLStreamException(ex);
}
}
}
}
public void close() throws XMLStreamException {
if (eventWriter != null) {
eventWriter.close();
}
}
public void flush() throws XMLStreamException {
if (eventWriter != null) {
eventWriter.flush();
}
}
public String getPrefix(String uri) throws XMLStreamException {
createEventWriter();
return eventWriter.getPrefix(uri);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
createEventWriter();
eventWriter.setDefaultNamespace(uri);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
createEventWriter();
eventWriter.setPrefix(prefix, uri);
}
private void createEventWriter() throws XMLStreamException {
if (eventWriter == null) {
WebServiceMessage response = messageContext.getResponse();
eventWriter = getEventWriter(response.getPayloadResult());
if (eventWriter == null) {
// as a final resort, use a stream, and transform that at endDocument()
os = new ByteArrayOutputStream();
eventWriter = getOutputFactory().createXMLEventWriter(os);
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
/**
* Abstract base class for endpoints use StAX. Provides an <code>XMLInputFactory</code> and an
* <code>XMLOutputFactory</code>.
*
* @author Arjen Poutsma
* @see XMLInputFactory
* @see XMLOutputFactory
*/
public abstract class AbstractStaxPayloadEndpoint extends TransformerObjectSupport {
private XMLInputFactory inputFactory;
private XMLOutputFactory outputFactory;
/**
* Returns an <code>XMLInputFactory</code> to read XML from.
*/
protected final XMLInputFactory getInputFactory() {
if (inputFactory == null) {
inputFactory = createXmlInputFactory();
}
return inputFactory;
}
/**
* Returns an <code>XMLOutputFactory</code> to write XML to.
*/
protected final XMLOutputFactory getOutputFactory() {
if (outputFactory == null) {
outputFactory = createXmlOutputFactory();
}
return outputFactory;
}
/**
* Create a <code>XMLInputFactory</code> that this endpoint will use to create <code>XMLStreamReader</code>s or
* <code>XMLEventReader</code>. Can be overridden in subclasses, adding further initialization of the factory. The
* resulting <code>XMLInputFactory</code> is cached, so this method will only be called once.
*
* @return the created <code>XMLInputFactory</code>
*/
protected XMLInputFactory createXmlInputFactory() {
return XMLInputFactory.newInstance();
}
/**
* Create a <code>XMLOutputFactory</code> that this endpoint will use to create <code>XMLStreamWriters</code>s or
* <code>XMLEventWriters</code>. Can be overridden in subclasses, adding further initialization of the factory. The
* resulting <code>XMLOutputFactory</code> is cached, so this method will only be called once.
*
* @return the created <code>XMLOutputFactory</code>
*/
protected XMLOutputFactory createXmlOutputFactory() {
return XMLOutputFactory.newInstance();
}
}

View File

@@ -0,0 +1,321 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.stream.XmlEventStreamReader;
import org.springframework.xml.transform.StaxResult;
import org.springframework.xml.transform.StaxSource;
/**
* Abstract base class for endpoints that handle the message payload with streaming StAX. Allows subclasses to read the
* request with a <code>XMLStreamReader</code>, and to create a response using a <code>XMLStreamWriter</code>.
*
* @author Arjen Poutsma
* @see #invokeInternal(javax.xml.stream.XMLStreamReader, javax.xml.stream.XMLStreamWriter)
* @see XMLStreamReader
* @see XMLStreamWriter
*/
public abstract class AbstractStaxStreamPayloadEndpoint extends AbstractStaxPayloadEndpoint implements MessageEndpoint {
public final void invoke(MessageContext messageContext) throws Exception {
XMLStreamReader streamReader = getStreamReader(messageContext.getRequest().getPayloadSource());
XMLStreamWriter streamWriter = new ResponseCreatingStreamWriter(messageContext);
invokeInternal(streamReader, streamWriter);
streamWriter.close();
}
private XMLStreamReader getStreamReader(Source source) throws XMLStreamException, TransformerException {
XMLStreamReader streamReader = null;
if (source instanceof StaxSource) {
streamReader = ((StaxSource) source).getXMLStreamReader();
StaxSource staxSource = (StaxSource) source;
streamReader = staxSource.getXMLStreamReader();
if (streamReader == null && staxSource.getXMLEventReader() != null) {
try {
streamReader = new XmlEventStreamReader(staxSource.getXMLEventReader());
}
catch (XMLStreamException ex) {
// ignore
}
}
}
if (streamReader == null) {
try {
streamReader = getInputFactory().createXMLStreamReader(source);
}
catch (XMLStreamException ex) {
// ignore
}
}
if (streamReader == null) {
// as a final resort, transform the source to a stream, and read from that
Transformer transformer = createTransformer();
ByteArrayOutputStream os = new ByteArrayOutputStream();
transformer.transform(source, new StreamResult(os));
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
streamReader = getInputFactory().createXMLStreamReader(is);
}
return streamReader;
}
private XMLStreamWriter getStreamWriter(Result result) {
XMLStreamWriter streamWriter = null;
if (result instanceof StaxResult) {
StaxResult staxResult = (StaxResult) result;
streamWriter = staxResult.getXMLStreamWriter();
}
if (streamWriter == null) {
try {
streamWriter = getOutputFactory().createXMLStreamWriter(result);
}
catch (XMLStreamException ex) {
// ignore
}
}
return streamWriter;
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a <code>XMLStreamReader</code>,
* and a <code>XMLStreamWriter</code> to write the response payload to.
*
* @param streamReader the reader to read the payload from
* @param streamWriter the writer to write the payload to
*/
protected abstract void invokeInternal(XMLStreamReader streamReader, XMLStreamWriter streamWriter) throws Exception;
/**
* Implementation of the <code>XMLStreamWriter</code> interface that creates a response
* <code>WebServiceMessage</code> as soon as any method is called, thus lazily creating the response.
*/
private class ResponseCreatingStreamWriter implements XMLStreamWriter {
private MessageContext messageContext;
private XMLStreamWriter streamWriter;
private ByteArrayOutputStream os;
private ResponseCreatingStreamWriter(MessageContext messageContext) {
this.messageContext = messageContext;
}
public NamespaceContext getNamespaceContext() {
return streamWriter.getNamespaceContext();
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
createStreamWriter();
streamWriter.setNamespaceContext(context);
}
public void close() throws XMLStreamException {
if (streamWriter != null) {
streamWriter.close();
if (os != null) {
streamWriter.flush();
// if we used an output stream cache, we have to transform it to the response again
try {
Transformer transformer = createTransformer();
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
transformer.transform(new StreamSource(is), messageContext.getResponse().getPayloadResult());
os = null;
}
catch (TransformerException ex) {
throw new XMLStreamException(ex);
}
}
streamWriter = null;
}
}
public void flush() throws XMLStreamException {
if (streamWriter != null) {
streamWriter.flush();
}
}
public String getPrefix(String uri) throws XMLStreamException {
createStreamWriter();
return streamWriter.getPrefix(uri);
}
public Object getProperty(String name) throws IllegalArgumentException {
return streamWriter.getProperty(name);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
createStreamWriter();
streamWriter.setDefaultNamespace(uri);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
createStreamWriter();
streamWriter.setPrefix(prefix, uri);
}
public void writeAttribute(String localName, String value) throws XMLStreamException {
createStreamWriter();
streamWriter.writeAttribute(localName, value);
}
public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
createStreamWriter();
streamWriter.writeAttribute(namespaceURI, localName, value);
}
public void writeAttribute(String prefix, String namespaceURI, String localName, String value)
throws XMLStreamException {
createStreamWriter();
streamWriter.writeAttribute(prefix, namespaceURI, localName, value);
}
public void writeCData(String data) throws XMLStreamException {
createStreamWriter();
streamWriter.writeCData(data);
}
public void writeCharacters(String text) throws XMLStreamException {
createStreamWriter();
streamWriter.writeCharacters(text);
}
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
createStreamWriter();
streamWriter.writeCharacters(text, start, len);
}
public void writeComment(String data) throws XMLStreamException {
createStreamWriter();
streamWriter.writeComment(data);
}
public void writeDTD(String dtd) throws XMLStreamException {
createStreamWriter();
streamWriter.writeDTD(dtd);
}
public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
createStreamWriter();
streamWriter.writeDefaultNamespace(namespaceURI);
}
public void writeEmptyElement(String localName) throws XMLStreamException {
createStreamWriter();
streamWriter.writeEmptyElement(localName);
}
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
createStreamWriter();
streamWriter.writeEmptyElement(namespaceURI, localName);
}
public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
createStreamWriter();
streamWriter.writeEmptyElement(prefix, localName, namespaceURI);
}
public void writeEndDocument() throws XMLStreamException {
createStreamWriter();
streamWriter.writeEndDocument();
}
public void writeEndElement() throws XMLStreamException {
createStreamWriter();
streamWriter.writeEndElement();
}
public void writeEntityRef(String name) throws XMLStreamException {
createStreamWriter();
streamWriter.writeEntityRef(name);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
createStreamWriter();
streamWriter.writeNamespace(prefix, namespaceURI);
}
public void writeProcessingInstruction(String target) throws XMLStreamException {
createStreamWriter();
streamWriter.writeProcessingInstruction(target);
}
public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
createStreamWriter();
streamWriter.writeProcessingInstruction(target, data);
}
public void writeStartDocument() throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartDocument();
}
public void writeStartDocument(String version) throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartDocument(version);
}
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartDocument(encoding, version);
}
public void writeStartElement(String localName) throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
createStreamWriter();
streamWriter.writeStartElement(prefix, localName, namespaceURI);
}
private void createStreamWriter() throws XMLStreamException {
if (streamWriter == null) {
WebServiceMessage response = messageContext.getResponse();
streamWriter = getStreamWriter(response.getPayloadResult());
if (streamWriter == null) {
// as a final resort, use a stream, and transform that at endDocument()
os = new ByteArrayOutputStream();
streamWriter = getOutputFactory().createXMLStreamWriter(os);
}
}
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import java.io.IOException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.ParsingException;
import nu.xom.converters.DOMConverter;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.springframework.xml.transform.StringSource;
/**
* Abstract base class for endpoints that handle the message payload as XOM elements. Offers the message payload as a
* XOM <code>Element</code>, and allows subclasses to create a response by returning an <code>Element</code>.
* <p/>
* An <code>AbstractXomPayloadEndpoint</code> only accept one payload element. Multiple payload elements are not in
* accordance with WS-I.
*
* @author Arjen Poutsma
* @see Element
*/
public abstract class AbstractXomPayloadEndpoint implements PayloadEndpoint {
public final Source invoke(Source request) throws Exception {
Element requestElement = null;
if (request instanceof DOMSource) {
requestElement = handleDomSource(request);
}
else if (request instanceof SAXSource) {
requestElement = handleSaxSource(request);
}
else if (request instanceof StreamSource) {
requestElement = handleStreamSource(request);
}
else {
throw new IllegalArgumentException(
"Source [" + request.getClass().getName() + "] is neither SAXSource, DOMSource, nor StreamSource");
}
Element responseElement = invokeInternal(requestElement);
return responseElement != null ? new StringSource(responseElement.toXML()) : null;
}
private Element handleStreamSource(Source request) throws ParsingException, IOException {
StreamSource streamSource = (StreamSource) request;
Builder builder = new Builder();
Document document = null;
if (streamSource.getInputStream() != null) {
document = builder.build(streamSource.getInputStream());
}
else if (streamSource.getReader() != null) {
document = builder.build(streamSource.getReader());
}
else {
throw new IllegalArgumentException("StreamSource contains neither byte stream nor character stream");
}
return document.getRootElement();
}
private Element handleSaxSource(Source request) throws ParsingException, IOException {
SAXSource saxSource = (SAXSource) request;
Builder builder = new Builder(saxSource.getXMLReader());
InputSource inputSource = saxSource.getInputSource();
Document document = null;
if (inputSource.getByteStream() != null) {
document = builder.build(inputSource.getByteStream());
}
else if (inputSource.getCharacterStream() != null) {
document = builder.build(inputSource.getCharacterStream());
}
else {
throw new IllegalArgumentException(
"InputSource in SAXSource contains neither byte stream nor " + "character stream");
}
return document.getRootElement();
}
private Element handleDomSource(Source request) {
Node w3cNode = ((DOMSource) request).getNode();
org.w3c.dom.Element w3cElement = null;
if (w3cNode.getNodeType() == Node.ELEMENT_NODE) {
w3cElement = (org.w3c.dom.Element) w3cNode;
}
else if (w3cNode.getNodeType() == Node.DOCUMENT_NODE) {
org.w3c.dom.Document w3cDocument = (org.w3c.dom.Document) w3cNode;
w3cElement = w3cDocument.getDocumentElement();
}
return DOMConverter.convert(w3cElement);
}
/**
* Template method. Subclasses must implement this. Offers the request payload as a XOM <code>Element</code>, and
* allows subclasses to return a response <code>Element</code>.
*
* @param requestElement the contents of the SOAP message as XOM element
* @return the response element. Can be <code>null</code> to specify no response.
*/
protected abstract Element invokeInternal(Element requestElement) throws Exception;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import org.springframework.ws.context.MessageContext;
/**
* Defines the basic contract for Web Services interested in the entire mesage payload.
* <p/>
* The main entrypoint is <code>invoke</code>, which gets invoked with the a message context. This context contains the
* request, and can be used to create a response.
*
* @author Arjen Poutsma
* @see #invoke(org.springframework.ws.context.MessageContext)
*/
public interface MessageEndpoint {
/**
* Invokes an operation. The given message context can be used to create a response.
*
* @param messageContext the message context
* @throws Exception if an exception occurs
*/
void invoke(MessageContext messageContext) throws Exception;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import org.springframework.ws.EndpointAdapter;
import org.springframework.ws.context.MessageContext;
/**
* Adapter to use a <code>MessageEndpoint</code> as the endpoint for a <code>EndpointInvocationChain</code>.
*
* @author Arjen Poutsma
* @see org.springframework.ws.EndpointInvocationChain
*/
public class MessageEndpointAdapter implements EndpointAdapter {
public boolean supports(Object endpoint) {
return endpoint instanceof MessageEndpoint;
}
public void invoke(MessageContext messageContext, Object endpoint) throws Exception {
((MessageEndpoint) endpoint).invoke(messageContext);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
/**
* Defines the basic contract for Web Services interested in the mesage payload.
* <p/>
* The main entrypoint is <code>invoke</code>, which gets invoked with the contents of the requesting message.
*
* @author Arjen Poutsma
* @see #invoke(javax.xml.transform.Source)
*/
public interface PayloadEndpoint {
/**
* Invokes an operation.
*
* @param request the request message
* @return the response message, may be <code>null</code>
* @throws Exception if an exception occurs
*/
Source invoke(Source request) throws Exception;
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import org.springframework.ws.EndpointAdapter;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
/**
* Adapter to use a <code>PayloadEndpoint</code> as the endpoint for a <code>EndpointInvocationChain</code>.
*
* @author Arjen Poutsma
* @see PayloadEndpoint
* @see org.springframework.ws.EndpointInvocationChain
*/
public class PayloadEndpointAdapter extends TransformerObjectSupport implements EndpointAdapter {
public boolean supports(Object endpoint) {
return endpoint instanceof PayloadEndpoint;
}
public void invoke(MessageContext messageContext, Object endpoint) throws Exception {
PayloadEndpoint payloadEndpoint = (PayloadEndpoint) endpoint;
Source requestSource = messageContext.getRequest().getPayloadSource();
Source responseSource = payloadEndpoint.invoke(requestSource);
if (responseSource != null) {
WebServiceMessage response = messageContext.getResponse();
Transformer transformer = createTransformer();
transformer.transform(responseSource, response.getPayloadResult());
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Convenient base class for objects that use a <code>Transformer</code>. Subclasses can call
* <code>createTransformer</code> to obtain a transformer. This should be done per incoming request, because
* <code>Transformer</code> instances are not thread-safe.
*
* @author Arjen Poutsma
* @see Transformer
* @see #createTransformer()
*/
public abstract class TransformerObjectSupport {
/**
* Logger available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private static TransformerFactory transformerFactory;
/**
* Creates a new <code>Transformer</code>. Must be called per request, as transformer is not thread-safe.
*
* @return the created transformer
* @throws TransformerConfigurationException
* if thrown by JAXP methods
*/
protected final Transformer createTransformer() throws TransformerConfigurationException {
if (transformerFactory == null) {
transformerFactory = createTransformerFactory();
}
return transformerFactory.newTransformer();
}
/**
* Create a <code>TransformerFactory</code> that this endpoint will use to create <code>Transformer</code>s. Can be
* overridden in subclasses, adding further initialization of the factory. The resulting
* <code>TransformerFactory</code> is cached, so this method will only be called once.
*
* @return the created <code>TransformerFactory</code>
* @throws TransformerFactoryConfigurationError
* if thrown by JAXP methods
*/
protected TransformerFactory createTransformerFactory() throws TransformerFactoryConfigurationError {
return TransformerFactory.newInstance();
}
}

View File

@@ -0,0 +1,327 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.interceptor;
import java.io.IOException;
import java.util.Locale;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.endpoint.TransformerObjectSupport;
import org.springframework.ws.soap.SoapBody;
import org.springframework.ws.soap.SoapFault;
import org.springframework.ws.soap.SoapFaultDetail;
import org.springframework.ws.soap.SoapFaultDetailElement;
import org.springframework.ws.soap.context.SoapMessageContext;
import org.springframework.xml.namespace.QNameUtils;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* Abstract base class for <code>EndpointInterceptor</code> implementations that validate part of the message using a
* schema. The exact message part is determined by the <code>getValidationRequestSource</code> and
* <code>getValidationResponseSource</code> template methods.
* <p/>
* By default, only the request message is validated, but this behaviour can be changed using the
* <code>validateRequest</code> and <code>validateResponse</code> properties. Responses that contains SOAP faults are
* not validated.
*
* @author Arjen Poutsma
* @see #getValidationRequestSource(org.springframework.ws.WebServiceMessage)
* @see #getValidationResponseSource(org.springframework.ws.WebServiceMessage)
*/
public abstract class AbstractValidatingInterceptor extends TransformerObjectSupport
implements EndpointInterceptor, InitializingBean {
/**
* Default SOAP Fault Detail name used when a validation errors occur on the request.
*
* @see #setDetailElementName(javax.xml.namespace.QName)
*/
public static final QName DEFAULT_DETAIL_ELEMENT_NAME =
QNameUtils.createQName("http://springframework.org/spring-ws", "ValidationError", "spring-ws");
/**
* Default SOAP Fault string used when a validation errors occur on the request.
*
* @see #setFaultStringOrReason(String)
*/
public static final String DEFAULT_FAULTSTRING_OR_REASON = "Validation error";
protected final Log logger = LogFactory.getLog(getClass());
private boolean addValidationErrorDetail = true;
private QName detailElementName = DEFAULT_DETAIL_ELEMENT_NAME;
private String faultStringOrReason = DEFAULT_FAULTSTRING_OR_REASON;
private Locale faultStringOrReasonLocale = Locale.ENGLISH;
private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML;
private Resource[] schemas;
private boolean validateRequest = true;
private boolean validateResponse = false;
private XmlValidator validator;
public boolean getAddValidationErrorDetail() {
return addValidationErrorDetail;
}
/**
* Indicates whether a SOAP Fault detail element should be created when a validation error occurs. This detail
* element will contain the exact validation errors. It is only added when the underlying message is a
* <code>SoapMessage</code>. Defaults to <code>true</code>.
*
* @see org.springframework.ws.soap.SoapFault#addFaultDetail()
*/
public void setAddValidationErrorDetail(boolean addValidationErrorDetail) {
this.addValidationErrorDetail = addValidationErrorDetail;
}
/**
* Returns the fault detail element name when validation errors occur on the request.
*/
public QName getDetailElementName() {
return detailElementName;
}
/**
* Sets the fault detail element name when validation errors occur on the request. Defaults to
* <code>DEFAULT_DETAIL_ELEMENT_NAME</code>.
*
* @see #DEFAULT_DETAIL_ELEMENT_NAME
*/
public void setDetailElementName(QName detailElementName) {
this.detailElementName = detailElementName;
}
/**
* Sets the SOAP <code>faultstring</code> or <code>Reason</code> used when validation errors occur on the request.
*/
public String getFaultStringOrReason() {
return faultStringOrReason;
}
/**
* Sets the SOAP <code>faultstring</code> or <code>Reason</code> used when validation errors occur on the request.
* It is only added when the underlying message is a <code>SoapMessage</code>. Defaults to
* <code>DEFAULT_FAULTSTRING_OR_REASON</code>.
*
* @see #DEFAULT_FAULTSTRING_OR_REASON
*/
public void setFaultStringOrReason(String faultStringOrReason) {
this.faultStringOrReason = faultStringOrReason;
}
/**
* Returns the SOAP fault reason locale used when validation errors occur on the request.
*/
public Locale getFaultStringOrReasonLocale() {
return faultStringOrReasonLocale;
}
/**
* Sets the SOAP fault reason locale used when validation errors occur on the request. It is only added when the
* underlying message is a <code>SoapMessage</code>. Defaults to English.
*
* @see java.util.Locale#ENGLISH
*/
public void setFaultStringOrReasonLocale(Locale faultStringOrReasonLocale) {
this.faultStringOrReasonLocale = faultStringOrReasonLocale;
}
public String getSchemaLanguage() {
return schemaLanguage;
}
/**
* Sets the schema language. Default is the W3C XML Schema: <code>http://www.w3.org/2001/XMLSchema"</code>.
*
* @see org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML
* @see org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_RELAX_NG
*/
public void setSchemaLanguage(String schemaLanguage) {
this.schemaLanguage = schemaLanguage;
}
/**
* Returns the schema resources to use for validation.
*/
public Resource[] getSchemas() {
return schemas;
}
/**
* Sets the schema resources to use for validation. Setting either this property or <code>schema</code> is
* required.
*/
public void setSchemas(Resource[] schemas) {
Assert.notEmpty(schemas, "schemas must not be empty or null");
for (int i = 0; i < schemas.length; i++) {
Assert.notNull(schemas[i], "schema must not be null");
Assert.isTrue(schemas[i].exists(), "schema \"" + schemas[i] + "\" does not exit");
}
this.schemas = schemas;
}
/**
* Sets the schema resource to use for validation. Setting either this property or <code>schemas</code> is
* required.
*/
public void setSchema(Resource schema) {
setSchemas(new Resource[]{schema});
}
/**
* Indicates whether the request should be validated against the schema. Default is <code>true</code>.
*/
public void setValidateRequest(boolean validateRequest) {
this.validateRequest = validateRequest;
}
/**
* Indicates whether the response should be validated against the schema. Default is <code>false</code>.
*/
public void setValidateResponse(boolean validateResponse) {
this.validateResponse = validateResponse;
}
/**
* Validates the request message in the given message context. Validation only occurs if
* <code>validateRequest</code> is set to <code>true</code>, which is the default.
* <p/>
* Returns <code>true</code> if the request is valid, or <code>false</code> if it isn't. Additionally, when the
* <code>messageContext</code> is a <code>SoapMessageContext</code>, a SOAP Fault is added as response.
*
* @param messageContext the message context
* @return <code>true</code> if the message is valid; <code>false</code> otherwise
* @see #setValidateRequest(boolean)
*/
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws IOException, SAXException, TransformerException {
if (validateRequest) {
Source requestSource = getValidationRequestSource(messageContext.getRequest());
if (requestSource != null) {
SAXParseException[] errors = validator.validate(requestSource);
if (!ObjectUtils.isEmpty(errors)) {
for (int i = 0; i < errors.length; i++) {
logger.warn("XML validation error on request: " + errors[i].getMessage());
}
if (messageContext instanceof SoapMessageContext) {
createRequestValidationFault((SoapMessageContext) messageContext, errors);
}
return false;
}
else if (logger.isDebugEnabled()) {
logger.debug("Request message validated");
}
}
}
return true;
}
/**
* Validates the response message in the given message context. Validation only occurs if
* <code>validateResponse</code> is set to <code>true</code>, which is <strong>not</strong> the default.
* <p/>
* Returns <code>true</code> if the request is valid, or <code>false</code> if it isn't.
*
* @param messageContext the message context.
* @return <code>true</code> if the response is valid; <code>false</code> otherwise
* @see #setValidateResponse(boolean)
*/
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws IOException, SAXException {
if (validateResponse) {
Source responseSource = getValidationResponseSource(messageContext.getResponse());
if (responseSource != null) {
SAXParseException[] errors = validator.validate(responseSource);
if (!ObjectUtils.isEmpty(errors)) {
for (int i = 0; i < errors.length; i++) {
logger.error("XML validation error on response: " + errors[i].getMessage());
}
return false;
}
else if (logger.isDebugEnabled()) {
logger.debug("Response message validated");
}
}
}
return true;
}
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(schemas, "setting either the schema or schemas property is required");
Assert.hasLength(schemaLanguage, "schemaLanguage is required");
for (int i = 0; i < schemas.length; i++) {
Assert.isTrue(schemas[i].exists(), "schema [" + schemas + "] does not exist");
}
if (logger.isInfoEnabled()) {
logger.info("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas));
}
validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage);
}
/**
* Creates a response soap message containing a <code>SoapFault</code> that descibes the validation errors.
*/
protected void createRequestValidationFault(SoapMessageContext context, SAXParseException[] errors)
throws TransformerException {
SoapBody body = context.getSoapResponse().getSoapBody();
SoapFault fault = body.addClientOrSenderFault(getFaultStringOrReason(), getFaultStringOrReasonLocale());
if (getAddValidationErrorDetail()) {
SoapFaultDetail detail = fault.addFaultDetail();
for (int i = 0; i < errors.length; i++) {
SoapFaultDetailElement detailElement = detail.addFaultDetailElement(getDetailElementName());
detailElement.addText(errors[i].getMessage());
}
}
}
/**
* Abstract template method that returns the part of the request message that is to be validated.
*
* @param request the request message
* @return the part of the message that is to validated, or <code>null</code> not to validate anything
*/
protected abstract Source getValidationRequestSource(WebServiceMessage request);
/**
* Abstract template method that returns the part of the response message that is to be validated.
*
* @param response the response message
* @return the part of the message that is to validated, or <code>null</code> not to validate anything
*/
protected abstract Source getValidationResponseSource(WebServiceMessage response);
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.interceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.context.MessageContext;
import org.w3c.dom.Element;
/**
* Default implementation of the <code>EndpointInterceptor</code> interface, for simplified implementation of
* pre-only/post-only interceptors.
*
* @author Arjen Poutsma
*/
public class EndpointInterceptorAdapter implements EndpointInterceptor {
/**
* Logger available to subclasses
*/
protected final Log logger = LogFactory.getLog(getClass());
/**
* Returns <code>false</code>.
*/
public boolean understands(Element header) {
return false;
}
/**
* Returns <code>true</code>.
*
* @return <code>true</code>
*/
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
return true;
}
/**
* Returns <code>true</code>.
*
* @return <code>true</code>
*/
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
return true;
}
/**
* Returns <code>true</code>.
*
* @return <code>true</code>
*/
public boolean handleFault(MessageContext messageContext, Object endpoint) {
return true;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.interceptor;
import javax.xml.transform.Source;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.endpoint.AbstractLoggingInterceptor;
/**
* Simple <code>EndpointInterceptor</code> that logs the payload of request and response messages. By default, both
* request and response messages are logged, but this behaviour can be changed using the <code>logRequest</code> and
* <code>logResponse</code> properties.
*
* @author Arjen Poutsma
* @see #setLogRequest(boolean)
* @see #setLogResponse(boolean)
*/
public class PayloadLoggingInterceptor extends AbstractLoggingInterceptor {
protected Source getSource(WebServiceMessage message) {
return message.getPayloadSource();
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.interceptor;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.sax.SaxUtils;
/**
* Interceptor that transforms the payload of <code>WebServiceMessage</code>s using XSLT stylesheet. Allows for seperate
* stylesheets for request and response. This interceptor is especially useful when supporting with multiple version of
* a Web service: you can transform the older message format to the new format.
* <p/>
* The stylesheets to use can be set using the <code>requestXslt</code> and <code>responseXslt</code> properties. Both
* of these are optional: if not set, the message is simply not transformed. Setting one of the two is required,
* though.
*
* @author Arjen Poutsma
* @see #setRequestXslt(org.springframework.core.io.Resource)
* @see #setResponseXslt(org.springframework.core.io.Resource)
*/
public class PayloadTransformingInterceptor implements EndpointInterceptor, InitializingBean {
private static final Log logger = LogFactory.getLog(PayloadTransformingInterceptor.class);
private Resource requestXslt;
private Resource responseXslt;
private Templates requestTemplates;
private Templates responseTemplates;
/**
* Sets the XSLT stylesheet to use for transforming incoming request.
*/
public void setRequestXslt(Resource requestXslt) {
this.requestXslt = requestXslt;
}
/**
* Sets the XSLT stylesheet to use for transforming outgoing responses.
*/
public void setResponseXslt(Resource responseXslt) {
this.responseXslt = responseXslt;
}
/**
* Transforms the request message in the given message context using a provided stylesheet. Transformation only
* occurs if the <code>requestXslt</code> has been set.
*
* @param messageContext the message context
* @return always returns <code>true</code>
* @see #setRequestXslt(org.springframework.core.io.Resource)
*/
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
if (requestTemplates != null) {
WebServiceMessage request = messageContext.getRequest();
Transformer transformer = requestTemplates.newTransformer();
transformer.transform(request.getPayloadSource(), request.getPayloadResult());
logger.debug("Request message transformed");
}
return true;
}
/**
* Transforms the response message in the given message context using a stylesheet. Transformation only occurs if
* the <code>responseXslt</code> has been set.
*
* @param messageContext the message context
* @return always returns <code>true</code>
* @see #setResponseXslt(org.springframework.core.io.Resource)
*/
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
if (responseTemplates != null) {
WebServiceMessage response = messageContext.getResponse();
Transformer transformer = responseTemplates.newTransformer();
transformer.transform(response.getPayloadSource(), response.getPayloadResult());
logger.debug("Response message transformed");
}
return true;
}
public void afterPropertiesSet() throws Exception {
if (requestXslt == null && responseXslt == null) {
throw new IllegalArgumentException("Setting either 'requestXslt' or 'responseXslt' is required");
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
if (requestXslt != null) {
Assert.isTrue(requestXslt.exists(), "requestXslt \"" + requestXslt + "\" does not exit");
if (logger.isInfoEnabled()) {
logger.info("Transforming request using " + requestXslt);
}
SAXSource requestSource = new SAXSource(SaxUtils.createInputSource(requestXslt));
requestTemplates = transformerFactory.newTemplates(requestSource);
}
if (responseXslt != null) {
Assert.isTrue(responseXslt.exists(), "responseXslt \"" + responseXslt + "\" does not exit");
if (logger.isInfoEnabled()) {
logger.info("Transforming response using " + responseXslt);
}
SAXSource responseSource = new SAXSource(SaxUtils.createInputSource(responseXslt));
responseTemplates = transformerFactory.newTemplates(responseSource);
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.interceptor;
import javax.xml.transform.Source;
import org.springframework.ws.WebServiceMessage;
/**
* Interceptor that validates the contents of <code>WebServiceMessage</code>s using a schema. Allows for both W3C XML
* and RELAX NG schemas.
* <p/>
* When the payload is invalid, this interceptor stops processing of the interceptor chain. Additionally, if the message
* is a SOAP request message, a SOAP Fault is created as reply. Invalid SOAP responses do not result in a fault.
* <p/>
* The schema to validate against is set with the <code>schema</code> property. By default, only the request message is
* validated, but this behaviour can be changed using the <code>validateRequest</code> and <code>validateResponse</code>
* properties. Responses that contains faults are not validated.
*
* @author Arjen Poutsma
* @see #setSchema
* @see #setValidateRequest(boolean)
* @see #setValidateResponse(boolean)
*/
public class PayloadValidatingInterceptor extends AbstractValidatingInterceptor {
/**
* Returns the payload source of the given message.
*/
protected Source getValidationRequestSource(WebServiceMessage request) {
return request.getPayloadSource();
}
/**
* Returns the payload source of the given message.
*/
protected Source getValidationResponseSource(WebServiceMessage response) {
return response.getPayloadSource();
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Provides miscellaneous endpoints <code>EndpointInterceptor</code> implementations.
</body>
</html>

View File

@@ -0,0 +1,147 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.mapping;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.EndpointInvocationChain;
import org.springframework.ws.EndpointMapping;
import org.springframework.ws.context.MessageContext;
/**
* Abstract base class for EndpointMapping implementations. Supports a default endpoint, and endpoint interceptors.
*
* @author Arjen Poutsma
* @see #getEndpointInternal(org.springframework.ws.context.MessageContext)
* @see org.springframework.ws.EndpointInterceptor
*/
public abstract class AbstractEndpointMapping extends ApplicationObjectSupport implements EndpointMapping {
private Object defaultEndpoint;
private EndpointInterceptor[] interceptors;
/**
* Returns the default endpoint for this endpoint mapping.
*
* @return the default endpoint mapping, or null if none
*/
protected final Object getDefaultEndpoint() {
return defaultEndpoint;
}
/**
* Sets the default endpoint for this endpoint mapping. This endpoint will be returned if no specific mapping was
* found.
* <p/>
* Default is <code>null</code>, indicating no default endpoint.
*
* @param defaultEndpoint the default endpoint, or null if none
*/
public final void setDefaultEndpoint(Object defaultEndpoint) {
this.defaultEndpoint = defaultEndpoint;
logger.info("Default mapping to endpoint [" + this.defaultEndpoint + "]");
}
/**
* Returns the the endpoint interceptors to apply to all endpoints mapped by this endpoint mapping.
*
* @return array of endpoint interceptors, or <code>null</code> if none
*/
public EndpointInterceptor[] getInterceptors() {
return interceptors;
}
/**
* Sets the endpoint interceptors to apply to all endpoints mapped by this endpoint mapping.
*
* @param interceptors array of endpoint interceptors, or <code>null</code> if none
*/
public final void setInterceptors(EndpointInterceptor[] interceptors) {
this.interceptors = interceptors;
}
/**
* Look up an endpoint for the given message context, falling back to the default endpoint if no specific one is
* found.
*
* @return the looked up endpoint instance, or the default endpoint
* @see #getEndpointInternal(org.springframework.ws.context.MessageContext)
*/
public final EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
Object endpoint = getEndpointInternal(messageContext);
if (endpoint == null) {
endpoint = defaultEndpoint;
}
if (endpoint == null) {
return null;
}
if (endpoint instanceof String) {
String endpointName = (String) endpoint;
endpoint = resolveStringEndpoint(endpointName);
if (endpoint == null) {
return null;
}
}
return createEndpointInvocationChain(messageContext, endpoint, interceptors);
}
/**
* Creates a new <code>EndpointInvocationChain</code> based on the given message context, endpoint, and
* interceptors. Default implementation creates a simple <code>EndpointInvocationChain</code> based on the set
* interceptors.
*
* @param endpoint the endpoint
* @param interceptors the endpoint interceptors
* @return the created invocation chain
* @see #setInterceptors(org.springframework.ws.EndpointInterceptor[])
*/
protected EndpointInvocationChain createEndpointInvocationChain(MessageContext messageContext,
Object endpoint,
EndpointInterceptor[] interceptors) {
return new EndpointInvocationChain(endpoint, interceptors);
}
/**
* Resolves an endpoint string. If the given string can is a bean name, it is resolved using the application
* context.
*
* @param endpointName the endpoint name
* @return the resolved enpoint, or <code>null</code> if the name could not be resolved
*/
protected Object resolveStringEndpoint(String endpointName) {
if (getApplicationContext().containsBean(endpointName)) {
return getApplicationContext().getBean(endpointName);
}
else {
return null;
}
}
/**
* Lookup an endpoint for the given request, returning <code>null</code> if no specific one is found. This template
* method is called by getEndpoint, a <code>null</code> return value will lead to the default handler, if one is
* set.
* <p/>
* The returned endpoint can be a string, in which case it is resolved as a bean name. Also, it can take the form
* <code>beanName#method</code>, in which case the method is resolved.
*
* @return the looked up endpoint instance, or null
* @throws Exception if there is an error
*/
protected abstract Object getEndpointInternal(MessageContext messageContext) throws Exception;
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.mapping;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContextException;
import org.springframework.util.StringUtils;
import org.springframework.ws.context.MessageContext;
/**
* Abstract base class for endpoint mapping that are based on a <code>Map</code>. Provides mappings of application
* context beans as well as a settable map.
* <p/>
* Subclasses determine the exact nature of the key in the enpoint map; this can be a qualified name, a SOAP Header, the
* result of a XPath validation. The values are always endpoint objects, or bean names of endpoint objects.
*
* @author Arjen Poutsma
*/
public abstract class AbstractMapBasedEndpointMapping extends AbstractEndpointMapping {
private boolean lazyInitEndpoints = false;
private boolean registerBeanNames = false;
private final Map endpointMap = new HashMap();
// holds mappings set via setEndpointMap and setMappings
private Map temporaryEndpointMap = new HashMap();
/**
* Set whether to lazily initialize endpoints. Only applicable to singleton endpoints, as prototypes are always
* lazily initialized. Default is <code>false</code>, as eager initialization allows for more efficiency through
* referencing the controller objects directly.
* <p/>
* If you want to allow your endpoints to be lazily initialized, make them "lazy-init" and set this flag to
* <code>true</code>. Just making them "lazy-init" will not work, as they are initialized through the references
* from the endpoint mapping in this case.
*/
public void setLazyInitEndpoints(boolean lazyInitEndpoints) {
this.lazyInitEndpoints = lazyInitEndpoints;
}
/**
* Set whether to register bean names found in the application context. Setting this to <code>true</code> will
* register all beans found in the application context under their name. Default is <code>false</code>.
*/
public final void setRegisterBeanNames(boolean registerBeanNames) {
this.registerBeanNames = registerBeanNames;
}
/**
* Sets a Map with keys and endpoint beans as values. The nature of the keys in the given map depends on the exact
* subclass used. They can be qualified names, for instance, or mime headers.
*
* @throws IllegalArgumentException if the endpoint is invalid
*/
public final void setEndpointMap(Map endpointMap) {
temporaryEndpointMap.putAll(endpointMap);
}
/**
* Maps keys to endpoint bean names. The nature of the property names depends on the exact subclass used. They can
* be qualified names, for instance, or mime headers.
*/
public void setMappings(Properties mappings) {
temporaryEndpointMap.putAll(mappings);
}
/**
* Validates the given endpoint key. Should return <code>true</code> is the given string is valid.
*/
protected abstract boolean validateLookupKey(String key);
/**
* Returns the the endpoint keys for the given message context.
*
* @return the registration keys
*/
protected abstract String getLookupKeyForMessage(MessageContext messageContext) throws Exception;
/**
* Lookup an endpoint for the given message. The extraction of the endpoint key is delegated to the concrete
* subclass.
*
* @return the looked up endpoint, or <code>null</code>
*/
protected Object getEndpointInternal(MessageContext messageContext) throws Exception {
String key = getLookupKeyForMessage(messageContext);
if (!StringUtils.hasLength(key)) {
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("Looking up endpoint for [" + key + "]");
}
return lookupEndpoint(key);
}
/**
* Looks up an endpoint instance for the given keys. All keys are tried in order.
*
* @param key key the beans are mapped to
* @return the associated endpoint instance, or <code>null</code> if not found
*/
protected Object lookupEndpoint(String key) {
return endpointMap.get(key);
}
/**
* Register the given endpoint instance under the registration key.
*
* @param key the string representation of the registration key
* @param endpoint the endpoint instance
* @throws org.springframework.beans.BeansException
* if the endpoint could not be registered
*/
protected void registerEndpoint(String key, Object endpoint) throws BeansException {
Object mappedEndpoint = endpointMap.get(key);
if (mappedEndpoint != null) {
throw new ApplicationContextException("Cannot map endpoint [" + endpoint + "] on registration key [" + key +
"]: there's already endpoint [" + mappedEndpoint + "] mapped");
}
if (!lazyInitEndpoints && endpoint instanceof String) {
String endpointName = (String) endpoint;
endpoint = resolveStringEndpoint(endpointName);
}
if (endpoint == null) {
throw new ApplicationContextException("Could not find endpoint for key [" + key + "]");
}
endpointMap.put(key, endpoint);
if (logger.isDebugEnabled()) {
logger.debug("Mapped key [" + key + "] onto endpoint [" + endpoint + "]");
}
}
/**
* Registers annd checks the set endpoints. Checks the beans set through <code>setEndpointMap</code> and
* <code>setMappings</code>, and registers the bean names found in the application context, if
* <code>registerBeanNames</code> is set to <code>true</code>.
*
* @throws ApplicationContextException if either of the endpoints defined via <code>setEndpointMap</code> or
* <code>setMappings</code> is invalid
* @see #setEndpointMap(java.util.Map)
* @see #setMappings(java.util.Properties)
* @see #setRegisterBeanNames(boolean)
*/
protected final void initApplicationContext() throws BeansException {
for (Iterator iter = temporaryEndpointMap.keySet().iterator(); iter.hasNext();) {
String key = (String) iter.next();
Object endpoint = temporaryEndpointMap.get(key);
if (!validateLookupKey(key)) {
throw new ApplicationContextException("Invalid key [" + key + "] for endpoint [" + endpoint + "]");
}
registerEndpoint(key, endpoint);
}
temporaryEndpointMap = null;
if (registerBeanNames) {
if (logger.isDebugEnabled()) {
logger.debug("Looking for endpoint mappings in application context: [" + getApplicationContext() + "]");
}
String[] beanNames = getApplicationContext().getBeanDefinitionNames();
for (int i = 0; i < beanNames.length; i++) {
if (validateLookupKey(beanNames[i])) {
registerEndpoint(beanNames[i], beanNames[i]);
}
String[] aliases = getApplicationContext().getAliases(beanNames[i]);
for (int j = 0; j < aliases.length; j++) {
if (validateLookupKey(aliases[j])) {
registerEndpoint(aliases[j], beanNames[i]);
}
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.mapping;
import javax.xml.namespace.QName;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.namespace.QNameUtils;
/**
* Abstract base class for <code>EndpointMapping</code>s that resolve qualified names as registration keys.
*
* @author Arjen Poutsma
*/
public abstract class AbstractQNameEndpointMapping extends AbstractMapBasedEndpointMapping {
protected final String getLookupKeyForMessage(MessageContext messageContext) throws Exception {
QName qName = resolveQName(messageContext);
return qName != null ? qName.toString() : null;
}
/**
* Template method that resolves the qualified names from the given SOAP message.
*
* @return an array of qualified names that serve as registration keys
*/
protected abstract QName resolveQName(MessageContext messageContext) throws Exception;
protected boolean validateLookupKey(String key) {
return QNameUtils.validateQName(key);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.endpoint.mapping;
import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.MessageContext;
import org.springframework.xml.namespace.QNameUtils;
import org.w3c.dom.Element;
/**
* Implementation of the <code>EndpointMapping</code> interface to map from the qualified name of the request payload
* root element. Supports both mapping to bean instances and mapping to bean names: the latter is required for prototype
* handlers.
* <p/>
* The <code>endpointMap</code> property is suitable for populating the endpoint map with bean references, e.g. via the
* map element in XML bean definitions.
* <p/>
* Mappings to bean names can be set via the <code>mappings</code> property, in a form accepted by the
* <code>java.util.Properties</code> class, like as follows:
* <pre>
* {http://www.springframework.org/spring-ws/samples/airline/schemas}BookFlight=bookFlightEndpoint
* {http://www.springframework.org/spring-ws/samples/airline/schemas}GetFlights=getFlightsEndpoint
* </pre>
* The syntax is QNAME=ENDPOINT_BEAN_NAME. Qualified names are parsed using the syntax described in
* <code>QNameEditor</code>.
*
* @author Arjen Poutsma
* @see org.springframework.xml.namespace.QNameEditor
*/
public class PayloadRootQNameEndpointMapping extends AbstractQNameEndpointMapping implements InitializingBean {
private static TransformerFactory transformerFactory;
protected QName resolveQName(MessageContext messageContext) throws TransformerException {
Element payloadElement = getMessagePayloadElement(messageContext.getRequest());
return QNameUtils.getQNameForNode(payloadElement);
}
private Element getMessagePayloadElement(WebServiceMessage message) throws TransformerException {
Transformer transformer = transformerFactory.newTransformer();
DOMResult domResult = new DOMResult();
transformer.transform(message.getPayloadSource(), domResult);
return (Element) domResult.getNode().getFirstChild();
}
public final void afterPropertiesSet() throws Exception {
transformerFactory = TransformerFactory.newInstance();
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Provides miscellaneous endpoints <code>EndpointMapping</code> implementations.
</body>
</html>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Provides standard endpoint, and <code>EndpointAdapter</code> implementations.
</body>
</html>

View File

@@ -0,0 +1,5 @@
<html>
<body>
Provides the core functionality of the Spring Web Services framework.
</body>
</html>

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox;
import org.springframework.ws.WebServiceMessage;
/**
* Defines the contract for Plain Old XML messages. Currently only a tagging interface.
*
* @author Arjen Poutsma
*/
public interface PoxMessage extends WebServiceMessage {
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox;
import org.springframework.ws.WebServiceMessageException;
/**
* Specific subclass of <code>WebServiceMessageException</code> for Plain Old XML messages.
*
* @author Arjen Poutsma
*/
public abstract class PoxMessageException extends WebServiceMessageException {
public PoxMessageException(String msg) {
super(msg);
}
public PoxMessageException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.context;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.context.AbstractMessageContext;
import org.springframework.ws.pox.PoxMessage;
import org.springframework.ws.transport.TransportRequest;
/**
* Abstract implementation of the <code>PoxMessageContext</code> interface. Implements base <code>MessageContext</code>
* methods by delegating to <code>PoxMessageContext</code> functionality.
*
* @author Arjen Poutsma
*/
public abstract class AbstractPoxMessageContext extends AbstractMessageContext implements PoxMessageContext {
protected AbstractPoxMessageContext(PoxMessage request, TransportRequest transportRequest) {
super(request, transportRequest);
}
public final PoxMessage getPoxResponse() {
return (PoxMessage) getResponse();
}
public final PoxMessage getPoxRequest() {
return (PoxMessage) getRequest();
}
protected final WebServiceMessage createResponseMessage() {
return createResponsePoxMessage();
}
protected abstract PoxMessage createResponsePoxMessage();
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.context;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.pox.PoxMessage;
/**
* Plain Old Xml-specific extension of the <code>MessageContext</code> interface. Contains methods to obtain
* <code>PoxMessage</code>s instead of <code>WebServiceMessage</code>s.
*
* @author Arjen Poutsma
*/
public interface PoxMessageContext extends MessageContext {
/**
* Returns the request POX message.
*
* @return the request message
*/
PoxMessage getPoxRequest();
/**
* Returns the response message, if created. Returns <code>null</code> if no response message was created so far.
*
* @return the response message, or <code>null</code> if none was created
* @see #hasResponse()
*/
PoxMessage getPoxResponse();
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains the <code>PoxMessageContext</code> interface.
</body>
</html>

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.dom;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.springframework.ws.pox.PoxMessage;
import org.w3c.dom.Document;
/**
* Implementation of the <code>PoxMessage</code> interface that is based on a DOM Document.
*
* @author Arjen Poutsma
* @see Document
*/
public class DomPoxMessage implements PoxMessage {
private final Document document;
private Transformer transformer;
/**
* Constructs a new instance of the <code>DomPoxMessage</code> with the given document.
*
* @param document the document to base the message on
*/
public DomPoxMessage(Document document, Transformer transformer) {
this.document = document;
this.transformer = transformer;
}
/**
* Returns the document underlying this message.
*/
public Document getDocument() {
return document;
}
public Result getPayloadResult() {
return new DOMResult(document);
}
public Source getPayloadSource() {
return new DOMSource(document);
}
public void writeTo(OutputStream outputStream) throws IOException {
try {
transformer.transform(getPayloadSource(), new StreamResult(outputStream));
}
catch (TransformerException ex) {
throw new DomPoxMessageException("Could not create transformer", ex);
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.dom;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.Transformer;
import org.springframework.util.Assert;
import org.springframework.ws.pox.PoxMessage;
import org.springframework.ws.pox.context.AbstractPoxMessageContext;
import org.springframework.ws.transport.TransportRequest;
import org.springframework.ws.transport.TransportResponse;
import org.w3c.dom.Document;
/**
* Implementation of the <code>MessageContext</code> that contains a <code>DomPoxMessage</code>.
*
* @author Arjen Poutsma
* @see DomPoxMessage
*/
public class DomPoxMessageContext extends AbstractPoxMessageContext {
private DocumentBuilder documentBuilder;
private Transformer transformer;
/**
* Creates a new <code>DomPoxMessageContext</code> with the given parameters.
*/
public DomPoxMessageContext(Document request,
TransportRequest transportRequest,
DocumentBuilder documentBuilder,
Transformer transformer) {
super(new DomPoxMessage(request, transformer), transportRequest);
Assert.notNull(documentBuilder, "documentBuilder must not be null");
Assert.notNull(transformer, "transformer must not be null");
this.documentBuilder = documentBuilder;
this.transformer = transformer;
}
protected PoxMessage createResponsePoxMessage() {
Document document = documentBuilder.newDocument();
return new DomPoxMessage(document, transformer);
}
public void sendResponse(TransportResponse transportResponse) throws IOException {
if (hasResponse()) {
transportResponse.addHeader("Content-Type", "text/xml");
getResponse().writeTo(transportResponse.getOutputStream());
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.dom;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.context.MessageContextFactory;
import org.springframework.ws.transport.TransportContext;
import org.springframework.ws.transport.TransportRequest;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
/**
* Implementation of the <code>MessageContextFactory</code> interface that creates a DOM
*
* @author Arjen Poutsma
* @see DomPoxMessageContext
*/
public class DomPoxMessageContextFactory implements MessageContextFactory, InitializingBean {
private DocumentBuilderFactory documentBuilderFactory;
private boolean namespaceAware = true;
private TransformerFactory transformerFactory;
private boolean validating = false;
/**
* Set whether or not the XML parser should be XML namespace aware. Default is <code>true</code>.
*/
public void setNamespaceAware(boolean namespaceAware) {
this.namespaceAware = namespaceAware;
}
/**
* Set if the XML parser should validate the document. Default is <code>false</code>.
*/
public void setValidating(boolean validating) {
this.validating = validating;
}
public void afterPropertiesSet() throws Exception {
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setValidating(validating);
documentBuilderFactory.setNamespaceAware(namespaceAware);
transformerFactory = TransformerFactory.newInstance();
}
public MessageContext createContext(TransportContext transportContext) throws IOException {
TransportRequest transportRequest = transportContext.getTransportRequest();
try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document request = documentBuilder.parse(transportRequest.getInputStream());
return new DomPoxMessageContext(request,
transportRequest,
documentBuilder,
transformerFactory.newTransformer());
}
catch (ParserConfigurationException ex) {
throw new DomPoxMessageException("Could not create message context", ex);
}
catch (SAXException ex) {
throw new DomPoxMessageException("Could not parse request message", ex);
}
catch (TransformerConfigurationException ex) {
throw new DomPoxMessageException("Could not create transormer", ex);
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.pox.dom;
import org.springframework.ws.pox.PoxMessageException;
/**
* Specific subclass of <code>PoxMessageException</code> for DOM Plain Old XML messages.
*
* @author Arjen Poutsma
*/
public class DomPoxMessageException extends PoxMessageException {
public DomPoxMessageException(String msg) {
super(msg);
}
public DomPoxMessageException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
Contains an implementation of the POX interfaces that is based on DOM.
</body>
</html>

View File

@@ -0,0 +1,6 @@
<html>
<body>
Provides the Plain Old XML (POX) functionality of the Spring Web Services framework. Contains the PoxMessage and related
interfaces.
</body>
</html>

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
/**
* Abstract implementation of the <code>SoapMessage</code> interface.
*
* @author Arjen Poutsma
*/
public abstract class AbstractSoapMessage implements SoapMessage {
private SoapVersion version;
/**
* Returns <code>getEnvelope().getBody()</code>.
*/
public SoapBody getSoapBody() {
return getEnvelope().getBody();
}
/**
* Returns <code>getEnvelope().getHeader()</code>.
*/
public SoapHeader getSoapHeader() {
return getEnvelope().getHeader();
}
/**
* Returns <code>getSoapBody().getPayloadSource()</code>.
*/
public Source getPayloadSource() {
return getSoapBody().getPayloadSource();
}
/**
* Returns <code>getSoapBody().getPayloadResult()</code>.
*/
public Result getPayloadResult() {
return getSoapBody().getPayloadResult();
}
public SoapVersion getVersion() {
if (version == null) {
String envelopeNamespace = getEnvelope().getName().getNamespaceURI();
if (SoapVersion.SOAP_11.getEnvelopeNamespaceUri().equals(envelopeNamespace)) {
version = SoapVersion.SOAP_11;
}
else if (SoapVersion.SOAP_12.getEnvelopeNamespaceUri().equals(envelopeNamespace)) {
version = SoapVersion.SOAP_12;
}
else {
throw new IllegalStateException(
"Unknown Envelope namespace uri '" + envelopeNamespace + "'. " + "Cannot deduce SoapVersion.");
}
}
return version;
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import java.io.IOException;
import java.io.InputStream;
/**
* Represents an attachment to a <code>SoapMessage</code>.
*
* @author Arjen Poutsma
* @see SoapMessage#getAttachments()
* @see SoapMessage#addAttachment(java.io.File)
* @see SoapMessage#addAttachment(org.springframework.core.io.InputStreamSource, String)
*/
public interface Attachment {
/**
* Returns the identifier of the attachment. Depending on the implementation used, this may be a MIME
* <code>Content-Id</code> header, a DIME ID, etc.
*
* @return the attachment identifier, or <code>null</code> if empty or not defined
*/
String getId();
/**
* Sets the identifier of the attachment. Depending on the implementation used, this may be a MIME
* <code>Content-Id</code> header, a DIME ID, etc.
*
* @param id the new attachment identifier, or <code>null</code> if empty or not defined
*/
void setId(String id);
/**
* Returns the content type of the attachment.
*
* @return the content type, or <code>null</code> if empty or not defined
*/
String getContentType();
/**
* Return an <code>InputStream</code> to read the contents of the attachment from. The user is responsible for
* closing the stream.
*
* @return the contents of the file as stream, or an empty stream if empty
* @throws IOException in case of access I/O errors
*/
InputStream getInputStream() throws IOException;
/**
* Returns the size of the attachment in bytes.
*
* @return the size of the attachment, or <code>0</code> if empty
*/
long getSize();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Exception thrown when a SOAP attachment could not be accessed.
*
* @author Arjen Poutsma
* @see Attachment
*/
public class AttachmentException extends SoapMessageException {
public AttachmentException(String msg) {
super(msg);
}
public AttachmentException(String msg, Throwable ex) {
super(msg, ex);
}
public AttachmentException(Throwable ex) {
super("Could not access body: " + ex.getMessage(), ex);
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import java.util.Locale;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
/**
* Represents the <code>Body</code> element in a SOAP message. A SOAP body contains the <strong>payload</strong> of the
* message. This payload can be custom XML, or a <code>SoapFault</code> (but not both).
* <p/>
* Note that the source returned by <code>getSource()</code> includes the SOAP Body element itself. For the contents of
* the body, use <code>getPayloadSource()</code>.
*
* @author Arjen Poutsma
* @see SoapEnvelope#getBody()
* @see #getPayloadSource()
* @see #getPayloadResult()
* @see SoapFault
*/
public interface SoapBody extends SoapElement {
/**
* Returns a <code>Source</code> that represents the contents of the body.
*
* @return the message contents
*/
Source getPayloadSource();
/**
* Returns a <code>Result</code> that represents the contents of the body.
*
* @return the messaage contents
*/
Result getPayloadResult();
/**
* Adds a <code>MustUnderstand</code> fault to the body. A <code>MustUnderstand</code> is returned when a SOAP
* header with a <code>MustUnderstand</code> attribute is not understood.
* <p/>
* Adding a fault removes the current content of the body.
*
* @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text
* @param locale the language of faultStringOrReason. Optional for SOAP 1.1
* @return the created <code>SoapFault</code>
*/
SoapFault addMustUnderstandFault(String faultStringOrReason, Locale locale) throws SoapFaultException;
/**
* Adds a <code>Client</code>/<code>Sender</code> fault to the body. For SOAP 1.1, this adds a fault with a
* <code>Client</code> fault code. For SOAP 1.2, this adds a fault with a <code>Sender</code> code.
* <p/>
* Adding a fault removes the current content of the body.
*
* @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text
* @param locale the language of faultStringOrReason. Optional for SOAP 1.1
* @return the created <code>SoapFault</code>
*/
SoapFault addClientOrSenderFault(String faultStringOrReason, Locale locale) throws SoapFaultException;
/**
* Adds a <code>Server</code>/<code>Receiver</code> fault to the body.For SOAP 1.1, this adds a fault with a
* <code>Server</code> fault code. For SOAP 1.2, this adds a fault with a <code>Receiver</code> code.
* <p/>
* Adding a fault removes the current content of the body.
*
* @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text
* @param locale the language of faultStringOrReason. Optional for SOAP 1.1
* @return the created <code>SoapFault</code>
*/
SoapFault addServerOrReceiverFault(String faultStringOrReason, Locale locale) throws SoapFaultException;
/**
* Adds a <code>VersionMismatch</code> fault to the body.
* <p/>
* Adding a fault removes the current content of the body.
*
* @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text
* @param locale the language of faultStringOrReason. Optional for SOAP 1.1
* @return the created <code>SoapFault</code>
*/
SoapFault addVersionMismatchFault(String faultStringOrReason, Locale locale) throws SoapFaultException;
/**
* Indicates whether this body has a <code>SoapFault</code>.
*
* @return <code>true</code> if the body has a fault; <code>false</code> otherwise
*/
boolean hasFault();
/**
* Returns the <code>SoapFault</code> of this body.
*
* @return the <code>SoapFault</code>, or <code>null</code> if none is present
*/
SoapFault getFault();
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Exception thrown when a SOAP body could not be accessed.
*
* @author Arjen Poutsma
*/
public class SoapBodyException extends SoapMessageException {
public SoapBodyException(String msg) {
super(msg);
}
public SoapBodyException(String msg, Throwable ex) {
super(msg, ex);
}
public SoapBodyException(Throwable ex) {
super("Could not access body: " + ex.getMessage(), ex);
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
/**
* The base interface for all elements that are contained in a SOAP message.
*
* @author Arjen Poutsma
* @see SoapMessage
*/
public interface SoapElement {
/**
* Returns the qualified name of this element.
*
* @return the qualified name of this element
*/
QName getName();
/**
* Returns the <code>Source</code> of this element. This includes the element itself, i.e.
* <code>SoapEnvelope.getSource()</code> will include the <code>Envelope</code> tag.
*
* @return the <code>Source</code> of this element
*/
Source getSource();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.context.MessageContext;
/**
* SOAP-specific extension of the <code>EndpointInterceptor</code> interface. Allows for handling of SOAP faults, which
* are considered different from regular responses.
*
* @author Arjen Poutsma
*/
public interface SoapEndpointInterceptor extends EndpointInterceptor {
/**
* Processes the fault. Both request and response of the message context should be filled; the body of the response
* message contains the fault.
*
* @param messageContext contains both request and response messages, the response should contains a SOAP Fault
* @param endpoint chosen endpoint to invoke
* @return <code>true</code> to continue processing of the reponse interceptor chain; <code>false</code> to indicate
* blocking of the response handler chain.
*/
boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception;
/**
* Given a <code>SoapHeaderElement</code>, return whether or not this <code>SoapEndpointInterceptor</code>
* understands it.
*
* @param header the header
* @return <code>true</code> if understood, <code>false</code> otherwise
*/
boolean understands(SoapHeaderElement header);
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import org.springframework.ws.EndpointInterceptor;
import org.springframework.ws.EndpointInvocationChain;
/**
* SOAP-specific subclass of the <code>EndpointInvocationChain</code>. Adds associated actors (SOAP 1.1) or roles (SOAP
* 1.2). Used by the <code>SoapMessageDispatcher</code> to determine the MustUnderstand headers for particular
* endpoint.
*
* @author Arjen Poutsma
* @see #getActorsOrRoles()
* @see SoapMessageDispatcher
*/
public class SoapEndpointInvocationChain extends EndpointInvocationChain {
private String[] actorsOrRoles;
/**
* Create new <code>SoapEndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
*/
public SoapEndpointInvocationChain(Object endpoint) {
super(endpoint);
}
/**
* Create new <code>SoapEndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
* @param interceptors the array of interceptors to apply
*/
public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors) {
super(endpoint, interceptors);
}
/**
* Create new <code>EndpointInvocationChain</code>.
*
* @param endpoint the endpoint object to invoke
* @param interceptors the array of interceptors to apply
* @param actorsOrRoles the array of actorsOrRoles to set
*/
public SoapEndpointInvocationChain(Object endpoint, EndpointInterceptor[] interceptors, String[] actorsOrRoles) {
super(endpoint, interceptors);
this.actorsOrRoles = actorsOrRoles;
}
/**
* Gets the actors (SOAP 1.1) or roles (SOAP 1.2) associated with an invocation of this chain and its contained
* interceptors and endpoint.
*
* @return a string array of URIs for SOAP actors/roles
*/
public String[] getActorsOrRoles() {
return actorsOrRoles;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import org.springframework.ws.EndpointMapping;
/**
* SOAP-specific sub-interface of the <code>EndpointMapping</code>. Adds associated actors (SOAP 1.1) or roles (SOAP
* 1.2). Used by the <code>SoapMessageDispatcher</code> to determine the MustUnderstand headers for particular
* endpoint.
* <p/>
* The main purpose for this interface is to add consitency between all SOAP-specific <code>EndpointMappings</code>. The
* <code>SoapMessageDispatcher</code> does not require all endpoint mappings to implement this interface.
*
* @author Arjen Poutsma
*/
public interface SoapEndpointMapping extends EndpointMapping {
/**
* Sets a single SOAP actor/actorOrRole to apply to all endpoints mapped by the delegate endpoint mapping.
*/
void setActorOrRole(String actorOrRole);
/**
* Sets the array of SOAP actors/actorsOrRoles to apply to all endpoints mapped by the delegate endpoint mapping.
*/
void setActorsOrRoles(String[] actorsOrRoles);
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Represents the <code>Envelope</code> element in a SOAP message. The header contains the optional
* <code>SoapHeader</code> and <code>SoapBody</code>.
*
* @author Arjen Poutsma
*/
public interface SoapEnvelope extends SoapElement {
/**
* Returns the <code>SoapHeader</code>. Returns <code>null</code> if no header is present.
*
* @return the <code>SoapHeader</code>, or <code>null</code>
* @throws SoapHeaderException if the header cannot be returned
*/
SoapHeader getHeader() throws SoapHeaderException;
/**
* Returns the <code>SoapBody</code>.
*
* @return the <code>SoapBody</code>
* @throws SoapBodyException if the header cannot be returned
*/
SoapBody getBody() throws SoapBodyException;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Exception thrown when a SOAP body could not be accessed.
*
* @author Arjen Poutsma
*/
public class SoapEnvelopeException extends SoapMessageException {
public SoapEnvelopeException(String msg) {
super(msg);
}
public SoapEnvelopeException(String msg, Throwable ex) {
super(msg, ex);
}
public SoapEnvelopeException(Throwable ex) {
super("Could not access envelope: " + ex.getMessage(), ex);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import javax.xml.namespace.QName;
/**
* Represents the <code>Fault</code> element in the body of a SOAP message. A faul consists of a fault code, string, and
* role.
*
* @author Arjen Poutsma
*/
public interface SoapFault extends SoapElement {
/**
* Returns the fault code.
*
* @return a <code>QName</code> representing the fault code
*/
QName getFaultCode();
/**
* Returns the fault actor or role. For SOAP 1.1, this returns the actor. For SOAP 1.2, this returns the role.
*/
String getFaultActorOrRole();
/**
* Sets the fault actor. For SOAP 1.1, this sets the actor. For SOAP 1.2, this sets the role.
*/
void setFaultActorOrRole(String faultActor);
/**
* Creates an optional <code>SoapFaultDetail</code> object and assigns it to this fault.
*
* @return the created detail
*/
SoapFaultDetail getFaultDetail();
/**
* Returns the optional detail element for this <code>SoapFault</code>.
*
* @return a fault detail
*/
SoapFaultDetail addFaultDetail();
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import java.util.Iterator;
import javax.xml.namespace.QName;
/**
* Represents the <code>detail</code> element in a SOAP fault. A detail contains <code>SoapFaultDetailElement</code>s,
* which represent the individual details.
*
* @author Arjen Poutsma
* @see SoapFaultDetailElement
*/
public interface SoapFaultDetail extends SoapElement {
/**
* Adds a new <code>SoapFaultDetailElement</code> with the specified qualified name to this detail.
*
* @param name the qualified name of the new detail element
* @return the created <code>SoapFaultDetailElement</code>
*/
SoapFaultDetailElement addFaultDetailElement(QName name);
/**
* Gets an iterator over all of the <code>SoapFaultDetailElement</code>s in this detail.
*
* @return an iterator over all the <code>SoapFaultDetailElement</code>s
* @see SoapFaultDetailElement
*/
Iterator getDetailEntries();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import javax.xml.transform.Result;
/**
* Represents the content for an individual SOAP detail entry in a SOAP Message. All
* <code>SoapFaultDetailElement</code>s are contained in a <code>SoapDetail</code>.
*
* @author Arjen Poutsma
* @see SoapFaultDetail
*/
public interface SoapFaultDetailElement extends SoapElement {
/**
* Returns a <code>Result</code> that allows for writing to the <strong>contents</strong> of the detail element.
*/
Result getResult();
/**
* Adds a new text node to this element.
*/
void addText(String text);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Exception thrown when a SOAP fault could not be accessed.
*
* @author Arjen Poutsma
*/
public class SoapFaultException extends SoapEnvelopeException {
public SoapFaultException(String msg) {
super(msg);
}
public SoapFaultException(String msg, Throwable ex) {
super(msg, ex);
}
public SoapFaultException(Throwable ex) {
super("Could not access fault: " + ex.getMessage(), ex);
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import java.util.Iterator;
import javax.xml.namespace.QName;
/**
* Represents the <code>Header</code> element in a SOAP message. A SOAP header contains <code>SoapHeaderElement</code>s,
* which represent the individual headers.
*
* @author Arjen Poutsma
* @see SoapHeaderElement
* @see SoapEnvelope#getHeader()
*/
public interface SoapHeader extends SoapElement {
/**
* Adds a new <code>SoapHeaderElement</code> with the specified qualified name to this header.
*
* @param name the qualified name of the new header element
* @return the created <code>SoapHeaderElement</code>
* @throws SoapHeaderException if the header cannot be created
*/
SoapHeaderElement addHeaderElement(QName name) throws SoapHeaderException;
/**
* Returns an <code>Iterator</code> over all the <code>SoapHeaderElement</code>s that have the specified actor or
* role and that have a <code>MustUnderstand</code> attribute whose value is equivalent to <code>true</code>.
*
* @param actorOrRole the actor (SOAP 1.1) or role (SOAP 1.2) for which to search
* @return an iterator over all the header elements that contain the specified actor/role and are marked as
* <code>MustUnderstand</code>
* @throws SoapHeaderException if the headers cannot be returned
* @see SoapHeaderElement
*/
Iterator examineMustUnderstandHeaderElements(String actorOrRole) throws SoapHeaderException;
/**
* Returns an <code>Iterator</code> over all the <code>SoapHeaderElement</code>s in this header.
*
* @return an iterator over all the header elements
* @throws SoapHeaderException if the header cannot be returned
* @see SoapHeaderElement
*/
Iterator examineAllHeaderElements() throws SoapHeaderException;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import javax.xml.transform.Result;
/**
* Represents the contents of an individual SOAP header in the a SOAP message. All <code>SoapHeaderElement</code>s are
* contained in a <code>SoapHeader</code>.
*
* @author Arjen Poutsma
* @see SoapHeader
*/
public interface SoapHeaderElement extends SoapElement {
/**
* Returns the actor or role for this header element. In a SOAP 1.1 compliant message, this will read the
* <code>actor</code> attribute; in SOAP 1.2, the <code>role</code> attribute.
*
* @return the role of the header
*/
String getActorOrRole() throws SoapHeaderException;
/**
* Sets the actor or role for this header element. In a SOAP 1.1 compliant message, this will result in an
* <code>actor</code> attribute being set; in SOAP 1.2, a <code>actorOrRole</code> attribute.
*
* @param actorOrRole the actorOrRole value
*/
void setActorOrRole(String actorOrRole) throws SoapHeaderException;
/**
* Indicates whether the <code>mustUnderstand</code> attribute for this header element is set.
*
* @return <code>true</code> if the <code>mustUnderstand</code> attribute is set; <code>false</code> otherwise
*/
boolean getMustUnderstand() throws SoapHeaderException;
/**
* Sets the <code>mustUnderstand</code> attribute for this header element. If the attribute is on, the role who
* receives the header must process it.
*
* @param mustUnderstand <code>true</code> to set the <code>mustUnderstand</code> attribute on; <code>false</code>
* to turn it off
*/
void setMustUnderstand(boolean mustUnderstand) throws SoapHeaderException;
/**
* Returns a <code>Result</code> that allows for writing to the <strong>contents</strong> of the header element.
*/
Result getResult() throws SoapHeaderException;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
/**
* Exception thrown when a SOAP header could not be accessed.
*
* @author Arjen Poutsma
*/
public class SoapHeaderException extends SoapMessageException {
public SoapHeaderException(String msg) {
super(msg);
}
public SoapHeaderException(String msg, Throwable ex) {
super(msg, ex);
}
public SoapHeaderException(Throwable ex) {
super("Could not access header: " + ex.getMessage(), ex);
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.soap;
import java.io.File;
import java.util.Iterator;
import org.springframework.core.io.InputStreamSource;
import org.springframework.ws.WebServiceMessage;
/**
* Represents an abstraction for SOAP messages, providing access to a SOAP Envelope. The contents of the SOAP body can
* be retrieved by <code>getPayloadSource()</code> and <code>getPayloadResult()</code> on
* <code>WebServiceMessage</code>, the super-interface of this interface.
*
* @author Arjen Poutsma
* @see #getPayloadSource()
* @see #getPayloadResult()
* @see #getEnvelope()
*/
public interface SoapMessage extends WebServiceMessage {
/**
* Returns the <code>SoapEnvelope</code> associated with this <code>SoapMessage</code>.
*/
SoapEnvelope getEnvelope() throws SoapEnvelopeException;
/**
* Returns the <code>SoapBody</code> associated with this <code>SoapMessage</code>. This is a convenience method for
* <code>getEnvelope().getBody()</code>.
*
* @see SoapEnvelope#getBody()
*/
SoapBody getSoapBody() throws SoapBodyException;
/**
* Returns the <code>SoapHeader</code> associated with this <code>SoapMessage</code>. This is a convenience method
* for <code>getEnvelope().getHeader()</code>.
*
* @see SoapEnvelope#getHeader()
*/
SoapHeader getSoapHeader() throws SoapHeaderException;
/**
* Returns the SOAP version of this message. This can be either SOAP 1.1 or SOAP 1.2.
*
* @return the SOAP version
* @see SoapVersion#SOAP_11
* @see SoapVersion#SOAP_12
*/
SoapVersion getVersion();
/**
* Returns the <code>Attachment</code> with the specified content Id.
*
* @return the attachment with the specified content id; or <code>null</code> if it cannot be found
* @throws AttachmentException in case of errors
*/
Attachment getAttachment(String contentId) throws AttachmentException;
/**
* Returns an <code>Iterator</code> over all <code>Attachment</code>s that are part of this
* <code>SoapMessage</code>.
*
* @return an iterator over all attachments
* @throws AttachmentException in case of errors
* @see Attachment
*/
Iterator getAttachments() throws AttachmentException;
/**
* Add an attachment to the <code>SoapMessage</code>, taking the content from a <code>java.io.File</code>.
* <p/>
* The content type will be determined by the name of the given content file. Do not use this for temporary files
* with arbitrary filenames (possibly ending in ".tmp" or the like)!
*
* @param file the File resource to take the content from
* @return the added attachment
* @throws AttachmentException in case of errors
* @see #addAttachment(InputStreamSource, String)
*/
Attachment addAttachment(File file) throws AttachmentException;
/**
* Add an attachment to the <code>SoapMessage</code>, taking the content from an
* <code>org.springframework.core.io.InputStreamResource</code>.
* <p/>
* Note that the <code>InputStream</code> returned by the source needs to be a <em>fresh one on each call</em>, as
* underlying implementations can invoke <code>getInputStream()</code> multiple times.
*
* @param inputStreamSource the resource to take the content from (all of Spring's Resource implementations can be
* passed in here)
* @param contentType the content type to use for the element
* @return the added attachment
* @throws AttachmentException in case of errors
* @see #addAttachment(java.io.File)
* @see org.springframework.core.io.Resource
*/
Attachment addAttachment(InputStreamSource inputStreamSource, String contentType);
}

Some files were not shown because too many files have changed in this diff Show More