Consistent use of NIO.2 for file read/write interactions
Issue: SPR-15748
This commit is contained in:
		
							parent
							
								
									d56fedc226
								
							
						
					
					
						commit
						12114a9d4c
					
				| 
						 | 
				
			
			@ -17,7 +17,6 @@
 | 
			
		|||
package org.springframework.core.io;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.FileNotFoundException;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +24,9 @@ import java.net.HttpURLConnection;
 | 
			
		|||
import java.net.URI;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.net.URLConnection;
 | 
			
		||||
import java.nio.channels.FileChannel;
 | 
			
		||||
import java.nio.channels.ReadableByteChannel;
 | 
			
		||||
import java.nio.file.StandardOpenOption;
 | 
			
		||||
 | 
			
		||||
import org.springframework.util.ResourceUtils;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +128,7 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
 | 
			
		|||
	@Override
 | 
			
		||||
	public ReadableByteChannel readableChannel() throws IOException {
 | 
			
		||||
		if (isFile()) {
 | 
			
		||||
			return new FileInputStream(getFile()).getChannel();
 | 
			
		||||
			return FileChannel.open(getFile().toPath(), StandardOpenOption.READ);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			return super.readableChannel();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,15 +17,16 @@
 | 
			
		|||
package org.springframework.core.io;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.net.URI;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.nio.channels.FileChannel;
 | 
			
		||||
import java.nio.channels.ReadableByteChannel;
 | 
			
		||||
import java.nio.channels.WritableByteChannel;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.StandardOpenOption;
 | 
			
		||||
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,9 +36,15 @@ import org.springframework.util.StringUtils;
 | 
			
		|||
 * Supports resolution as a {@code File} and also as a {@code URL}.
 | 
			
		||||
 * Implements the extended {@link WritableResource} interface.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Note: As of Spring Framework 5.0, this {@link Resource} implementation
 | 
			
		||||
 * uses NIO.2 API for read/write interactions. Nevertheless, in contrast to
 | 
			
		||||
 * {@link PathResource}, it primarily manages a {@code java.io.File} handle.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Juergen Hoeller
 | 
			
		||||
 * @since 28.12.2003
 | 
			
		||||
 * @see PathResource
 | 
			
		||||
 * @see java.io.File
 | 
			
		||||
 * @see java.nio.file.Files
 | 
			
		||||
 */
 | 
			
		||||
public class FileSystemResource extends AbstractResource implements WritableResource {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +120,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
 | 
			
		|||
	 */
 | 
			
		||||
	@Override
 | 
			
		||||
	public InputStream getInputStream() throws IOException {
 | 
			
		||||
		return new FileInputStream(this.file);
 | 
			
		||||
		return Files.newInputStream(this.file.toPath());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +140,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
 | 
			
		|||
	 */
 | 
			
		||||
	@Override
 | 
			
		||||
	public OutputStream getOutputStream() throws IOException {
 | 
			
		||||
		return new FileOutputStream(this.file);
 | 
			
		||||
		return Files.newOutputStream(this.file.toPath());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +183,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
 | 
			
		|||
	 */
 | 
			
		||||
	@Override
 | 
			
		||||
	public ReadableByteChannel readableChannel() throws IOException {
 | 
			
		||||
		return new FileInputStream(this.file).getChannel();
 | 
			
		||||
		return FileChannel.open(getFile().toPath(), StandardOpenOption.READ);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +192,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso
 | 
			
		|||
	 */
 | 
			
		||||
	@Override
 | 
			
		||||
	public WritableByteChannel writableChannel() throws IOException {
 | 
			
		||||
		return new FileOutputStream(this.file).getChannel();
 | 
			
		||||
		return FileChannel.open(getFile().toPath(), StandardOpenOption.WRITE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,9 @@ import org.springframework.util.Assert;
 | 
			
		|||
 * @author Philippe Marschall
 | 
			
		||||
 * @author Juergen Hoeller
 | 
			
		||||
 * @since 4.0
 | 
			
		||||
 * @see FileSystemResource
 | 
			
		||||
 * @see java.nio.file.Path
 | 
			
		||||
 * @see java.nio.file.Files
 | 
			
		||||
 */
 | 
			
		||||
public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +54,7 @@ public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		|||
	 * Create a new PathResource from a Path handle.
 | 
			
		||||
	 * <p>Note: Unlike {@link FileSystemResource}, when building relative resources
 | 
			
		||||
	 * via {@link #createRelative}, the relative path will be built <i>underneath</i>
 | 
			
		||||
	 * the given root:
 | 
			
		||||
	 * e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * the given root: e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * @param path a Path handle
 | 
			
		||||
	 */
 | 
			
		||||
	public PathResource(Path path) {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,8 +66,7 @@ public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		|||
	 * Create a new PathResource from a Path handle.
 | 
			
		||||
	 * <p>Note: Unlike {@link FileSystemResource}, when building relative resources
 | 
			
		||||
	 * via {@link #createRelative}, the relative path will be built <i>underneath</i>
 | 
			
		||||
	 * the given root:
 | 
			
		||||
	 * e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * the given root: e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * @param path a path
 | 
			
		||||
	 * @see java.nio.file.Paths#get(String, String...)
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +79,7 @@ public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		|||
	 * Create a new PathResource from a Path handle.
 | 
			
		||||
	 * <p>Note: Unlike {@link FileSystemResource}, when building relative resources
 | 
			
		||||
	 * via {@link #createRelative}, the relative path will be built <i>underneath</i>
 | 
			
		||||
	 * the given root:
 | 
			
		||||
	 * e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * the given root: e.g. Paths.get("C:/dir1/"), relative path "dir2" -> "C:/dir1/dir2"!
 | 
			
		||||
	 * @see java.nio.file.Paths#get(URI)
 | 
			
		||||
	 * @param uri a path URI
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +192,7 @@ public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		|||
		catch (UnsupportedOperationException ex) {
 | 
			
		||||
			// Only paths on the default file system can be converted to a File:
 | 
			
		||||
			// Do exception translation for cases where conversion is not possible.
 | 
			
		||||
			throw new FileNotFoundException(this.path + " cannot be resolved to " + "absolute file path");
 | 
			
		||||
			throw new FileNotFoundException(this.path + " cannot be resolved to absolute file path");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -231,11 +230,11 @@ public class PathResource extends AbstractResource implements WritableResource {
 | 
			
		|||
	public long lastModified() throws IOException {
 | 
			
		||||
		// We can not use the superclass method since it uses conversion to a File and
 | 
			
		||||
		// only a Path on the default file system can be converted to a File...
 | 
			
		||||
		return Files.getLastModifiedTime(path).toMillis();
 | 
			
		||||
		return Files.getLastModifiedTime(this.path).toMillis();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * This implementation creates a FileResource, applying the given path
 | 
			
		||||
	 * This implementation creates a PathResource, applying the given path
 | 
			
		||||
	 * relative to the path of the underlying file of this resource descriptor.
 | 
			
		||||
	 * @see java.nio.file.Path#resolve(String)
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,19 +16,16 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.util;
 | 
			
		||||
 | 
			
		||||
import java.io.BufferedInputStream;
 | 
			
		||||
import java.io.BufferedOutputStream;
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.ByteArrayOutputStream;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.io.Reader;
 | 
			
		||||
import java.io.StringWriter;
 | 
			
		||||
import java.io.Writer;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
 | 
			
		||||
import org.springframework.lang.Nullable;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,6 +39,7 @@ import org.springframework.lang.Nullable;
 | 
			
		|||
 * @author Juergen Hoeller
 | 
			
		||||
 * @since 06.10.2003
 | 
			
		||||
 * @see StreamUtils
 | 
			
		||||
 * @see FileSystemUtils
 | 
			
		||||
 */
 | 
			
		||||
public abstract class FileCopyUtils {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +60,7 @@ public abstract class FileCopyUtils {
 | 
			
		|||
	public static int copy(File in, File out) throws IOException {
 | 
			
		||||
		Assert.notNull(in, "No input File specified");
 | 
			
		||||
		Assert.notNull(out, "No output File specified");
 | 
			
		||||
 | 
			
		||||
		return copy(new BufferedInputStream(new FileInputStream(in)),
 | 
			
		||||
				new BufferedOutputStream(new FileOutputStream(out)));
 | 
			
		||||
		return copy(Files.newInputStream(in.toPath()), Files.newOutputStream(out.toPath()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -76,10 +72,7 @@ public abstract class FileCopyUtils {
 | 
			
		|||
	public static void copy(byte[] in, File out) throws IOException {
 | 
			
		||||
		Assert.notNull(in, "No input byte array specified");
 | 
			
		||||
		Assert.notNull(out, "No output File specified");
 | 
			
		||||
 | 
			
		||||
		ByteArrayInputStream inStream = new ByteArrayInputStream(in);
 | 
			
		||||
		OutputStream outStream = new BufferedOutputStream(new FileOutputStream(out));
 | 
			
		||||
		copy(inStream, outStream);
 | 
			
		||||
		copy(new ByteArrayInputStream(in), Files.newOutputStream(out.toPath()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
| 
						 | 
				
			
			@ -90,8 +83,7 @@ public abstract class FileCopyUtils {
 | 
			
		|||
	 */
 | 
			
		||||
	public static byte[] copyToByteArray(File in) throws IOException {
 | 
			
		||||
		Assert.notNull(in, "No input File specified");
 | 
			
		||||
 | 
			
		||||
		return copyToByteArray(new BufferedInputStream(new FileInputStream(in)));
 | 
			
		||||
		return copyToByteArray(Files.newInputStream(in.toPath()));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,11 @@ package org.springframework.util;
 | 
			
		|||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.FileVisitResult;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.nio.file.SimpleFileVisitor;
 | 
			
		||||
import java.nio.file.attribute.BasicFileAttributes;
 | 
			
		||||
 | 
			
		||||
import org.springframework.lang.Nullable;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -27,29 +32,60 @@ import org.springframework.lang.Nullable;
 | 
			
		|||
 * @author Rob Harrop
 | 
			
		||||
 * @author Juergen Hoeller
 | 
			
		||||
 * @since 2.5.3
 | 
			
		||||
 * @deprecated as of Spring Framework 5.0, in favor of native NIO API usage
 | 
			
		||||
 * @see java.io.File
 | 
			
		||||
 * @see java.nio.file.Path
 | 
			
		||||
 * @see java.nio.file.Files
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
public abstract class FileSystemUtils {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Delete the supplied {@link File} - for directories,
 | 
			
		||||
	 * recursively delete any nested directories or files as well.
 | 
			
		||||
	 * <p>Note: Like {@link File#delete()}, this method does not throw any
 | 
			
		||||
	 * exception but rather silently returns {@code false} in case of I/O
 | 
			
		||||
	 * errors. Consider using {@link #deleteRecursively(Path)} for NIO-style
 | 
			
		||||
	 * handling of I/O errors, clearly differentiating between non-existence
 | 
			
		||||
	 * and failure to delete an existing file.
 | 
			
		||||
	 * @param root the root {@code File} to delete
 | 
			
		||||
	 * @return {@code true} if the {@code File} was deleted,
 | 
			
		||||
	 * @return {@code true} if the {@code File} was successfully deleted,
 | 
			
		||||
	 * otherwise {@code false}
 | 
			
		||||
	 */
 | 
			
		||||
	public static boolean deleteRecursively(@Nullable File root) {
 | 
			
		||||
		if (root != null && root.exists()) {
 | 
			
		||||
			if (root.isDirectory()) {
 | 
			
		||||
				File[] children = root.listFiles();
 | 
			
		||||
				if (children != null) {
 | 
			
		||||
					for (File child : children) {
 | 
			
		||||
						deleteRecursively(child);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		if (root != null) {
 | 
			
		||||
			try {
 | 
			
		||||
				return deleteRecursively(root.toPath());
 | 
			
		||||
			}
 | 
			
		||||
			return root.delete();
 | 
			
		||||
			catch (IOException ex) {
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Delete the supplied {@link File} - for directories,
 | 
			
		||||
	 * recursively delete any nested directories or files as well.
 | 
			
		||||
	 * @param root the root {@code File} to delete
 | 
			
		||||
	 * @return {@code true} if the {@code File} existed and was deleted,
 | 
			
		||||
	 * or {@code false} it it did not exist
 | 
			
		||||
	 * @throws IOException in the case of I/O errors
 | 
			
		||||
	 * @since 5.0
 | 
			
		||||
	 */
 | 
			
		||||
	public static boolean deleteRecursively(@Nullable Path root) throws IOException {
 | 
			
		||||
		if (root != null) {
 | 
			
		||||
			Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
 | 
			
		||||
				@Override
 | 
			
		||||
				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
 | 
			
		||||
					Files.delete(file);
 | 
			
		||||
					return FileVisitResult.CONTINUE;
 | 
			
		||||
				}
 | 
			
		||||
				@Override
 | 
			
		||||
				public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
 | 
			
		||||
					Files.delete(dir);
 | 
			
		||||
					return FileVisitResult.CONTINUE;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
			return Files.deleteIfExists(root);
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -61,43 +97,44 @@ public abstract class FileSystemUtils {
 | 
			
		|||
	 * @param dest the destination directory
 | 
			
		||||
	 * @throws IOException in the case of I/O errors
 | 
			
		||||
	 */
 | 
			
		||||
	public static void copyRecursively(@Nullable File src, File dest) throws IOException {
 | 
			
		||||
		Assert.isTrue(src != null && (src.isDirectory() || src.isFile()),
 | 
			
		||||
				"Source File must denote a directory or file");
 | 
			
		||||
	public static void copyRecursively(File src, File dest) throws IOException {
 | 
			
		||||
		Assert.notNull(src, "Source File must not be null");
 | 
			
		||||
		Assert.notNull(dest, "Destination File must not be null");
 | 
			
		||||
		doCopyRecursively(src, dest);
 | 
			
		||||
		copyRecursively(src.toPath(), dest.toPath());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Actually copy the contents of the {@code src} file/directory
 | 
			
		||||
	 * Recursively copy the contents of the {@code src} file/directory
 | 
			
		||||
	 * to the {@code dest} file/directory.
 | 
			
		||||
	 * @param src the source directory
 | 
			
		||||
	 * @param dest the destination directory
 | 
			
		||||
	 * @throws IOException in the case of I/O errors
 | 
			
		||||
	 * @since 5.0
 | 
			
		||||
	 */
 | 
			
		||||
	private static void doCopyRecursively(File src, File dest) throws IOException {
 | 
			
		||||
		if (src.isDirectory()) {
 | 
			
		||||
			dest.mkdir();
 | 
			
		||||
			File[] entries = src.listFiles();
 | 
			
		||||
			if (entries == null) {
 | 
			
		||||
				throw new IOException("Could not list files in directory: " + src);
 | 
			
		||||
			}
 | 
			
		||||
			for (File entry : entries) {
 | 
			
		||||
				doCopyRecursively(entry, new File(dest, entry.getName()));
 | 
			
		||||
			}
 | 
			
		||||
	public static void copyRecursively(Path src, Path dest) throws IOException {
 | 
			
		||||
		Assert.notNull(src, "Source Path must not be null");
 | 
			
		||||
		Assert.notNull(dest, "Destination Path must not be null");
 | 
			
		||||
		BasicFileAttributes srcAttr = Files.readAttributes(src, BasicFileAttributes.class);
 | 
			
		||||
 | 
			
		||||
		if (srcAttr.isDirectory()) {
 | 
			
		||||
			Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
 | 
			
		||||
				@Override
 | 
			
		||||
				public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
 | 
			
		||||
					Files.createDirectories(dest.resolve(src.relativize(dir)));
 | 
			
		||||
					return FileVisitResult.CONTINUE;
 | 
			
		||||
				}
 | 
			
		||||
				@Override
 | 
			
		||||
				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
 | 
			
		||||
					Files.copy(file, dest.resolve(src.relativize(file)));
 | 
			
		||||
					return FileVisitResult.CONTINUE;
 | 
			
		||||
				}
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		else if (src.isFile()) {
 | 
			
		||||
			try {
 | 
			
		||||
				dest.createNewFile();
 | 
			
		||||
			}
 | 
			
		||||
			catch (IOException ex) {
 | 
			
		||||
				throw new IOException("Failed to create file: " + dest, ex);
 | 
			
		||||
			}
 | 
			
		||||
			FileCopyUtils.copy(src, dest);
 | 
			
		||||
		else if (srcAttr.isRegularFile()) {
 | 
			
		||||
			Files.copy(src, dest);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			// Special File handle: neither a file not a directory.
 | 
			
		||||
			// Simply skip it when contained in nested directory...
 | 
			
		||||
			throw new IllegalArgumentException("Source File must denote a directory or file");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ import static org.junit.Assert.*;
 | 
			
		|||
/**
 | 
			
		||||
 * @author Rob Harrop
 | 
			
		||||
 */
 | 
			
		||||
@Deprecated
 | 
			
		||||
public class FileSystemUtilsTests {
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,6 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.expression.spel.standard;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.net.URL;
 | 
			
		||||
import java.net.URLClassLoader;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
| 
						 | 
				
			
			@ -244,40 +241,6 @@ public class SpelCompiler implements Opcodes {
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * For debugging purposes, dump the specified byte code into a file on the disk.
 | 
			
		||||
	 * Not yet hooked in, needs conditionally calling based on a sys prop.
 | 
			
		||||
	 * @param expressionText the text of the expression compiled
 | 
			
		||||
	 * @param name the name of the class being used for the compiled expression
 | 
			
		||||
	 * @param bytecode the bytecode for the generated class
 | 
			
		||||
	 */
 | 
			
		||||
	@SuppressWarnings("unused")
 | 
			
		||||
	private static void dump(String expressionText, String name, byte[] bytecode) {
 | 
			
		||||
		String nameToUse = name.replace('.', '/');
 | 
			
		||||
		String dir = (nameToUse.indexOf('/') != -1 ? nameToUse.substring(0, nameToUse.lastIndexOf('/')) : "");
 | 
			
		||||
		String dumpLocation = null;
 | 
			
		||||
		try {
 | 
			
		||||
			File tempFile = File.createTempFile("tmp", null);
 | 
			
		||||
			dumpLocation = tempFile + File.separator + nameToUse + ".class";
 | 
			
		||||
			tempFile.delete();
 | 
			
		||||
			File f = new File(tempFile, dir);
 | 
			
		||||
			f.mkdirs();
 | 
			
		||||
			// System.out.println("Expression '" + expressionText + "' compiled code dumped to " + dumpLocation);
 | 
			
		||||
			if (logger.isDebugEnabled()) {
 | 
			
		||||
				logger.debug("Expression '" + expressionText + "' compiled code dumped to " + dumpLocation);
 | 
			
		||||
			}
 | 
			
		||||
			f = new File(dumpLocation);
 | 
			
		||||
			FileOutputStream fos = new FileOutputStream(f);
 | 
			
		||||
			fos.write(bytecode);
 | 
			
		||||
			fos.flush();
 | 
			
		||||
			fos.close();
 | 
			
		||||
		}
 | 
			
		||||
		catch (IOException ex) {
 | 
			
		||||
			throw new IllegalStateException(
 | 
			
		||||
					"Unexpected problem dumping class '" + nameToUse + "' into " + dumpLocation, ex);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * A ChildClassLoader will load the generated compiled expression classes.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,6 @@
 | 
			
		|||
package org.springframework.http.codec.multipart;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.nio.channels.Channels;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +24,7 @@ import java.nio.channels.FileChannel;
 | 
			
		|||
import java.nio.channels.ReadableByteChannel;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.nio.file.StandardOpenOption;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
| 
						 | 
				
			
			@ -187,9 +187,9 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		private Part createPart(StreamStorage storage, HttpHeaders httpHeaders) {
 | 
			
		||||
			String fileName = MultipartUtils.getFileName(httpHeaders);
 | 
			
		||||
			if (fileName != null) {
 | 
			
		||||
				return new SynchronossFilePart(httpHeaders, storage, fileName, this.bufferFactory);
 | 
			
		||||
			String filename = MultipartUtils.getFileName(httpHeaders);
 | 
			
		||||
			if (filename != null) {
 | 
			
		||||
				return new SynchronossFilePart(httpHeaders, storage, this.bufferFactory, filename);
 | 
			
		||||
			}
 | 
			
		||||
			else if (MultipartUtils.isFormField(httpHeaders, this.context)) {
 | 
			
		||||
				String value = MultipartUtils.readFormParameterValue(storage, httpHeaders);
 | 
			
		||||
| 
						 | 
				
			
			@ -200,13 +200,6 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private Part createPart(HttpHeaders httpHeaders, StreamStorage storage) {
 | 
			
		||||
			String fileName = MultipartUtils.getFileName(httpHeaders);
 | 
			
		||||
			return fileName != null ?
 | 
			
		||||
					new SynchronossFilePart(httpHeaders, storage, fileName, this.bufferFactory) :
 | 
			
		||||
					new DefaultSynchronossPart(httpHeaders, storage, this.bufferFactory);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public void onError(String message, Throwable cause) {
 | 
			
		||||
			if (this.terminated.getAndIncrement() == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -284,15 +277,18 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
 | 
			
		|||
 | 
			
		||||
	private static class SynchronossFilePart extends DefaultSynchronossPart implements FilePart {
 | 
			
		||||
 | 
			
		||||
		public SynchronossFilePart(HttpHeaders headers, StreamStorage storage,
 | 
			
		||||
				String fileName, DataBufferFactory factory) {
 | 
			
		||||
		private final String filename;
 | 
			
		||||
 | 
			
		||||
		public SynchronossFilePart(
 | 
			
		||||
				HttpHeaders headers, StreamStorage storage, DataBufferFactory factory, String filename) {
 | 
			
		||||
 | 
			
		||||
			super(headers, storage, factory);
 | 
			
		||||
			this.filename = filename;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
		public String filename() {
 | 
			
		||||
			return MultipartUtils.getFileName(headers());
 | 
			
		||||
			return this.filename;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -301,8 +297,7 @@ public class SynchronossPartHttpMessageReader implements HttpMessageReader<Part>
 | 
			
		|||
			FileChannel output = null;
 | 
			
		||||
			try {
 | 
			
		||||
				input = Channels.newChannel(getStorage().getInputStream());
 | 
			
		||||
				output = new FileOutputStream(destination).getChannel();
 | 
			
		||||
 | 
			
		||||
				output = FileChannel.open(destination.toPath(), StandardOpenOption.WRITE);
 | 
			
		||||
				long size = (input instanceof FileChannel ? ((FileChannel) input).size() : Long.MAX_VALUE);
 | 
			
		||||
				long totalWritten = 0;
 | 
			
		||||
				while (totalWritten < size) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,10 +17,10 @@
 | 
			
		|||
package org.springframework.http.server.reactive;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.nio.channels.FileChannel;
 | 
			
		||||
import java.nio.file.StandardOpenOption;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ public class UndertowServerHttpResponse extends AbstractListenerServerHttpRespon
 | 
			
		|||
		return doCommit(() -> {
 | 
			
		||||
			FileChannel source = null;
 | 
			
		||||
			try {
 | 
			
		||||
				source = new FileInputStream(file).getChannel();
 | 
			
		||||
				source = FileChannel.open(file.toPath(), StandardOpenOption.READ);
 | 
			
		||||
				StreamSinkChannel destination = getUndertowExchange().getResponseChannel();
 | 
			
		||||
				Channels.transferBlocking(destination, source, position, count);
 | 
			
		||||
				return Mono.empty();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,12 +17,12 @@
 | 
			
		|||
package org.springframework.web.multipart.support;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.FileOutputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
| 
						 | 
				
			
			@ -317,7 +317,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
 | 
			
		|||
				// At least we offloaded the file from memory storage; it'll get deleted
 | 
			
		||||
				// from the temp dir eventually in any case. And for our user's purposes,
 | 
			
		||||
				// we can manually copy it to the requested location as a fallback.
 | 
			
		||||
				FileCopyUtils.copy(this.part.getInputStream(), new FileOutputStream(dest));
 | 
			
		||||
				FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath()));
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue