Added more bean definition parsers

This commit is contained in:
Vishal Puri 2007-05-17 12:57:16 +00:00
parent 1a06723404
commit a01bb3bbee
11 changed files with 518 additions and 0 deletions

View File

@ -0,0 +1,50 @@
/**
*
*/
package org.acegisecurity.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.acegisecurity.ui.AccessDeniedHandler;
import org.acegisecurity.ui.ExceptionTranslationFilter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.util.Assert;
/**
* @author vpuri
*
*/
public class AccessDeniedHandlerBeanDefinitionLocator implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map m = beanFactory.getBeansOfType(AccessDeniedHandler.class);
List l = new ArrayList(m.values());
if (m.size() > 1) {
throw new IllegalArgumentException(
"More than one AccessDeniedHandler beans detected please refer to the one using "
+ " [ accessDeniedBeanRef ] " + "attribute");
}
else if (m.size() == 1) {
// use this
String[] names = beanFactory.getBeanNamesForType(ExceptionTranslationFilter.class);
Assert.notEmpty(names, "No bean of type ExceptionTranslationFilter found in ApplicationContext");
RootBeanDefinition definition = (RootBeanDefinition) beanFactory.getBeanDefinition(names[0]);
Assert.isAssignable(AccessDeniedHandler.class, l.get(0).getClass());
definition.getPropertyValues().addPropertyValue("accessDeniedHandler", l.get(0));
}
else {
// use the default one for now
}
}
}

View File

@ -0,0 +1,58 @@
/**
*
*/
package org.acegisecurity.config;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* @author vpuri
*
*/
public class AuthenticationProcessingFilterBeanDefinitionParser extends AbstractBeanDefinitionParser implements
BeanDefinitionParser {
// ~ Instance fields
// ================================================================================================
private static final String AUTHENTICATION_URL = "authenticationUrl";
private static final String ERROR_FORM_URL = "errorFormUrl";
private static final String DEFAULT_TARGET_URL = "defaultTargetUrl";
// ~ Methods
// ================================================================================================
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
RootBeanDefinition definition = new RootBeanDefinition(AuthenticationProcessingFilter.class);
setPropertyIfAvailable(element, AUTHENTICATION_URL, "filterProcessesUrl", definition);
setPropertyIfAvailable(element, ERROR_FORM_URL, "authenticationFailureUrl", definition);
setPropertyIfAvailable(element, DEFAULT_TARGET_URL, "defaultTargetUrl", definition);
// register BFPP to re-unite all other collaborators
RootBeanDefinition postProcessor = new RootBeanDefinition(
AuthenticationProcessingFilterDependenciesConfigurer.class);
parserContext.getReaderContext().registerWithGeneratedName(postProcessor);
return definition;
}
private void setPropertyIfAvailable(Element element, String attribute, String property,
RootBeanDefinition definition) {
String propertyValue = element.getAttribute(attribute);
if (StringUtils.hasText(propertyValue)) {
definition.getPropertyValues().addPropertyValue(property, propertyValue);
}
}
}

View File

@ -0,0 +1,43 @@
/**
*
*/
package org.acegisecurity.config;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.ui.rememberme.RememberMeServices;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
/**
* @author vpuri
*
*/
public class AuthenticationProcessingFilterDependenciesConfigurer implements BeanFactoryPostProcessor {
// ~ Methods
// ================================================================================================
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String [] authenticationProcessingFilter = beanFactory.getBeanNamesForType(AuthenticationProcessingFilter.class);
RootBeanDefinition def = (RootBeanDefinition)beanFactory.getBeanDefinition(authenticationProcessingFilter[0]);
String[] remServiceNames = beanFactory.getBeanNamesForType(RememberMeServices.class);
RootBeanDefinition rememberMeServices = (RootBeanDefinition) beanFactory.getBeanDefinition(remServiceNames[0]);
if (remServiceNames.length > 0)
def.getPropertyValues()
.addPropertyValue("rememberMeServices", rememberMeServices);
String[] authManager = beanFactory.getBeanNamesForType(AuthenticationManager.class);
RootBeanDefinition authenticationManager = (RootBeanDefinition) beanFactory.getBeanDefinition(authManager[0]);
if (authManager.length > 0)
def.getPropertyValues().addPropertyValue("authenticationManager", authenticationManager);
}
}

View File

@ -0,0 +1,121 @@
/**
*
*/
package org.acegisecurity.config;
import org.acegisecurity.ui.AccessDeniedHandlerImpl;
import org.acegisecurity.ui.ExceptionTranslationFilter;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Basically accessDeniedUrl is optional, we if unspecified impl will
* auto-detect any AccessDeniedHandler in ctx and use it; alternately if there
* are > 1 such handlers, we can nominate the one to use via
* accessDeniedBeanRef;
*
* @author vpuri
* @since
*/
public class ExceptionTranslationFilterBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String ACCESS_DENIED = "access-denied";
private static final String ACCESS_DENIED_REF = "accessDeniedBeanRef";
private static final String ACCESS_DENIED_URL = "accessDeniedUrl";
private static final String ENTRY_POINT = "entry-point";
private static final String ENTRY_POINT_REF ="entryPointBeanRef";
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
RootBeanDefinition exceptionFilterDef = new RootBeanDefinition(ExceptionTranslationFilter.class);
// add handler
Element accessDeniedElement = DomUtils.getChildElementByTagName(element, ACCESS_DENIED);
setAccessDeniedHandlerProperty(parserContext, exceptionFilterDef, accessDeniedElement);
Element entryPointElement = DomUtils.getChildElementByTagName(element, ENTRY_POINT);
setEntryPointProperty(exceptionFilterDef, entryPointElement);
return exceptionFilterDef;
}
private void setEntryPointProperty(RootBeanDefinition exceptionFilterDef, Element entryPointElement) {
if (entryPointElement != null) {
setBeanReferenceOrInnerBeanDefinitions(exceptionFilterDef, entryPointElement, "authenticationEntryPoint",
entryPointElement.getAttribute(ENTRY_POINT_REF));
}
}
/**
*
* @param parserContext
* @param repositoryBeanDef
* @param element
*/
private void setAccessDeniedHandlerProperty(ParserContext parserContext, RootBeanDefinition exceptionFilterDef,
Element accessDeniedElement) {
if (accessDeniedElement != null) {
setBeanReferenceOrInnerBeanDefinitions(exceptionFilterDef, accessDeniedElement, "accessDeniedHandler",
accessDeniedElement.getAttribute(ACCESS_DENIED_REF));
}
else {
// register BFPP to check if handler exist in application context,
// if > 1 throw error saying ref should be specified as there are
// more than one
RootBeanDefinition accessDeniedHandlerLocatorBeanDef = new RootBeanDefinition(
AccessDeniedHandlerBeanDefinitionLocator.class);
parserContext.getReaderContext().registerWithGeneratedName(accessDeniedHandlerLocatorBeanDef);
}
}
/**
*
* @param repositoryBeanDef
* @param element
* @param property
* @param reference
*/
private void setBeanReferenceOrInnerBeanDefinitions(RootBeanDefinition exceptionFilterDef,
Element element, String property, String beanRef) {
// check for encoderBeanRef attribute
if (StringUtils.hasLength(beanRef)) {
exceptionFilterDef.getPropertyValues().addPropertyValue(property,
new RuntimeBeanReference(beanRef));
}
else {
doSetInnerBeanDefinitions(exceptionFilterDef, element, property);
}
}
/**
*
* @param repositoryBeanDef
* @param element
* @param property
*/
private void doSetInnerBeanDefinitions(RootBeanDefinition exceptionFilterDef, Element accessDeniedElement,
String property) {
RootBeanDefinition accessDeniedHandlerBeanDef = new RootBeanDefinition(AccessDeniedHandlerImpl.class);
setPropertyIfAvailable(accessDeniedElement, ACCESS_DENIED_URL, "errorPage", accessDeniedHandlerBeanDef);
exceptionFilterDef.getPropertyValues().addPropertyValue(property, accessDeniedHandlerBeanDef);
}
private void setPropertyIfAvailable(Element element, String attribute, String property,
RootBeanDefinition definition) {
String propertyValue = element.getAttribute(attribute);
if (StringUtils.hasText(propertyValue)) {
definition.getPropertyValues().addPropertyValue(property, propertyValue);
}
}
}

View File

@ -0,0 +1,25 @@
/**
*
*/
package org.acegisecurity.config;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import junit.framework.TestCase;
/**
* @author vpuri
*
*/
public class AuthenticationProcessingFilterNamespaceTests extends TestCase {
public void testAuthenticationFilterBeanDefinition() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/acegisecurity/config/authentication-form-filter.xml");
ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) context
.getAutowireCapableBeanFactory();
}
}

View File

@ -0,0 +1,47 @@
package org.acegisecurity.config;
import javax.servlet.Filter;
import junit.framework.TestCase;
import org.acegisecurity.ui.ExceptionTranslationFilter;
import org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ExceptionTranslationParserTests extends TestCase {
public void testParsingBeanReferences() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/acegisecurity/config/exception-translation-beanref.xml");
ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) context
.getAutowireCapableBeanFactory();
String[] beanNames = factory.getBeanNamesForType(Filter.class);
assertEquals(1, beanNames.length);
RootBeanDefinition def = (RootBeanDefinition) factory.getBeanDefinition(beanNames[0]);
assertEquals(ExceptionTranslationFilter.class.getName(), def.getBeanClassName());
// check collaborators
PropertyValue accessDeniedHandler = def.getPropertyValues().getPropertyValue("accessDeniedHandler");
assertNotNull(accessDeniedHandler);
assertEquals(accessDeniedHandler.getValue(), new RuntimeBeanReference("theBeanToUse"));
PropertyValue entryPoint = def.getPropertyValues().getPropertyValue("authenticationEntryPoint");
assertNotNull(entryPoint);
assertEquals(entryPoint.getValue(), new RuntimeBeanReference("authenticationProcessingFilterEntryPoint"));
}
public void testRuntimeBeanDependencies() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"org/acegisecurity/config/exception-translation-beanref.xml");
ExceptionTranslationFilter filter = (ExceptionTranslationFilter) context.getBean("exceptionTranslationFilter");
AuthenticationProcessingFilterEntryPoint entryPoint = (AuthenticationProcessingFilterEntryPoint) filter
.getAuthenticationEntryPoint();
assertEquals("/acegilogin.jsp", entryPoint.getLoginFormUrl());
assertFalse(entryPoint.getForceHttps());
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
<!-- AuthenticationEntryPoints handled across the system via Ordered interface; every Acegi entry point has an order; the highest order wins and
is used as the entry point by ExceptionTranslationFilter; for things like BasicAuthenticationfilter, they're smart enough to know they need a
BasicAuthenticationProcessingFilterEntryPoint, so they use that one; here we have an entryPointOrder to say when we make the BasicEntryPoint,
we will call setOrder(2) such that this app effectively will use somehing with a higher order as the app-wide default -->
<security:authentication-basic id="id"
realmName="Spring Security Application" entryPointOrder="2" />
</beans>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
<!-- the URLs are all mandatory and have no defaults (well, except authenticationUrl) -->
<security:authentication-form id="authenticationProcessinFilter"
authenticationUrl="/login" defaultTargetUrl="/login.html"
errorFormUrl="error.html" />
<!-- make it optional, if not supplied autodetect all auth-providers from app ctx, using Ordered to resolve their order -->
<security:authentication-mechanism id="authenticationManager">
<security:authentication-jdbc ref="authenticationRepository"/>
</security:authentication-mechanism>
<!-- dao authentication provider -->
<security:authentication-repository id="authenticationRepository" repositoryBeanRef="userDetailsService"/>
<security:authentication-remember-me-services
id="rememberMeServices" key="someValue" />
<bean id="userDetailsService"
class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:mem:test</value>
<!-- <value>jdbc:hsqldb:hsql://localhost/acl</value> -->
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
</beans>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
<!-- Basically accessDeniedUrl is optional, we if unspecified impl will auto-detect any AccessDeniedHandler in ctx and use it;
alternately if there are > 1 such handlers, we can nominate the one to use via accessDeniedBeanRef; provide nested elements for
other props; i do not mind if you move the access denied stuff to a sub-element -->
<security:exception-translation id="exceptionTranslationFilter">
<security:entry-point
entryPointBeanRef="authenticationProcessingFilterEntryPoint" />
</security:exception-translation>
<bean id="theBeanToUse"
class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
<bean id="authenticationProcessingFilterEntryPoint"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl">
<value>/acegilogin.jsp</value>
</property>
<property name="forceHttps">
<value>false</value>
</property>
</bean>
</beans>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
<!-- Basically accessDeniedUrl is optional, we if unspecified impl will auto-detect any AccessDeniedHandler in ctx and use it;
alternately if there are > 1 such handlers, we can nominate the one to use via accessDeniedBeanRef; provide nested elements for
other props; i do not mind if you move the access denied stuff to a sub-element -->
<security:exception-translation id="exceptionTranslationFilter">
<security:access-denied accessDeniedBeanRef="theBeanToUse" />
<security:entry-point
entryPointBeanRef="authenticationProcessingFilterEntryPoint" />
</security:exception-translation>
<bean id="theBeanToUse"
class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
<bean id="authenticationProcessingFilterEntryPoint"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl">
<value>/acegilogin.jsp</value>
</property>
<property name="forceHttps">
<value>false</value>
</property>
</bean>
</beans>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- http://www.springframework.org/schema/security file:/Users/vpuri/interface21/acegisecurity/trunk/acegisecurity/core/src/main/resources/org/acegisecurity/config/spring-security-2.0.xsd -->
<!-- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd" -->
<!-- introspect all bean definitions for an explicit object of a "required" type, and if not found, add it. You can turn OFF ones you dont want added via attributes -->
<security:security-autoconfig exceptionTranslation="disable"
sessionContextIntegration="disable" logoutSupport="disable"
filterChain="disable" servletRequestEmulation="disabled"
anonyomousRoleGranter="disabled" />
</beans>