[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