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 }