diff --git a/core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java b/core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java index c6f197c1..bd38b08e 100644 --- a/core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/EndpointInterceptor.java @@ -1,11 +1,11 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -96,4 +96,6 @@ public interface EndpointInterceptor { * blocking of the response handler chain. */ boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception; + + void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex); } diff --git a/core/src/main/java/org/springframework/ws/server/MessageDispatcher.java b/core/src/main/java/org/springframework/ws/server/MessageDispatcher.java index 512c0fc0..e8966db2 100644 --- a/core/src/main/java/org/springframework/ws/server/MessageDispatcher.java +++ b/core/src/main/java/org/springframework/ws/server/MessageDispatcher.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -221,6 +221,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa interceptorIndex = i; if (!interceptor.handleRequest(messageContext, mappedEndpoint.getEndpoint())) { triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); + triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null); return; } } @@ -231,6 +232,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa // Apply handleResponse methods of registered interceptors triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); + triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null); } catch (NoEndpointFoundException ex) { // No triggering of interceptors if no endpoint is found @@ -243,6 +245,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa Object endpoint = mappedEndpoint != null ? mappedEndpoint.getEndpoint() : null; processEndpointException(messageContext, endpoint, ex); triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext); + triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, ex); } } @@ -359,6 +362,40 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa } } + /** + * Trigger afterCompletion callbacks on the mapped EndpointInterceptors. + * Will just invoke afterCompletion for all interceptors whose handleRequest invocation + * has successfully completed and returned true, in addition to the last interceptor who + * returned false. + * + * @param mappedEndpoint the mapped EndpointInvocationChain + * @param interceptorIndex index of last interceptor that successfully completed + * @param ex Exception thrown on handler execution, or null if none + * @see EndpointInterceptor#afterCompletion + */ + private void triggerAfterCompletion(EndpointInvocationChain mappedEndpoint, + int interceptorIndex, + MessageContext messageContext, + Exception ex) throws Exception { + + // Apply afterCompletion methods of registered interceptors. + if (mappedEndpoint != null) { + EndpointInterceptor[] interceptors = mappedEndpoint.getInterceptors(); + if (interceptors != null) { + for (int i = interceptorIndex; i >= 0; i--) { + EndpointInterceptor interceptor = interceptors[i]; + try { + interceptor.afterCompletion(messageContext, mappedEndpoint.getEndpoint(), ex); + } + catch (Throwable ex2) { + logger.error("EndpointInterceptor.afterCompletion threw exception", ex2); + } + } + } + } + } + + /** * Initialize the EndpointAdapters used by this class. If no adapter beans are explicitly set by using * the endpointAdapters property, we use the default strategies. diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java b/core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java index 93486478..a6db110f 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/AbstractLoggingInterceptor.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -111,6 +111,10 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor return true; } + /** Does nothing by default*/ + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + } + /** * Determine whether the {@link #logger} field is enabled. *

diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java index 8a1b2686..816c3a43 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/AbstractValidatingInterceptor.java @@ -257,6 +257,10 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup return true; } + /** Does nothing by default.*/ + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + } + /** * Abstract template method that returns the part of the request message that is to be validated. * diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java index 044877cd..53e3244d 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/DelegatingSmartEndpointInterceptor.java @@ -85,4 +85,8 @@ public class DelegatingSmartEndpointInterceptor implements SmartEndpointIntercep public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return getDelegate().handleFault(messageContext, endpoint); } + + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + getDelegate().afterCompletion(messageContext, endpoint, ex); + } } diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java index 29545c9a..fc85e6a8 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/EndpointInterceptorAdapter.java @@ -1,11 +1,11 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -16,10 +16,11 @@ package org.springframework.ws.server.endpoint.interceptor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; /** @@ -65,4 +66,10 @@ public class EndpointInterceptorAdapter implements EndpointInterceptor { public boolean handleFault(MessageContext messageContext, Object endpoint) { return true; } + + /** + * Does nothing by default. + */ + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + } } diff --git a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java index 932c48d0..135c2551 100644 --- a/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java +++ b/core/src/main/java/org/springframework/ws/server/endpoint/interceptor/PayloadTransformingInterceptor.java @@ -1,11 +1,11 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,11 +26,6 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.XMLReaderFactory; - import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; @@ -40,6 +35,11 @@ import org.springframework.ws.server.EndpointInterceptor; import org.springframework.xml.transform.ResourceSource; import org.springframework.xml.transform.TransformerObjectSupport; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + /** * Interceptor that transforms the payload of WebServiceMessages using XSLT stylesheet. Allows for seperate * stylesheets for request and response. This interceptor is especially useful when supporting with multiple version of @@ -125,6 +125,10 @@ public class PayloadTransformingInterceptor extends TransformerObjectSupport return true; } + /** Does nothing by default.*/ + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + } + public void afterPropertiesSet() throws Exception { if (requestXslt == null && responseXslt == null) { throw new IllegalArgumentException("Setting either 'requestXslt' or 'responseXslt' is required"); diff --git a/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java b/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java index b5b1bc21..f59071c6 100644 --- a/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java +++ b/core/src/main/java/org/springframework/ws/soap/addressing/server/AddressingEndpointInterceptor.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -178,6 +178,9 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor { return responseMessageId; } + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + } + public boolean understands(SoapHeaderElement header) { return version.understands(header); } diff --git a/core/src/test/java/org/springframework/ws/server/MessageDispatcherTest.java b/core/src/test/java/org/springframework/ws/server/MessageDispatcherTest.java index 3d831c79..bb1080ff 100644 --- a/core/src/test/java/org/springframework/ws/server/MessageDispatcherTest.java +++ b/core/src/test/java/org/springframework/ws/server/MessageDispatcherTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -171,8 +171,8 @@ public class MessageDispatcherTest { EndpointMapping mappingMock = createMock(EndpointMapping.class); dispatcher.setEndpointMappings(Collections.singletonList(mappingMock)); - EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class); - EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class); + EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class); + EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class); expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true); expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true); @@ -182,6 +182,9 @@ public class MessageDispatcherTest { expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(true); expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true); + interceptorMock2.afterCompletion(messageContext, endpoint, null); + interceptorMock1.afterCompletion(messageContext, endpoint, null); + EndpointInvocationChain chain = new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2}); @@ -208,8 +211,8 @@ public class MessageDispatcherTest { EndpointMapping mappingMock = createMock(EndpointMapping.class); dispatcher.setEndpointMappings(Collections.singletonList(mappingMock)); - EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class); - EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class); + EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class); + EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class); EndpointInvocationChain chain = new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2}); @@ -217,6 +220,8 @@ public class MessageDispatcherTest { expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true); expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true); + interceptorMock2.afterCompletion(messageContext, endpoint, null); + interceptorMock1.afterCompletion(messageContext, endpoint, null); adapterMock.invoke(messageContext, endpoint); @@ -235,13 +240,14 @@ public class MessageDispatcherTest { EndpointMapping mappingMock = createMock(EndpointMapping.class); dispatcher.setEndpointMappings(Collections.singletonList(mappingMock)); - EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class); - EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class); + EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class); + EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class); Object endpoint = new Object(); expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(false); expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true); + interceptorMock1.afterCompletion(messageContext, endpoint, null); EndpointInvocationChain chain = new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2}); @@ -267,13 +273,15 @@ public class MessageDispatcherTest { EndpointMapping mappingMock = createMock(EndpointMapping.class); dispatcher.setEndpointMappings(Collections.singletonList(mappingMock)); - EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class); - EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class); + EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class); + EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class); Object endpoint = new Object(); expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true); expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(false); expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(false); + interceptorMock1.afterCompletion(messageContext, endpoint, null); + interceptorMock2.afterCompletion(messageContext, endpoint, null); EndpointInvocationChain chain = new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2}); @@ -290,7 +298,7 @@ public class MessageDispatcherTest { verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock); } - + @Test public void testFaultFlow() throws Exception { EndpointAdapter adapterMock = createMock(EndpointAdapter.class); @@ -302,11 +310,12 @@ public class MessageDispatcherTest { EndpointMapping mappingMock = createMock(EndpointMapping.class); dispatcher.setEndpointMappings(Collections.singletonList(mappingMock)); - EndpointInterceptor interceptorMock = createMock(EndpointInterceptor.class); + EndpointInterceptor interceptorMock = createStrictMock(EndpointInterceptor.class); expect(interceptorMock.handleRequest(messageContext, endpoint)).andReturn(true); adapterMock.invoke(messageContext, endpoint); expect(interceptorMock.handleFault(messageContext, endpoint)).andReturn(true); + interceptorMock.afterCompletion(messageContext, endpoint, null); EndpointInvocationChain chain = new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock}); diff --git a/parent/pom.xml b/parent/pom.xml index 33a0dbf5..355a3d08 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -352,7 +352,7 @@ org.apache.ws.commons.schema XmlSchema - 1.4.3 + 1.4.5 diff --git a/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java index 0690d920..a5a00ab8 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java +++ b/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java @@ -1,11 +1,11 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,9 +20,6 @@ import java.util.Iterator; import java.util.Locale; import javax.xml.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.util.Assert; import org.springframework.ws.client.WebServiceClientException; import org.springframework.ws.client.support.interceptor.ClientInterceptor; @@ -36,6 +33,9 @@ import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.server.SoapEndpointInterceptor; import org.springframework.ws.soap.soap11.Soap11Body; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** * Interceptor base class for interceptors that handle WS-Security. Can be used on the server side, registered in a * {@link org.springframework.ws.server.endpoint.mapping.AbstractEndpointMapping#setInterceptors(org.springframework.ws.server.EndpointInterceptor[]) @@ -166,17 +166,19 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter if (!result) { messageContext.clearResponse(); } - cleanUp(); } return result; } /** Returns true, i.e. fault responses are not secured. */ public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { - cleanUp(); return true; } + public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { + cleanUp(); + } + public boolean understands(SoapHeaderElement headerElement) { return WS_SECURITY_NAME.equals(headerElement.getName()); } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java index d6a07b03..fbda3802 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,12 +18,12 @@ package org.springframework.ws.soap.security.wss4j; import java.util.Properties; -import org.springframework.security.core.Authentication; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; @@ -69,6 +69,7 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa // test clean up messageContext.getResponse(); interceptor.handleResponse(messageContext, null); + interceptor.afterCompletion(messageContext, null, null); assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication()); } @@ -83,6 +84,7 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa // test clean up messageContext.getResponse(); interceptor.handleResponse(messageContext, null); + interceptor.afterCompletion(messageContext, null, null); assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication()); } diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java b/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java index 121ea22b..17384606 100644 --- a/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java +++ b/security/src/test/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptorTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,10 +26,11 @@ import org.springframework.ws.soap.saaj.SaajSoapMessage; import org.springframework.ws.soap.saaj.SaajSoapMessageFactory; import org.springframework.ws.soap.security.WsSecurityValidationException; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.*; + public class XwsSecurityInterceptorTest { private MessageFactory messageFactory; @@ -48,14 +49,14 @@ public class XwsSecurityInterceptorTest { @Override protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) throws XwsSecuritySecurementException { - Assert.fail("secure not expected"); + fail("secure not expected"); } @Override protected void validateMessage(SoapMessage message, MessageContext messageContext) throws WsSecurityValidationException { SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message; - Assert.assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage()); + assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage()); saajSoapMessage.setSaajMessage(validatedRequest); } @@ -63,13 +64,14 @@ public class XwsSecurityInterceptorTest { MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory)); interceptor.handleRequest(context, null); - Assert.assertEquals("Invalid request", validatedRequest, - ((SaajSoapMessage) context.getRequest()).getSaajMessage()); + assertEquals("Invalid request", validatedRequest, ((SaajSoapMessage) context.getRequest()).getSaajMessage()); } @Test public void testHandleServerResponse() throws Exception { final SOAPMessage securedResponse = messageFactory.createMessage(); + final boolean[] cleanupCalled = new boolean[1]; + cleanupCalled[0] = false; XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() { @Override @@ -82,21 +84,49 @@ public class XwsSecurityInterceptorTest { @Override protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext) throws WsSecurityValidationException { - Assert.fail("validate not expected"); + fail("validate not expected"); } + @Override + protected void cleanUp() { + cleanupCalled[0] = true; + } }; + SOAPMessage request = messageFactory.createMessage(); MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory)); context.getResponse(); interceptor.handleResponse(context, null); - Assert.assertEquals("Invalid response", securedResponse, - ((SaajSoapMessage) context.getResponse()).getSaajMessage()); + interceptor.afterCompletion(context, null, null); + assertEquals("Invalid response", securedResponse, ((SaajSoapMessage) context.getResponse()).getSaajMessage()); + assertTrue("Cleanup not called", cleanupCalled[0]); } @Test - public void testhandleClientRequest() throws Exception { + public void testHandleServerFault() throws Exception { + final boolean[] cleanupCalled = new boolean[1]; + cleanupCalled[0] = false; + XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() { + + + @Override + protected void cleanUp() { + cleanupCalled[0] = true; + } + }; + + SOAPMessage request = messageFactory.createMessage(); + MessageContext context = + new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory)); + context.getResponse(); + interceptor.handleFault(context, null); + interceptor.afterCompletion(context, null, null); + assertTrue("Cleanup not called", cleanupCalled[0]); + } + + @Test + public void testHandleClientRequest() throws Exception { final SOAPMessage request = messageFactory.createMessage(); final SOAPMessage securedRequest = messageFactory.createMessage(); XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() { @@ -105,22 +135,21 @@ public class XwsSecurityInterceptorTest { protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) throws XwsSecuritySecurementException { SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage; - Assert.assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage()); + assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage()); saajSoapMessage.setSaajMessage(securedRequest); } @Override protected void validateMessage(SoapMessage message, MessageContext messageContext) throws WsSecurityValidationException { - Assert.fail("validate not expected"); + fail("validate not expected"); } }; MessageContext context = new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory)); interceptor.handleRequest(context); - Assert.assertEquals("Invalid request", securedRequest, - ((SaajSoapMessage) context.getRequest()).getSaajMessage()); + assertEquals("Invalid request", securedRequest, ((SaajSoapMessage) context.getRequest()).getSaajMessage()); } @Test @@ -131,7 +160,7 @@ public class XwsSecurityInterceptorTest { @Override protected void secureMessage(SoapMessage message, MessageContext messageContext) throws XwsSecuritySecurementException { - Assert.fail("secure not expected"); + fail("secure not expected"); } @Override @@ -147,8 +176,7 @@ public class XwsSecurityInterceptorTest { new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory)); context.getResponse(); interceptor.handleResponse(context); - Assert.assertEquals("Invalid response", validatedResponse, - ((SaajSoapMessage) context.getResponse()).getSaajMessage()); + assertEquals("Invalid response", validatedResponse, ((SaajSoapMessage) context.getResponse()).getSaajMessage()); } } \ No newline at end of file diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java index 3b569d5d..9897b25b 100644 --- a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java +++ b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,9 +17,9 @@ package org.springframework.ws.soap.security.xwss.callback; import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -110,7 +110,7 @@ public class SpringDigestPasswordValidationCallbackHandlerTest { } @Test - public void testAuthenticateUserDigestDisbaled() throws Exception { + public void testAuthenticateUserDigestDisabled() throws Exception { User user = new User(username, "Ernie", false, true, true, true, new GrantedAuthority[0]); expect(userDetailsService.loadUserByUsername(username)).andReturn(user); diff --git a/xml/src/test/resources/org/springframework/xml/xsd/xml.xsd b/xml/src/test/resources/org/springframework/xml/xsd/xml.xsd new file mode 100644 index 00000000..aea7d0db --- /dev/null +++ b/xml/src/test/resources/org/springframework/xml/xsd/xml.xsd @@ -0,0 +1,287 @@ + + + + + + +

+

About the XML namespace

+ +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+ + + + + + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + +
+ + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + +
+ + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ + + diff --git a/xml/src/test/resources/org/springframework/xml/xsd/xmlNamespace.xsd b/xml/src/test/resources/org/springframework/xml/xsd/xmlNamespace.xsd index eebd4bc5..a94f7491 100644 --- a/xml/src/test/resources/org/springframework/xml/xsd/xmlNamespace.xsd +++ b/xml/src/test/resources/org/springframework/xml/xsd/xmlNamespace.xsd @@ -4,7 +4,7 @@ xmlns="http://www.springframework.org/spring-ws/xmlNamespace" elementFormDefault="qualified" attributeFormDefault="unqualified"> - +