diff --git a/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java index e7a2610191..eefb646413 100644 --- a/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/AnonymousBeanDefinitionParser.java @@ -5,7 +5,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; -import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; @@ -22,13 +21,13 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_KEY = "key"; static final String DEF_KEY = "doesNotMatter"; - static final String ATT_USERNAME = "username"; - static final String DEF_USERNAME = "roleAnonymous"; + static final String ATT_USERNAME = "username"; + static final String DEF_USERNAME = "roleAnonymous"; - static final String ATT_GRANTED_AUTHORITY = "granted-authority"; - static final String DEF_GRANTED_AUTHORITY = "ROLE_ANONYMOUS"; + static final String ATT_GRANTED_AUTHORITY = "granted-authority"; + static final String DEF_GRANTED_AUTHORITY = "ROLE_ANONYMOUS"; - protected final Log logger = LogFactory.getLog(getClass()); + protected final Log logger = LogFactory.getLog(getClass()); public BeanDefinition parse(Element element, ParserContext parserContext) { String grantedAuthority = null; @@ -44,15 +43,15 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser { } if (!StringUtils.hasText(grantedAuthority)) { - grantedAuthority = DEF_GRANTED_AUTHORITY; + grantedAuthority = DEF_GRANTED_AUTHORITY; } if (!StringUtils.hasText(username)) { - username = DEF_USERNAME; + username = DEF_USERNAME; } if (!StringUtils.hasText(key)) { - key = DEF_KEY; + key = DEF_KEY; } RootBeanDefinition filter = new RootBeanDefinition(AnonymousProcessingFilter.class); @@ -65,14 +64,14 @@ public class AnonymousBeanDefinitionParser implements BeanDefinitionParser { provider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); provider.setSource(source); provider.getPropertyValues().addPropertyValue(ATT_KEY, key); - + parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER, provider); ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.ANONYMOUS_AUTHENTICATION_PROVIDER); parserContext.getRegistry().registerBeanDefinition(BeanIds.ANONYMOUS_PROCESSING_FILTER, filter); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.ANONYMOUS_PROCESSING_FILTER)); parserContext.registerComponent(new BeanComponentDefinition(filter, BeanIds.ANONYMOUS_PROCESSING_FILTER)); - + return null; } } diff --git a/core/src/main/java/org/springframework/security/config/ApacheDSContainer.java b/core/src/main/java/org/springframework/security/config/ApacheDSContainer.java index 584f09895d..b307551a2f 100644 --- a/core/src/main/java/org/springframework/security/config/ApacheDSContainer.java +++ b/core/src/main/java/org/springframework/security/config/ApacheDSContainer.java @@ -112,7 +112,7 @@ class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, configuration.setWorkingDirectory(workingDir); } - + @SuppressWarnings("unchecked") public void start() { if (isRunning()) { return; @@ -171,6 +171,7 @@ class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle, } + @SuppressWarnings("unchecked") public void stop() { Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, ServerContextFactory.class.getName()); diff --git a/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java index c9638e322f..f3a2d0852c 100644 --- a/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/ConcurrentSessionsBeanDefinitionParser.java @@ -31,50 +31,50 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar static final String ATT_EXCEPTION_IF_MAX_EXCEEDED = "exception-if-maximum-exceeded"; static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias"; static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref"; - + public BeanDefinition parse(Element element, ParserContext parserContext) { - CompositeComponentDefinition compositeDef = - new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); - parserContext.pushContainingComponent(compositeDef); - - BeanDefinitionRegistry beanRegistry = parserContext.getRegistry(); + CompositeComponentDefinition compositeDef = + new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); + parserContext.pushContainingComponent(compositeDef); + + BeanDefinitionRegistry beanRegistry = parserContext.getRegistry(); String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF); - - if (!StringUtils.hasText(sessionRegistryId)) { - RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class); + + if (!StringUtils.hasText(sessionRegistryId)) { + RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl.class); beanRegistry.registerBeanDefinition(BeanIds.SESSION_REGISTRY, sessionRegistry); parserContext.registerComponent(new BeanComponentDefinition(sessionRegistry, BeanIds.SESSION_REGISTRY)); sessionRegistryId = BeanIds.SESSION_REGISTRY; } else { - // Register the default ID as an alias so that things like session fixation filter can access it - beanRegistry.registerAlias(sessionRegistryId, BeanIds.SESSION_REGISTRY); + // Register the default ID as an alias so that things like session fixation filter can access it + beanRegistry.registerAlias(sessionRegistryId, BeanIds.SESSION_REGISTRY); } String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS); if (StringUtils.hasText(registryAlias)) { - beanRegistry.registerAlias(sessionRegistryId, registryAlias); - } + beanRegistry.registerAlias(sessionRegistryId, registryAlias); + } BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter.class); filterBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId)); Object source = parserContext.extractSource(element); - filterBuilder.setSource(source); + filterBuilder.getRawBeanDefinition().setSource(source); filterBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String expiryUrl = element.getAttribute(ATT_EXPIRY_URL); if (StringUtils.hasText(expiryUrl)) { - ConfigUtils.validateHttpRedirect(expiryUrl, parserContext, source); + ConfigUtils.validateHttpRedirect(expiryUrl, parserContext, source); filterBuilder.addPropertyValue("expiredUrl", expiryUrl); - } + } BeanDefinitionBuilder controllerBuilder - = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class); - controllerBuilder.setSource(source); - controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionControllerImpl.class); + controllerBuilder.getRawBeanDefinition().setSource(source); + controllerBuilder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); controllerBuilder.addPropertyValue("sessionRegistry", new RuntimeBeanReference(sessionRegistryId)); String maxSessions = element.getAttribute(ATT_MAX_SESSIONS); @@ -90,17 +90,17 @@ public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionPar } BeanDefinition controller = controllerBuilder.getBeanDefinition(); - + beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_CONTROLLER, controller); parserContext.registerComponent(new BeanComponentDefinition(controller, BeanIds.CONCURRENT_SESSION_CONTROLLER)); beanRegistry.registerBeanDefinition(BeanIds.CONCURRENT_SESSION_FILTER, filterBuilder.getBeanDefinition()); parserContext.registerComponent(new BeanComponentDefinition(filterBuilder.getBeanDefinition(), BeanIds.CONCURRENT_SESSION_FILTER)); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.CONCURRENT_SESSION_FILTER)); - + ConfigUtils.setSessionControllerOnAuthenticationManager(parserContext, BeanIds.CONCURRENT_SESSION_CONTROLLER, element); - + parserContext.popAndRegisterContainingComponent(); - + return null; } } diff --git a/core/src/main/java/org/springframework/security/config/ConfigUtils.java b/core/src/main/java/org/springframework/security/config/ConfigUtils.java index 1656d9026a..afaab55bee 100644 --- a/core/src/main/java/org/springframework/security/config/ConfigUtils.java +++ b/core/src/main/java/org/springframework/security/config/ConfigUtils.java @@ -31,6 +31,7 @@ import org.w3c.dom.Element; */ abstract class ConfigUtils { + @SuppressWarnings("unchecked") static void registerDefaultWebAccessManagerIfNecessary(ParserContext parserContext) { if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.WEB_ACCESS_MANAGER)) { parserContext.getRegistry().registerBeanDefinition(BeanIds.WEB_ACCESS_MANAGER, @@ -38,6 +39,7 @@ abstract class ConfigUtils { } } + @SuppressWarnings("unchecked") static void registerDefaultMethodAccessManagerIfNecessary(ParserContext parserContext) { if (!parserContext.getRegistry().containsBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER)) { parserContext.getRegistry().registerBeanDefinition(BeanIds.METHOD_ACCESS_MANAGER, @@ -45,6 +47,7 @@ abstract class ConfigUtils { } } + @SuppressWarnings("unchecked") private static BeanDefinition createAccessManagerBean(Class... voters) { ManagedList defaultVoters = new ManagedList(voters.length); @@ -122,6 +125,7 @@ abstract class ConfigUtils { pc.getRegistry().registerBeanDefinition(BeanIds.FILTER_LIST, filterList); } + @SuppressWarnings("unchecked") static void addHttpFilter(ParserContext pc, BeanMetadataElement filter) { registerFilterChainPostProcessorIfNecessary(pc); diff --git a/core/src/main/java/org/springframework/security/config/CustomAfterInvocationProviderBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/CustomAfterInvocationProviderBeanDefinitionDecorator.java index ab522a0dd7..326a863d8c 100644 --- a/core/src/main/java/org/springframework/security/config/CustomAfterInvocationProviderBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/CustomAfterInvocationProviderBeanDefinitionDecorator.java @@ -6,7 +6,7 @@ import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Node; /** - * Adds the decorated {@link org.springframework.security.afterinvocation.AfterInvocationProvider} to the + * Adds the decorated {@link org.springframework.security.afterinvocation.AfterInvocationProvider} to the * AfterInvocationProviderManager's list. * * @author Luke Taylor @@ -15,10 +15,11 @@ import org.w3c.dom.Node; */ public class CustomAfterInvocationProviderBeanDefinitionDecorator implements BeanDefinitionDecorator { - public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { + @SuppressWarnings("unchecked") + public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { ConfigUtils.getRegisteredAfterInvocationProviders(parserContext).add(holder.getBeanDefinition()); return holder; - } + } } diff --git a/core/src/main/java/org/springframework/security/config/CustomAuthenticationProviderBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/CustomAuthenticationProviderBeanDefinitionDecorator.java index 5bbdb38e57..5a1bc40e0e 100644 --- a/core/src/main/java/org/springframework/security/config/CustomAuthenticationProviderBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/CustomAuthenticationProviderBeanDefinitionDecorator.java @@ -1,13 +1,10 @@ package org.springframework.security.config; +import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.xml.BeanDefinitionDecorator; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.RuntimeBeanReference; - import org.w3c.dom.Node; - /** * Adds the decorated {@link org.springframework.security.providers.AuthenticationProvider} to the ProviderManager's * list. diff --git a/core/src/main/java/org/springframework/security/config/EntryPointInjectionBeanPostProcessor.java b/core/src/main/java/org/springframework/security/config/EntryPointInjectionBeanPostProcessor.java index a65486b60f..bf13438f80 100644 --- a/core/src/main/java/org/springframework/security/config/EntryPointInjectionBeanPostProcessor.java +++ b/core/src/main/java/org/springframework/security/config/EntryPointInjectionBeanPostProcessor.java @@ -14,25 +14,26 @@ import org.springframework.security.ui.ExceptionTranslationFilter; import org.springframework.util.Assert; /** - * + * * @author Luke Taylor * @since 2.0.2 */ public class EntryPointInjectionBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware { private final Log logger = LogFactory.getLog(getClass()); - private ConfigurableListableBeanFactory beanFactory; + private ConfigurableListableBeanFactory beanFactory; - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + @SuppressWarnings("unchecked") + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!BeanIds.EXCEPTION_TRANSLATION_FILTER.equals(beanName)) { - return bean; + return bean; } - + logger.info("Selecting AuthenticationEntryPoint for use in ExceptionTranslationFilter"); - - ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER); + + ExceptionTranslationFilter etf = (ExceptionTranslationFilter) beanFactory.getBean(BeanIds.EXCEPTION_TRANSLATION_FILTER); Object entryPoint = null; - + if (beanFactory.containsBean(BeanIds.MAIN_ENTRY_POINT)) { entryPoint = beanFactory.getBean(BeanIds.MAIN_ENTRY_POINT); logger.info("Using main configured AuthenticationEntryPoint."); @@ -42,18 +43,18 @@ public class EntryPointInjectionBeanPostProcessor implements BeanPostProcessor, Assert.isTrue(entryPoints.size() == 1, "More than one AuthenticationEntryPoint defined in context"); entryPoint = entryPoints.values().toArray()[0]; } - + logger.info("Using bean '" + entryPoint + "' as the entry point."); etf.setAuthenticationEntryPoint((AuthenticationEntryPoint) entryPoint); - - return bean; - } - - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; - } + return bean; + } + + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; + } } diff --git a/core/src/main/java/org/springframework/security/config/FilterChainMapBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/FilterChainMapBeanDefinitionDecorator.java index 7ca3e44ef1..c9800532ac 100644 --- a/core/src/main/java/org/springframework/security/config/FilterChainMapBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/FilterChainMapBeanDefinitionDecorator.java @@ -22,6 +22,8 @@ import java.util.*; * @version $Id$ */ class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDecorator { + + @SuppressWarnings("unchecked") public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder holder, ParserContext parserContext) { BeanDefinition filterChainProxy = holder.getBeanDefinition(); @@ -34,22 +36,20 @@ class FilterChainMapBeanDefinitionDecorator implements BeanDefinitionDecorator { filterChainProxy.getPropertyValues().addPropertyValue("matcher", new RegexUrlPathMatcher()); } - Iterator filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN).iterator(); + List filterChainElts = DomUtils.getChildElementsByTagName(elt, Elements.FILTER_CHAIN); - while (filterChainElts.hasNext()) { - Element chain = (Element) filterChainElts.next(); + for (Element chain : filterChainElts) { String path = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN); + String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); if(!StringUtils.hasText(path)) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_PATH_PATTERN + "' must not be empty", elt); } - String filters = chain.getAttribute(HttpSecurityBeanDefinitionParser.ATT_FILTERS); - if(!StringUtils.hasText(filters)) { parserContext.getReaderContext().error("The attribute '" + HttpSecurityBeanDefinitionParser.ATT_FILTERS + - "'must not be empty", elt); + "'must not be empty", elt); } if (filters.equals(HttpSecurityBeanDefinitionParser.OPT_FILTERS_NONE)) { diff --git a/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java b/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java index 08f833bf6f..cbfe31ef21 100644 --- a/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java +++ b/core/src/main/java/org/springframework/security/config/FilterChainProxyPostProcessor.java @@ -18,7 +18,7 @@ import org.springframework.core.OrderComparator; import org.springframework.core.Ordered; import org.springframework.security.ConfigAttribute; import org.springframework.security.config.ConfigUtils.FilterChainList; -import org.springframework.security.context.HttpSessionContextIntegrationFilter; +import org.springframework.security.context.SecurityContextPersistenceFilter; import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource; import org.springframework.security.intercept.web.FilterSecurityInterceptor; import org.springframework.security.providers.anonymous.AnonymousAuthenticationToken; @@ -98,7 +98,7 @@ public class FilterChainProxyPostProcessor implements BeanPostProcessor, BeanFac * Checks the filter list for possible errors and logs them */ private void checkFilterStack(List filters) { - checkForDuplicates(HttpSessionContextIntegrationFilter.class, filters); + checkForDuplicates(SecurityContextPersistenceFilter.class, filters); checkForDuplicates(AuthenticationProcessingFilter.class, filters); checkForDuplicates(SessionFixationProtectionFilter.class, filters); checkForDuplicates(BasicProcessingFilter.class, filters); diff --git a/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java index 20a6ac91ec..836d1e44ed 100644 --- a/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/FilterInvocationDefinitionSourceBeanDefinitionParser.java @@ -27,6 +27,7 @@ public class FilterInvocationDefinitionSourceBeanDefinitionParser extends Abstra return "org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource"; } + @SuppressWarnings("unchecked") protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { List interceptUrls = DomUtils.getChildElementsByTagName(element, "intercept-url"); diff --git a/core/src/main/java/org/springframework/security/config/FormLoginBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/FormLoginBeanDefinitionParser.java index 4e2756d43e..06a8bad3f8 100644 --- a/core/src/main/java/org/springframework/security/config/FormLoginBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/FormLoginBeanDefinitionParser.java @@ -29,7 +29,7 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { static final String DEF_LOGIN_PAGE = DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL; static final String ATT_FORM_LOGIN_TARGET_URL = "default-target-url"; - static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target"; + static final String ATT_ALWAYS_USE_DEFAULT_TARGET_URL = "always-use-default-target"; static final String DEF_FORM_LOGIN_TARGET_URL = "/"; static final String ATT_FORM_LOGIN_AUTHENTICATION_FAILURE_URL = "authentication-failure-url"; @@ -37,14 +37,14 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { String defaultLoginProcessingUrl; String filterClassName; - + RootBeanDefinition filterBean; RootBeanDefinition entryPointBean; String loginPage; - + FormLoginBeanDefinitionParser(String defaultLoginProcessingUrl, String filterClassName) { - this.defaultLoginProcessingUrl = defaultLoginProcessingUrl; - this.filterClassName = filterClassName; + this.defaultLoginProcessingUrl = defaultLoginProcessingUrl; + this.filterClassName = filterClassName; } public BeanDefinition parse(Element elt, ParserContext pc) { @@ -52,23 +52,23 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { String defaultTargetUrl = null; String authenticationFailureUrl = null; String alwaysUseDefault = null; - + Object source = null; - // Copy values from the session fixation protection filter - final Boolean sessionFixationProtectionEnabled = + // Copy values from the session fixation protection filter + final Boolean sessionFixationProtectionEnabled = new Boolean(pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER)); Boolean migrateSessionAttributes = Boolean.FALSE; - + if (sessionFixationProtectionEnabled.booleanValue()) { - PropertyValue pv = + PropertyValue pv = pc.getRegistry().getBeanDefinition(BeanIds.SESSION_FIXATION_PROTECTION_FILTER) .getPropertyValues().getPropertyValue("migrateSessionAttributes"); - migrateSessionAttributes = (Boolean)pv.getValue(); - } - + migrateSessionAttributes = (Boolean)pv.getValue(); + } + if (elt != null) { - source = pc.extractSource(elt); + source = pc.extractSource(elt); loginUrl = elt.getAttribute(ATT_LOGIN_URL); ConfigUtils.validateHttpRedirect(loginUrl, pc, source); defaultTargetUrl = elt.getAttribute(ATT_FORM_LOGIN_TARGET_URL); @@ -77,58 +77,58 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { ConfigUtils.validateHttpRedirect(authenticationFailureUrl, pc, source); alwaysUseDefault = elt.getAttribute(ATT_ALWAYS_USE_DEFAULT_TARGET_URL); loginPage = elt.getAttribute(ATT_LOGIN_PAGE); - + if (!StringUtils.hasText(loginPage)) { - loginPage = null; + loginPage = null; } ConfigUtils.validateHttpRedirect(loginPage, pc, source); - + } ConfigUtils.registerProviderManagerIfNecessary(pc); - + filterBean = createFilterBean(loginUrl, defaultTargetUrl, alwaysUseDefault, loginPage, authenticationFailureUrl); filterBean.setSource(source); filterBean.getPropertyValues().addPropertyValue("authenticationManager", new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); - - filterBean.getPropertyValues().addPropertyValue("invalidateSessionOnSuccessfulAuthentication", + + filterBean.getPropertyValues().addPropertyValue("invalidateSessionOnSuccessfulAuthentication", sessionFixationProtectionEnabled); - filterBean.getPropertyValues().addPropertyValue("migrateInvalidatedSessionAttributes", - migrateSessionAttributes); - + filterBean.getPropertyValues().addPropertyValue("migrateInvalidatedSessionAttributes", + migrateSessionAttributes); + if (pc.getRegistry().containsBeanDefinition(BeanIds.REMEMBER_ME_SERVICES)) { - filterBean.getPropertyValues().addPropertyValue("rememberMeServices", + filterBean.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES) ); } - + if (pc.getRegistry().containsBeanDefinition(BeanIds.SESSION_REGISTRY)) { - filterBean.getPropertyValues().addPropertyValue("sessionRegistry", + filterBean.getPropertyValues().addPropertyValue("sessionRegistry", new RuntimeBeanReference(BeanIds.SESSION_REGISTRY)); } BeanDefinitionBuilder entryPointBuilder = BeanDefinitionBuilder.rootBeanDefinition(AuthenticationProcessingFilterEntryPoint.class); - entryPointBuilder.setSource(source); + entryPointBuilder.getRawBeanDefinition().setSource(source); entryPointBuilder.addPropertyValue("loginFormUrl", loginPage != null ? loginPage : DEF_LOGIN_PAGE); entryPointBean = (RootBeanDefinition) entryPointBuilder.getBeanDefinition(); return null; } - private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault, - String loginPage, String authenticationFailureUrl) { - + private RootBeanDefinition createFilterBean(String loginUrl, String defaultTargetUrl, String alwaysUseDefault, + String loginPage, String authenticationFailureUrl) { + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName); if (!StringUtils.hasText(loginUrl)) { - loginUrl = defaultLoginProcessingUrl; + loginUrl = defaultLoginProcessingUrl; } if ("true".equals(alwaysUseDefault)) { - filterBuilder.addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE); + filterBuilder.addPropertyValue("alwaysUseDefaultTargetUrl", Boolean.TRUE); } - + filterBuilder.addPropertyValue("filterProcessesUrl", loginUrl); if (!StringUtils.hasText(defaultTargetUrl)) { @@ -138,12 +138,12 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { filterBuilder.addPropertyValue("defaultTargetUrl", defaultTargetUrl); if (!StringUtils.hasText(authenticationFailureUrl)) { - // Fallback to redisplaying the custom login page, if one was specified - if (StringUtils.hasText(loginPage)) { - authenticationFailureUrl = loginPage; - } else { + // Fallback to redisplaying the custom login page, if one was specified + if (StringUtils.hasText(loginPage)) { + authenticationFailureUrl = loginPage; + } else { authenticationFailureUrl = DEF_FORM_LOGIN_AUTHENTICATION_FAILURE_URL; - } + } } filterBuilder.addPropertyValue("authenticationFailureUrl", authenticationFailureUrl); @@ -151,15 +151,15 @@ public class FormLoginBeanDefinitionParser implements BeanDefinitionParser { return (RootBeanDefinition) filterBuilder.getBeanDefinition(); } - RootBeanDefinition getFilterBean() { - return filterBean; - } + RootBeanDefinition getFilterBean() { + return filterBean; + } - RootBeanDefinition getEntryPointBean() { - return entryPointBean; - } + RootBeanDefinition getEntryPointBean() { + return entryPointBean; + } - String getLoginPage() { - return loginPage; - } + String getLoginPage() { + return loginPage; + } } diff --git a/core/src/main/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParser.java index dceacde27a..9ec92c7ce6 100644 --- a/core/src/main/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/GlobalMethodSecurityBeanDefinitionParser.java @@ -1,7 +1,6 @@ package org.springframework.security.config; import java.util.ArrayList; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -30,7 +29,6 @@ import org.springframework.security.intercept.method.aopalliance.MethodSecurityI import org.springframework.security.vote.AffirmativeBased; import org.springframework.security.vote.AuthenticatedVoter; import org.springframework.security.vote.RoleVoter; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -67,6 +65,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { private static final String ATT_USE_SECURED = "secured-annotations"; private static final String ATT_USE_EXPRESSIONS = "expression-annotations"; + @SuppressWarnings("unchecked") public BeanDefinition parse(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); // The list of method metadata delegates @@ -92,7 +91,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { delegates.add(mapBasedMethodDefinitionSource); // Now create a Map for each sub-element - Map pointcutMap = parseProtectPointcuts(parserContext, + Map> pointcutMap = parseProtectPointcuts(parserContext, DomUtils.getChildElementsByTagName(element, Elements.PROTECT_POINTCUT)); if (pointcutMap.size() > 0) { @@ -122,6 +121,7 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { * expression voter if expression-based access control is enabled. If expressions are in use, a after-invocation * provider will also be registered to handle post-invocation filtering and authorization expression annotations. */ + @SuppressWarnings("unchecked") private void registerAccessManager(Element element, ParserContext pc, boolean jsr250Enabled, boolean expressionsEnabled) { Element expressionHandlerElt = DomUtils.getChildElementByTagName(element, Elements.EXPRESSION_HANDLER); BeanDefinitionBuilder accessMgrBuilder = BeanDefinitionBuilder.rootBeanDefinition(AffirmativeBased.class); @@ -170,7 +170,8 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { parserContext.getRegistry().registerBeanDefinition(DELEGATING_METHOD_DEFINITION_SOURCE_ID, delegatingMethodDefinitionSource); } - private void registerProtectPointcutPostProcessor(ParserContext parserContext, Map pointcutMap, + private void registerProtectPointcutPostProcessor(ParserContext parserContext, + Map> pointcutMap, MapBasedMethodDefinitionSource mapBasedMethodDefinitionSource, Object source) { RootBeanDefinition ppbp = new RootBeanDefinition(ProtectPointcutPostProcessor.class); ppbp.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); @@ -180,11 +181,10 @@ class GlobalMethodSecurityBeanDefinitionParser implements BeanDefinitionParser { parserContext.getRegistry().registerBeanDefinition(BeanIds.PROTECT_POINTCUT_POST_PROCESSOR, ppbp); } - private Map parseProtectPointcuts(ParserContext parserContext, List protectPointcutElts) { - Map pointcutMap = new LinkedHashMap(); + private Map> parseProtectPointcuts(ParserContext parserContext, List protectPointcutElts) { + Map> pointcutMap = new LinkedHashMap>(); - for (Iterator i = protectPointcutElts.iterator(); i.hasNext();) { - Element childElt = (Element) i.next(); + for (Element childElt : protectPointcutElts) { String accessConfig = childElt.getAttribute(ATT_ACCESS); String expression = childElt.getAttribute(ATT_EXPRESSION); diff --git a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java index 8676c9073b..d34c907af0 100644 --- a/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/HttpSecurityBeanDefinitionParser.java @@ -1,7 +1,6 @@ package org.springframework.security.config; import java.util.Collections; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -103,6 +102,9 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_USE_EXPRESSIONS = "use-expressions"; static final String DEF_USE_EXPRESSIONS = "false"; + static final String ATT_SECURITY_CONTEXT_REPOSITORY = "security-context-repository-ref"; + + @SuppressWarnings("unchecked") public BeanDefinition parse(Element element, ParserContext parserContext) { ConfigUtils.registerProviderManagerIfNecessary(parserContext); final BeanDefinitionRegistry registry = parserContext.getRegistry(); @@ -206,6 +208,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } } + @SuppressWarnings("unchecked") private void registerFilterChainProxy(ParserContext pc, Map filterChainMap, UrlMatcher matcher, Object source) { if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) { pc.getReaderContext().error("Duplicate element detected", source); @@ -222,24 +225,37 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { private boolean registerSecurityContextPersistenceFilter(Element element, ParserContext pc) { BeanDefinitionBuilder scpf = BeanDefinitionBuilder.rootBeanDefinition(SecurityContextPersistenceFilter.class); - BeanDefinitionBuilder contextRepo = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSecurityContextRepository.class); boolean sessionCreationAllowed = true; + String repoRef = element.getAttribute(ATT_SECURITY_CONTEXT_REPOSITORY); String createSession = element.getAttribute(ATT_CREATE_SESSION); - if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) { - contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); - scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); - } else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) { - contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE); - scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); - sessionCreationAllowed = false; - } else { - createSession = DEF_CREATE_SESSION_IF_REQUIRED; - contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); - scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); - } - scpf.addPropertyValue("securityContextRepository", contextRepo.getBeanDefinition()); + if (StringUtils.hasText(repoRef)) { + scpf.addPropertyReference("securityContextRepository", repoRef); + + if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) { + scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); + } else if (StringUtils.hasText(createSession)) { + pc.getReaderContext().error("If using security-context-repository-ref, the only value you can set for " + + "'create-session' is 'always'. Other session creation logic should be handled by the " + + "SecurityContextRepository", element); + } + } else { + BeanDefinitionBuilder contextRepo = BeanDefinitionBuilder.rootBeanDefinition(HttpSessionSecurityContextRepository.class); + if (OPT_CREATE_SESSION_ALWAYS.equals(createSession)) { + contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); + scpf.addPropertyValue("forceEagerSessionCreation", Boolean.TRUE); + } else if (OPT_CREATE_SESSION_NEVER.equals(createSession)) { + contextRepo.addPropertyValue("allowSessionCreation", Boolean.FALSE); + scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); + sessionCreationAllowed = false; + } else { + createSession = DEF_CREATE_SESSION_IF_REQUIRED; + contextRepo.addPropertyValue("allowSessionCreation", Boolean.TRUE); + scpf.addPropertyValue("forceEagerSessionCreation", Boolean.FALSE); + } + scpf.addPropertyValue("securityContextRepository", contextRepo.getBeanDefinition()); + } pc.getRegistry().registerBeanDefinition(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER, scpf.getBeanDefinition()); ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.SECURITY_CONTEXT_PERSISTENCE_FILTER)); @@ -292,7 +308,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { } private void registerFilterSecurityInterceptor(Element element, ParserContext pc, UrlMatcher matcher, - String accessManagerId, LinkedHashMap filterInvocationDefinitionMap) { + String accessManagerId, LinkedHashMap> filterInvocationDefinitionMap) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(FilterSecurityInterceptor.class); builder.addPropertyReference("accessDecisionManager", accessManagerId); @@ -311,6 +327,7 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.FILTER_SECURITY_INTERCEPTOR)); } + @SuppressWarnings("unchecked") private void registerChannelProcessingBeans(ParserContext pc, UrlMatcher matcher, LinkedHashMap channelRequestMap) { RootBeanDefinition channelFilter = new RootBeanDefinition(ChannelProcessingFilter.class); channelFilter.getPropertyValues().addPropertyValue("channelDecisionManager", @@ -535,15 +552,13 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { * Parses the intercept-url elements and populates the FilterChainProxy's filter chain Map and the * map used to create the FilterInvocationDefintionSource for the FilterSecurityInterceptor. */ - void parseInterceptUrlsForChannelSecurityAndFilterChain(List urlElts, Map filterChainMap, Map channelRequestMap, + @SuppressWarnings("unchecked") + void parseInterceptUrlsForChannelSecurityAndFilterChain(List urlElts, Map filterChainMap, Map channelRequestMap, boolean useLowerCasePaths, ParserContext parserContext) { - Iterator urlEltsIterator = urlElts.iterator(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); - while (urlEltsIterator.hasNext()) { - Element urlElt = (Element) urlEltsIterator.next(); - + for (Element urlElt : urlElts) { String path = urlElt.getAttribute(ATT_PATH_PATTERN); if(!StringUtils.hasText(path)) { diff --git a/core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java index 58ad96b26b..5c0468190a 100644 --- a/core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/InterceptMethodsBeanDefinitionDecorator.java @@ -1,10 +1,7 @@ package org.springframework.security.config; -import java.util.Iterator; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; @@ -45,8 +42,7 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto static final String ATT_ACCESS = "access"; private static final String ATT_ACCESS_MGR = "access-decision-manager-ref"; - private Log logger = LogFactory.getLog(getClass()); - + @SuppressWarnings("unchecked") protected BeanDefinition createInterceptorDefinition(Node node) { Element interceptMethodsElt = (Element)node; BeanDefinitionBuilder interceptor = BeanDefinitionBuilder.rootBeanDefinition(MethodSecurityInterceptor.class); @@ -66,16 +62,14 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto // Lookup parent bean information Element parent = (Element) node.getParentNode(); String parentBeanClass = parent.getAttribute("class"); - String parentBeanId = parent.getAttribute("id"); parent = null; // Parse the included methods - List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); + List methods = DomUtils.getChildElementsByTagName(interceptMethodsElt, Elements.PROTECT); StringBuffer sb = new StringBuffer(); - for (Iterator i = methods.iterator(); i.hasNext();) { - Element protectmethodElt = (Element) i.next(); + for (Element protectmethodElt : methods) { String accessConfig = protectmethodElt.getAttribute(ATT_ACCESS); // Support inference of class names diff --git a/core/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java index e9fa08a483..dd1e917117 100644 --- a/core/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/LdapProviderBeanDefinitionParser.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; @@ -22,54 +23,54 @@ import org.w3c.dom.Element; */ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { private Log logger = LogFactory.getLog(getClass()); - + private static final String ATT_USER_DN_PATTERN = "user-dn-pattern"; private static final String ATT_USER_PASSWORD = "password-attribute"; - private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH; - + private static final String ATT_HASH = PasswordEncoderParser.ATT_HASH; + private static final String DEF_USER_SEARCH_FILTER = "uid={0}"; - + private static final String PROVIDER_CLASS = "org.springframework.security.providers.ldap.LdapAuthenticationProvider"; private static final String BIND_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.BindAuthenticator"; private static final String PASSWD_AUTH_CLASS = "org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator"; public BeanDefinition parse(Element elt, ParserContext parserContext) { RuntimeBeanReference contextSource = LdapUserServiceBeanDefinitionParser.parseServerReference(elt, parserContext); - + BeanDefinition searchBean = LdapUserServiceBeanDefinitionParser.parseSearchBean(elt, parserContext); String userDnPattern = elt.getAttribute(ATT_USER_DN_PATTERN); - + String[] userDnPatternArray = new String[0]; - + if (StringUtils.hasText(userDnPattern)) { userDnPatternArray = new String[] {userDnPattern}; // TODO: Validate the pattern and make sure it is a valid DN. } else if (searchBean == null) { logger.info("No search information or DN pattern specified. Using default search filter '" + DEF_USER_SEARCH_FILTER + "'"); - BeanDefinitionBuilder searchBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS); - searchBeanBuilder.setSource(elt); - searchBeanBuilder.addConstructorArg(""); - searchBeanBuilder.addConstructorArg(DEF_USER_SEARCH_FILTER); - searchBeanBuilder.addConstructorArg(contextSource); + BeanDefinitionBuilder searchBeanBuilder = BeanDefinitionBuilder.rootBeanDefinition(LdapUserServiceBeanDefinitionParser.LDAP_SEARCH_CLASS); + searchBeanBuilder.getRawBeanDefinition().setSource(elt); + searchBeanBuilder.addConstructorArgValue(""); + searchBeanBuilder.addConstructorArgValue(DEF_USER_SEARCH_FILTER); + searchBeanBuilder.addConstructorArgValue(contextSource); searchBean = searchBeanBuilder.getBeanDefinition(); } - - BeanDefinitionBuilder authenticatorBuilder = - BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS); + + BeanDefinitionBuilder authenticatorBuilder = + BeanDefinitionBuilder.rootBeanDefinition(BIND_AUTH_CLASS); Element passwordCompareElt = DomUtils.getChildElementByTagName(elt, Elements.LDAP_PASSWORD_COMPARE); - + if (passwordCompareElt != null) { - authenticatorBuilder = - BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS); - + authenticatorBuilder = + BeanDefinitionBuilder.rootBeanDefinition(PASSWD_AUTH_CLASS); + String passwordAttribute = passwordCompareElt.getAttribute(ATT_USER_PASSWORD); if (StringUtils.hasText(passwordAttribute)) { - authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute); + authenticatorBuilder.addPropertyValue("passwordAttributeName", passwordAttribute); } - + Element passwordEncoderElement = DomUtils.getChildElementByTagName(passwordCompareElt, Elements.PASSWORD_ENCODER); String hash = passwordCompareElt.getAttribute(ATT_HASH); - + if (passwordEncoderElement != null) { if (StringUtils.hasText(hash)) { parserContext.getReaderContext().warning("Attribute 'hash' cannot be used with 'password-encoder' and " + @@ -77,31 +78,31 @@ public class LdapProviderBeanDefinitionParser implements BeanDefinitionParser { } PasswordEncoderParser pep = new PasswordEncoderParser(passwordEncoderElement, parserContext); authenticatorBuilder.addPropertyValue("passwordEncoder", pep.getPasswordEncoder()); - + if (pep.getSaltSource() != null) { - parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", - passwordEncoderElement); + parserContext.getReaderContext().warning("Salt source information isn't valid when used with LDAP", + passwordEncoderElement); } } else if (StringUtils.hasText(hash)) { - Class encoderClass = (Class) PasswordEncoderParser.ENCODER_CLASSES.get(hash); + Class encoderClass = PasswordEncoderParser.ENCODER_CLASSES.get(hash); authenticatorBuilder.addPropertyValue("passwordEncoder", new RootBeanDefinition(encoderClass)); } } - - authenticatorBuilder.addConstructorArg(contextSource); + + authenticatorBuilder.addConstructorArgValue(contextSource); authenticatorBuilder.addPropertyValue("userDnPatterns", userDnPatternArray); - + if (searchBean != null) { - authenticatorBuilder.addPropertyValue("userSearch", searchBean); + authenticatorBuilder.addPropertyValue("userSearch", searchBean); } - + BeanDefinitionBuilder ldapProvider = BeanDefinitionBuilder.rootBeanDefinition(PROVIDER_CLASS); - ldapProvider.addConstructorArg(authenticatorBuilder.getBeanDefinition()); - ldapProvider.addConstructorArg(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); - ldapProvider.addPropertyValue("userDetailsContextMapper", - LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext)); + ldapProvider.addConstructorArgValue(authenticatorBuilder.getBeanDefinition()); + ldapProvider.addConstructorArgValue(LdapUserServiceBeanDefinitionParser.parseAuthoritiesPopulator(elt, parserContext)); + ldapProvider.addPropertyValue("userDetailsContextMapper", + LdapUserServiceBeanDefinitionParser.parseUserDetailsClass(elt, parserContext)); parserContext.getRegistry().registerBeanDefinition(BeanIds.LDAP_AUTHENTICATION_PROVIDER, ldapProvider.getBeanDefinition()); - + ConfigUtils.addAuthenticationProvider(parserContext, BeanIds.LDAP_AUTHENTICATION_PROVIDER); return null; diff --git a/core/src/main/java/org/springframework/security/config/LdapServerBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/LdapServerBeanDefinitionParser.java index 5a91b91aa1..85ad1fbf4c 100644 --- a/core/src/main/java/org/springframework/security/config/LdapServerBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/LdapServerBeanDefinitionParser.java @@ -23,8 +23,8 @@ import org.apache.commons.logging.LogFactory; * @version $Id$ */ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { - private static final String CONTEXT_SOURCE_CLASS="org.springframework.security.ldap.DefaultSpringSecurityContextSource"; - + private static final String CONTEXT_SOURCE_CLASS="org.springframework.security.ldap.DefaultSpringSecurityContextSource"; + private final Log logger = LogFactory.getLog(getClass()); /** Defines the Url of the ldap server to use. If not specified, an embedded apache DS instance will be created */ @@ -96,15 +96,16 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { * * @see ApacheDSContainer */ + @SuppressWarnings("unchecked") private RootBeanDefinition createEmbeddedServer(Element element, ParserContext parserContext) { Object source = parserContext.extractSource(element); - BeanDefinitionBuilder configuration = - BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.configuration.MutableServerStartupConfiguration"); - BeanDefinitionBuilder partition = - BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration"); - configuration.setSource(source); - partition.setSource(source); - + BeanDefinitionBuilder configuration = + BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.configuration.MutableServerStartupConfiguration"); + BeanDefinitionBuilder partition = + BeanDefinitionBuilder.rootBeanDefinition("org.apache.directory.server.core.partition.impl.btree.MutableBTreePartitionConfiguration"); + configuration.getRawBeanDefinition().setSource(source); + partition.getRawBeanDefinition().setSource(source); + Attributes rootAttributes = new BasicAttributes("dc", "springsecurity"); Attribute a = new BasicAttribute("objectClass"); a.add("top"); @@ -143,7 +144,7 @@ public class LdapServerBeanDefinitionParser implements BeanDefinitionParser { String url = "ldap://127.0.0.1:" + port + "/" + suffix; BeanDefinitionBuilder contextSource = BeanDefinitionBuilder.rootBeanDefinition(CONTEXT_SOURCE_CLASS); - contextSource.addConstructorArg(url); + contextSource.addConstructorArgValue(url); contextSource.addPropertyValue("userDn", "uid=admin,ou=system"); contextSource.addPropertyValue("password", "secret"); diff --git a/core/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java index a0f050fb68..a5443fab4a 100644 --- a/core/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/LdapUserServiceBeanDefinitionParser.java @@ -46,8 +46,8 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ parserContext.getReaderContext().error("User search filter must be supplied", elt); } - builder.addConstructorArg(parseSearchBean(elt, parserContext)); - builder.addConstructorArg(parseAuthoritiesPopulator(elt, parserContext)); + builder.addConstructorArgValue(parseSearchBean(elt, parserContext)); + builder.addConstructorArgValue(parseAuthoritiesPopulator(elt, parserContext)); builder.addPropertyValue("userDetailsMapper", parseUserDetailsClass(elt, parserContext)); } @@ -69,10 +69,10 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ } BeanDefinitionBuilder searchBuilder = BeanDefinitionBuilder.rootBeanDefinition(LDAP_SEARCH_CLASS); - searchBuilder.setSource(source); - searchBuilder.addConstructorArg(userSearchBase); - searchBuilder.addConstructorArg(userSearchFilter); - searchBuilder.addConstructorArg(parseServerReference(elt, parserContext)); + searchBuilder.getRawBeanDefinition().setSource(source); + searchBuilder.addConstructorArgValue(userSearchBase); + searchBuilder.addConstructorArgValue(userSearchFilter); + searchBuilder.addConstructorArgValue(parseServerReference(elt, parserContext)); return (RootBeanDefinition) searchBuilder.getBeanDefinition(); } @@ -119,9 +119,9 @@ public class LdapUserServiceBeanDefinitionParser extends AbstractUserDetailsServ } BeanDefinitionBuilder populator = BeanDefinitionBuilder.rootBeanDefinition(LDAP_AUTHORITIES_POPULATOR_CLASS); - populator.setSource(parserContext.extractSource(elt)); - populator.addConstructorArg(parseServerReference(elt, parserContext)); - populator.addConstructorArg(groupSearchBase); + populator.getRawBeanDefinition().setSource(parserContext.extractSource(elt)); + populator.addConstructorArgValue(parseServerReference(elt, parserContext)); + populator.addConstructorArgValue(groupSearchBase); populator.addPropertyValue("groupSearchFilter", groupSearchFilter); populator.addPropertyValue("searchSubtree", Boolean.TRUE); diff --git a/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java index 023bf7fa44..93a43317ae 100644 --- a/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/LogoutBeanDefinitionParser.java @@ -18,30 +18,31 @@ import org.w3c.dom.Element; */ public class LogoutBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_LOGOUT_SUCCESS_URL = "logout-success-url"; - static final String DEF_LOGOUT_SUCCESS_URL = "/"; + static final String DEF_LOGOUT_SUCCESS_URL = "/"; - static final String ATT_INVALIDATE_SESSION = "invalidate-session"; - static final String DEF_INVALIDATE_SESSION = "true"; + static final String ATT_INVALIDATE_SESSION = "invalidate-session"; + static final String DEF_INVALIDATE_SESSION = "true"; - static final String ATT_LOGOUT_URL = "logout-url"; - static final String DEF_LOGOUT_URL = "/j_spring_security_logout"; - - String rememberMeServices; + static final String ATT_LOGOUT_URL = "logout-url"; + static final String DEF_LOGOUT_URL = "/j_spring_security_logout"; - public LogoutBeanDefinitionParser(String rememberMeServices) { - this.rememberMeServices = rememberMeServices; - } + String rememberMeServices; - public BeanDefinition parse(Element element, ParserContext parserContext) { - String logoutUrl = null; + public LogoutBeanDefinitionParser(String rememberMeServices) { + this.rememberMeServices = rememberMeServices; + } + + @SuppressWarnings("unchecked") + public BeanDefinition parse(Element element, ParserContext parserContext) { + String logoutUrl = null; String logoutSuccessUrl = null; String invalidateSession = null; BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); if (element != null) { - Object source = parserContext.extractSource(element); - builder.setSource(source); + Object source = parserContext.extractSource(element); + builder.getRawBeanDefinition().setSource(source); logoutUrl = element.getAttribute(ATT_LOGOUT_URL); ConfigUtils.validateHttpRedirect(logoutUrl, parserContext, source); logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL); @@ -50,25 +51,25 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser { } if (!StringUtils.hasText(logoutUrl)) { - logoutUrl = DEF_LOGOUT_URL; + logoutUrl = DEF_LOGOUT_URL; } builder.addPropertyValue("filterProcessesUrl", logoutUrl); if (!StringUtils.hasText(logoutSuccessUrl)) { logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL; } - builder.addConstructorArg(logoutSuccessUrl); + builder.addConstructorArgValue(logoutSuccessUrl); if (!StringUtils.hasText(invalidateSession)) { - invalidateSession = DEF_INVALIDATE_SESSION; + invalidateSession = DEF_INVALIDATE_SESSION; } ManagedList handlers = new ManagedList(); SecurityContextLogoutHandler sclh = new SecurityContextLogoutHandler(); if ("true".equals(invalidateSession)) { - sclh.setInvalidateHttpSession(true); + sclh.setInvalidateHttpSession(true); } else { - sclh.setInvalidateHttpSession(false); + sclh.setInvalidateHttpSession(false); } handlers.add(sclh); @@ -76,11 +77,11 @@ public class LogoutBeanDefinitionParser implements BeanDefinitionParser { handlers.add(new RuntimeBeanReference(rememberMeServices)); } - builder.addConstructorArg(handlers); + builder.addConstructorArgValue(handlers); parserContext.getRegistry().registerBeanDefinition(BeanIds.LOGOUT_FILTER, builder.getBeanDefinition()); ConfigUtils.addHttpFilter(parserContext, new RuntimeBeanReference(BeanIds.LOGOUT_FILTER)); - + return null; - } + } } diff --git a/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java b/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java index e1427642bb..0d61492296 100644 --- a/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java +++ b/core/src/main/java/org/springframework/security/config/OrderedFilterBeanDefinitionDecorator.java @@ -40,8 +40,8 @@ public class OrderedFilterBeanDefinitionDecorator implements BeanDefinitionDecor String order = getOrder(elt, parserContext); BeanDefinitionBuilder wrapper = BeanDefinitionBuilder.rootBeanDefinition("org.springframework.security.config.OrderedFilterBeanDefinitionDecorator$OrderedFilterDecorator"); - wrapper.addConstructorArg(holder.getBeanName()); - wrapper.addConstructorArg(new RuntimeBeanReference(holder.getBeanName())); + wrapper.addConstructorArgValue(holder.getBeanName()); + wrapper.addConstructorArgValue(new RuntimeBeanReference(holder.getBeanName())); if (StringUtils.hasText(order)) { wrapper.addPropertyValue("order", order); diff --git a/core/src/main/java/org/springframework/security/config/PasswordEncoderParser.java b/core/src/main/java/org/springframework/security/config/PasswordEncoderParser.java index 08b9a1f9d0..5f9b2ef8cc 100644 --- a/core/src/main/java/org/springframework/security/config/PasswordEncoderParser.java +++ b/core/src/main/java/org/springframework/security/config/PasswordEncoderParser.java @@ -2,6 +2,7 @@ package org.springframework.security.config; import org.springframework.security.providers.encoding.Md4PasswordEncoder; import org.springframework.security.providers.encoding.Md5PasswordEncoder; +import org.springframework.security.providers.encoding.PasswordEncoder; import org.springframework.security.providers.encoding.PlaintextPasswordEncoder; import org.springframework.security.providers.encoding.ShaPasswordEncoder; import org.springframework.security.providers.encoding.BaseDigestPasswordEncoder; @@ -33,17 +34,17 @@ public class PasswordEncoderParser { static final String ATT_REF = "ref"; static final String ATT_HASH = "hash"; static final String ATT_BASE_64 = "base64"; - static final String OPT_HASH_PLAINTEXT = "plaintext"; + static final String OPT_HASH_PLAINTEXT = "plaintext"; static final String OPT_HASH_SHA = "sha"; - static final String OPT_HASH_SHA256 = "sha-256"; + static final String OPT_HASH_SHA256 = "sha-256"; static final String OPT_HASH_MD4 = "md4"; static final String OPT_HASH_MD5 = "md5"; static final String OPT_HASH_LDAP_SHA = "{sha}"; - static final Map ENCODER_CLASSES; + static final Map> ENCODER_CLASSES; static { - ENCODER_CLASSES = new HashMap(); + ENCODER_CLASSES = new HashMap>(6); ENCODER_CLASSES.put(OPT_HASH_PLAINTEXT, PlaintextPasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_SHA, ShaPasswordEncoder.class); ENCODER_CLASSES.put(OPT_HASH_SHA256, ShaPasswordEncoder.class); @@ -64,7 +65,7 @@ public class PasswordEncoderParser { private void parse(Element element, ParserContext parserContext) { String hash = element.getAttribute(ATT_HASH); boolean useBase64 = false; - + if (StringUtils.hasText(element.getAttribute(ATT_BASE_64))) { useBase64 = new Boolean(element.getAttribute(ATT_BASE_64)).booleanValue(); } @@ -74,13 +75,13 @@ public class PasswordEncoderParser { if (StringUtils.hasText(ref)) { passwordEncoder = new RuntimeBeanReference(ref); } else { - Class beanClass = (Class) ENCODER_CLASSES.get(hash); + Class beanClass = ENCODER_CLASSES.get(hash); RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass); - + if (OPT_HASH_SHA256.equals(hash)) { - beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new Integer(256)); + beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, new Integer(256)); } - + beanDefinition.setSource(parserContext.extractSource(element)); if (useBase64) { if (BaseDigestPasswordEncoder.class.isAssignableFrom(beanClass)) { diff --git a/core/src/main/java/org/springframework/security/config/PortMappingsBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/PortMappingsBeanDefinitionParser.java index 27431dce16..d5ec6baf2f 100644 --- a/core/src/main/java/org/springframework/security/config/PortMappingsBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/PortMappingsBeanDefinitionParser.java @@ -11,7 +11,6 @@ import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import java.util.List; -import java.util.Iterator; import java.util.Map; import java.util.HashMap; @@ -26,21 +25,20 @@ public class PortMappingsBeanDefinitionParser implements BeanDefinitionParser { public static final String ATT_HTTP_PORT = "http"; public static final String ATT_HTTPS_PORT = "https"; + @SuppressWarnings("unchecked") public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition portMapper = new RootBeanDefinition(PortMapperImpl.class); portMapper.setSource(parserContext.extractSource(element)); if (element != null) { - List mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING); + List mappingElts = DomUtils.getChildElementsByTagName(element, Elements.PORT_MAPPING); if(mappingElts.isEmpty()) { parserContext.getReaderContext().error("No port-mapping child elements specified", element); } Map mappings = new HashMap(); - Iterator iterator = mappingElts.iterator(); - while (iterator.hasNext()) { - Element elt = (Element) iterator.next(); + for (Element elt : mappingElts) { String httpPort = elt.getAttribute(ATT_HTTP_PORT); String httpsPort = elt.getAttribute(ATT_HTTPS_PORT); diff --git a/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java b/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java index bc0cc6a72f..c5ec0d9763 100644 --- a/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java +++ b/core/src/main/java/org/springframework/security/config/RememberMeBeanDefinitionParser.java @@ -4,7 +4,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; @@ -25,14 +24,14 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_KEY = "key"; static final String DEF_KEY = "SpringSecured"; - static final String ATT_DATA_SOURCE = "data-source-ref"; - static final String ATT_SERVICES_REF = "services-ref"; - static final String ATT_TOKEN_REPOSITORY = "token-repository-ref"; - static final String ATT_USER_SERVICE_REF = "user-service-ref"; - static final String ATT_TOKEN_VALIDITY = "token-validity-seconds"; + static final String ATT_DATA_SOURCE = "data-source-ref"; + static final String ATT_SERVICES_REF = "services-ref"; + static final String ATT_TOKEN_REPOSITORY = "token-repository-ref"; + static final String ATT_USER_SERVICE_REF = "user-service-ref"; + static final String ATT_TOKEN_VALIDITY = "token-validity-seconds"; - protected final Log logger = LogFactory.getLog(getClass()); - private String servicesName; + protected final Log logger = LogFactory.getLog(getClass()); + private String servicesName; public BeanDefinition parse(Element element, ParserContext parserContext) { String tokenRepository = null; @@ -52,11 +51,11 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { tokenValiditySeconds = element.getAttribute(ATT_TOKEN_VALIDITY); source = parserContext.extractSource(element); } - + if (!StringUtils.hasText(key)) { - key = DEF_KEY; - } - + key = DEF_KEY; + } + RootBeanDefinition services = null; boolean dataSourceSet = StringUtils.hasText(dataSource); @@ -64,15 +63,15 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { boolean servicesRefSet = StringUtils.hasText(rememberMeServicesRef); boolean userServiceSet = StringUtils.hasText(userServiceRef); boolean tokenValiditySet = StringUtils.hasText(tokenValiditySeconds); - + if (servicesRefSet && (dataSourceSet || tokenRepoSet || userServiceSet || tokenValiditySet)) { - parserContext.getReaderContext().error(ATT_SERVICES_REF + " can't be used in combination with attributes " - + ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + " or " + ATT_TOKEN_VALIDITY, source); + parserContext.getReaderContext().error(ATT_SERVICES_REF + " can't be used in combination with attributes " + + ATT_TOKEN_REPOSITORY + "," + ATT_DATA_SOURCE + ", " + ATT_USER_SERVICE_REF + " or " + ATT_TOKEN_VALIDITY, source); } - + if (dataSourceSet && tokenRepoSet) { - parserContext.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + - ATT_DATA_SOURCE +" but not both", source); + parserContext.getReaderContext().error("Specify " + ATT_TOKEN_REPOSITORY + " or " + + ATT_DATA_SOURCE +" but not both", source); } boolean isPersistent = dataSourceSet | tokenRepoSet; @@ -94,34 +93,34 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { } if (services != null) { - if (userServiceSet) { - services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef)); - } - - if (tokenValiditySet) { - services.getPropertyValues().addPropertyValue("tokenValiditySeconds", new Integer(tokenValiditySeconds)); - } - services.setSource(source); - services.getPropertyValues().addPropertyValue(ATT_KEY, key); - parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services); - servicesName = BeanIds.REMEMBER_ME_SERVICES; + if (userServiceSet) { + services.getPropertyValues().addPropertyValue("userDetailsService", new RuntimeBeanReference(userServiceRef)); + } + + if (tokenValiditySet) { + services.getPropertyValues().addPropertyValue("tokenValiditySeconds", new Integer(tokenValiditySeconds)); + } + services.setSource(source); + services.getPropertyValues().addPropertyValue(ATT_KEY, key); + parserContext.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_SERVICES, services); + servicesName = BeanIds.REMEMBER_ME_SERVICES; } else { - servicesName = rememberMeServicesRef; - parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES); + servicesName = rememberMeServicesRef; + parserContext.getRegistry().registerAlias(rememberMeServicesRef, BeanIds.REMEMBER_ME_SERVICES); } - - registerProvider(parserContext, source, key); - + + registerProvider(parserContext, source, key); + registerFilter(parserContext, source); return null; } - - String getServicesName() { - return servicesName; - } - private void registerProvider(ParserContext pc, Object source, String key) { + String getServicesName() { + return servicesName; + } + + private void registerProvider(ParserContext pc, Object source, String key) { //BeanDefinition authManager = ConfigUtils.registerProviderManagerIfNecessary(pc); RootBeanDefinition provider = new RootBeanDefinition(RememberMeAuthenticationProvider.class); provider.setSource(source); @@ -129,17 +128,17 @@ public class RememberMeBeanDefinitionParser implements BeanDefinitionParser { pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER, provider); ConfigUtils.addAuthenticationProvider(pc, BeanIds.REMEMBER_ME_AUTHENTICATION_PROVIDER); } - + private void registerFilter(ParserContext pc, Object source) { RootBeanDefinition filter = new RootBeanDefinition(RememberMeProcessingFilter.class); filter.setSource(source); filter.getPropertyValues().addPropertyValue("authenticationManager", - new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); - + new RuntimeBeanReference(BeanIds.AUTHENTICATION_MANAGER)); + filter.getPropertyValues().addPropertyValue("rememberMeServices", new RuntimeBeanReference(BeanIds.REMEMBER_ME_SERVICES)); pc.getRegistry().registerBeanDefinition(BeanIds.REMEMBER_ME_FILTER, filter); - ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER)); + ConfigUtils.addHttpFilter(pc, new RuntimeBeanReference(BeanIds.REMEMBER_ME_FILTER)); } }