package be.error.wsproxy.interceptors;
import java.util.List;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.server.EndpointMapping;
import org.springframework.ws.server.MessageDispatcher;
import org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor;
/**
* This interceptor will only delegate if no service specific interceptors are configured. This is useful when accessing
* a new target service via the proxy module for which no extra configuration has been foreseen. From the moment service
* specific interceptors are configured, this interceptor will be skipped automatically.
*
* @author Koen Serneels
*/
public class DefaultInterceptorExecutor implements EndpointInterceptor {
@Autowired
private MessageDispatcher messageDispatcher;
private final EndpointInterceptor delegate;
public DefaultInterceptorExecutor(EndpointInterceptor delegate) {
this.delegate = delegate;
}
@Override
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
if (shouldInvoke(messageContext)) {
return delegate.handleFault(messageContext, endpoint);
}
return true;
}
@Override
public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
if (shouldInvoke(messageContext)) {
return delegate.handleRequest(messageContext, endpoint);
}
return true;
}
@Override
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
if (shouldInvoke(messageContext)) {
return delegate.handleResponse(messageContext, endpoint);
}
return true;
}
private boolean shouldInvoke(MessageContext messageContext) throws Exception {
List<EndpointMapping> endpointMappings = messageDispatcher.getEndpointMappings();
// There should be only one endpoint mapped in the module: check it
Assert.isTrue(endpointMappings != null && endpointMappings.size() == 1);
EndpointMapping endpointMapping = endpointMappings.iterator().next();
for (EndpointInterceptor endpointInterceptor : endpointMapping.getEndpoint(messageContext).getInterceptors()) {
// Check to see if the interceptor is directly an instance of a service specific interceptor.
// If so, we don't have to fall back to our default delegate
if (endpointInterceptor instanceof ServiceSpecificEndpointInterceptor) {
return false;
}
// Check to see if the interceptor is decorated by DelegatingSmartEndpointInterceptor
// Unfortunately there is no standard API way of detecting this, so we need some reflection.
// If so, check that the decorated instance is instance of a service specific interceptor.
// If so, we don't have to fall back to our default delegate
if (endpointInterceptor instanceof DelegatingSmartEndpointInterceptor) {
if (FieldUtils.readField(endpointInterceptor, "delegate", true) instanceof ServiceSpecificEndpointInterceptor) {
return false;
}
}
}
return true;
}
@Override
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
// Do nothing
}
}