1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util.resource;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.MalformedURLException;
25 import java.net.URI;
26 import java.net.URISyntaxException;
27 import java.net.URL;
28 import java.nio.channels.FileChannel;
29 import java.nio.channels.ReadableByteChannel;
30 import java.nio.file.DirectoryIteratorException;
31 import java.nio.file.DirectoryStream;
32 import java.nio.file.Files;
33 import java.nio.file.InvalidPathException;
34 import java.nio.file.LinkOption;
35 import java.nio.file.Path;
36 import java.nio.file.StandardCopyOption;
37 import java.nio.file.StandardOpenOption;
38 import java.nio.file.attribute.FileTime;
39 import java.util.ArrayList;
40 import java.util.List;
41
42 import org.eclipse.jetty.util.log.Log;
43 import org.eclipse.jetty.util.log.Logger;
44
45
46
47
48 public class PathResource extends Resource
49 {
50 private static final Logger LOG = Log.getLogger(PathResource.class);
51
52 private final Path path;
53 private final URI uri;
54 private LinkOption linkOptions[] = new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
55
56 public PathResource(File file)
57 {
58 this(file.toPath());
59 }
60
61 public PathResource(Path path)
62 {
63 this.path = path;
64 this.uri = this.path.toUri();
65 }
66
67 public PathResource(URI uri) throws IOException
68 {
69 if (!uri.isAbsolute())
70 {
71 throw new IllegalArgumentException("not an absolute uri");
72 }
73
74 if (!uri.getScheme().equalsIgnoreCase("file"))
75 {
76 throw new IllegalArgumentException("not file: scheme");
77 }
78
79 Path path;
80 try
81 {
82 path = new File(uri).toPath();
83 }
84 catch (InvalidPathException e)
85 {
86 throw e;
87 }
88 catch (IllegalArgumentException e)
89 {
90 throw e;
91 }
92 catch (Exception e)
93 {
94 LOG.ignore(e);
95 throw new IOException("Unable to build Path from: " + uri,e);
96 }
97
98 this.path = path;
99 this.uri = path.toUri();
100 }
101
102 public PathResource(URL url) throws IOException, URISyntaxException
103 {
104 this(url.toURI());
105 }
106
107 @Override
108 public Resource addPath(String apath) throws IOException, MalformedURLException
109 {
110 return new PathResource(this.path.resolve(apath));
111 }
112
113 @Override
114 public void close()
115 {
116
117 }
118
119 @Override
120 public boolean delete() throws SecurityException
121 {
122 try
123 {
124 return Files.deleteIfExists(path);
125 }
126 catch (IOException e)
127 {
128 LOG.ignore(e);
129 return false;
130 }
131 }
132
133 @Override
134 public boolean equals(Object obj)
135 {
136 if (this == obj)
137 {
138 return true;
139 }
140 if (obj == null)
141 {
142 return false;
143 }
144 if (getClass() != obj.getClass())
145 {
146 return false;
147 }
148 PathResource other = (PathResource)obj;
149 if (path == null)
150 {
151 if (other.path != null)
152 {
153 return false;
154 }
155 }
156 else if (!path.equals(other.path))
157 {
158 return false;
159 }
160 return true;
161 }
162
163 @Override
164 public boolean exists()
165 {
166 return Files.exists(path,linkOptions);
167 }
168
169 @Override
170 public File getFile() throws IOException
171 {
172 return path.toFile();
173 }
174
175 public boolean getFollowLinks()
176 {
177 return (linkOptions != null) && (linkOptions.length > 0) && (linkOptions[0] == LinkOption.NOFOLLOW_LINKS);
178 }
179
180 @Override
181 public InputStream getInputStream() throws IOException
182 {
183 return Files.newInputStream(path,StandardOpenOption.READ);
184 }
185
186 @Override
187 public String getName()
188 {
189 return path.toAbsolutePath().toString();
190 }
191
192 @Override
193 public ReadableByteChannel getReadableByteChannel() throws IOException
194 {
195 return FileChannel.open(path,StandardOpenOption.READ);
196 }
197
198 @Override
199 public URI getURI()
200 {
201 return this.uri;
202 }
203
204 @Override
205 public URL getURL()
206 {
207 try
208 {
209 return path.toUri().toURL();
210 }
211 catch (MalformedURLException e)
212 {
213 return null;
214 }
215 }
216
217 @Override
218 public int hashCode()
219 {
220 final int prime = 31;
221 int result = 1;
222 result = (prime * result) + ((path == null)?0:path.hashCode());
223 return result;
224 }
225
226 @Override
227 public boolean isContainedIn(Resource r) throws MalformedURLException
228 {
229
230 return false;
231 }
232
233 @Override
234 public boolean isDirectory()
235 {
236 return Files.isDirectory(path,linkOptions);
237 }
238
239 @Override
240 public long lastModified()
241 {
242 try
243 {
244 FileTime ft = Files.getLastModifiedTime(path,linkOptions);
245 return ft.toMillis();
246 }
247 catch (IOException e)
248 {
249 LOG.ignore(e);
250 return 0;
251 }
252 }
253
254 @Override
255 public long length()
256 {
257 try
258 {
259 return Files.size(path);
260 }
261 catch (IOException e)
262 {
263
264 return 0L;
265 }
266 }
267
268 @Override
269 public URI getAlias()
270 {
271 if (Files.isSymbolicLink(path))
272 {
273 try
274 {
275 return path.toRealPath().toUri();
276 }
277 catch (IOException e)
278 {
279 LOG.debug(e);
280 return null;
281 }
282 }
283 else
284 {
285 return null;
286 }
287 }
288
289 @Override
290 public String[] list()
291 {
292 try (DirectoryStream<Path> dir = Files.newDirectoryStream(path))
293 {
294 List<String> entries = new ArrayList<>();
295 for (Path entry : dir)
296 {
297 String name = entry.getFileName().toString();
298
299 if (Files.isDirectory(entry))
300 {
301 name += "/";
302 }
303
304 entries.add(name);
305 }
306 int size = entries.size();
307 return entries.toArray(new String[size]);
308 }
309 catch (DirectoryIteratorException e)
310 {
311 LOG.debug(e);
312 }
313 catch (IOException e)
314 {
315 LOG.debug(e);
316 }
317 return null;
318 }
319
320 @Override
321 public boolean renameTo(Resource dest) throws SecurityException
322 {
323 if (dest instanceof PathResource)
324 {
325 PathResource destRes = (PathResource)dest;
326 try
327 {
328 Path result = Files.move(path,destRes.path,StandardCopyOption.ATOMIC_MOVE);
329 return Files.exists(result,linkOptions);
330 }
331 catch (IOException e)
332 {
333 LOG.ignore(e);
334 return false;
335 }
336 }
337 else
338 {
339 return false;
340 }
341 }
342
343 public void setFollowLinks(boolean followLinks)
344 {
345 if (followLinks)
346 {
347 linkOptions = new LinkOption[0];
348 }
349 else
350 {
351 linkOptions = new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
352 }
353 }
354 }