Refactor ResourceUtils and rename getWritableResource(:Resource) as asStrictlyWritableResource(:Resource).

Add additional, lenient asWritableResource(:Resource) method return an Optional<WritableResource> if the given Resource is not an instance of WritableResource.

Resolves gh-92.
This commit is contained in:
John Blum
2020-07-20 17:43:41 -07:00
parent 290dbc3e48
commit 3ed0145ea7
2 changed files with 169 additions and 121 deletions

View File

@@ -34,6 +34,50 @@ import org.springframework.lang.Nullable;
*/
public abstract class ResourceUtils {
/**
* Returns the {@link Resource} as a {@link WritableResource} if possible.
*
* This method makes a best effort to determine whether the target {@link Resource} is actually {@literal writable}.
* Even still, it may be possible that a write to the target {@link Resource} will fail.
*
* The {@link Resource} is {@literal writable} if the {@link Resource} is an instance of {@link WritableResource}
* and {@link WritableResource#isWritable()} returns {@literal true}.
*
* @param resource {@link Resource} to cast to a {@link WritableResource}.
* @return a {@link WritableResource} from the target {@link Resource} if possible; never {@literal null}.
* @throws IllegalStateException if the target {@link Resource} is not {@literal writable}.
* @see org.springframework.core.io.WritableResource
* @see org.springframework.core.io.Resource
*/
public static @NonNull WritableResource asStrictlyWritableResource(@Nullable Resource resource) {
return Optional.ofNullable(resource)
.filter(WritableResource.class::isInstance)
.map(WritableResource.class::cast)
.filter(WritableResource::isWritable)
.orElseThrow(() -> newIllegalStateException("Resource [%s] is not writable",
ResourceUtils.nullSafeGetDescription(resource)));
}
/**
* {@link Optional Optionally} return the {@link Resource} as a {@link WritableResource}.
*
* The {@link Resource} must be an instance of {@link WritableResource}.
*
* @param resource {@link Resource} to cast to a {@link WritableResource}.
* @return the {@link Resource} as a {@link WritableResource} if the {@link Resource}
* is an instance of {@link WritableResource}, otherwise returns {@link Optional#empty()}.
* @see org.springframework.core.io.WritableResource
* @see org.springframework.core.io.Resource
* @see java.util.Optional
*/
public static Optional<WritableResource> asWritableResource(@Nullable Resource resource) {
return Optional.ofNullable(resource)
.filter(WritableResource.class::isInstance)
.map(WritableResource.class::cast);
}
/**
* Determines whether the given byte array is {@literal null} or {@literal empty}.
*
@@ -69,28 +113,6 @@ public abstract class ResourceUtils {
return resource instanceof WritableResource && ((WritableResource) resource).isWritable();
}
/**
* Returns the {@link Resource} as a {@link WritableResource} if possible.
*
* This method makes a best effort to determine whether the target {@link Resource} is actually {@literal writable}.
* Even still, it may be possible that a write to the target {@link Resource} will fail.
*
* @param resource {@link Resource} to cast as a {@link WritableResource}.
* @return a {@link WritableResource} from the target {@link Resource} if possible; never {@literal null}.
* @throws IllegalStateException if the target {@link Resource} is not writable.
* @see org.springframework.core.io.Resource
* @see org.springframework.core.io.WritableResource
*/
public static @NonNull WritableResource getWritableResource(@Nullable Resource resource) {
return Optional.ofNullable(resource)
.filter(WritableResource.class::isInstance)
.map(WritableResource.class::cast)
.filter(WritableResource::isWritable)
.orElseThrow(() -> newIllegalStateException("Resource [%s] is not writable",
ResourceUtils.nullSafeGetDescription(resource)));
}
/**
* Null-safe method to get the {@link Resource#getDescription() description} of the given {@link Resource}.
*

View File

@@ -18,6 +18,7 @@ package org.springframework.geode.core.io.support;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@@ -41,6 +42,130 @@ import org.springframework.core.io.WritableResource;
*/
public class ResourceUtilsUnitTests {
@Test
public void asStrictlyWritableResourceReturnsWritableResourceFromResource() {
WritableResource mockResource = mock(WritableResource.class);
doReturn(true).when(mockResource).isWritable();
assertThat(ResourceUtils.asStrictlyWritableResource(mockResource)).isEqualTo(mockResource);
verify(mockResource, times(1)).isWritable();
verifyNoMoreInteractions(mockResource);
}
@Test(expected = IllegalStateException.class)
public void asStrictlyWritableResourceFromResourceThrowsIllegalStateException() {
Resource mockResource = mock(Resource.class);
doReturn("MOCK").when(mockResource).getDescription();
try {
ResourceUtils.asStrictlyWritableResource(mockResource);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [MOCK] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verify(mockResource, times(1)).getDescription();
verifyNoMoreInteractions(mockResource);
}
}
@Test(expected = IllegalStateException.class)
public void asStrictlyWritableResourceFromNullThrowsIllegalStateException() {
try {
ResourceUtils.asStrictlyWritableResource(null);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [null] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test(expected = IllegalStateException.class)
public void asStrictlyWritableResourceFromNonWritableWritableResourceInstanceThrowsIllegalStateException() {
WritableResource mockResource = mock(WritableResource.class);
doReturn("TEST").when(mockResource).getDescription();
doReturn(false).when(mockResource).isWritable();
try {
ResourceUtils.asStrictlyWritableResource(mockResource);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [TEST] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verify(mockResource, times(1)).getDescription();
verify(mockResource, times(1)).isWritable();
verifyNoMoreInteractions(mockResource);
}
}
@Test
public void asWritableResourceWithWritableResourceInstance() {
WritableResource mockResource = mock(WritableResource.class);
assertThat(ResourceUtils.asWritableResource(mockResource).orElse(null)).isEqualTo(mockResource);
verify(mockResource, never()).isWritable();
}
@Test
public void asWritableResourceWithResourceInstance() {
Resource mockResource = mock(Resource.class);
assertThat(ResourceUtils.asWritableResource(mockResource).orElse(null)).isNull();
verifyNoInteractions(mockResource);
}
@Test
public void asWritableResourceWithNullIsNullSafe() {
assertThat(ResourceUtils.asWritableResource(null).isPresent()).isFalse();
}
@Test
public void isNotEmptyWithNonEmptyByteArrayReturnsTrue() {
byte[] array = {
(byte) 0xCA,
(byte) 0xFE,
(byte) 0xBA,
(byte) 0xBE
};
assertThat(ResourceUtils.isNotEmpty(array)).isTrue();
}
@Test
public void isNotEmptyWithEmptyByteArrayReturnsFalse() {
assertThat(ResourceUtils.isNotEmpty(new byte[0])).isFalse();
}
@Test
public void isNotEmptyWithNullByteArrayReturnsFalse() {
assertThat(ResourceUtils.isNotEmpty(null)).isFalse();
}
@Test
public void isReadableWithReadableResourceReturnsTrue() {
@@ -113,105 +238,6 @@ public class ResourceUtilsUnitTests {
assertThat(ResourceUtils.isWritable(null)).isFalse();
}
@Test
public void getWritableResourceReturnsWritableResourceFromResource() {
WritableResource mockResource = mock(WritableResource.class);
doReturn(true).when(mockResource).isWritable();
assertThat(ResourceUtils.getWritableResource(mockResource)).isEqualTo(mockResource);
verify(mockResource, times(1)).isWritable();
verifyNoMoreInteractions(mockResource);
}
@Test(expected = IllegalStateException.class)
public void getWritableResourceFromResourceThrowsIllegalStateException() {
Resource mockResource = mock(Resource.class);
doReturn("MOCK").when(mockResource).getDescription();
try {
ResourceUtils.getWritableResource(mockResource);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [MOCK] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verify(mockResource, times(1)).getDescription();
verifyNoMoreInteractions(mockResource);
}
}
@Test(expected = IllegalStateException.class)
public void getWritableResourceFromNullThrowsIllegalStateException() {
try {
ResourceUtils.getWritableResource(null);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [null] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
}
@Test(expected = IllegalStateException.class)
public void getWritableResourceFromNonWritableWritableResourceThrowsIllegalStateException() {
WritableResource mockResource = mock(WritableResource.class);
doReturn("TEST").when(mockResource).getDescription();
doReturn(false).when(mockResource).isWritable();
try {
ResourceUtils.getWritableResource(mockResource);
}
catch (IllegalStateException expected) {
assertThat(expected).hasMessage("Resource [TEST] is not writable");
assertThat(expected).hasNoCause();
throw expected;
}
finally {
verify(mockResource, times(1)).getDescription();
verify(mockResource, times(1)).isWritable();
verifyNoMoreInteractions(mockResource);
}
}
@Test
public void isNotEmptyWithNonEmptyByteArrayReturnsTrue() {
byte[] array = {
(byte) 0xCA,
(byte) 0xFE,
(byte) 0xBA,
(byte) 0xBE
};
assertThat(ResourceUtils.isNotEmpty(array)).isTrue();
}
@Test
public void isNotEmptyWithEmptyByteArrayReturnsFalse() {
assertThat(ResourceUtils.isNotEmpty(new byte[0])).isFalse();
}
@Test
public void isNotEmptyWithNullByteArrayReturnsFalse() {
assertThat(ResourceUtils.isNotEmpty(null)).isFalse();
}
@Test
public void nullSafeDescriptionWithNonNullResource() {