1   /*
2    * Copyright ${YEAR} the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.soap.server.endpoint;
18  
19  import java.io.IOException;
20  import java.util.Iterator;
21  import javax.xml.namespace.QName;
22  import javax.xml.soap.Detail;
23  import javax.xml.soap.DetailEntry;
24  import javax.xml.soap.MessageFactory;
25  import javax.xml.soap.SOAPFault;
26  import javax.xml.soap.SOAPMessage;
27  import javax.xml.transform.Result;
28  import javax.xml.transform.Source;
29  
30  import junit.framework.TestCase;
31  import org.springframework.context.support.ResourceBundleMessageSource;
32  import org.springframework.oxm.Marshaller;
33  import org.springframework.oxm.Unmarshaller;
34  import org.springframework.oxm.XmlMappingException;
35  import org.springframework.validation.Errors;
36  import org.springframework.validation.ValidationUtils;
37  import org.springframework.validation.Validator;
38  import org.springframework.ws.context.DefaultMessageContext;
39  import org.springframework.ws.context.MessageContext;
40  import org.springframework.ws.soap.saaj.SaajSoapMessage;
41  import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
42  
43  public class FaultCreatingValidatingMarshallingPayloadEndpointTest extends TestCase {
44  
45      private MessageContext messageContext;
46  
47      private ResourceBundleMessageSource messageSource;
48  
49      protected void setUp() throws Exception {
50          this.messageSource = new ResourceBundleMessageSource();
51          this.messageSource.setBasename("org.springframework.ws.soap.server.endpoint.messages");
52          MessageFactory messageFactory = MessageFactory.newInstance();
53          SOAPMessage request = messageFactory.createMessage();
54          request.getSOAPBody().addBodyElement(new QName("http://www.springframework.org/spring-ws", "request"));
55          messageContext =
56                  new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
57      }
58  
59      public void testValidationIncorrect() throws Exception {
60          Person p = new Person("", -1);
61          PersonMarshaller marshaller = new PersonMarshaller(p);
62  
63          AbstractFaultCreatingValidatingMarshallingPayloadEndpoint endpoint =
64                  new AbstractFaultCreatingValidatingMarshallingPayloadEndpoint() {
65  
66                      protected Object invokeInternal(Object requestObject) throws Exception {
67                          fail("No expected");
68                          return null;
69                      }
70                  };
71          endpoint.setValidator(new PersonValidator());
72          endpoint.setMessageSource(messageSource);
73          endpoint.setMarshaller(marshaller);
74          endpoint.setUnmarshaller(marshaller);
75  
76          endpoint.invoke(messageContext);
77  
78          SOAPMessage response = ((SaajSoapMessage) messageContext.getResponse()).getSaajMessage();
79          assertTrue("Response has no fault", response.getSOAPBody().hasFault());
80          SOAPFault fault = response.getSOAPBody().getFault();
81          assertEquals("Invalid fault code", new QName("http://schemas.xmlsoap.org/soap/envelope/", "Client"),
82                  fault.getFaultCodeAsQName());
83          assertEquals("Invalid fault string", endpoint.getFaultStringOrReason(), fault.getFaultString());
84          Detail detail = fault.getDetail();
85          assertNotNull("No detail", detail);
86          Iterator iterator = detail.getDetailEntries();
87          assertTrue("No detail entry", iterator.hasNext());
88          DetailEntry detailEntry = (DetailEntry) iterator.next();
89          assertEquals("Invalid detail entry name", new QName("http://springframework.org/spring-ws", "ValidationError"),
90                  detailEntry.getElementQName());
91          assertEquals("Invalid detail entry text", "Name is required", detailEntry.getTextContent());
92          assertTrue("No detail entry", iterator.hasNext());
93          detailEntry = (DetailEntry) iterator.next();
94          assertEquals("Invalid detail entry name", new QName("http://springframework.org/spring-ws", "ValidationError"),
95                  detailEntry.getElementQName());
96          assertEquals("Invalid detail entry text", "Age Cannot be negative", detailEntry.getTextContent());
97          assertFalse("Too many detail entries", iterator.hasNext());
98      }
99  
100     public void testValidationCorrect() throws Exception {
101         Person p = new Person("John", 42);
102         PersonMarshaller marshaller = new PersonMarshaller(p);
103         AbstractFaultCreatingValidatingMarshallingPayloadEndpoint endpoint =
104                 new AbstractFaultCreatingValidatingMarshallingPayloadEndpoint() {
105 
106                     protected Object invokeInternal(Object requestObject) throws Exception {
107                         return null;
108                     }
109                 };
110         endpoint.setValidator(new PersonValidator());
111         endpoint.setMessageSource(messageSource);
112         endpoint.setMarshaller(marshaller);
113         endpoint.setUnmarshaller(marshaller);
114 
115         endpoint.invoke(messageContext);
116 
117         SOAPMessage response = ((SaajSoapMessage) messageContext.getResponse()).getSaajMessage();
118         assertFalse("Response has fault", response.getSOAPBody().hasFault());
119     }
120 
121     private static class PersonValidator implements Validator {
122 
123         public boolean supports(Class clazz) {
124             return Person.class.equals(clazz);
125         }
126 
127         public void validate(Object obj, Errors e) {
128             ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
129             Person p = (Person) obj;
130             if (p.getAge() < 0) {
131                 e.rejectValue("age", "age.negativevalue");
132             }
133             else if (p.getAge() > 110) {
134                 e.rejectValue("age", "too.darn.old");
135             }
136         }
137     }
138 
139     private static class Person {
140 
141         private String name;
142 
143         private int age;
144 
145         private Person(String name, int age) {
146             this.name = name;
147             this.age = age;
148         }
149 
150         public String getName() {
151             return name;
152         }
153 
154         public void setName(String name) {
155             this.name = name;
156         }
157 
158         public int getAge() {
159             return age;
160         }
161 
162         public void setAge(int age) {
163             this.age = age;
164         }
165 
166         public String toString() {
167             return "Person{" + name + "," + age + "}";
168         }
169     }
170 
171     private static class PersonMarshaller implements Unmarshaller, Marshaller {
172 
173         private final Person person;
174 
175         private PersonMarshaller(Person person) {
176             this.person = person;
177         }
178 
179         public Object unmarshal(Source source) throws XmlMappingException, IOException {
180             return person;
181         }
182 
183         public boolean supports(Class clazz) {
184             return Person.class.equals(clazz);
185         }
186 
187         public void marshal(Object graph, Result result) throws XmlMappingException, IOException {
188         }
189     }
190 
191 }