View Javadoc

1   /*
2    * Copyright 2007 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.interceptor;
18  
19  import java.util.Locale;
20  import javax.xml.namespace.QName;
21  import javax.xml.transform.TransformerException;
22  
23  import org.springframework.ws.context.MessageContext;
24  import org.springframework.ws.server.endpoint.interceptor.AbstractValidatingInterceptor;
25  import org.springframework.ws.soap.SoapBody;
26  import org.springframework.ws.soap.SoapFault;
27  import org.springframework.ws.soap.SoapFaultDetail;
28  import org.springframework.ws.soap.SoapFaultDetailElement;
29  import org.springframework.ws.soap.SoapMessage;
30  import org.springframework.xml.namespace.QNameUtils;
31  import org.xml.sax.SAXParseException;
32  
33  /**
34   * Subclass of <code>AbstractValidatingInterceptor</code> that creates a SOAP Fault whenever the request message cannot
35   * be validated. The contents of the SOAP Fault can be specified by setting the <code>addValidationErrorDetail</code>,
36   * <code>faultStringOrReason</code>, or  <code>detailElementName</code> properties. Further customizing can be
37   * accomplished by overriding <code>handleRequestValidationErrors</code>.
38   *
39   * @author Arjen Poutsma
40   * @see #setAddValidationErrorDetail(boolean)
41   * @see #setFaultStringOrReason(String)
42   * @see #DEFAULT_FAULTSTRING_OR_REASON
43   * @see #setDetailElementName(javax.xml.namespace.QName)
44   * @see #DEFAULT_DETAIL_ELEMENT_NAME
45   * @see #handleResponseValidationErrors(org.springframework.ws.context.MessageContext,org.xml.sax.SAXParseException[])
46   * @since 1.0.0
47   */
48  public abstract class AbstractFaultCreatingValidatingInterceptor extends AbstractValidatingInterceptor {
49  
50      /**
51       * Default SOAP Fault Detail name used when a validation errors occur on the request.
52       *
53       * @see #setDetailElementName(javax.xml.namespace.QName)
54       */
55      public static final QName DEFAULT_DETAIL_ELEMENT_NAME =
56              QNameUtils.createQName("http://springframework.org/spring-ws", "ValidationError", "spring-ws");
57  
58      /**
59       * Default SOAP Fault string used when a validation errors occur on the request.
60       *
61       * @see #setFaultStringOrReason(String)
62       */
63      public static final String DEFAULT_FAULTSTRING_OR_REASON = "Validation error";
64  
65      private boolean addValidationErrorDetail = true;
66  
67      private QName detailElementName = DEFAULT_DETAIL_ELEMENT_NAME;
68  
69      private String faultStringOrReason = DEFAULT_FAULTSTRING_OR_REASON;
70  
71      private Locale faultStringOrReasonLocale = Locale.ENGLISH;
72  
73      /**
74       * Returns whether a SOAP Fault detail element should be created when a validation error occurs. This detail element
75       * will contain the exact validation errors. It is only added when the underlying message is a
76       * <code>SoapMessage</code>. Defaults to <code>true</code>.
77       *
78       * @see org.springframework.ws.soap.SoapFault#addFaultDetail()
79       */
80      public boolean getAddValidationErrorDetail() {
81          return addValidationErrorDetail;
82      }
83  
84      /**
85       * Indicates whether a SOAP Fault detail element should be created when a validation error occurs. This detail
86       * element will contain the exact validation errors. It is only added when the underlying message is a
87       * <code>SoapMessage</code>. Defaults to <code>true</code>.
88       *
89       * @see org.springframework.ws.soap.SoapFault#addFaultDetail()
90       */
91      public void setAddValidationErrorDetail(boolean addValidationErrorDetail) {
92          this.addValidationErrorDetail = addValidationErrorDetail;
93      }
94  
95      /** Returns the fault detail element name when validation errors occur on the request. */
96      public QName getDetailElementName() {
97          return detailElementName;
98      }
99  
100     /**
101      * Sets the fault detail element name when validation errors occur on the request. Defaults to
102      * <code>DEFAULT_DETAIL_ELEMENT_NAME</code>.
103      *
104      * @see #DEFAULT_DETAIL_ELEMENT_NAME
105      */
106     public void setDetailElementName(QName detailElementName) {
107         this.detailElementName = detailElementName;
108     }
109 
110     /** Sets the SOAP <code>faultstring</code> or <code>Reason</code> used when validation errors occur on the request. */
111     public String getFaultStringOrReason() {
112         return faultStringOrReason;
113     }
114 
115     /**
116      * Sets the SOAP <code>faultstring</code> or <code>Reason</code> used when validation errors occur on the request.
117      * It is only added when the underlying message is a <code>SoapMessage</code>. Defaults to
118      * <code>DEFAULT_FAULTSTRING_OR_REASON</code>.
119      *
120      * @see #DEFAULT_FAULTSTRING_OR_REASON
121      */
122     public void setFaultStringOrReason(String faultStringOrReason) {
123         this.faultStringOrReason = faultStringOrReason;
124     }
125 
126     /** Returns the SOAP fault reason locale used when validation errors occur on the request. */
127     public Locale getFaultStringOrReasonLocale() {
128         return faultStringOrReasonLocale;
129     }
130 
131     /**
132      * Sets the SOAP fault reason locale used when validation errors occur on the request.  It is only added when the
133      * underlying message is a <code>SoapMessage</code>. Defaults to English.
134      *
135      * @see java.util.Locale#ENGLISH
136      */
137     public void setFaultStringOrReasonLocale(Locale faultStringOrReasonLocale) {
138         this.faultStringOrReasonLocale = faultStringOrReasonLocale;
139     }
140 
141     /**
142      * Template method that is called when the request message contains validation errors. This implementation logs all
143      * errors, returns <code>false</code>, and creates a {@link SoapBody#addClientOrSenderFault(String,Locale) client or
144      * sender} {@link SoapFault}, adding a {@link SoapFaultDetail} with all errors if the
145      * <code>addValidationErrorDetail</code> property is <code>true</code>.
146      *
147      * @param messageContext the message context
148      * @param errors         the validation errors
149      * @return <code>true</code> to continue processing the request, <code>false</code> (the default) otherwise
150      */
151     protected boolean handleRequestValidationErrors(MessageContext messageContext, SAXParseException[] errors)
152             throws TransformerException {
153         for (int i = 0; i < errors.length; i++) {
154             logger.warn("XML validation error on request: " + errors[i].getMessage());
155         }
156         if (messageContext.getResponse() instanceof SoapMessage) {
157             SoapMessage response = (SoapMessage) messageContext.getResponse();
158             SoapBody body = response.getSoapBody();
159             SoapFault fault = body.addClientOrSenderFault(getFaultStringOrReason(), getFaultStringOrReasonLocale());
160             if (getAddValidationErrorDetail()) {
161                 SoapFaultDetail detail = fault.addFaultDetail();
162                 for (int i = 0; i < errors.length; i++) {
163                     SoapFaultDetailElement detailElement = detail.addFaultDetailElement(getDetailElementName());
164                     detailElement.addText(errors[i].getMessage());
165                 }
166             }
167         }
168         return false;
169     }
170 }