Skip to content

Commit 16dfd55

Browse files
committed
SWS-670 - sws:interceptors
1 parent df9d82a commit 16dfd55

File tree

15 files changed

+800
-67
lines changed

15 files changed

+800
-67
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright 2005-2010 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.config;
18+
19+
import java.util.List;
20+
21+
import org.springframework.beans.factory.config.BeanDefinition;
22+
import org.springframework.beans.factory.config.BeanDefinitionHolder;
23+
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
24+
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
25+
import org.springframework.beans.factory.support.RootBeanDefinition;
26+
import org.springframework.beans.factory.xml.BeanDefinitionParser;
27+
import org.springframework.beans.factory.xml.ParserContext;
28+
import org.springframework.util.xml.DomUtils;
29+
import org.springframework.ws.server.SmartEndpointInterceptor;
30+
import org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor;
31+
import org.springframework.ws.server.endpoint.interceptor.PayloadRootSmartEndpointInterceptor;
32+
import org.springframework.ws.soap.server.endpoint.interceptor.SoapActionSmartEndpointInterceptor;
33+
34+
import org.w3c.dom.Element;
35+
36+
/**
37+
* Parser for the {@code <sws:interceptors/>} element.
38+
*
39+
* @author Arjen Poutsma
40+
* @since 2.0
41+
*/
42+
class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
43+
44+
public BeanDefinition parse(Element element, ParserContext parserContext) {
45+
CompositeComponentDefinition compDefinition =
46+
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
47+
parserContext.pushContainingComponent(compDefinition);
48+
49+
List<Element> childElements = DomUtils.getChildElements(element);
50+
for (Element childElement : childElements) {
51+
if ("bean".equals(childElement.getLocalName())) {
52+
RootBeanDefinition smartInterceptorDef =
53+
createSmartInterceptorDefinition(DelegatingSmartEndpointInterceptor.class, childElement,
54+
parserContext);
55+
BeanDefinitionHolder interceptorDef = createInterceptorDefinition(parserContext, childElement);
56+
57+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, interceptorDef);
58+
59+
registerSmartInterceptor(parserContext, smartInterceptorDef);
60+
}
61+
else if ("payloadRoot".equals(childElement.getLocalName())) {
62+
List<Element> beanElements = DomUtils.getChildElementsByTagName(childElement, "bean");
63+
for (Element beanElement : beanElements) {
64+
RootBeanDefinition smartInterceptorDef =
65+
createSmartInterceptorDefinition(PayloadRootSmartEndpointInterceptor.class, childElement,
66+
parserContext);
67+
BeanDefinitionHolder interceptorDef = createInterceptorDefinition(parserContext, beanElement);
68+
69+
String namespaceUri = childElement.getAttribute("namespaceUri");
70+
String localPart = childElement.getAttribute("localPart");
71+
72+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, interceptorDef);
73+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, namespaceUri);
74+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, localPart);
75+
76+
registerSmartInterceptor(parserContext, smartInterceptorDef);
77+
}
78+
}
79+
else if ("soapAction".equals(childElement.getLocalName())) {
80+
List<Element> beanElements = DomUtils.getChildElementsByTagName(childElement, "bean");
81+
for (Element beanElement : beanElements) {
82+
RootBeanDefinition smartInterceptorDef =
83+
createSmartInterceptorDefinition(SoapActionSmartEndpointInterceptor.class, childElement,
84+
parserContext);
85+
BeanDefinitionHolder interceptorDef = createInterceptorDefinition(parserContext, beanElement);
86+
87+
String soapAction = childElement.getAttribute("value");
88+
89+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, interceptorDef);
90+
smartInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, soapAction);
91+
92+
registerSmartInterceptor(parserContext, smartInterceptorDef);
93+
}
94+
}
95+
}
96+
97+
parserContext.popAndRegisterContainingComponent();
98+
return null;
99+
}
100+
101+
private void registerSmartInterceptor(ParserContext parserContext, RootBeanDefinition smartInterceptorDef) {
102+
String mappedInterceptorName =
103+
parserContext.getReaderContext().registerWithGeneratedName(smartInterceptorDef);
104+
parserContext
105+
.registerComponent(new BeanComponentDefinition(smartInterceptorDef, mappedInterceptorName));
106+
}
107+
108+
private BeanDefinitionHolder createInterceptorDefinition(ParserContext parserContext, Element element) {
109+
BeanDefinitionHolder interceptorDef =
110+
parserContext.getDelegate().parseBeanDefinitionElement(element);
111+
interceptorDef =
112+
parserContext.getDelegate().decorateBeanDefinitionIfRequired(element, interceptorDef);
113+
return interceptorDef;
114+
}
115+
116+
private RootBeanDefinition createSmartInterceptorDefinition(Class<? extends SmartEndpointInterceptor> interceptorClass,
117+
Element element,
118+
ParserContext parserContext) {
119+
RootBeanDefinition smartInterceptorDef = new RootBeanDefinition(interceptorClass);
120+
smartInterceptorDef.setSource(parserContext.extractSource(element));
121+
smartInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
122+
return smartInterceptorDef;
123+
}
124+
125+
}

core/src/main/java/org/springframework/ws/config/WebServicesNamespaceHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ public class WebServicesNamespaceHandler extends NamespaceHandlerSupport {
2929

3030
public void init() {
3131
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
32-
registerBeanDefinitionParser("marshalling-endpoints", new MarshallingEndpointsBeanDefinitionParser());
33-
registerBeanDefinitionParser("xpath-endpoints", new XPathEndpointsBeanDefinitionParser());
32+
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
3433
registerBeanDefinitionParser("static-wsdl", new StaticWsdlBeanDefinitionParser());
3534
registerBeanDefinitionParser("dynamic-wsdl", new DynamicWsdlBeanDefinitionParser());
35+
registerBeanDefinitionParser("marshalling-endpoints", new MarshallingEndpointsBeanDefinitionParser());
36+
registerBeanDefinitionParser("xpath-endpoints", new XPathEndpointsBeanDefinitionParser());
3637
}
3738
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2005-2010 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.server;
18+
19+
import org.springframework.ws.context.MessageContext;
20+
21+
/**
22+
* Extension of the {@link EndpointInterceptor} interface that adds a way to
23+
* @author Arjen Poutsma
24+
* @since 2.0
25+
*/
26+
public interface SmartEndpointInterceptor extends EndpointInterceptor {
27+
28+
/**
29+
* Indicates whether this interceptor should intercept the given message context.
30+
*
31+
* @param messageContext contains the incoming request message
32+
* @param endpoint chosen endpoint to invoke
33+
* @return {@code true} to indicate that this interceptor applies; {@code false} otherwise
34+
*/
35+
boolean shouldIntercept(MessageContext messageContext, Object endpoint);
36+
37+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2005-2010 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.server.endpoint.interceptor;
18+
19+
import org.springframework.util.Assert;
20+
import org.springframework.ws.WebServiceMessage;
21+
import org.springframework.ws.context.MessageContext;
22+
import org.springframework.ws.server.EndpointInterceptor;
23+
import org.springframework.ws.server.SmartEndpointInterceptor;
24+
25+
/**
26+
* Implementation of the {@link SmartEndpointInterceptor} interface that delegates to a delegate {@link
27+
* EndpointInterceptor}.
28+
*
29+
* @author Arjen Poutsma
30+
* @since 2.0
31+
*/
32+
public class DelegatingSmartEndpointInterceptor implements SmartEndpointInterceptor {
33+
34+
private final EndpointInterceptor delegate;
35+
36+
/**
37+
* Creates a new instance of the {@code DelegatingSmartEndpointInterceptor} with the given delegate.
38+
*
39+
* @param delegate the endpoint interceptor to delegate to.
40+
*/
41+
public DelegatingSmartEndpointInterceptor(EndpointInterceptor delegate) {
42+
Assert.notNull(delegate, "'delegate' must not be null");
43+
this.delegate = delegate;
44+
}
45+
46+
/**
47+
* {@inheritDoc}
48+
* <p/>
49+
* This implementation delegates to {@link #shouldIntercept(WebServiceMessage, Object)}.
50+
*/
51+
public boolean shouldIntercept(MessageContext messageContext, Object endpoint) {
52+
WebServiceMessage request = messageContext.getRequest();
53+
return request != null && shouldIntercept(request, endpoint);
54+
}
55+
56+
/**
57+
* Indicates whether this interceptor should intercept the given request message.
58+
* <p/>
59+
* This implementation always returns {@code true}.
60+
*
61+
* @param request the request message
62+
* @param endpoint chosen endpoint to invoke
63+
* @return {@code true} to indicate that this interceptor applies; {@code false} otherwise
64+
*/
65+
protected boolean shouldIntercept(WebServiceMessage request, Object endpoint) {
66+
return true;
67+
}
68+
69+
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
70+
return delegate.handleRequest(messageContext, endpoint);
71+
}
72+
73+
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
74+
return delegate.handleResponse(messageContext, endpoint);
75+
}
76+
77+
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
78+
return delegate.handleFault(messageContext, endpoint);
79+
}
80+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2005-2010 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.server.endpoint.interceptor;
18+
19+
import javax.xml.namespace.QName;
20+
import javax.xml.transform.TransformerException;
21+
22+
import org.springframework.util.Assert;
23+
import org.springframework.util.StringUtils;
24+
import org.springframework.ws.WebServiceMessage;
25+
import org.springframework.ws.server.EndpointInterceptor;
26+
import org.springframework.ws.server.endpoint.support.PayloadRootUtils;
27+
import org.springframework.xml.transform.TransformerHelper;
28+
29+
/**
30+
* Implementation of the {@link org.springframework.ws.server.SmartEndpointInterceptor} interface that only intercepts
31+
* requests that have a specified namespace URI or local part (or both) as payload root.
32+
*
33+
* @author Arjen Poutsma
34+
* @since 2.0
35+
*/
36+
public class PayloadRootSmartEndpointInterceptor extends DelegatingSmartEndpointInterceptor {
37+
38+
private TransformerHelper transformerHelper = new TransformerHelper();
39+
40+
private final String namespaceUri;
41+
42+
private final String localPart;
43+
44+
public PayloadRootSmartEndpointInterceptor(EndpointInterceptor delegate, String namespaceUri, String localPart) {
45+
super(delegate);
46+
Assert.hasLength(namespaceUri, "namespaceUri can not be empty");
47+
this.namespaceUri = namespaceUri;
48+
this.localPart = localPart;
49+
}
50+
51+
public void setTransformerHelper(TransformerHelper transformerHelper) {
52+
this.transformerHelper = transformerHelper;
53+
}
54+
55+
@Override
56+
protected boolean shouldIntercept(WebServiceMessage request, Object endpoint) {
57+
try {
58+
QName payloadRootName = PayloadRootUtils.getPayloadRootQName(request.getPayloadSource(), transformerHelper);
59+
return !(StringUtils.hasLength(namespaceUri) && !namespaceUri.equals(payloadRootName.getNamespaceURI()) ||
60+
StringUtils.hasLength(localPart) && !localPart.equals(payloadRootName.getLocalPart()));
61+
62+
}
63+
catch (TransformerException e) {
64+
return false;
65+
}
66+
}
67+
}

core/src/main/java/org/springframework/ws/server/endpoint/mapping/AbstractAnnotationMethodEndpointMapping.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -57,6 +57,7 @@ protected Class<? extends Annotation> getEndpointAnnotationType() {
5757

5858
@Override
5959
protected final void initApplicationContext() throws BeansException {
60+
super.initApplicationContext();
6061
if (logger.isDebugEnabled()) {
6162
logger.debug("Looking for endpoints in application context: " + getApplicationContext());
6263
}

0 commit comments

Comments
 (0)