001: /*
002: * Copyright 2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ws.soap.server.endpoint;
018:
019: import java.util.Enumeration;
020: import java.util.Properties;
021:
022: import org.springframework.util.CollectionUtils;
023:
024: /**
025: * Exception resolver that allows for mapping exception class names to SOAP Faults. The mappings are set using the
026: * <code>exceptionMappings</code> property, the format of which is documented in {@link SoapFaultDefinitionEditor}.
027: *
028: * @author Arjen Poutsma
029: * @since 1.0.0
030: */
031: public class SoapFaultMappingExceptionResolver extends
032: AbstractSoapFaultDefinitionExceptionResolver {
033:
034: private Properties exceptionMappings;
035:
036: /**
037: * Set the mappings between exception class names and SOAP Faults. The exception class name can be a substring, with
038: * no wildcard support at present.
039: * <p/>
040: * The values of the given properties object should use the format described in
041: * <code>SoapFaultDefinitionEditor</code>.
042: * <p/>
043: * Follows the same matching algorithm as <code>SimpleMappingExceptionResolver</code>.
044: *
045: * @param mappings exception patterns (can also be fully qualified class names) as keys, fault definition texts as
046: * values
047: * @see SoapFaultDefinitionEditor
048: * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
049: */
050: public void setExceptionMappings(Properties mappings) {
051: exceptionMappings = mappings;
052: }
053:
054: protected SoapFaultDefinition getFaultDefinition(Object endpoint,
055: Exception ex) {
056: if (!CollectionUtils.isEmpty(exceptionMappings)) {
057: String definitionText = null;
058: int deepest = Integer.MAX_VALUE;
059: for (Enumeration names = exceptionMappings.propertyNames(); names
060: .hasMoreElements();) {
061: String exceptionMapping = (String) names.nextElement();
062: int depth = getDepth(exceptionMapping, ex);
063: if (depth >= 0 && depth < deepest) {
064: deepest = depth;
065: definitionText = exceptionMappings
066: .getProperty(exceptionMapping);
067: }
068: }
069: if (definitionText != null) {
070: SoapFaultDefinitionEditor editor = new SoapFaultDefinitionEditor();
071: editor.setAsText(definitionText);
072: return (SoapFaultDefinition) editor.getValue();
073: }
074: }
075: return null;
076: }
077:
078: /**
079: * Return the depth to the superclass matching. <code>0</code> means ex matches exactly. Returns <code>-1</code> if
080: * there's no match. Otherwise, returns depth. Lowest depth wins.
081: * <p/>
082: * Follows the same algorithm as RollbackRuleAttribute, and SimpleMappingExceptionResolver
083: *
084: * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
085: */
086: protected int getDepth(String exceptionMapping, Exception ex) {
087: return getDepth(exceptionMapping, ex.getClass(), 0);
088: }
089:
090: private int getDepth(String exceptionMapping, Class exceptionClass,
091: int depth) {
092: if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
093: return depth;
094: }
095: if (exceptionClass.equals(Throwable.class)) {
096: return -1;
097: }
098: return getDepth(exceptionMapping, exceptionClass
099: .getSuperclass(), depth + 1);
100: }
101:
102: }
|