[spring-extensions] branch master updated: OSJ-191 - Support for OpenSAML security features in HTTPResource layer
Scott Cantor
cantor.2 at osu.edu
Thu Dec 29 19:25:46 EST 2016
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository spring-extensions.
View the commit online:
http://git.shibboleth.net/view/?p=spring-extensions.git;a=commit;h=eb429703cebb54dce0bf74ef47802f1589a37748
The following commit(s) were added to refs/heads/master by this push:
new eb42970 OSJ-191 - Support for OpenSAML security features in HTTPResource layer
eb42970 is described below
commit eb429703cebb54dce0bf74ef47802f1589a37748
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Dec 29 19:25:44 2016 -0500
OSJ-191 - Support for OpenSAML security features in HTTPResource layer
https://issues.shibboleth.net/jira/browse/OSJ-191
Add injected handler support to manipulate client context.
---
.project | 4 +-
pom.xml | 4 +-
.../ext/spring/resource/HTTPResource.java | 89 +++++++++++++++++++---
.../ext/spring/resource/HTTPResourceTest.java | 57 ++++++++++++--
.../ext/spring/resource/TestHTTPResource.java | 2 +-
.../ext/spring/resource/FileBackedHTTPBean.xml | 2 +-
.../ext/spring/resource/MemBackedHTTPBean.xml | 2 +-
7 files changed, 135 insertions(+), 25 deletions(-)
diff --git a/.project b/.project
index 1f4627c..d2e569a 100644
--- a/.project
+++ b/.project
@@ -16,12 +16,12 @@
</arguments>
</buildCommand>
<buildCommand>
- <name>org.eclipse.m2e.core.maven2Builder</name>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
diff --git a/pom.xml b/pom.xml
index 538dc80..dc03572 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
<groupId>net.shibboleth.ext</groupId>
<artifactId>spring-extensions</artifactId>
- <version>5.3.1-SNAPSHOT</version>
+ <version>5.4.0-SNAPSHOT</version>
<name>Spring Framework Extension</name>
<description>
@@ -21,7 +21,7 @@
</description>
<properties>
- <java-support.version>7.3.1-SNAPSHOT</java-support.version>
+ <java-support.version>7.4.0-SNAPSHOT</java-support.version>
</properties>
<repositories>
diff --git a/src/main/java/net/shibboleth/ext/spring/resource/HTTPResource.java b/src/main/java/net/shibboleth/ext/spring/resource/HTTPResource.java
index c9e112f..47cade9 100644
--- a/src/main/java/net/shibboleth/ext/spring/resource/HTTPResource.java
+++ b/src/main/java/net/shibboleth/ext/spring/resource/HTTPResource.java
@@ -27,10 +27,12 @@ import java.net.URL;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.component.AbstractIdentifiedInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
@@ -44,6 +46,7 @@ import org.apache.http.client.cache.HttpCacheContext;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.DateUtils;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
@@ -65,9 +68,12 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
/** HTTP Client used to pull the resource. */
@Nonnull private final HttpClient httpClient;
-
+
/** URL to the Resource. */
@Nonnull private final URL resourceURL;
+
+ /** Optional handler to pre- and post-process context. */
+ @Nullable private HttpClientContextHandler httpClientContextHandler;
/**
* Constructor.
@@ -78,9 +84,9 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
*/
public HTTPResource(@Nonnull @ParameterName(name="client") final HttpClient client,
@Nonnull @NotEmpty @ParameterName(name="url") final String url) throws IOException {
- httpClient = Constraint.isNotNull(client, "The Client must not be null");
+ httpClient = Constraint.isNotNull(client, "HttpClient cannot be null");
final String trimmedAddress =
- Constraint.isNotNull(StringSupport.trimOrNull(url), "Provided URL must be non empty and non null");
+ Constraint.isNotNull(StringSupport.trimOrNull(url), "Provided URL cannot be null or empty");
resourceURL = new URL(trimmedAddress);
}
@@ -94,10 +100,21 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
*/
public HTTPResource(@Nonnull @ParameterName(name="") final HttpClient client,
@Nonnull @ParameterName(name="url") final URL url) throws IOException {
- httpClient = Constraint.isNotNull(client, "The Client must not be null");
- resourceURL = Constraint.isNotNull(url, "Provided URL must be non empty and non null");
+ httpClient = Constraint.isNotNull(client, "HttpClient cannot be null");
+ resourceURL = Constraint.isNotNull(url, "Provided URL cannot be null or empty");
}
+
+ /**
+ * Set a handler to manipulate the {@link HttpClientContext}.
+ *
+ * @param handler the handler to install
+ */
+ public void setHttpClientContextHandler(@Nonnull final HttpClientContextHandler handler) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ httpClientContextHandler = handler;
+ }
/**
* Build the {@link HttpCacheContext} instance which will be used to invoke the {@link HttpClient} request.
@@ -143,10 +160,20 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
@Override public InputStream getInputStream() throws IOException {
final HttpGet httpGet = new HttpGet(resourceURL.toExternalForm());
final HttpCacheContext context = buildHttpClientContext();
- HttpResponse response = null;
-
+
+ if (httpClientContextHandler != null) {
+ log.debug("Invoking HttpClientContextHandler prior to execution");
+ httpClientContextHandler.invokeBefore(context, httpGet);
+ }
+
log.debug("Attempting to get data from remote resource '{}'", resourceURL);
- response = httpClient.execute(httpGet, context);
+ final HttpResponse response = httpClient.execute(httpGet, context);
+
+ if (httpClientContextHandler != null) {
+ log.debug("Invoking HttpClientContextHandler after execution");
+ httpClientContextHandler.invokeAfter(context, httpGet);
+ }
+
reportCachingStatus(context);
final int httpStatusCode = response.getStatusLine().getStatusCode();
@@ -230,7 +257,19 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
HttpResponse httpResponse = null;
try {
final HttpCacheContext context = buildHttpClientContext();
+
+ if (httpClientContextHandler != null) {
+ log.debug("Invoking HttpClientContextHandler prior to execution");
+ httpClientContextHandler.invokeBefore(context, httpRequest);
+ }
+
httpResponse = httpClient.execute(httpRequest, context);
+
+ if (httpClientContextHandler != null) {
+ log.debug("Invoking HttpClientContextHandler after execution");
+ httpClientContextHandler.invokeAfter(context, httpRequest);
+ }
+
reportCachingStatus(context);
EntityUtils.consume(httpResponse.getEntity());
return httpResponse;
@@ -345,10 +384,40 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
}
/**
+ * Extension that allows the {@link HttpClientContext} to be externally manipulated before use.
+ */
+ @ThreadSafe
+ public static interface HttpClientContextHandler {
+
+ /**
+ * Perform any desired context modifications before use.
+ *
+ * @param context the context to operate on
+ * @param request the request that will be executed
+ *
+ * @throws IOException if the call should be aborted
+ */
+ void invokeBefore(@Nonnull final HttpClientContext context, @Nonnull final HttpUriRequest request)
+ throws IOException;
+
+ /**
+ * Perform any desired context modifications after use.
+ *
+ * @param context the context to operate on
+ * @param request the request that was executed
+ *
+ * @throws IOException if the call should be aborted
+ */
+ void invokeAfter(@Nonnull final HttpClientContext context, @Nonnull final HttpUriRequest request)
+ throws IOException;
+
+ }
+
+ /**
* A wrapper around the entity content {@link InputStream} represented by an {@link HttpResponse}
* that closes the stream and the HttpResponse when {@link #close()} is invoked.
*/
- private static class ConnectionClosingInputStream extends InputStream {
+ private static class ConnectionClosingInputStream extends InputStream {
/** HTTP response that is being wrapped. */
private final HttpResponse response;
@@ -362,7 +431,7 @@ public class HTTPResource extends AbstractIdentifiedInitializableComponent imple
* @param httpResponse HTTP method that was invoked
* @throws IOException if there is a problem getting the entity content input stream from the response
*/
- public ConnectionClosingInputStream(final HttpResponse httpResponse) throws IOException {
+ public ConnectionClosingInputStream(@Nonnull final HttpResponse httpResponse) throws IOException {
response = httpResponse;
stream = response.getEntity().getContent();
}
diff --git a/src/test/java/net/shibboleth/ext/spring/resource/HTTPResourceTest.java b/src/test/java/net/shibboleth/ext/spring/resource/HTTPResourceTest.java
index a9c6b59..405db1b 100644
--- a/src/test/java/net/shibboleth/ext/spring/resource/HTTPResourceTest.java
+++ b/src/test/java/net/shibboleth/ext/spring/resource/HTTPResourceTest.java
@@ -23,12 +23,15 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
+import net.shibboleth.ext.spring.resource.HTTPResource.HttpClientContextHandler;
import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
import net.shibboleth.utilities.java.support.httpclient.InMemoryCachingHttpClientBuilder;
import org.apache.http.client.HttpClient;
import org.apache.http.client.cache.CacheResponseStatus;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.joda.time.DateTime;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@@ -62,6 +65,44 @@ public class HTTPResourceTest {
Assert.assertTrue(existsResource.exists());
Assert.assertFalse(notExistsResource.exists());
}
+
+ @Test public void contextHandlerNoopTest() throws IOException {
+ final HTTPResource existsResource = new HTTPResource(client, existsURL);
+ existsResource.setHttpClientContextHandler(new HttpClientContextHandler() {
+ public void invokeBefore(HttpClientContext context, HttpUriRequest request) throws IOException {
+ }
+ public void invokeAfter(HttpClientContext context, HttpUriRequest request) throws IOException {
+ }
+ });
+
+ Assert.assertTrue(existsResource.exists());
+ }
+
+ @Test public void contextHandlerFailBeforeTest() throws IOException {
+ final HTTPResource existsResource = new HTTPResource(client, existsURL);
+ existsResource.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 {
+ }
+ });
+
+ Assert.assertFalse(existsResource.exists());
+ }
+
+ @Test public void contextHandlerFailAfterTest() throws IOException {
+ final HTTPResource existsResource = new HTTPResource(client, existsURL);
+ existsResource.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");
+ }
+ });
+
+ Assert.assertFalse(existsResource.exists());
+ }
@Test public void testCompare() throws IOException {
@@ -89,9 +130,9 @@ public class HTTPResourceTest {
final TestHTTPResource what = new TestHTTPResource(client, existsURL);
Assert.assertTrue(what.exists());
- Assert.assertNull(what.getLasteCacheResponseStatus());
+ Assert.assertNull(what.getLastCacheResponseStatus());
Assert.assertTrue(ResourceTestHelper.compare(what, new ClassPathResource("net/shibboleth/ext/spring/resource/document.xml")));
- Assert.assertNull(what.getLasteCacheResponseStatus());
+ Assert.assertNull(what.getLastCacheResponseStatus());
}
@Test public void testCachedCache() throws Exception {
@@ -100,10 +141,10 @@ public class HTTPResourceTest {
builder.setMaxCacheEntries(3);
final TestHTTPResource what = new TestHTTPResource(builder.buildClient(), existsURL);
Assert.assertTrue(what.exists());
- Assert.assertNotNull(what.getLasteCacheResponseStatus());
+ Assert.assertNotNull(what.getLastCacheResponseStatus());
Assert.assertTrue(ResourceTestHelper.compare(what, new ClassPathResource("net/shibboleth/ext/spring/resource/document.xml")));
- Assert.assertEquals(what.getLasteCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
+ Assert.assertEquals(what.getLastCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
}
private GenericApplicationContext getContext(final String fileName, final File theDir) {
@@ -131,10 +172,10 @@ public class HTTPResourceTest {
final TestHTTPResource what = beans.iterator().next();
Assert.assertTrue(what.exists());
- Assert.assertNotNull(what.getLasteCacheResponseStatus());
+ Assert.assertNotNull(what.getLastCacheResponseStatus());
Assert.assertTrue(ResourceTestHelper.compare(what, new ClassPathResource("net/shibboleth/ext/spring/resource/document.xml")));
- Assert.assertEquals(what.getLasteCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
+ Assert.assertEquals(what.getLastCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
} finally {
((GenericApplicationContext) context.getParent()).close();
context.close();
@@ -164,10 +205,10 @@ public class HTTPResourceTest {
final TestHTTPResource what = beans.iterator().next();
Assert.assertTrue(what.exists());
- Assert.assertNotNull(what.getLasteCacheResponseStatus());
+ Assert.assertNotNull(what.getLastCacheResponseStatus());
Assert.assertTrue(ResourceTestHelper.compare(what, new ClassPathResource("net/shibboleth/ext/spring/resource/document.xml")));
- Assert.assertEquals(what.getLasteCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
+ Assert.assertEquals(what.getLastCacheResponseStatus(), CacheResponseStatus.CACHE_HIT);
} finally {
if (null != theDir) {
emptyDir(theDir);
diff --git a/src/test/java/net/shibboleth/ext/spring/resource/TestHTTPResource.java b/src/test/java/net/shibboleth/ext/spring/resource/TestHTTPResource.java
index 210c87f..69066ba 100644
--- a/src/test/java/net/shibboleth/ext/spring/resource/TestHTTPResource.java
+++ b/src/test/java/net/shibboleth/ext/spring/resource/TestHTTPResource.java
@@ -38,7 +38,7 @@ class TestHTTPResource extends HTTPResource {
super.reportCachingStatus(context);
}
- public CacheResponseStatus getLasteCacheResponseStatus() {
+ public CacheResponseStatus getLastCacheResponseStatus() {
return responseStatus;
}
diff --git a/src/test/resources/net/shibboleth/ext/spring/resource/FileBackedHTTPBean.xml b/src/test/resources/net/shibboleth/ext/spring/resource/FileBackedHTTPBean.xml
index 57efed2..f0ef12c 100644
--- a/src/test/resources/net/shibboleth/ext/spring/resource/FileBackedHTTPBean.xml
+++ b/src/test/resources/net/shibboleth/ext/spring/resource/FileBackedHTTPBean.xml
@@ -14,7 +14,7 @@
<bean id="ShibResource" class="net.shibboleth.ext.spring.resource.HTTPResource"
c:client-ref="apacheClient" c:url="https://git.shibboleth.net/view/?p=spring-extensions.git;a=blob_plain;f=src/test/resources/data/document.xml;h=e8ec7c0d20c7a6b8193e1868398cda0c28df45ed;hb=HEAD" />
-<!-- for testing we will use out test resource -->
+<!-- for testing we will use our test resource -->
<bean id="TestResource" class="net.shibboleth.ext.spring.resource.TestHTTPResource"
c:client-ref="apacheClient" c:url="https://git.shibboleth.net/view/?p=spring-extensions.git;a=blob_plain;f=src/test/resources/data/document.xml;h=e8ec7c0d20c7a6b8193e1868398cda0c28df45ed;hb=HEAD" />
diff --git a/src/test/resources/net/shibboleth/ext/spring/resource/MemBackedHTTPBean.xml b/src/test/resources/net/shibboleth/ext/spring/resource/MemBackedHTTPBean.xml
index 5e795cf..25b89a1 100644
--- a/src/test/resources/net/shibboleth/ext/spring/resource/MemBackedHTTPBean.xml
+++ b/src/test/resources/net/shibboleth/ext/spring/resource/MemBackedHTTPBean.xml
@@ -13,7 +13,7 @@
<bean id="Resource" class="net.shibboleth.ext.spring.resource.HTTPResource"
c:client-ref="apacheClient" c:url="https://git.shibboleth.net/view/?p=spring-extensions.git;a=blob_plain;f=src/test/resources/data/document.xml;h=e8ec7c0d20c7a6b8193e1868398cda0c28df45ed;hb=HEAD" />
- <!-- for testing we will use out test resource -->
+ <!-- for testing we will use our test resource -->
<bean id="TestResource" class="net.shibboleth.ext.spring.resource.TestHTTPResource"
c:client-ref="apacheClient" c:url="https://git.shibboleth.net/view/?p=spring-extensions.git;a=blob_plain;f=src/test/resources/data/document.xml;h=e8ec7c0d20c7a6b8193e1868398cda0c28df45ed;hb=HEAD" />
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list