View Javadoc

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  	 */
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  	 */
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  	 */
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
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
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 	 */
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
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
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
138 	public File getFile() {
139 		return this.file;
140 	}
141 
142 	/**
143 	 * This implementation returns the underlying File's length.
144 	 */
145 	@Override
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
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
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 	 */
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 	 */
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 	 */
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
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
214 	public int hashCode() {
215 		return this.path.hashCode();
216 	}
217 
218 }