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.FileInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.net.MalformedURLException;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.net.URL;
29 import java.net.URLConnection;
30 import java.nio.channels.FileChannel;
31 import java.nio.channels.ReadableByteChannel;
32 import java.nio.file.StandardOpenOption;
33 import java.security.Permission;
34
35 import org.eclipse.jetty.util.IO;
36 import org.eclipse.jetty.util.URIUtil;
37 import org.eclipse.jetty.util.log.Log;
38 import org.eclipse.jetty.util.log.Logger;
39
40
41
42
43
44
45
46
47
48
49
50 public class FileResource extends Resource
51 {
52 private static final Logger LOG = Log.getLogger(FileResource.class);
53
54
55 private final File _file;
56 private final String _uri;
57 private final URI _alias;
58
59
60 public FileResource(URL url)
61 throws IOException, URISyntaxException
62 {
63 File file;
64 try
65 {
66
67 file =new File(url.toURI());
68 }
69 catch (URISyntaxException e)
70 {
71 throw e;
72 }
73 catch (Exception e)
74 {
75 if (!url.toString().startsWith("file:"))
76 throw new IllegalArgumentException("!file:");
77
78 LOG.ignore(e);
79 try
80 {
81
82 String file_url="file:"+URIUtil.encodePath(url.toString().substring(5));
83 URI uri = new URI(file_url);
84 if (uri.getAuthority()==null)
85 file = new File(uri);
86 else
87 file = new File("//"+uri.getAuthority()+URIUtil.decodePath(url.getFile()));
88 }
89 catch (Exception e2)
90 {
91 LOG.ignore(e2);
92
93 URLConnection connection=url.openConnection();
94 Permission perm = connection.getPermission();
95 file = new File(perm==null?url.getFile():perm.getName());
96 }
97 }
98
99 _file=file;
100 _uri=normalizeURI(_file,url.toURI());
101 _alias=checkAlias(_file);
102 }
103
104
105 public FileResource(URI uri)
106 {
107 File file=new File(uri);
108 _file=file;
109 URI file_uri=_file.toURI();
110 _uri=normalizeURI(_file,uri);
111
112 if (!_uri.equals(file_uri) && !_uri.toString().equals(file_uri.toString()))
113 {
114
115 if (!file_uri.toString().equals(URIUtil.decodePath(uri.toString())))
116 _alias=_file.toURI();
117 else
118 _alias=checkAlias(_file);
119 }
120 else
121 _alias=checkAlias(_file);
122 }
123
124
125 FileResource(File file)
126 {
127 _file=file;
128 _uri=normalizeURI(_file,_file.toURI());
129 _alias=checkAlias(_file);
130 }
131
132
133 private static String normalizeURI(File file, URI uri)
134 {
135 String u =uri.toASCIIString();
136 if (file.isDirectory())
137 {
138 if(!u.endsWith("/"))
139 u+="/";
140 }
141 else if (file.exists() && u.endsWith("/"))
142 u=u.substring(0,u.length()-1);
143 return u;
144 }
145
146
147 private static URI checkAlias(File file)
148 {
149 try
150 {
151 String abs=file.getAbsolutePath();
152 String can=file.getCanonicalPath();
153
154 if (!abs.equals(can))
155 {
156 LOG.debug("ALIAS abs={} can={}",abs,can);
157 return new File(can).toURI();
158 }
159 }
160 catch(IOException e)
161 {
162 LOG.warn("bad alias for {}: {}",file,e.toString());
163 LOG.debug(e);
164 try
165 {
166 return new URI("http://eclipse.org/bad/canonical/alias");
167 }
168 catch(Exception e2)
169 {
170 LOG.ignore(e2);
171 throw new RuntimeException(e);
172 }
173 }
174
175 return null;
176 }
177
178
179 @Override
180 public Resource addPath(String path)
181 throws IOException,MalformedURLException
182 {
183 path = org.eclipse.jetty.util.URIUtil.canonicalPath(path);
184
185 if (path==null)
186 throw new MalformedURLException();
187
188 if ("/".equals(path))
189 return this;
190
191 path=URIUtil.encodePath(path);
192
193 URI uri;
194 try
195 {
196 if (_file.isDirectory())
197 {
198
199 uri=new URI(URIUtil.addPaths(_uri,path));
200 }
201 else
202 {
203 uri=new URI(_uri+path);
204 }
205 }
206 catch(final URISyntaxException e)
207 {
208 throw new MalformedURLException(){{initCause(e);}};
209 }
210
211 return new FileResource(uri);
212 }
213
214
215
216 @Override
217 public URI getAlias()
218 {
219 return _alias;
220 }
221
222
223
224
225
226 @Override
227 public boolean exists()
228 {
229 return _file.exists();
230 }
231
232
233
234
235
236 @Override
237 public long lastModified()
238 {
239 return _file.lastModified();
240 }
241
242
243
244
245
246 @Override
247 public boolean isDirectory()
248 {
249 return _file.exists() && _file.isDirectory() || _uri.endsWith("/");
250 }
251
252
253
254
255
256 @Override
257 public long length()
258 {
259 return _file.length();
260 }
261
262
263
264
265
266
267 @Override
268 public String getName()
269 {
270 return _file.getAbsolutePath();
271 }
272
273
274
275
276
277
278 @Override
279 public File getFile()
280 {
281 return _file;
282 }
283
284
285
286
287
288 @Override
289 public InputStream getInputStream() throws IOException
290 {
291 return new FileInputStream(_file);
292 }
293
294
295 @Override
296 public ReadableByteChannel getReadableByteChannel() throws IOException
297 {
298 return FileChannel.open(_file.toPath(),StandardOpenOption.READ);
299 }
300
301
302
303
304
305 @Override
306 public boolean delete()
307 throws SecurityException
308 {
309 return _file.delete();
310 }
311
312
313
314
315
316 @Override
317 public boolean renameTo( Resource dest)
318 throws SecurityException
319 {
320 if( dest instanceof FileResource)
321 return _file.renameTo( ((FileResource)dest)._file);
322 else
323 return false;
324 }
325
326
327
328
329
330 @Override
331 public String[] list()
332 {
333 String[] list =_file.list();
334 if (list==null)
335 return null;
336 for (int i=list.length;i-->0;)
337 {
338 if (new File(_file,list[i]).isDirectory() &&
339 !list[i].endsWith("/"))
340 list[i]+="/";
341 }
342 return list;
343 }
344
345
346
347
348
349
350 @Override
351 public boolean equals( Object o)
352 {
353 if (this == o)
354 return true;
355
356 if (null == o || ! (o instanceof FileResource))
357 return false;
358
359 FileResource f=(FileResource)o;
360 return f._file == _file || (null != _file && _file.equals(f._file));
361 }
362
363
364
365
366
367 @Override
368 public int hashCode()
369 {
370 return null == _file ? super.hashCode() : _file.hashCode();
371 }
372
373
374 @Override
375 public void copyTo(File destination)
376 throws IOException
377 {
378 if (isDirectory())
379 {
380 IO.copyDir(getFile(),destination);
381 }
382 else
383 {
384 if (destination.exists())
385 throw new IllegalArgumentException(destination+" exists");
386 IO.copy(getFile(),destination);
387 }
388 }
389
390 @Override
391 public boolean isContainedIn(Resource r) throws MalformedURLException
392 {
393 return false;
394 }
395
396 @Override
397 public void close()
398 {
399 }
400
401 @Override
402 public URL getURL()
403 {
404 try
405 {
406 return new URL(_uri);
407 }
408 catch (MalformedURLException e)
409 {
410 throw new IllegalStateException(e);
411 }
412 }
413
414 @Override
415 public URI getURI()
416 {
417 return _file.toURI();
418 }
419
420 @Override
421 public String toString()
422 {
423 return _uri;
424 }
425
426 }