[spring-extensions] branch maint-5 updated: JSE-24 - Conditional resource type

Scott Cantor cantor.2 at osu.edu
Tue Dec 19 11:50:11 EST 2017


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch maint-5
in repository spring-extensions.

View the commit online:
http://git.shibboleth.net/view/?p=spring-extensions.git;a=commit;h=54adbf87eb2dc63d73a3d61b7fa439f12400445d

The following commit(s) were added to refs/heads/maint-5 by this push:
       new  54adbf8   JSE-24 - Conditional resource type
54adbf8 is described below

commit 54adbf87eb2dc63d73a3d61b7fa439f12400445d
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Dec 19 11:50:08 2017 -0500

    JSE-24 - Conditional resource type
    
    https://issues.shibboleth.net/jira/browse/JSE-24
---
 .../ext/spring/resource/ConditionalResource.java   | 223 +++++++++++++++++++++
 .../spring/resource/ConditionalResourceTest.java   | 154 ++++++++++++++
 .../shibboleth/ext/spring/resource/conditional.xml |  15 ++
 3 files changed, 392 insertions(+)

diff --git a/src/main/java/net/shibboleth/ext/spring/resource/ConditionalResource.java b/src/main/java/net/shibboleth/ext/spring/resource/ConditionalResource.java
new file mode 100644
index 0000000..2c9e571
--- /dev/null
+++ b/src/main/java/net/shibboleth/ext/spring/resource/ConditionalResource.java
@@ -0,0 +1,223 @@
+/*
+ * 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.resource;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanNameAware;
+import org.springframework.core.io.Resource;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractIdentifiedInitializableComponent;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * A wrapper that guards a {@link Resource} that may be absent by returning an empty bean file instead.
+ */
+public class ConditionalResource extends AbstractIdentifiedInitializableComponent
+        implements Resource, BeanNameAware, net.shibboleth.utilities.java.support.resource.Resource {
+
+    /** Dummy content. */
+    @Nonnull @NotEmpty private static final String EMPTY_RESOURCE =
+            "<beans xmlns=\"http://www.springframework.org/schema/beans\""
+                    + " 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\""
+                    + "></beans>"; 
+    
+    /** Logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(ConditionalResource.class);
+
+    /** Cached log prefix. */
+    @Nullable private String logPrefix;
+    
+    /** Resource to wrap. */
+    @Nonnull private final Resource wrappedResource;
+    
+    /**
+     * Constructor.
+     *
+     * @param wrapped the resource to wrap
+     */
+    public ConditionalResource(@Nonnull final Resource wrapped) {
+        wrappedResource = Constraint.isNotNull(wrapped, "Wrapped resource cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    @Override public void setId(@Nonnull @NotEmpty final String id) {
+        super.setId(id);
+    }
+
+    /** {@inheritDoc} */
+    public InputStream getInputStream() throws IOException {
+        try {
+            return wrappedResource.getInputStream();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} getInputStream failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} getInputStream failed on wrapped resource", getLogPrefix());
+            }
+            return new ByteArrayInputStream(EMPTY_RESOURCE.getBytes(StandardCharsets.UTF_8));
+        }
+    }
+
+    /** {@inheritDoc} */
+    public net.shibboleth.utilities.java.support.resource.Resource createRelativeResource(final String relativePath)
+            throws IOException {
+        
+        final Resource relative = wrappedResource.createRelative(relativePath);
+        if (relative instanceof net.shibboleth.utilities.java.support.resource.Resource) {
+            return (net.shibboleth.utilities.java.support.resource.Resource) relative;
+        }
+        
+        return ResourceHelper.of(relative);
+    }
+
+    /** {@inheritDoc} */
+    public void setBeanName(final String name) {
+        setId(name);
+    }
+
+    /** {@inheritDoc} */
+    public boolean exists() {
+        if (!wrappedResource.exists()) {
+            log.info("{} Wrapped resource does not exist", getLogPrefix());
+        }
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isReadable() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isOpen() {
+        return wrappedResource.isOpen();
+    }
+
+    /** {@inheritDoc} */
+    public URL getURL() throws IOException {
+        try {
+            return wrappedResource.getURL();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} getURL failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} getURL failed on wrapped resource", getLogPrefix());
+            }
+            return null;
+        }
+    }
+
+    /** {@inheritDoc} */
+    public URI getURI() throws IOException {
+        try {
+            return wrappedResource.getURI();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} getURI failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} getURI failed on wrapped resource", getLogPrefix());
+            }
+            return null;
+        }
+    }
+
+    /** {@inheritDoc} */
+    public File getFile() throws IOException {
+        try {
+            return wrappedResource.getFile();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} getFile failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} getFile failed on wrapped resource", getLogPrefix());
+            }
+            return null;
+        }
+    }
+
+    /** {@inheritDoc} */
+    public long contentLength() throws IOException {
+        try {
+            return wrappedResource.contentLength();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} contentLength failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} contentLength failed on wrapped resource", getLogPrefix());
+            }
+            return EMPTY_RESOURCE.length();
+        }
+    }
+
+    /** {@inheritDoc} */
+    public long lastModified() throws IOException {
+        try {
+            return wrappedResource.lastModified();
+        } catch (final IOException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("{} lastModified failed on wrapped resource", getLogPrefix(), e);
+            } else {
+                log.info("{} lastModified failed on wrapped resource", getLogPrefix());
+            }
+            return 0;
+        }
+    }
+
+    /** {@inheritDoc} */
+    public Resource createRelative(final String relativePath) throws IOException {
+        return wrappedResource.createRelative(relativePath);
+    }
+
+    /** {@inheritDoc} */
+    public String getFilename() {
+        return wrappedResource.getFilename();
+    }
+
+    /** {@inheritDoc} */
+    public String getDescription() {
+        return wrappedResource.getDescription();
+    }
+
+    /**
+     * Return a prefix for logging messages for this component.
+     * 
+     * @return a string for insertion at the beginning of any log messages
+     */
+    @Nonnull @NotEmpty protected String getLogPrefix() {
+        if (logPrefix == null) {
+            logPrefix = "ConditionalResource " + getId() + ":";
+        }
+        return logPrefix;
+    }
+    
+}
\ No newline at end of file
diff --git a/src/test/java/net/shibboleth/ext/spring/resource/ConditionalResourceTest.java b/src/test/java/net/shibboleth/ext/spring/resource/ConditionalResourceTest.java
new file mode 100644
index 0000000..ddc2a2b
--- /dev/null
+++ b/src/test/java/net/shibboleth/ext/spring/resource/ConditionalResourceTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.resource;
+
+import java.io.IOException;
+
+import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientContextHandler;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Test for {@link ConditionalResource}.
+ */
+public class ConditionalResourceTest {
+
+    private final String existsURL =
+            "https://git.shibboleth.net/view/?p=spring-extensions.git;a=blob_plain;f=src/test/resources/data/document.xml;h=e8ec7c0d20c7a6b8193e1868398cda0c28df45ed;hb=HEAD";
+
+    private final String nonExistsURL =
+            "http://svn.shibboleth.net/view/utilities/spring-extensions/trunk/src/test/resources/data/documxent.xml?view=co";
+
+    private HttpClient client;
+
+    @BeforeClass public void setupClient() throws Exception {
+        client = (new HttpClientBuilder()).buildClient();
+    }
+
+    @Test public void existsTest() throws IOException, ComponentInitializationException {
+        final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
+        final HTTPResource notExistsHTTPResource = new HTTPResource(client, nonExistsURL);
+        
+        final ConditionalResource existsResource = new ConditionalResource(existsHTTPResource);
+        final ConditionalResource notExistsResource = new ConditionalResource(notExistsHTTPResource);
+        
+        existsResource.setId("test");
+        existsResource.initialize();
+        
+        notExistsResource.setId("test");
+        notExistsResource.initialize();
+
+        Assert.assertTrue(existsResource.exists());
+        Assert.assertTrue(notExistsResource.exists());
+    }
+    
+    
+    @Test public void contextHandlerFailBeforeTest() throws IOException, ComponentInitializationException {
+        final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
+        existsHTTPResource.setHttpClientContextHandler(new HttpClientContextHandler() {
+            public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+                throw new IOException("Fail");
+            }
+            public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+            }
+        });
+        
+        final ConditionalResource existsResource = new ConditionalResource(existsHTTPResource);
+        existsResource.setId("test");
+        existsResource.initialize();
+
+        Assert.assertTrue(existsResource.exists());
+    }
+    
+    @Test public void contextHandlerFailAfterTest() throws IOException, ComponentInitializationException {
+        final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
+        existsHTTPResource.setHttpClientContextHandler(new HttpClientContextHandler() {
+            public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+            }
+            public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+                throw new IOException("Fail");
+            }
+        });
+
+        final ConditionalResource existsResource = new ConditionalResource(existsHTTPResource);
+        existsResource.setId("test");
+        existsResource.initialize();
+        
+        Assert.assertTrue(existsResource.exists());
+    }
+
+    @Test public void testCompare() throws IOException, ComponentInitializationException {
+
+        final HTTPResource existsHTTPResource = new HTTPResource(client, existsURL);
+        
+        final ConditionalResource existsResource = new ConditionalResource(existsHTTPResource);
+        existsResource.setId("test");
+        existsResource.initialize();
+        
+        Assert.assertTrue(ResourceTestHelper.compare(existsResource, new ClassPathResource(
+                "net/shibboleth/ext/spring/resource/document.xml")));
+    }
+    
+    @Test public void testBeanExists() {
+        final ClassPathResource existsCPResource =
+                new ClassPathResource("net/shibboleth/ext/spring/resource/conditional.xml");
+        final ConditionalResource existsResource = new ConditionalResource(existsCPResource);
+        
+        final GenericApplicationContext parentContext = new GenericApplicationContext();
+        parentContext.refresh(); // THIS IS REQUIRED
+
+        final GenericApplicationContext context = new GenericApplicationContext(parentContext);
+        final XmlBeanDefinitionReader beanDefinitionReader = new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+        beanDefinitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+        beanDefinitionReader.loadBeanDefinitions(existsResource);
+        context.refresh();
+        
+        Assert.assertEquals(context.getBean("testBean"), "foo");
+    }
+    
+    @Test public void testBeanMissing() {
+        final ClassPathResource missingCPResource =
+                new ClassPathResource("net/shibboleth/ext/spring/resource/missing.xml");
+        final ConditionalResource missingResource = new ConditionalResource(missingCPResource);
+        
+        final GenericApplicationContext parentContext = new GenericApplicationContext();
+        parentContext.refresh(); // THIS IS REQUIRED
+
+        final GenericApplicationContext context = new GenericApplicationContext(parentContext);
+        final XmlBeanDefinitionReader beanDefinitionReader = new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+        beanDefinitionReader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
+        beanDefinitionReader.loadBeanDefinitions(missingResource);
+        context.refresh();
+        
+        Assert.assertFalse(context.containsBean("testBean"));
+    }
+    
+}
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/ext/spring/resource/conditional.xml b/src/test/resources/net/shibboleth/ext/spring/resource/conditional.xml
new file mode 100644
index 0000000..56b351b
--- /dev/null
+++ b/src/test/resources/net/shibboleth/ext/spring/resource/conditional.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:c="http://www.springframework.org/schema/c"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
+    default-init-method="initialize"
+    default-destroy-method="destroy">
+
+
+	<bean id="testBean"
+		class="java.lang.String"
+		c:_0="foo" />
+        
+</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