From ef3b9de7661af17a48ff7025463203e5fde2d940 Mon Sep 17 00:00:00 2001 From: Pascal Gehl Date: Wed, 21 Jan 2015 10:32:10 -0500 Subject: [PATCH] SEC-2825: Add And/Or MessageMatcher implementations --- .../AbstractMessageMatcherComposite.java | 71 +++++++++++ .../util/matcher/AndMessageMatcher.java | 62 +++++++++ .../util/matcher/OrMessageMatcher.java | 62 +++++++++ .../util/matcher/AndMessageMatcherTest.java | 119 ++++++++++++++++++ .../util/matcher/OrMessageMatcherTest.java | 119 ++++++++++++++++++ 5 files changed, 433 insertions(+) create mode 100644 messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java create mode 100644 messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java create mode 100644 messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java create mode 100644 messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java create mode 100644 messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java new file mode 100644 index 0000000000..b4b5821fa0 --- /dev/null +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AbstractMessageMatcherComposite.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * 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.springframework.security.messaging.util.matcher; + +import static java.util.Arrays.asList; +import static org.apache.commons.logging.LogFactory.getLog; +import static org.springframework.util.Assert.notEmpty; + +import java.util.List; + +import org.apache.commons.logging.Log; + +/** + * Abstract {@link MessageMatcher} containing multiple {@link MessageMatcher} + * + * @since 4.0 + */ +public abstract class AbstractMessageMatcherComposite implements MessageMatcher { + private final Log logger = getLog(getClass()); + + private final List> messageMatchers; + + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + public AbstractMessageMatcherComposite(List> messageMatchers) { + notEmpty(messageMatchers, "messageMatchers must contain a value"); + if (messageMatchers.contains(null)) { + throw new IllegalArgumentException("messageMatchers cannot contain null values"); + } + this.messageMatchers = messageMatchers; + + } + + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + @SafeVarargs + public AbstractMessageMatcherComposite(MessageMatcher... messagetMatchers) { + this(asList(messagetMatchers)); + } + + public List> getMessageMatchers() { + return messageMatchers; + } + + public Log getLogger() { + return logger; + } + @Override + public String toString() { + return getClass().getSimpleName()+ "[messageMatchers=" + messageMatchers + "]"; + } +} diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java new file mode 100644 index 0000000000..13ebe3deb4 --- /dev/null +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/AndMessageMatcher.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * 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.springframework.security.messaging.util.matcher; + +import java.util.List; + +import org.springframework.messaging.Message; + +/** + * {@link MessageMatcher} that will return true if all of the passed in {@link MessageMatcher} instances match. + * + * @since 4.0 + */ +public class AndMessageMatcher extends AbstractMessageMatcherComposite { + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + public AndMessageMatcher(List> messageMatchers) { + super(messageMatchers); + } + + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + @SafeVarargs + public AndMessageMatcher(MessageMatcher... messagetMatchers) { + super(messagetMatchers); + + } + + @Override + public boolean matches(Message message) { + for (MessageMatcher matcher : getMessageMatchers()) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Trying to match using " + matcher); + } + if (!matcher.matches(message)) { + getLogger().debug("Did not match"); + return false; + } + } + getLogger().debug("All messagetMatchers returned true"); + return true; + } +} \ No newline at end of file diff --git a/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java new file mode 100644 index 0000000000..ad51de41a4 --- /dev/null +++ b/messaging/src/main/java/org/springframework/security/messaging/util/matcher/OrMessageMatcher.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * 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.springframework.security.messaging.util.matcher; + +import java.util.List; + +import org.springframework.messaging.Message; + +/** + * {@link MessageMatcher} that will return true if any of the passed in {@link MessageMatcher} instances match. + * + * @since 4.0 + */ +public class OrMessageMatcher extends AbstractMessageMatcherComposite { + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + public OrMessageMatcher(List> messageMatchers) { + super(messageMatchers); + } + + /** + * Creates a new instance + * + * @param messageMatchers the {@link MessageMatcher} instances to try + */ + @SafeVarargs + public OrMessageMatcher(MessageMatcher... messagetMatchers) { + super(messagetMatchers); + + } + + @Override + public boolean matches(Message message) { + for (MessageMatcher matcher : getMessageMatchers()) { + if (getLogger().isDebugEnabled()) { + getLogger().debug("Trying to match using " + matcher); + } + if (matcher.matches(message)) { + getLogger().debug("matched"); + return true; + } + } + getLogger().debug("No matches found"); + return false; + } +} diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java new file mode 100644 index 0000000000..d7f26c044f --- /dev/null +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/AndMessageMatcherTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * 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.springframework.security.messaging.util.matcher; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.messaging.Message; + +@RunWith(MockitoJUnitRunner.class) +public class AndMessageMatcherTest { + @Mock + private MessageMatcher delegate; + + @Mock + private MessageMatcher delegate2; + + @Mock + private Message message; + + private MessageMatcher matcher; + + @Test(expected = NullPointerException.class) + public void constructorNullArray() { + new AndMessageMatcher((MessageMatcher[]) null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorArrayContainsNull() { + new AndMessageMatcher((MessageMatcher)null); + } + + @SuppressWarnings("unchecked") + @Test(expected = IllegalArgumentException.class) + public void constructorEmptyArray() { + new AndMessageMatcher((MessageMatcher[])new MessageMatcher[0]); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorNullList() { + new AndMessageMatcher((List>) null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorListContainsNull() { + new AndMessageMatcher(Arrays.asList((MessageMatcher)null)); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorEmptyList() { + new AndMessageMatcher(Collections.>emptyList()); + } + + @Test + public void matchesSingleTrue() { + when(delegate.matches(message)).thenReturn(true); + matcher = new AndMessageMatcher(delegate); + + assertThat(matcher.matches(message)).isTrue(); + } + + @Test + public void matchesMultiTrue() { + when(delegate.matches(message)).thenReturn(true); + when(delegate2.matches(message)).thenReturn(true); + matcher = new AndMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isTrue(); + } + + + @Test + public void matchesSingleFalse() { + when(delegate.matches(message)).thenReturn(false); + matcher = new AndMessageMatcher(delegate); + + assertThat(matcher.matches(message)).isFalse(); + } + + @Test + public void matchesMultiBothFalse() { + when(delegate.matches(message)).thenReturn(false); + when(delegate2.matches(message)).thenReturn(false); + matcher = new AndMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isFalse(); + } + + @Test + public void matchesMultiSingleFalse() { + when(delegate.matches(message)).thenReturn(true); + when(delegate2.matches(message)).thenReturn(false); + matcher = new AndMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isFalse(); + } +} + diff --git a/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java new file mode 100644 index 0000000000..16f1d0530b --- /dev/null +++ b/messaging/src/test/java/org/springframework/security/messaging/util/matcher/OrMessageMatcherTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2002-2015 the original author or authors. + * + * 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.springframework.security.messaging.util.matcher; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.messaging.Message; + +@RunWith(MockitoJUnitRunner.class) +public class OrMessageMatcherTest { + @Mock + private MessageMatcher delegate; + + @Mock + private MessageMatcher delegate2; + + @Mock + private Message message; + + private MessageMatcher matcher; + + @Test(expected = NullPointerException.class) + public void constructorNullArray() { + new OrMessageMatcher((MessageMatcher[]) null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorArrayContainsNull() { + new OrMessageMatcher((MessageMatcher)null); + } + + @SuppressWarnings("unchecked") + @Test(expected = IllegalArgumentException.class) + public void constructorEmptyArray() { + new OrMessageMatcher((MessageMatcher[])new MessageMatcher[0]); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorNullList() { + new OrMessageMatcher((List>) null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorListContainsNull() { + new OrMessageMatcher(Arrays.asList((MessageMatcher)null)); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorEmptyList() { + new OrMessageMatcher(Collections.>emptyList()); + } + + @Test + public void matchesSingleTrue() { + when(delegate.matches(message)).thenReturn(true); + matcher = new OrMessageMatcher(delegate); + + assertThat(matcher.matches(message)).isTrue(); + } + + @Test + public void matchesMultiTrue() { + when(delegate.matches(message)).thenReturn(true); + when(delegate2.matches(message)).thenReturn(true); + matcher = new OrMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isTrue(); + } + + + @Test + public void matchesSingleFalse() { + when(delegate.matches(message)).thenReturn(false); + matcher = new OrMessageMatcher(delegate); + + assertThat(matcher.matches(message)).isFalse(); + } + + @Test + public void matchesMultiBothFalse() { + when(delegate.matches(message)).thenReturn(false); + when(delegate2.matches(message)).thenReturn(false); + matcher = new OrMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isFalse(); + } + + @Test + public void matchesMultiSingleFalse() { + when(delegate.matches(message)).thenReturn(true); + when(delegate2.matches(message)).thenReturn(false); + matcher = new OrMessageMatcher(delegate, delegate2); + + assertThat(matcher.matches(message)).isTrue(); + } +} +