[spring-extensions] branch main updated: IDP-1652 - Redesign handling of lists of descriptors
Scott Cantor
cantor.2 at osu.edu
Tue Aug 18 15:29:24 UTC 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository spring-extensions.
View the commit online:
http://git.shibboleth.net/view/?p=spring-extensions.git;a=commit;h=502227bebf371a45b89af4c299c8b10a8e7bef9b
The following commit(s) were added to refs/heads/main by this push:
new 502227b IDP-1652 - Redesign handling of lists of descriptors
502227b is described below
commit 502227bebf371a45b89af4c299c8b10a8e7bef9b
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Aug 18 11:29:16 2020 -0400
IDP-1652 - Redesign handling of lists of descriptors
https://issues.shibboleth.net/jira/browse/IDP-1652
Utility class to merge static lists and Autowired objects.
---
.../spring/util/IdentifiedComponentManager.java | 102 +++++++++++++
.../util/IdentifiedComponentManagerTest.java | 167 +++++++++++++++++++++
.../net/shibboleth/ext/spring/util/combined.xml | 28 ++++
.../net/shibboleth/ext/spring/util/freeOnly.xml | 26 ++++
.../net/shibboleth/ext/spring/util/overlap.xml | 29 ++++
.../net/shibboleth/ext/spring/util/staticOnly.xml | 27 ++++
6 files changed, 379 insertions(+)
diff --git a/src/main/java/net/shibboleth/ext/spring/util/IdentifiedComponentManager.java b/src/main/java/net/shibboleth/ext/spring/util/IdentifiedComponentManager.java
new file mode 100644
index 0000000..08a89a1
--- /dev/null
+++ b/src/main/java/net/shibboleth/ext/spring/util/IdentifiedComponentManager.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.ext.spring.util;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.IdentifiedComponent;
+
+/**
+ * Class used for auto-wiring free-standing identified objects along with explicitly declared
+ * bean collections.
+ *
+ * <p>This class marries old-style "explicit" list-based configuration of a collection of
+ * objects with annotation-driven discovery of objects of the same type.</p>
+ *
+ * <p>Specializations of this class are expected to fix the type and add an Autowired
+ * constructor to receive the free-standing objects.</p>
+ *
+ * @param <T> descriptor type
+ */
+public class IdentifiedComponentManager<T extends IdentifiedComponent> {
+
+ /** Class logger. */
+ @Nonnull private Logger log = LoggerFactory.getLogger(IdentifiedComponentManager.class);
+
+ /** Underlying collection. */
+ @Nonnull @NonnullElements private Collection<T> components;
+
+ /**
+ * Auto-wiring point for free-standing objects.
+ *
+ * @param freeObjects free-standing objects
+ */
+ public IdentifiedComponentManager(@Nullable @NonnullElements final Collection<T> freeObjects) {
+ if (freeObjects != null) {
+ components = List.copyOf(freeObjects);
+ } else {
+ components = Collections.emptyList();
+ }
+ }
+
+ /**
+ * Sets additional non-autowired components to merge in.
+ *
+ * <p>For now, this set is prepended to any auto-wired objects and any auto-wired objects
+ * are excluded if they have the same identifier as an explicitly injected object.</p>
+ *
+ * @param additionalObjects additional objects
+ */
+ public void setComponents(@Nullable @NonnullElements final Collection<T> additionalObjects) {
+ if (additionalObjects != null) {
+ final Collection<T> holder = new LinkedHashSet<>(additionalObjects);
+ holder.addAll(
+ components.stream()
+ .filter(obj -> {
+ if (holder.contains(obj)) {
+ log.info("Replacing auto-wired component: {}", obj.getId());
+ return false;
+ }
+ return true;
+ })
+ .collect(Collectors.toUnmodifiableList()));
+ components = List.copyOf(holder);
+ }
+ }
+
+ /**
+ * Gets the final collection of merged components.
+ *
+ * @return merged components
+ */
+ @Nonnull @NonnullElements public Collection<T> getComponents() {
+ return components;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/net/shibboleth/ext/spring/util/IdentifiedComponentManagerTest.java b/src/test/java/net/shibboleth/ext/spring/util/IdentifiedComponentManagerTest.java
new file mode 100644
index 0000000..dbb9690
--- /dev/null
+++ b/src/test/java/net/shibboleth/ext/spring/util/IdentifiedComponentManagerTest.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 net.shibboleth.ext.spring.util;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.annotation.Nonnull;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiableInitializableComponent;
+
+/**
+ * Test for {@link IdentifiedComponentManager}.
+ */
+ at SuppressWarnings("javadoc")
+public class IdentifiedComponentManagerTest {
+
+ @Test public void testCombining() {
+ final ApplicationContext context = getContext("net/shibboleth/ext/spring/util/combined.xml");
+
+ final MockComponentManager manager = context.getBean(MockComponentManager.class);
+ Assert.assertNotNull(manager);
+ Assert.assertEquals(manager.getComponents().size(), 3);
+
+ Iterator<MockComponent> i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getId(), "One");
+ Assert.assertEquals(i.next().getId(), "Two");
+ Assert.assertEquals(i.next().getId(), "Three");
+
+ i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getData(), "Foo1");
+ Assert.assertEquals(i.next().getData(), "Foo2");
+ Assert.assertEquals(i.next().getData(), "Foo3");
+ }
+
+ @Test public void testOverlap() {
+ final ApplicationContext context = getContext("net/shibboleth/ext/spring/util/overlap.xml");
+
+ final MockComponentManager manager = context.getBean(MockComponentManager.class);
+ Assert.assertNotNull(manager);
+ Assert.assertEquals(manager.getComponents().size(), 3);
+
+ Iterator<MockComponent> i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getId(), "One");
+ Assert.assertEquals(i.next().getId(), "Three");
+ Assert.assertEquals(i.next().getId(), "Two");
+
+ i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getData(), "Foo1");
+ Assert.assertEquals(i.next().getData(), "Foo3");
+ Assert.assertEquals(i.next().getData(), "Foo2");
+ }
+
+ @Test public void testStaticOnly() {
+ final ApplicationContext context = getContext("net/shibboleth/ext/spring/util/staticOnly.xml");
+
+ final MockComponentManager manager = context.getBean(MockComponentManager.class);
+ Assert.assertNotNull(manager);
+ Assert.assertEquals(manager.getComponents().size(), 3);
+
+ Iterator<MockComponent> i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getId(), "One");
+ Assert.assertEquals(i.next().getId(), "Two");
+ Assert.assertEquals(i.next().getId(), "Three");
+
+ i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getData(), "Foo1");
+ Assert.assertEquals(i.next().getData(), "Foo2");
+ Assert.assertEquals(i.next().getData(), "Foo3");
+ }
+
+ @Test public void testFreeOnly() {
+ final ApplicationContext context = getContext("net/shibboleth/ext/spring/util/freeOnly.xml");
+
+ final MockComponentManager manager = context.getBean(MockComponentManager.class);
+ Assert.assertNotNull(manager);
+ Assert.assertEquals(manager.getComponents().size(), 1);
+
+ Iterator<MockComponent> i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getId(), "Three");
+
+ i = manager.getComponents().iterator();
+ Assert.assertEquals(i.next().getData(), "Foo3");
+ }
+
+ private ApplicationContext getContext(final String config) {
+ final GenericApplicationContext context = new GenericApplicationContext();
+ final XmlBeanDefinitionReader beanDefinitionReader = new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+ beanDefinitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+ beanDefinitionReader.loadBeanDefinitions(config);
+ context.refresh();
+
+ return context;
+ }
+
+ public static class MockComponent extends AbstractIdentifiableInitializableComponent {
+
+ private final String data;
+
+ public MockComponent(final String s) {
+ data = s;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return getId().hashCode();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof MockComponent) {
+ return getId().equals(((MockComponent) obj).getId());
+ }
+
+ return false;
+ }
+ }
+
+ public static class MockComponentManager extends IdentifiedComponentManager<MockComponent> {
+ /**
+ * Constructor.
+ *
+ * @param freeObjects
+ */
+ @Autowired
+ public MockComponentManager(@Nonnull @NonnullElements final Collection<MockComponent> freeObjects) {
+ super(freeObjects);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/ext/spring/util/combined.xml b/src/test/resources/net/shibboleth/ext/spring/util/combined.xml
new file mode 100644
index 0000000..d182b33
--- /dev/null
+++ b/src/test/resources/net/shibboleth/ext/spring/util/combined.xml
@@ -0,0 +1,28 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+
+ <context:annotation-config />
+
+ <util:list id="StaticList">
+ <bean id="One" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo1" />
+ <bean id="Two" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo2" />
+ </util:list>
+
+ <bean id="Three" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo3" />
+
+ <bean class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponentManager"
+ p:components-ref="StaticList" />
+
+</beans>
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/ext/spring/util/freeOnly.xml b/src/test/resources/net/shibboleth/ext/spring/util/freeOnly.xml
new file mode 100644
index 0000000..fc3c104
--- /dev/null
+++ b/src/test/resources/net/shibboleth/ext/spring/util/freeOnly.xml
@@ -0,0 +1,26 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+
+ <context:annotation-config />
+
+ <util:list id="StaticList">
+ </util:list>
+
+ <bean id="Three" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo3" />
+
+ <bean class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponentManager"
+ p:components-ref="StaticList" />
+
+</beans>
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/ext/spring/util/overlap.xml b/src/test/resources/net/shibboleth/ext/spring/util/overlap.xml
new file mode 100644
index 0000000..ae95f9d
--- /dev/null
+++ b/src/test/resources/net/shibboleth/ext/spring/util/overlap.xml
@@ -0,0 +1,29 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+
+ <context:annotation-config />
+
+ <util:list id="StaticList">
+ <bean id="One" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo1" />
+ <bean id="Three" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo3" />
+ <bean id="Two" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo2" />
+ </util:list>
+
+ <bean p:id="Three" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo4" />
+
+ <bean class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponentManager"
+ p:components-ref="StaticList" />
+
+</beans>
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/ext/spring/util/staticOnly.xml b/src/test/resources/net/shibboleth/ext/spring/util/staticOnly.xml
new file mode 100644
index 0000000..8ca3167
--- /dev/null
+++ b/src/test/resources/net/shibboleth/ext/spring/util/staticOnly.xml
@@ -0,0 +1,27 @@
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
+
+ <bean class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
+
+ <context:annotation-config />
+
+ <util:list id="StaticList">
+ <bean id="One" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo1" />
+ <bean id="Two" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo2" />
+ <bean id="Three" class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponent" c:_0="Foo3" />
+ </util:list>
+
+ <bean class="net.shibboleth.ext.spring.util.IdentifiedComponentManagerTest.MockComponentManager"
+ p:components-ref="StaticList" />
+
+</beans>
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list