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 }