Browse Source

StreamUtils.emptyInput() for consistent empty InputStream exposure

Issue: SPR-13563
pull/888/head
Juergen Hoeller 9 years ago
parent
commit
66177dfd8c
  1. 4
      spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java
  2. 18
      spring-core/src/main/java/org/springframework/util/StreamUtils.java
  3. 4
      spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java
  4. 4
      spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java
  5. 4
      spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java
  6. 2
      spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java
  7. 6
      spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java
  8. 4
      spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java
  9. 21
      spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java

4
spring-context/src/test/java/org/springframework/scripting/support/ResourceScriptSourceTests.java

@ -16,13 +16,13 @@ @@ -16,13 +16,13 @@
package org.springframework.scripting.support;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.junit.Test;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@ -59,7 +59,7 @@ public class ResourceScriptSourceTests { @@ -59,7 +59,7 @@ public class ResourceScriptSourceTests {
// does not support File-based reading; delegates to InputStream-style reading...
//resource.getFile();
//mock.setThrowable(new FileNotFoundException());
given(resource.getInputStream()).willReturn(new ByteArrayInputStream(new byte[0]));
given(resource.getInputStream()).willReturn(StreamUtils.emptyInput());
ResourceScriptSource scriptSource = new ResourceScriptSource(resource);
assertTrue("ResourceScriptSource must start off in the 'isModified' state (it obviously isn't).", scriptSource.isModified());

18
spring-core/src/main/java/org/springframework/util/StreamUtils.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* 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.
@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
package org.springframework.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
@ -43,6 +44,8 @@ public abstract class StreamUtils { @@ -43,6 +44,8 @@ public abstract class StreamUtils {
public static final int BUFFER_SIZE = 4096;
private static final byte[] EMPTY_CONTENT = new byte[0];
/**
* Copy the contents of the given InputStream into a new byte array.
@ -129,7 +132,16 @@ public abstract class StreamUtils { @@ -129,7 +132,16 @@ public abstract class StreamUtils {
}
/**
* Returns a variant of the given {@link InputStream} where calling
* Return an efficient empty {@link InputStream}.
* @return a {@link ByteArrayInputStream} based on an empty byte array
* @since 4.2.2
*/
public static InputStream emptyInput() {
return new ByteArrayInputStream(EMPTY_CONTENT);
}
/**
* Return a variant of the given {@link InputStream} where calling
* {@link InputStream#close() close()} has no effect.
* @param in the InputStream to decorate
* @return a version of the InputStream that ignores calls to close
@ -140,7 +152,7 @@ public abstract class StreamUtils { @@ -140,7 +152,7 @@ public abstract class StreamUtils {
}
/**
* Returns a variant of the given {@link OutputStream} where calling
* Return a variant of the given {@link OutputStream} where calling
* {@link OutputStream#close() close()} has no effect.
* @param out the OutputStream to decorate
* @return a version of the OutputStream that ignores calls to close

4
spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java

@ -39,7 +39,6 @@ import java.util.Locale; @@ -39,7 +39,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
@ -59,6 +58,7 @@ import org.springframework.util.Assert; @@ -59,6 +58,7 @@ import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
/**
@ -122,7 +122,7 @@ public class MockHttpServletRequest implements HttpServletRequest { @@ -122,7 +122,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
private static final String CHARSET_PREFIX = "charset=";
private static final ServletInputStream EMPTY_SERVLET_INPUT_STREAM =
new DelegatingServletInputStream(new ByteArrayInputStream(new byte[0]));
new DelegatingServletInputStream(StreamUtils.emptyInput());
/**
* Date formats as specified in the HTTP RFC

4
spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.http.converter.json;
import java.io.ByteArrayInputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
@ -54,6 +53,7 @@ import org.springframework.beans.FatalBeanException; @@ -54,6 +53,7 @@ import org.springframework.beans.FatalBeanException;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
/**
@ -761,7 +761,7 @@ public class Jackson2ObjectMapperBuilder { @@ -761,7 +761,7 @@ public class Jackson2ObjectMapperBuilder {
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
return new ByteArrayInputStream(new byte[0]);
return StreamUtils.emptyInput();
}
};
}

4
spring-web/src/main/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverter.java

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.http.converter.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@ -46,6 +45,7 @@ import org.springframework.http.converter.GenericHttpMessageConverter; @@ -46,6 +45,7 @@ import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;
/**
* An {@code HttpMessageConverter} that can read XML collections using JAXB2.
@ -256,7 +256,7 @@ public class Jaxb2CollectionHttpMessageConverter<T extends Collection> @@ -256,7 +256,7 @@ public class Jaxb2CollectionHttpMessageConverter<T extends Collection>
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
return new ByteArrayInputStream(new byte[0]);
return StreamUtils.emptyInput();
}
};

2
spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java

@ -289,7 +289,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe @@ -289,7 +289,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
private static final XMLResolver NO_OP_XML_RESOLVER = new XMLResolver() {
@Override
public Object resolveEntity(String publicID, String systemID, String base, String ns) {
return new ByteArrayInputStream(new byte[0]);
return StreamUtils.emptyInput();
}
};

6
spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartFile.java

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
package org.springframework.web.multipart.commons;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -28,10 +27,11 @@ import org.apache.commons.fileupload.disk.DiskFileItem; @@ -28,10 +27,11 @@ import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;
/**
* MultipartFile implementation for Apache Commons FileUpload.
* {@link MultipartFile} implementation for Apache Commons FileUpload.
*
* @author Trevor D. Cook
* @author Juergen Hoeller
@ -124,7 +124,7 @@ public class CommonsMultipartFile implements MultipartFile, Serializable { @@ -124,7 +124,7 @@ public class CommonsMultipartFile implements MultipartFile, Serializable {
throw new IllegalStateException("File has been moved - cannot be read again");
}
InputStream inputStream = this.fileItem.getInputStream();
return (inputStream != null ? inputStream : new ByteArrayInputStream(new byte[0]));
return (inputStream != null ? inputStream : StreamUtils.emptyInput());
}
@Override

4
spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java

@ -39,7 +39,6 @@ import java.util.Locale; @@ -39,7 +39,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
@ -59,6 +58,7 @@ import org.springframework.util.Assert; @@ -59,6 +58,7 @@ import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
/**
@ -122,7 +122,7 @@ public class MockHttpServletRequest implements HttpServletRequest { @@ -122,7 +122,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
private static final String CHARSET_PREFIX = "charset=";
private static final ServletInputStream EMPTY_SERVLET_INPUT_STREAM =
new DelegatingServletInputStream(new ByteArrayInputStream(new byte[0]));
new DelegatingServletInputStream(StreamUtils.emptyInput());
/**
* Date formats as specified in the HTTP RFC

21
spring-web/src/test/java/org/springframework/web/filter/ShallowEtagHeaderFilterTests.java

@ -16,16 +16,15 @@ @@ -16,16 +16,15 @@
package org.springframework.web.filter;
import java.io.ByteArrayInputStream;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StreamUtils;
import static org.junit.Assert.*;
@ -36,27 +35,23 @@ import static org.junit.Assert.*; @@ -36,27 +35,23 @@ import static org.junit.Assert.*;
*/
public class ShallowEtagHeaderFilterTests {
private ShallowEtagHeaderFilter filter;
private final ShallowEtagHeaderFilter filter = new ShallowEtagHeaderFilter();
@Before
public void createFilter() throws Exception {
filter = new ShallowEtagHeaderFilter();
}
@Test
public void isEligibleForEtag() {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();
assertTrue(filter.isEligibleForEtag(request, response, 200, new ByteArrayInputStream(new byte[0])));
assertFalse(filter.isEligibleForEtag(request, response, 300, new ByteArrayInputStream(new byte[0])));
assertTrue(filter.isEligibleForEtag(request, response, 200, StreamUtils.emptyInput()));
assertFalse(filter.isEligibleForEtag(request, response, 300, StreamUtils.emptyInput()));
request = new MockHttpServletRequest("POST", "/hotels");
assertFalse(filter.isEligibleForEtag(request, response, 200, new ByteArrayInputStream(new byte[0])));
assertFalse(filter.isEligibleForEtag(request, response, 200, StreamUtils.emptyInput()));
request = new MockHttpServletRequest("POST", "/hotels");
request.addHeader("Cache-Control","must-revalidate, no-store");
assertFalse(filter.isEligibleForEtag(request, response, 200, new ByteArrayInputStream(new byte[0])));
assertFalse(filter.isEligibleForEtag(request, response, 200, StreamUtils.emptyInput()));
}
@Test
@ -120,9 +115,7 @@ public class ShallowEtagHeaderFilterTests { @@ -120,9 +115,7 @@ public class ShallowEtagHeaderFilterTests {
assertArrayEquals("Invalid content", new byte[0], response.getContentAsByteArray());
}
// SPR-12960
@Test
@Test // SPR-12960
public void filterWriterWithDisabledCaching() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels");
MockHttpServletResponse response = new MockHttpServletResponse();

Loading…
Cancel
Save