From 46af40046656db29c383f1038260e4b920874516 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Thu, 6 Jul 2006 17:05:08 +0000 Subject: [PATCH] Added FilterInvocationDefinition interface to unify FilterInvocationDefinitionSource and FilterInvocationDefinitionMap --- .../web/FilterInvocationDefinition.java | 27 ++++++ ... FilterInvocationDefinitionDecorator.java} | 76 +++++++++++++---- ...ilterInvocationDefinitionSourceEditor.java | 11 ++- ...athBasedFilterInvocationDefinitionMap.java | 2 +- ...ExpBasedFilterInvocationDefinitionMap.java | 2 +- ...lterInvocationDefinitionDecoratorTest.java | 82 +++++++++++++++++++ .../web/FilterSecurityInterceptorTests.java | 2 +- .../web/MockFilterInvocationDefinition.java | 64 +++++++++++++++ 8 files changed, 243 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.java rename core/src/main/java/org/acegisecurity/intercept/web/{FilterInvocationDefinitionMapDecorator.java => FilterInvocationDefinitionDecorator.java} (56%) create mode 100644 core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecoratorTest.java create mode 100644 core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinition.java diff --git a/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.java b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.java new file mode 100644 index 0000000000..5587936eeb --- /dev/null +++ b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinition.java @@ -0,0 +1,27 @@ +/* Copyright 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.acegisecurity.intercept.web; + +/** + * Interface to join {@link FilterInvocationDefinitionMap} and + * {@link FilterInvocationDefinitionSource}. + * + * @author Carlos Sanchez + * @version $Id$ + * @since 1.1 + */ +public interface FilterInvocationDefinition extends FilterInvocationDefinitionMap, FilterInvocationDefinitionSource { +} diff --git a/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapDecorator.java b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecorator.java similarity index 56% rename from core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapDecorator.java rename to core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecorator.java index 917c282ee3..69bf9ef9e2 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapDecorator.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecorator.java @@ -22,23 +22,31 @@ import org.acegisecurity.ConfigAttributeDefinition; import org.acegisecurity.SecurityConfig; /** - * Decorator of {@link FilterInvocationDefinitionMap} for easier configuration, + *

+ * Decorator of {@link FilterInvocationDefinition} for easier configuration, * using {@link FilterInvocationDefinitionSourceMapping}. + *

+ * + *

+ * Delegates all calls to decorated object set in constructor + * {@link #FilterInvocationDefinitionDecorator(FilterInvocationDefinition)} or + * by calling {@link #setDecorated(FilterInvocationDefinition)} + *

* * @author Carlos Sanchez * @version $Id$ + * @since 1.1 */ -public class FilterInvocationDefinitionMapDecorator { +public class FilterInvocationDefinitionDecorator implements FilterInvocationDefinition { - private FilterInvocationDefinitionMap decorated; + private FilterInvocationDefinition decorated; private List mappings; - public FilterInvocationDefinitionMapDecorator() { + public FilterInvocationDefinitionDecorator() { } - public FilterInvocationDefinitionMapDecorator( - FilterInvocationDefinitionMap decorated) { + public FilterInvocationDefinitionDecorator(FilterInvocationDefinition decorated) { this.setDecorated(decorated); } @@ -46,18 +54,18 @@ public class FilterInvocationDefinitionMapDecorator { * Set the decorated object * * @param decorated - * the decorated {@link FilterInvocationDefinitionMap} + * the decorated {@link FilterInvocationDefinition} */ - public void setDecorated(FilterInvocationDefinitionMap decorated) { + public void setDecorated(FilterInvocationDefinition decorated) { this.decorated = decorated; } /** * Get decorated object * - * @return the decorated {@link FilterInvocationDefinitionMap} + * @return the decorated {@link FilterInvocationDefinition} */ - public FilterInvocationDefinitionMap getDecorated() { + public FilterInvocationDefinition getDecorated() { return decorated; } @@ -78,12 +86,10 @@ public class FilterInvocationDefinitionMapDecorator { this.mappings = mappings; Iterator it = mappings.iterator(); while (it.hasNext()) { - FilterInvocationDefinitionSourceMapping mapping = (FilterInvocationDefinitionSourceMapping) it - .next(); + FilterInvocationDefinitionSourceMapping mapping = (FilterInvocationDefinitionSourceMapping) it.next(); ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); - Iterator configAttributesIt = mapping.getConfigAttributes() - .iterator(); + Iterator configAttributesIt = mapping.getConfigAttributes().iterator(); while (configAttributesIt.hasNext()) { String s = (String) configAttributesIt.next(); configDefinition.addConfigAttribute(new SecurityConfig(s)); @@ -102,4 +108,46 @@ public class FilterInvocationDefinitionMapDecorator { public List getMappings() { return mappings; } + + /** + * Delegate to decorated object + */ + public void addSecureUrl(String expression, ConfigAttributeDefinition attr) { + getDecorated().addSecureUrl(expression, attr); + } + + /** + * Delegate to decorated object + */ + public boolean isConvertUrlToLowercaseBeforeComparison() { + return getDecorated().isConvertUrlToLowercaseBeforeComparison(); + } + + /** + * Delegate to decorated object + */ + public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { + getDecorated().setConvertUrlToLowercaseBeforeComparison(convertUrlToLowercaseBeforeComparison); + } + + /** + * Delegate to decorated object + */ + public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { + return getDecorated().getAttributes(object); + } + + /** + * Delegate to decorated object + */ + public Iterator getConfigAttributeDefinitions() { + return getDecorated().getConfigAttributeDefinitions(); + } + + /** + * Delegate to decorated object + */ + public boolean supports(Class clazz) { + return getDecorated().supports(clazz); + } } diff --git a/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditor.java b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditor.java index 1fb957cc8e..7b8450bbca 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditor.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditor.java @@ -49,14 +49,15 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor //~ Methods ======================================================================================================== public void setAsText(String s) throws IllegalArgumentException { - FilterInvocationDefinitionMap source = new RegExpBasedFilterInvocationDefinitionMap(); + FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator(); + source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap()); if ((s == null) || "".equals(s)) { // Leave target object empty } else { // Check if we need to override the default definition map if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) { - source = new PathBasedFilterInvocationDefinitionMap(); + source.setDecorated(new PathBasedFilterInvocationDefinitionMap()); if (logger.isDebugEnabled()) { logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT @@ -139,7 +140,7 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor // Attempt to detect malformed lines (as per SEC-204) if (source.isConvertUrlToLowercaseBeforeComparison() - && source instanceof PathBasedFilterInvocationDefinitionMap) { + && source.getDecorated() instanceof PathBasedFilterInvocationDefinitionMap) { // Should all be lowercase; check each character // We only do this for Ant (regexp have control chars) for (int i = 0; i < name.length(); i++) { @@ -166,9 +167,7 @@ public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSuppor mappings.add(mapping); } - FilterInvocationDefinitionMapDecorator decorator = new FilterInvocationDefinitionMapDecorator( - source); - decorator.setMappings(mappings); + source.setMappings(mappings); } setValue(source); diff --git a/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDefinitionMap.java b/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDefinitionMap.java index fdfb9960e1..2c0aaaeee4 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDefinitionMap.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/PathBasedFilterInvocationDefinitionMap.java @@ -44,7 +44,7 @@ import java.util.Vector; * @version $Id$ */ public class PathBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource - implements FilterInvocationDefinitionMap { + implements FilterInvocationDefinition { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class); diff --git a/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationDefinitionMap.java b/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationDefinitionMap.java index 7aa88a3988..ad50e8da08 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationDefinitionMap.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/RegExpBasedFilterInvocationDefinitionMap.java @@ -45,7 +45,7 @@ import java.util.Vector; *

If no registered regular expressions match the HTTP URL, null is returned.

*/ public class RegExpBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource - implements FilterInvocationDefinitionMap { + implements FilterInvocationDefinition { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(RegExpBasedFilterInvocationDefinitionMap.class); diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecoratorTest.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecoratorTest.java new file mode 100644 index 0000000000..43aeedf28c --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionDecoratorTest.java @@ -0,0 +1,82 @@ +/* Copyright 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.acegisecurity.intercept.web; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.acegisecurity.ConfigAttributeDefinition; +import org.acegisecurity.SecurityConfig; + +import junit.framework.TestCase; + +/** + * Test for {@link FilterInvocationDefinitionDecorator} + * + * @author Carlos Sanchez + * @version $Id$ + */ +public class FilterInvocationDefinitionDecoratorTest extends TestCase { + + private FilterInvocationDefinitionDecorator decorator; + + private FilterInvocationDefinition decorated; + + protected void setUp() throws Exception { + super.setUp(); + decorated = new MockFilterInvocationDefinition(); + decorator = new FilterInvocationDefinitionDecorator(decorated); + } + + public void testFilterInvocationDefinitionMapDecorator() { + decorator = new FilterInvocationDefinitionDecorator(); + decorator.setDecorated(decorated); + assertEquals(decorated, decorator.getDecorated()); + } + + public void testSetMappings() { + List roles = new ArrayList(); + roles.add("ROLE_USER"); + roles.add("ROLE_ADMIN"); + + FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping(); + mapping.setUrl("/secure/**"); + mapping.setConfigAttributes(roles); + + List mappings = new ArrayList(); + mappings.add(mapping); + + decorator.setMappings(mappings); + + ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition(); + Iterator it = roles.iterator(); + while (it.hasNext()) { + String role = (String) it.next(); + configDefinition.addConfigAttribute(new SecurityConfig(role)); + } + + it = decorator.getConfigAttributeDefinitions(); + int i = 0; + while (it.hasNext()) { + i++; + assertEquals(configDefinition, it.next()); + } + assertEquals(1, i); + + assertEquals(mappings, decorator.getMappings()); + } +} diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java index 29c576d04f..019c4a6a90 100644 --- a/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java +++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java @@ -241,7 +241,7 @@ public class FilterSecurityInterceptorTests extends TestCase { PathBasedFilterInvocationDefinitionMap filterInvocationDefinitionSource = new PathBasedFilterInvocationDefinitionMap(); filterInvocationDefinitionSource .setConvertUrlToLowercaseBeforeComparison(true); - FilterInvocationDefinitionMapDecorator decorator = new FilterInvocationDefinitionMapDecorator( + FilterInvocationDefinitionDecorator decorator = new FilterInvocationDefinitionDecorator( filterInvocationDefinitionSource); decorator.setMappings(mappings); diff --git a/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinition.java b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinition.java new file mode 100644 index 0000000000..40449ecdc8 --- /dev/null +++ b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinition.java @@ -0,0 +1,64 @@ +/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.acegisecurity.intercept.web; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.acegisecurity.ConfigAttributeDefinition; + +/** + * Mock for {@link FilterInvocationDefinitionMap} + * + * @author Carlos Sanchez + * @version $Id: MockFilterInvocationDefinitionSource.java 1496 2006-05-23 + * 13:38:33Z benalex $ + */ +public class MockFilterInvocationDefinition implements FilterInvocationDefinition { + + private Map secureUrls = new HashMap(); + + private boolean convertUrlToLowercaseBeforeComparison = false; + + public void addSecureUrl(String expression, ConfigAttributeDefinition attr) { + secureUrls.put(expression, attr); + } + + public boolean isConvertUrlToLowercaseBeforeComparison() { + return convertUrlToLowercaseBeforeComparison; + } + + public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) { + this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison; + } + + public ConfigAttributeDefinition getSecureUrl(String expression) { + return (ConfigAttributeDefinition) secureUrls.get(expression); + } + + public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { + return (ConfigAttributeDefinition) secureUrls.get(object); + } + + public Iterator getConfigAttributeDefinitions() { + return secureUrls.values().iterator(); + } + + public boolean supports(Class clazz) { + return true; + } +}