Minimizing class loading in parsers and using the parser context error handling capabilities rather than throwing Exceptions or using assertions. This facilitates proper tooling support (INT-114).

This commit is contained in:
Mark Fisher
2008-12-11 21:31:13 +00:00
parent 38edabe807
commit 57888a9f62
2 changed files with 44 additions and 22 deletions

View File

@@ -38,8 +38,17 @@ import org.springframework.util.Assert;
*/
public class ChannelInvocationDefinitionSource implements ObjectDefinitionSource {
private final Map<Pattern, ChannelAccessPolicy> patternMappings =
new LinkedHashMap<Pattern, ChannelAccessPolicy>();
private final Map<Pattern, ChannelAccessPolicy> patternMappings;
public ChannelInvocationDefinitionSource() {
this(null);
}
public ChannelInvocationDefinitionSource(Map<Pattern, ChannelAccessPolicy> patternMappings) {
this.patternMappings = (patternMappings != null) ? patternMappings
: new LinkedHashMap<Pattern, ChannelAccessPolicy>();
}
public void addPatternMapping(Pattern pattern, ChannelAccessPolicy accessPolicy) {

View File

@@ -21,32 +21,33 @@ import java.util.regex.Pattern;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.security.channel.ChannelAccessPolicy;
import org.springframework.integration.security.channel.ChannelInvocationDefinitionSource;
import org.springframework.integration.security.channel.ChannelSecurityInterceptor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
/**
* Creates a {@link ChannelSecurityInterceptor} to control send and receive access,
* and creates a {@link ChannelSecurityInterceptorBeanPostProcessor} to apply the
* interceptor to {@link MessageChannel}s whose names match the specified patterns.
* Creates a {@link org.springframework.integration.security.channel.ChannelSecurityInterceptor}
* to control send and receive access, and creates a bean post-processor to apply the
* interceptor to {@link org.springframework.integration.core.MessageChannel}s
* whose names match the specified patterns.
*
* @author Jonas Partner
* @author Mark Fisher
*/
public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
private final static String BASE_PACKAGE_NAME = "org.springframework.integration.security";
@Override
protected Class<?> getBeanClass(Element element) {
return ChannelSecurityInterceptorBeanPostProcessor.class;
protected String getBeanClassName(Element element) {
return BASE_PACKAGE_NAME + ".config.ChannelSecurityInterceptorBeanPostProcessor";
}
@Override
@@ -56,9 +57,10 @@ public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
ChannelInvocationDefinitionSource objectDefinitionSource = this.parseObjectDefinitionSource(element);
BeanDefinitionBuilder interceptorBuilder = BeanDefinitionBuilder.genericBeanDefinition(ChannelSecurityInterceptor.class);
interceptorBuilder.addConstructorArgValue(objectDefinitionSource);
String objectDefinitionSourceBeanName = this.parseObjectDefinitionSource(element, parserContext);
BeanDefinitionBuilder interceptorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
BASE_PACKAGE_NAME + ".channel.ChannelSecurityInterceptor");
interceptorBuilder.addConstructorArgReference(objectDefinitionSourceBeanName);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(interceptorBuilder, element, "authentication-manager");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(interceptorBuilder, element, "access-decision-manager");
String interceptorBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(
@@ -66,20 +68,31 @@ public class SecuredChannelsParser extends AbstractSingleBeanDefinitionParser {
builder.addConstructorArgReference(interceptorBeanName);
}
@SuppressWarnings("unchecked")
private ChannelInvocationDefinitionSource parseObjectDefinitionSource(Element element) {
ChannelInvocationDefinitionSource objectDefinitionSource = new ChannelInvocationDefinitionSource();
private String parseObjectDefinitionSource(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
BASE_PACKAGE_NAME + ".channel.ChannelInvocationDefinitionSource");
List<Element> accessPolicyElements = (List<Element>) DomUtils.getChildElementsByTagName(element, "access-policy");
ManagedMap patternMappings = new ManagedMap();
for (Element accessPolicyElement : accessPolicyElements) {
Pattern pattern = Pattern.compile(accessPolicyElement.getAttribute("pattern"));
String sendAccess = accessPolicyElement.getAttribute("send-access");
String receiveAccess = accessPolicyElement.getAttribute("receive-access");
Assert.isTrue(StringUtils.hasText(sendAccess) || StringUtils.hasText(receiveAccess),
"At least one of 'send-access' or 'receive-access' must be provided.");
objectDefinitionSource.addPatternMapping(pattern, new ChannelAccessPolicy(sendAccess, receiveAccess));
if (!StringUtils.hasText(sendAccess) && !StringUtils.hasText(receiveAccess)) {
parserContext.getReaderContext().error(
"At least one of 'send-access' or 'receive-access' must be provided.", accessPolicyElement);
}
BeanDefinitionBuilder accessPolicyBuilder = BeanDefinitionBuilder.genericBeanDefinition(
BASE_PACKAGE_NAME + ".channel.ChannelAccessPolicy");
accessPolicyBuilder.addConstructorArgValue(sendAccess);
accessPolicyBuilder.addConstructorArgValue(receiveAccess);
accessPolicyBuilder.getBeanDefinition().setRole(BeanDefinition.ROLE_SUPPORT);
patternMappings.put(pattern, accessPolicyBuilder.getBeanDefinition());
}
return objectDefinitionSource;
builder.addConstructorArgValue(patternMappings);
builder.setRole(BeanDefinition.ROLE_SUPPORT);
return BeanDefinitionReaderUtils.registerWithGeneratedName(
builder.getBeanDefinition(), parserContext.getRegistry());
}
}