1 /* 2 * Copyright 2002-2012 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.core.io; 18 19 import java.io.File; 20 import java.io.FileInputStream; 21 import java.io.FileOutputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.OutputStream; 25 import java.net.URI; 26 import java.net.URL; 27 28 import org.springframework.util.Assert; 29 import org.springframework.util.StringUtils; 30 31 /** 32 * {@link Resource} implementation for <code>java.io.File</code> handles. 33 * Obviously supports resolution as File, and also as URL. 34 * Implements the extended {@link WritableResource} interface. 35 * 36 * @author Juergen Hoeller 37 * @since 28.12.2003 38 * @see java.io.File 39 */ 40 public class FileSystemResource extends AbstractResource implements WritableResource { 41 42 private final File file; 43 44 private final String path; 45 46 47 /** 48 * Create a new FileSystemResource from a File handle. 49 * <p>Note: When building relative resources via {@link #createRelative}, 50 * the relative path will apply <i>at the same directory level</i>: 51 * e.g. new File("C:/dir1"), relative path "dir2" -> "C:/dir2"! 52 * If you prefer to have relative paths built underneath the given root 53 * directory, use the {@link #FileSystemResource(String) constructor with a file path} 54 * to append a trailing slash to the root path: "C:/dir1/", which 55 * indicates this directory as root for all relative paths. 56 * @param file a File handle 57 */ FileSystemResource(File file)58 public FileSystemResource(File file) { 59 Assert.notNull(file, "File must not be null"); 60 this.file = file; 61 this.path = StringUtils.cleanPath(file.getPath()); 62 } 63 64 /** 65 * Create a new FileSystemResource from a file path. 66 * <p>Note: When building relative resources via {@link #createRelative}, 67 * it makes a difference whether the specified resource base path here 68 * ends with a slash or not. In the case of "C:/dir1/", relative paths 69 * will be built underneath that root: e.g. relative path "dir2" -> 70 * "C:/dir1/dir2". In the case of "C:/dir1", relative paths will apply 71 * at the same directory level: relative path "dir2" -> "C:/dir2". 72 * @param path a file path 73 */ FileSystemResource(String path)74 public FileSystemResource(String path) { 75 Assert.notNull(path, "Path must not be null"); 76 this.file = new File(path); 77 this.path = StringUtils.cleanPath(path); 78 } 79 80 /** 81 * Return the file path for this resource. 82 */ getPath()83 public final String getPath() { 84 return this.path; 85 } 86 87 88 /** 89 * This implementation returns whether the underlying file exists. 90 * @see java.io.File#exists() 91 */ 92 @Override exists()93 public boolean exists() { 94 return this.file.exists(); 95 } 96 97 /** 98 * This implementation checks whether the underlying file is marked as readable 99 * (and corresponds to an actual file with content, not to a directory). 100 * @see java.io.File#canRead() 101 * @see java.io.File#isDirectory() 102 */ 103 @Override isReadable()104 public boolean isReadable() { 105 return (this.file.canRead() && !this.file.isDirectory()); 106 } 107 108 /** 109 * This implementation opens a FileInputStream for the underlying file. 110 * @see java.io.FileInputStream 111 */ getInputStream()112 public InputStream getInputStream() throws IOException { 113 return new FileInputStream(this.file); 114 } 115 116 /** 117 * This implementation returns a URL for the underlying file. 118 * @see java.io.File#toURI() 119 */ 120 @Override getURL()121 public URL getURL() throws IOException { 122 return this.file.toURI().toURL(); 123 } 124 125 /** 126 * This implementation returns a URI for the underlying file. 127 * @see java.io.File#toURI() 128 */ 129 @Override getURI()130 public URI getURI() throws IOException { 131 return this.file.toURI(); 132 } 133 134 /** 135 * This implementation returns the underlying File reference. 136 */ 137 @Override getFile()138 public File getFile() { 139 return this.file; 140 } 141 142 /** 143 * This implementation returns the underlying File's length. 144 */ 145 @Override contentLength()146 public long contentLength() throws IOException { 147 return this.file.length(); 148 } 149 150 /** 151 * This implementation creates a FileSystemResource, applying the given path 152 * relative to the path of the underlying file of this resource descriptor. 153 * @see org.springframework.util.StringUtils#applyRelativePath(String, String) 154 */ 155 @Override createRelative(String relativePath)156 public Resource createRelative(String relativePath) { 157 String pathToUse = StringUtils.applyRelativePath(this.path, relativePath); 158 return new FileSystemResource(pathToUse); 159 } 160 161 /** 162 * This implementation returns the name of the file. 163 * @see java.io.File#getName() 164 */ 165 @Override getFilename()166 public String getFilename() { 167 return this.file.getName(); 168 } 169 170 /** 171 * This implementation returns a description that includes the absolute 172 * path of the file. 173 * @see java.io.File#getAbsolutePath() 174 */ getDescription()175 public String getDescription() { 176 return "file [" + this.file.getAbsolutePath() + "]"; 177 } 178 179 180 // implementation of WritableResource 181 182 /** 183 * This implementation checks whether the underlying file is marked as writable 184 * (and corresponds to an actual file with content, not to a directory). 185 * @see java.io.File#canWrite() 186 * @see java.io.File#isDirectory() 187 */ isWritable()188 public boolean isWritable() { 189 return (this.file.canWrite() && !this.file.isDirectory()); 190 } 191 192 /** 193 * This implementation opens a FileOutputStream for the underlying file. 194 * @see java.io.FileOutputStream 195 */ getOutputStream()196 public OutputStream getOutputStream() throws IOException { 197 return new FileOutputStream(this.file); 198 } 199 200 201 /** 202 * This implementation compares the underlying File references. 203 */ 204 @Override equals(Object obj)205 public boolean equals(Object obj) { 206 return (obj == this || 207 (obj instanceof FileSystemResource && this.path.equals(((FileSystemResource) obj).path))); 208 } 209 210 /** 211 * This implementation returns the hash code of the underlying File reference. 212 */ 213 @Override hashCode()214 public int hashCode() { 215 return this.path.hashCode(); 216 } 217 218 } 219