Add writableChannel to WritableResource

This commit introduces a `writableChannel()` method to
`WritableResource`, defaulting to `Channels.newChannel`, but with
overrides for file-based resources.
This commit is contained in:
Arjen Poutsma 2017-05-03 11:19:55 +02:00
parent 9d8e9cf243
commit ed4bd43cac
4 changed files with 63 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -178,6 +179,15 @@ public class FileSystemResource extends AbstractResource implements WritableReso
return new FileInputStream(this.file).getChannel(); return new FileInputStream(this.file).getChannel();
} }
/**
* This implementation opens a FileChannel for the underlying file.
* @see java.nio.channels.FileChannel
*/
@Override
public WritableByteChannel writableChannel() throws IOException {
return new FileOutputStream(this.file).getChannel();
}
/** /**
* This implementation returns the underlying File's length. * This implementation returns the underlying File's length.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.OpenOption; import java.nio.file.OpenOption;
import java.nio.file.Path; import java.nio.file.Path;
@ -197,14 +198,23 @@ public class PathResource extends AbstractResource implements WritableResource {
} }
/** /**
* This implementation opens a InputStream for the underlying file. * This implementation opens a Channel for the underlying file.
* @see java.nio.file.spi.FileSystemProvider#newInputStream(Path, OpenOption...) * @see Files#newByteChannel(Path, OpenOption...)
*/ */
@Override @Override
public ReadableByteChannel readableChannel() throws IOException { public ReadableByteChannel readableChannel() throws IOException {
return Files.newByteChannel(this.path, StandardOpenOption.READ); return Files.newByteChannel(this.path, StandardOpenOption.READ);
} }
/**
* This implementation opens a Channel for the underlying file.
* @see Files#newByteChannel(Path, OpenOption...)
*/
@Override
public WritableByteChannel writableChannel() throws IOException {
return Files.newByteChannel(this.path, StandardOpenOption.WRITE);
}
/** /**
* This implementation returns the underlying File's length. * This implementation returns the underlying File's length.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package org.springframework.core.io;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
/** /**
* Extended interface for a resource that supports writing to it. * Extended interface for a resource that supports writing to it.
@ -51,4 +53,19 @@ public interface WritableResource extends Resource {
*/ */
OutputStream getOutputStream() throws IOException; OutputStream getOutputStream() throws IOException;
/**
* Return a {@link WritableByteChannel}.
* <p>It is expected that each call creates a <i>fresh</i> channel.
* <p>The default implementation returns {@link Channels#newChannel(OutputStream)}
* with the result of {@link #getOutputStream()}.
* @return the byte channel for the underlying resource (must not be {@code null})
* @throws java.io.FileNotFoundException if the underlying resource doesn't exist
* @throws IOException if the content channel could not be opened
* @since 5.0
* @see #getOutputStream()
*/
default WritableByteChannel writableChannel() throws IOException {
return Channels.newChannel(getOutputStream());
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,6 +21,8 @@ import java.io.FileNotFoundException;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.AccessDeniedException; import java.nio.file.AccessDeniedException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
@ -272,7 +274,7 @@ public class PathResourceTests {
@Test @Test
public void outputStream() throws Exception { public void outputStream() throws Exception {
PathResource resource = new PathResource(temporaryFolder.newFile("test").toPath()); PathResource resource = new PathResource(temporaryFolder.newFile("test").toPath());
FileCopyUtils.copy("test".getBytes(), resource.getOutputStream()); FileCopyUtils.copy("test".getBytes(StandardCharsets.UTF_8), resource.getOutputStream());
assertThat(resource.contentLength(), equalTo(4L)); assertThat(resource.contentLength(), equalTo(4L));
} }
@ -328,4 +330,21 @@ public class PathResourceTests {
resource.readableChannel(); resource.readableChannel();
} }
@Test
public void getWritableChannel() throws Exception {
PathResource resource = new PathResource(temporaryFolder.newFile("test").toPath());
ByteBuffer buffer = ByteBuffer.wrap("test".getBytes(StandardCharsets.UTF_8));
WritableByteChannel channel = null;
try {
channel = resource.writableChannel();
channel.write(buffer);
}
finally {
if (channel != null) {
channel.close();
}
}
assertThat(resource.contentLength(), equalTo(4L));
}
} }