Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/resource/Resource.java @ 825:7fb7c1915788
remove jetty.util.B64Code
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 14 Sep 2016 16:38:33 -0600 |
parents | 8e9db0bbf4f9 |
children | f89abbfb3a8f |
comparison
equal
deleted
inserted
replaced
824:90bf40ba1ec2 | 825:7fb7c1915788 |
---|---|
29 import java.net.URLConnection; | 29 import java.net.URLConnection; |
30 import java.text.DateFormat; | 30 import java.text.DateFormat; |
31 import java.util.Arrays; | 31 import java.util.Arrays; |
32 import java.util.Date; | 32 import java.util.Date; |
33 | 33 |
34 import org.eclipse.jetty.util.B64Code; | 34 import java.util.Base64; |
35 import org.eclipse.jetty.util.IO; | 35 import org.eclipse.jetty.util.IO; |
36 import org.eclipse.jetty.util.Loader; | 36 import org.eclipse.jetty.util.Loader; |
37 import org.eclipse.jetty.util.StringUtil; | 37 import org.eclipse.jetty.util.StringUtil; |
38 import org.eclipse.jetty.util.URIUtil; | 38 import org.eclipse.jetty.util.URIUtil; |
39 import org.slf4j.Logger; | 39 import org.slf4j.Logger; |
44 /** | 44 /** |
45 * Abstract resource class. | 45 * Abstract resource class. |
46 */ | 46 */ |
47 public abstract class Resource implements ResourceFactory | 47 public abstract class Resource implements ResourceFactory |
48 { | 48 { |
49 private static final Logger LOG = LoggerFactory.getLogger(Resource.class); | 49 private static final Logger LOG = LoggerFactory.getLogger(Resource.class); |
50 public static boolean __defaultUseCaches = true; | 50 public static boolean __defaultUseCaches = true; |
51 volatile Object _associate; | 51 volatile Object _associate; |
52 | 52 |
53 /* ------------------------------------------------------------ */ | 53 /* ------------------------------------------------------------ */ |
54 /** | 54 /** |
55 * Change the default setting for url connection caches. | 55 * Change the default setting for url connection caches. |
56 * Subsequent URLConnections will use this default. | 56 * Subsequent URLConnections will use this default. |
57 * @param useCaches | 57 * @param useCaches |
58 */ | 58 */ |
59 public static void setDefaultUseCaches (boolean useCaches) | 59 public static void setDefaultUseCaches (boolean useCaches) |
60 { | 60 { |
61 __defaultUseCaches=useCaches; | 61 __defaultUseCaches=useCaches; |
62 } | 62 } |
63 | 63 |
64 /* ------------------------------------------------------------ */ | 64 /* ------------------------------------------------------------ */ |
65 public static boolean getDefaultUseCaches () | 65 public static boolean getDefaultUseCaches () |
66 { | 66 { |
67 return __defaultUseCaches; | 67 return __defaultUseCaches; |
68 } | 68 } |
69 | 69 |
70 /* ------------------------------------------------------------ */ | 70 /* ------------------------------------------------------------ */ |
71 /** Construct a resource from a uri. | 71 /** Construct a resource from a uri. |
72 * @param uri A URI. | 72 * @param uri A URI. |
73 * @return A Resource object. | 73 * @return A Resource object. |
74 * @throws IOException Problem accessing URI | 74 * @throws IOException Problem accessing URI |
75 */ | 75 */ |
76 public static Resource newResource(URI uri) | 76 public static Resource newResource(URI uri) |
77 throws IOException | 77 throws IOException |
78 { | 78 { |
79 return newResource(uri.toURL()); | 79 return newResource(uri.toURL()); |
80 } | 80 } |
81 | 81 |
82 /* ------------------------------------------------------------ */ | 82 /* ------------------------------------------------------------ */ |
83 /** Construct a resource from a url. | 83 /** Construct a resource from a url. |
84 * @param url A URL. | 84 * @param url A URL. |
85 * @return A Resource object. | 85 * @return A Resource object. |
86 * @throws IOException Problem accessing URL | 86 * @throws IOException Problem accessing URL |
87 */ | 87 */ |
88 public static Resource newResource(URL url) | 88 public static Resource newResource(URL url) |
89 throws IOException | 89 throws IOException |
90 { | 90 { |
91 return newResource(url, __defaultUseCaches); | 91 return newResource(url, __defaultUseCaches); |
92 } | 92 } |
93 | 93 |
94 /* ------------------------------------------------------------ */ | 94 /* ------------------------------------------------------------ */ |
95 /** | 95 /** |
96 * Construct a resource from a url. | 96 * Construct a resource from a url. |
97 * @param url the url for which to make the resource | 97 * @param url the url for which to make the resource |
98 * @param useCaches true enables URLConnection caching if applicable to the type of resource | 98 * @param useCaches true enables URLConnection caching if applicable to the type of resource |
99 * @return | 99 * @return |
100 */ | 100 */ |
101 static Resource newResource(URL url, boolean useCaches) | 101 static Resource newResource(URL url, boolean useCaches) |
102 { | 102 { |
103 if (url==null) | 103 if (url==null) |
104 return null; | 104 return null; |
105 | 105 |
106 String url_string=url.toExternalForm(); | 106 String url_string=url.toExternalForm(); |
107 if( url_string.startsWith( "file:")) | 107 if( url_string.startsWith( "file:")) |
108 { | 108 { |
109 try | 109 try |
110 { | 110 { |
111 FileResource fileResource= new FileResource(url); | 111 FileResource fileResource= new FileResource(url); |
112 return fileResource; | 112 return fileResource; |
113 } | 113 } |
114 catch(Exception e) | 114 catch(Exception e) |
115 { | 115 { |
116 LOG.debug("EXCEPTION",e); | 116 LOG.debug("EXCEPTION",e); |
117 return new BadResource(url,e.toString()); | 117 return new BadResource(url,e.toString()); |
118 } | 118 } |
119 } | 119 } |
120 else if( url_string.startsWith( "jar:file:")) | 120 else if( url_string.startsWith( "jar:file:")) |
121 { | 121 { |
122 return new JarFileResource(url, useCaches); | 122 return new JarFileResource(url, useCaches); |
123 } | 123 } |
124 else if( url_string.startsWith( "jar:")) | 124 else if( url_string.startsWith( "jar:")) |
125 { | 125 { |
126 return new JarResource(url, useCaches); | 126 return new JarResource(url, useCaches); |
127 } | 127 } |
128 | 128 |
129 return new URLResource(url,null,useCaches); | 129 return new URLResource(url,null,useCaches); |
130 } | 130 } |
131 | 131 |
132 | 132 |
133 | 133 |
134 /* ------------------------------------------------------------ */ | 134 /* ------------------------------------------------------------ */ |
135 /** Construct a resource from a string. | 135 /** Construct a resource from a string. |
136 * @param resource A URL or filename. | 136 * @param resource A URL or filename. |
137 * @return A Resource object. | 137 * @return A Resource object. |
138 */ | 138 */ |
139 public static Resource newResource(String resource) | 139 public static Resource newResource(String resource) |
140 throws MalformedURLException, IOException | 140 throws MalformedURLException, IOException |
141 { | 141 { |
142 return newResource(resource, __defaultUseCaches); | 142 return newResource(resource, __defaultUseCaches); |
143 } | 143 } |
144 | 144 |
145 /* ------------------------------------------------------------ */ | 145 /* ------------------------------------------------------------ */ |
146 /** Construct a resource from a string. | 146 /** Construct a resource from a string. |
147 * @param resource A URL or filename. | 147 * @param resource A URL or filename. |
148 * @param useCaches controls URLConnection caching | 148 * @param useCaches controls URLConnection caching |
149 * @return A Resource object. | 149 * @return A Resource object. |
150 */ | 150 */ |
151 public static Resource newResource (String resource, boolean useCaches) | 151 public static Resource newResource (String resource, boolean useCaches) |
152 throws MalformedURLException, IOException | 152 throws MalformedURLException, IOException |
153 { | 153 { |
154 URL url=null; | 154 URL url=null; |
155 try | 155 try |
156 { | 156 { |
157 // Try to format as a URL? | 157 // Try to format as a URL? |
158 url = new URL(resource); | 158 url = new URL(resource); |
159 } | 159 } |
160 catch(MalformedURLException e) | 160 catch(MalformedURLException e) |
161 { | 161 { |
162 if(!resource.startsWith("ftp:") && | 162 if(!resource.startsWith("ftp:") && |
163 !resource.startsWith("file:") && | 163 !resource.startsWith("file:") && |
164 !resource.startsWith("jar:")) | 164 !resource.startsWith("jar:")) |
165 { | 165 { |
166 try | 166 try |
167 { | 167 { |
168 // It's a file. | 168 // It's a file. |
169 if (resource.startsWith("./")) | 169 if (resource.startsWith("./")) |
170 resource=resource.substring(2); | 170 resource=resource.substring(2); |
171 | 171 |
172 File file=new File(resource).getCanonicalFile(); | 172 File file=new File(resource).getCanonicalFile(); |
173 url=Resource.toURL(file); | 173 url=Resource.toURL(file); |
174 | 174 |
175 URLConnection connection=url.openConnection(); | 175 URLConnection connection=url.openConnection(); |
176 connection.setUseCaches(useCaches); | 176 connection.setUseCaches(useCaches); |
177 return new FileResource(url,connection,file); | 177 return new FileResource(url,connection,file); |
178 } | 178 } |
179 catch(Exception e2) | 179 catch(Exception e2) |
180 { | 180 { |
181 LOG.debug("EXCEPTION",e2); | 181 LOG.debug("EXCEPTION",e2); |
182 throw e; | 182 throw e; |
183 } | 183 } |
184 } | 184 } |
185 else | 185 else |
186 { | 186 { |
187 LOG.warn("Bad Resource: "+resource); | 187 LOG.warn("Bad Resource: "+resource); |
188 throw e; | 188 throw e; |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 return newResource(url); | 192 return newResource(url); |
193 } | 193 } |
194 | 194 |
195 /* ------------------------------------------------------------ */ | 195 /* ------------------------------------------------------------ */ |
196 public static Resource newResource (File file) | 196 public static Resource newResource (File file) |
197 throws MalformedURLException, IOException | 197 throws MalformedURLException, IOException |
198 { | 198 { |
199 file = file.getCanonicalFile(); | 199 file = file.getCanonicalFile(); |
200 URL url = Resource.toURL(file); | 200 URL url = Resource.toURL(file); |
201 | 201 |
202 URLConnection connection = url.openConnection(); | 202 URLConnection connection = url.openConnection(); |
203 FileResource fileResource = new FileResource(url, connection, file); | 203 FileResource fileResource = new FileResource(url, connection, file); |
204 return fileResource; | 204 return fileResource; |
205 } | 205 } |
206 | 206 |
207 /* ------------------------------------------------------------ */ | 207 /* ------------------------------------------------------------ */ |
208 /** Construct a system resource from a string. | 208 /** Construct a system resource from a string. |
209 * The resource is tried as classloader resource before being | 209 * The resource is tried as classloader resource before being |
210 * treated as a normal resource. | 210 * treated as a normal resource. |
211 * @param resource Resource as string representation | 211 * @param resource Resource as string representation |
212 * @return The new Resource | 212 * @return The new Resource |
213 * @throws IOException Problem accessing resource. | 213 * @throws IOException Problem accessing resource. |
214 */ | 214 */ |
215 public static Resource newSystemResource(String resource) | 215 public static Resource newSystemResource(String resource) |
216 throws IOException | 216 throws IOException |
217 { | 217 { |
218 URL url=null; | 218 URL url=null; |
219 // Try to format as a URL? | 219 // Try to format as a URL? |
220 ClassLoader loader=Thread.currentThread().getContextClassLoader(); | 220 ClassLoader loader=Thread.currentThread().getContextClassLoader(); |
221 if (loader!=null) | 221 if (loader!=null) |
222 { | 222 { |
223 try | 223 try |
224 { | 224 { |
225 url = loader.getResource(resource); | 225 url = loader.getResource(resource); |
226 if (url == null && resource.startsWith("/")) | 226 if (url == null && resource.startsWith("/")) |
227 url = loader.getResource(resource.substring(1)); | 227 url = loader.getResource(resource.substring(1)); |
228 } | 228 } |
229 catch (IllegalArgumentException e) | 229 catch (IllegalArgumentException e) |
230 { | 230 { |
231 // Catches scenario where a bad Windows path like "C:\dev" is | 231 // Catches scenario where a bad Windows path like "C:\dev" is |
232 // improperly escaped, which various downstream classloaders | 232 // improperly escaped, which various downstream classloaders |
233 // tend to have a problem with | 233 // tend to have a problem with |
234 url = null; | 234 url = null; |
235 } | 235 } |
236 } | 236 } |
237 if (url==null) | 237 if (url==null) |
238 { | 238 { |
239 loader=Resource.class.getClassLoader(); | 239 loader=Resource.class.getClassLoader(); |
240 if (loader!=null) | 240 if (loader!=null) |
241 { | 241 { |
242 url=loader.getResource(resource); | 242 url=loader.getResource(resource); |
243 if (url==null && resource.startsWith("/")) | 243 if (url==null && resource.startsWith("/")) |
244 url=loader.getResource(resource.substring(1)); | 244 url=loader.getResource(resource.substring(1)); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 if (url==null) | 248 if (url==null) |
249 { | 249 { |
250 url=ClassLoader.getSystemResource(resource); | 250 url=ClassLoader.getSystemResource(resource); |
251 if (url==null && resource.startsWith("/")) | 251 if (url==null && resource.startsWith("/")) |
252 url=ClassLoader.getSystemResource(resource.substring(1)); | 252 url=ClassLoader.getSystemResource(resource.substring(1)); |
253 } | 253 } |
254 | 254 |
255 if (url==null) | 255 if (url==null) |
256 return null; | 256 return null; |
257 | 257 |
258 return newResource(url); | 258 return newResource(url); |
259 } | 259 } |
260 | 260 |
261 /* ------------------------------------------------------------ */ | 261 /* ------------------------------------------------------------ */ |
262 /** Find a classpath resource. | 262 /** Find a classpath resource. |
263 */ | 263 */ |
264 public static Resource newClassPathResource(String resource) | 264 public static Resource newClassPathResource(String resource) |
265 { | 265 { |
266 return newClassPathResource(resource,true,false); | 266 return newClassPathResource(resource,true,false); |
267 } | 267 } |
268 | 268 |
269 /* ------------------------------------------------------------ */ | 269 /* ------------------------------------------------------------ */ |
270 /** Find a classpath resource. | 270 /** Find a classpath resource. |
271 * The {@link java.lang.Class#getResource(String)} method is used to lookup the resource. If it is not | 271 * The {@link java.lang.Class#getResource(String)} method is used to lookup the resource. If it is not |
272 * found, then the {@link Loader#getResource(Class, String, boolean)} method is used. | 272 * found, then the {@link Loader#getResource(Class, String, boolean)} method is used. |
273 * If it is still not found, then {@link ClassLoader#getSystemResource(String)} is used. | 273 * If it is still not found, then {@link ClassLoader#getSystemResource(String)} is used. |
274 * Unlike {@link ClassLoader#getSystemResource(String)} this method does not check for normal resources. | 274 * Unlike {@link ClassLoader#getSystemResource(String)} this method does not check for normal resources. |
275 * @param name The relative name of the resource | 275 * @param name The relative name of the resource |
276 * @param useCaches True if URL caches are to be used. | 276 * @param useCaches True if URL caches are to be used. |
277 * @param checkParents True if forced searching of parent Classloaders is performed to work around | 277 * @param checkParents True if forced searching of parent Classloaders is performed to work around |
278 * loaders with inverted priorities | 278 * loaders with inverted priorities |
279 * @return Resource or null | 279 * @return Resource or null |
280 */ | 280 */ |
281 public static Resource newClassPathResource(String name,boolean useCaches,boolean checkParents) | 281 public static Resource newClassPathResource(String name,boolean useCaches,boolean checkParents) |
282 { | 282 { |
283 URL url=Resource.class.getResource(name); | 283 URL url=Resource.class.getResource(name); |
284 | 284 |
285 if (url==null) | 285 if (url==null) |
286 url=Loader.getResource(Resource.class,name,checkParents); | 286 url=Loader.getResource(Resource.class,name,checkParents); |
287 if (url==null) | 287 if (url==null) |
288 return null; | 288 return null; |
289 return newResource(url,useCaches); | 289 return newResource(url,useCaches); |
290 } | 290 } |
291 | 291 |
292 /* ------------------------------------------------------------ */ | 292 /* ------------------------------------------------------------ */ |
293 public static boolean isContainedIn (Resource r, Resource containingResource) throws MalformedURLException | 293 public static boolean isContainedIn (Resource r, Resource containingResource) throws MalformedURLException |
294 { | 294 { |
295 return r.isContainedIn(containingResource); | 295 return r.isContainedIn(containingResource); |
296 } | 296 } |
297 | 297 |
298 /* ------------------------------------------------------------ */ | 298 /* ------------------------------------------------------------ */ |
299 @Override | 299 @Override |
300 protected void finalize() | 300 protected void finalize() |
301 { | 301 { |
302 release(); | 302 release(); |
303 } | 303 } |
304 | 304 |
305 /* ------------------------------------------------------------ */ | 305 /* ------------------------------------------------------------ */ |
306 public abstract boolean isContainedIn (Resource r) throws MalformedURLException; | 306 public abstract boolean isContainedIn (Resource r) throws MalformedURLException; |
307 | 307 |
308 | 308 |
309 /* ------------------------------------------------------------ */ | 309 /* ------------------------------------------------------------ */ |
310 /** Release any temporary resources held by the resource. | 310 /** Release any temporary resources held by the resource. |
311 */ | 311 */ |
312 public abstract void release(); | 312 public abstract void release(); |
313 | 313 |
314 | 314 |
315 /* ------------------------------------------------------------ */ | 315 /* ------------------------------------------------------------ */ |
316 /** | 316 /** |
317 * Returns true if the respresened resource exists. | 317 * Returns true if the respresened resource exists. |
318 */ | 318 */ |
319 public abstract boolean exists(); | 319 public abstract boolean exists(); |
320 | 320 |
321 | 321 |
322 /* ------------------------------------------------------------ */ | 322 /* ------------------------------------------------------------ */ |
323 /** | 323 /** |
324 * Returns true if the respresenetd resource is a container/directory. | 324 * Returns true if the respresenetd resource is a container/directory. |
325 * If the resource is not a file, resources ending with "/" are | 325 * If the resource is not a file, resources ending with "/" are |
326 * considered directories. | 326 * considered directories. |
327 */ | 327 */ |
328 public abstract boolean isDirectory(); | 328 public abstract boolean isDirectory(); |
329 | 329 |
330 /* ------------------------------------------------------------ */ | 330 /* ------------------------------------------------------------ */ |
331 /** | 331 /** |
332 * Returns the last modified time | 332 * Returns the last modified time |
333 */ | 333 */ |
334 public abstract long lastModified(); | 334 public abstract long lastModified(); |
335 | 335 |
336 | 336 |
337 /* ------------------------------------------------------------ */ | 337 /* ------------------------------------------------------------ */ |
338 /** | 338 /** |
339 * Return the length of the resource | 339 * Return the length of the resource |
340 */ | 340 */ |
341 public abstract long length(); | 341 public abstract long length(); |
342 | 342 |
343 | 343 |
344 /* ------------------------------------------------------------ */ | 344 /* ------------------------------------------------------------ */ |
345 /** | 345 /** |
346 * Returns an URL representing the given resource | 346 * Returns an URL representing the given resource |
347 */ | 347 */ |
348 public abstract URL getURL(); | 348 public abstract URL getURL(); |
349 | 349 |
350 /* ------------------------------------------------------------ */ | 350 /* ------------------------------------------------------------ */ |
351 /** | 351 /** |
352 * Returns an URI representing the given resource | 352 * Returns an URI representing the given resource |
353 */ | 353 */ |
354 public URI getURI() | 354 public URI getURI() |
355 { | 355 { |
356 try | 356 try |
357 { | 357 { |
358 return getURL().toURI(); | 358 return getURL().toURI(); |
359 } | 359 } |
360 catch(Exception e) | 360 catch(Exception e) |
361 { | 361 { |
362 throw new RuntimeException(e); | 362 throw new RuntimeException(e); |
363 } | 363 } |
364 } | 364 } |
365 | 365 |
366 | 366 |
367 /* ------------------------------------------------------------ */ | 367 /* ------------------------------------------------------------ */ |
368 /** | 368 /** |
369 * Returns an File representing the given resource or NULL if this | 369 * Returns an File representing the given resource or NULL if this |
370 * is not possible. | 370 * is not possible. |
371 */ | 371 */ |
372 public abstract File getFile() | 372 public abstract File getFile() |
373 throws IOException; | 373 throws IOException; |
374 | 374 |
375 | 375 |
376 /* ------------------------------------------------------------ */ | 376 /* ------------------------------------------------------------ */ |
377 /** | 377 /** |
378 * Returns the name of the resource | 378 * Returns the name of the resource |
379 */ | 379 */ |
380 public abstract String getName(); | 380 public abstract String getName(); |
381 | 381 |
382 | 382 |
383 /* ------------------------------------------------------------ */ | 383 /* ------------------------------------------------------------ */ |
384 /** | 384 /** |
385 * Returns an input stream to the resource | 385 * Returns an input stream to the resource |
386 */ | 386 */ |
387 public abstract InputStream getInputStream() | 387 public abstract InputStream getInputStream() |
388 throws java.io.IOException; | 388 throws java.io.IOException; |
389 | 389 |
390 /* ------------------------------------------------------------ */ | 390 /* ------------------------------------------------------------ */ |
391 /** | 391 /** |
392 * Returns an output stream to the resource | 392 * Returns an output stream to the resource |
393 */ | 393 */ |
394 public abstract OutputStream getOutputStream() | 394 public abstract OutputStream getOutputStream() |
395 throws java.io.IOException, SecurityException; | 395 throws java.io.IOException, SecurityException; |
396 | 396 |
397 /* ------------------------------------------------------------ */ | 397 /* ------------------------------------------------------------ */ |
398 /** | 398 /** |
399 * Deletes the given resource | 399 * Deletes the given resource |
400 */ | 400 */ |
401 public abstract boolean delete() | 401 public abstract boolean delete() |
402 throws SecurityException; | 402 throws SecurityException; |
403 | 403 |
404 /* ------------------------------------------------------------ */ | 404 /* ------------------------------------------------------------ */ |
405 /** | 405 /** |
406 * Rename the given resource | 406 * Rename the given resource |
407 */ | 407 */ |
408 public abstract boolean renameTo( Resource dest) | 408 public abstract boolean renameTo( Resource dest) |
409 throws SecurityException; | 409 throws SecurityException; |
410 | 410 |
411 /* ------------------------------------------------------------ */ | 411 /* ------------------------------------------------------------ */ |
412 /** | 412 /** |
413 * Returns a list of resource names contained in the given resource | 413 * Returns a list of resource names contained in the given resource |
414 * The resource names are not URL encoded. | 414 * The resource names are not URL encoded. |
415 */ | 415 */ |
416 public abstract String[] list(); | 416 public abstract String[] list(); |
417 | 417 |
418 /* ------------------------------------------------------------ */ | 418 /* ------------------------------------------------------------ */ |
419 /** | 419 /** |
420 * Returns the resource contained inside the current resource with the | 420 * Returns the resource contained inside the current resource with the |
421 * given name. | 421 * given name. |
422 * @param path The path segment to add, which should be encoded by the | 422 * @param path The path segment to add, which should be encoded by the |
423 * encode method. | 423 * encode method. |
424 */ | 424 */ |
425 public abstract Resource addPath(String path) | 425 public abstract Resource addPath(String path) |
426 throws IOException,MalformedURLException; | 426 throws IOException,MalformedURLException; |
427 | 427 |
428 /* ------------------------------------------------------------ */ | 428 /* ------------------------------------------------------------ */ |
429 /** Get a resource from withing this resource. | 429 /** Get a resource from withing this resource. |
430 * <p> | 430 * <p> |
431 * This method is essentially an alias for {@link #addPath(String)}, but without checked exceptions. | 431 * This method is essentially an alias for {@link #addPath(String)}, but without checked exceptions. |
432 * This method satisfied the {@link ResourceFactory} interface. | 432 * This method satisfied the {@link ResourceFactory} interface. |
433 * @see org.eclipse.jetty.util.resource.ResourceFactory#getResource(java.lang.String) | 433 * @see org.eclipse.jetty.util.resource.ResourceFactory#getResource(java.lang.String) |
434 */ | 434 */ |
435 public Resource getResource(String path) | 435 public Resource getResource(String path) |
436 { | 436 { |
437 try | 437 try |
438 { | 438 { |
439 return addPath(path); | 439 return addPath(path); |
440 } | 440 } |
441 catch(Exception e) | 441 catch(Exception e) |
442 { | 442 { |
443 LOG.debug("",e); | 443 LOG.debug("",e); |
444 return null; | 444 return null; |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 /* ------------------------------------------------------------ */ | 448 /* ------------------------------------------------------------ */ |
449 /** Encode according to this resource type. | 449 /** Encode according to this resource type. |
450 * The default implementation calls URI.encodePath(uri) | 450 * The default implementation calls URI.encodePath(uri) |
451 * @param uri | 451 * @param uri |
452 * @return String encoded for this resource type. | 452 * @return String encoded for this resource type. |
453 */ | 453 */ |
454 public String encode(String uri) | 454 public String encode(String uri) |
455 { | 455 { |
456 return URIUtil.encodePath(uri); | 456 return URIUtil.encodePath(uri); |
457 } | 457 } |
458 | 458 |
459 /* ------------------------------------------------------------ */ | 459 /* ------------------------------------------------------------ */ |
460 public Object getAssociate() | 460 public Object getAssociate() |
461 { | 461 { |
462 return _associate; | 462 return _associate; |
463 } | 463 } |
464 | 464 |
465 /* ------------------------------------------------------------ */ | 465 /* ------------------------------------------------------------ */ |
466 public void setAssociate(Object o) | 466 public void setAssociate(Object o) |
467 { | 467 { |
468 _associate=o; | 468 _associate=o; |
469 } | 469 } |
470 | 470 |
471 /* ------------------------------------------------------------ */ | 471 /* ------------------------------------------------------------ */ |
472 /** | 472 /** |
473 * @return The canonical Alias of this resource or null if none. | 473 * @return The canonical Alias of this resource or null if none. |
474 */ | 474 */ |
475 public URL getAlias() | 475 public URL getAlias() |
476 { | 476 { |
477 return null; | 477 return null; |
478 } | 478 } |
479 | 479 |
480 /* ------------------------------------------------------------ */ | 480 /* ------------------------------------------------------------ */ |
481 /** Get the resource list as a HTML directory listing. | 481 /** Get the resource list as a HTML directory listing. |
482 * @param base The base URL | 482 * @param base The base URL |
483 * @param parent True if the parent directory should be included | 483 * @param parent True if the parent directory should be included |
484 * @return String of HTML | 484 * @return String of HTML |
485 */ | 485 */ |
486 public String getListHTML(String base,boolean parent) | 486 public String getListHTML(String base,boolean parent) |
487 throws IOException | 487 throws IOException |
488 { | 488 { |
489 base=URIUtil.canonicalPath(base); | 489 base=URIUtil.canonicalPath(base); |
490 if (base==null || !isDirectory()) | 490 if (base==null || !isDirectory()) |
491 return null; | 491 return null; |
492 | 492 |
493 String[] ls = list(); | 493 String[] ls = list(); |
494 if (ls==null) | 494 if (ls==null) |
495 return null; | 495 return null; |
496 Arrays.sort(ls); | 496 Arrays.sort(ls); |
497 | 497 |
498 String decodedBase = URIUtil.decodePath(base); | 498 String decodedBase = URIUtil.decodePath(base); |
499 String title = "Directory: "+deTag(decodedBase); | 499 String title = "Directory: "+deTag(decodedBase); |
500 | 500 |
501 StringBuilder buf=new StringBuilder(4096); | 501 StringBuilder buf=new StringBuilder(4096); |
502 buf.append("<HTML><HEAD>"); | 502 buf.append("<HTML><HEAD>"); |
503 buf.append("<LINK HREF=\"").append("jetty-dir.css").append("\" REL=\"stylesheet\" TYPE=\"text/css\"/><TITLE>"); | 503 buf.append("<LINK HREF=\"").append("jetty-dir.css").append("\" REL=\"stylesheet\" TYPE=\"text/css\"/><TITLE>"); |
504 buf.append(title); | 504 buf.append(title); |
505 buf.append("</TITLE></HEAD><BODY>\n<H1>"); | 505 buf.append("</TITLE></HEAD><BODY>\n<H1>"); |
506 buf.append(title); | 506 buf.append(title); |
507 buf.append("</H1>\n<TABLE BORDER=0>\n"); | 507 buf.append("</H1>\n<TABLE BORDER=0>\n"); |
508 | 508 |
509 if (parent) | 509 if (parent) |
510 { | 510 { |
511 buf.append("<TR><TD><A HREF=\""); | 511 buf.append("<TR><TD><A HREF=\""); |
512 buf.append(URIUtil.addPaths(base,"../")); | 512 buf.append(URIUtil.addPaths(base,"../")); |
513 buf.append("\">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n"); | 513 buf.append("\">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n"); |
514 } | 514 } |
515 | 515 |
516 String encodedBase = hrefEncodeURI(base); | 516 String encodedBase = hrefEncodeURI(base); |
517 | 517 |
518 DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM, | 518 DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM, |
519 DateFormat.MEDIUM); | 519 DateFormat.MEDIUM); |
520 for (int i=0 ; i< ls.length ; i++) | 520 for (int i=0 ; i< ls.length ; i++) |
521 { | 521 { |
522 Resource item = addPath(ls[i]); | 522 Resource item = addPath(ls[i]); |
523 | 523 |
524 buf.append("\n<TR><TD><A HREF=\""); | 524 buf.append("\n<TR><TD><A HREF=\""); |
525 String path=URIUtil.addPaths(encodedBase,URIUtil.encodePath(ls[i])); | 525 String path=URIUtil.addPaths(encodedBase,URIUtil.encodePath(ls[i])); |
526 | 526 |
527 buf.append(path); | 527 buf.append(path); |
528 | 528 |
529 if (item.isDirectory() && !path.endsWith("/")) | 529 if (item.isDirectory() && !path.endsWith("/")) |
530 buf.append(URIUtil.SLASH); | 530 buf.append(URIUtil.SLASH); |
531 | 531 |
532 // URIUtil.encodePath(buf,path); | 532 // URIUtil.encodePath(buf,path); |
533 buf.append("\">"); | 533 buf.append("\">"); |
534 buf.append(deTag(ls[i])); | 534 buf.append(deTag(ls[i])); |
535 buf.append(" "); | 535 buf.append(" "); |
536 buf.append("</A></TD><TD ALIGN=right>"); | 536 buf.append("</A></TD><TD ALIGN=right>"); |
537 buf.append(item.length()); | 537 buf.append(item.length()); |
538 buf.append(" bytes </TD><TD>"); | 538 buf.append(" bytes </TD><TD>"); |
539 buf.append(dfmt.format(new Date(item.lastModified()))); | 539 buf.append(dfmt.format(new Date(item.lastModified()))); |
540 buf.append("</TD></TR>"); | 540 buf.append("</TD></TR>"); |
541 } | 541 } |
542 buf.append("</TABLE>\n"); | 542 buf.append("</TABLE>\n"); |
543 buf.append("</BODY></HTML>\n"); | 543 buf.append("</BODY></HTML>\n"); |
544 | 544 |
545 return buf.toString(); | 545 return buf.toString(); |
546 } | 546 } |
547 | 547 |
548 /** | 548 /** |
549 * Encode any characters that could break the URI string in an HREF. | 549 * Encode any characters that could break the URI string in an HREF. |
550 * Such as <a href="/path/to;<script>Window.alert("XSS"+'%20'+"here");</script>">Link</a> | 550 * Such as <a href="/path/to;<script>Window.alert("XSS"+'%20'+"here");</script>">Link</a> |
551 * | 551 * |
552 * The above example would parse incorrectly on various browsers as the "<" or '"' characters | 552 * The above example would parse incorrectly on various browsers as the "<" or '"' characters |
553 * would end the href attribute value string prematurely. | 553 * would end the href attribute value string prematurely. |
554 * | 554 * |
555 * @param raw the raw text to encode. | 555 * @param raw the raw text to encode. |
556 * @return the defanged text. | 556 * @return the defanged text. |
557 */ | 557 */ |
558 private static String hrefEncodeURI(String raw) | 558 private static String hrefEncodeURI(String raw) |
559 { | 559 { |
560 StringBuffer buf = null; | 560 StringBuffer buf = null; |
561 | 561 |
562 loop: | 562 loop: |
563 for (int i=0;i<raw.length();i++) | 563 for (int i=0;i<raw.length();i++) |
564 { | 564 { |
565 char c=raw.charAt(i); | 565 char c=raw.charAt(i); |
566 switch(c) | 566 switch(c) |
567 { | 567 { |
568 case '\'': | 568 case '\'': |
569 case '"': | 569 case '"': |
570 case '<': | 570 case '<': |
571 case '>': | 571 case '>': |
572 buf=new StringBuffer(raw.length()<<1); | 572 buf=new StringBuffer(raw.length()<<1); |
573 break loop; | 573 break loop; |
574 } | 574 } |
575 } | 575 } |
576 if (buf==null) | 576 if (buf==null) |
577 return raw; | 577 return raw; |
578 | 578 |
579 for (int i=0;i<raw.length();i++) | 579 for (int i=0;i<raw.length();i++) |
580 { | 580 { |
581 char c=raw.charAt(i); | 581 char c=raw.charAt(i); |
582 switch(c) | 582 switch(c) |
583 { | 583 { |
584 case '"': | 584 case '"': |
585 buf.append("%22"); | 585 buf.append("%22"); |
586 continue; | 586 continue; |
587 case '\'': | 587 case '\'': |
588 buf.append("%27"); | 588 buf.append("%27"); |
589 continue; | 589 continue; |
590 case '<': | 590 case '<': |
591 buf.append("%3C"); | 591 buf.append("%3C"); |
592 continue; | 592 continue; |
593 case '>': | 593 case '>': |
594 buf.append("%3E"); | 594 buf.append("%3E"); |
595 continue; | 595 continue; |
596 default: | 596 default: |
597 buf.append(c); | 597 buf.append(c); |
598 continue; | 598 continue; |
599 } | 599 } |
600 } | 600 } |
601 | 601 |
602 return buf.toString(); | 602 return buf.toString(); |
603 } | 603 } |
604 | 604 |
605 private static String deTag(String raw) | 605 private static String deTag(String raw) |
606 { | 606 { |
607 return StringUtil.replace( StringUtil.replace(raw,"<","<"), ">", ">"); | 607 return StringUtil.replace( StringUtil.replace(raw,"<","<"), ">", ">"); |
608 } | 608 } |
609 | 609 |
610 /* ------------------------------------------------------------ */ | 610 /* ------------------------------------------------------------ */ |
611 /** | 611 /** |
612 * @param out | 612 * @param out |
613 * @param start First byte to write | 613 * @param start First byte to write |
614 * @param count Bytes to write or -1 for all of them. | 614 * @param count Bytes to write or -1 for all of them. |
615 */ | 615 */ |
616 public void writeTo(OutputStream out,long start,long count) | 616 public void writeTo(OutputStream out,long start,long count) |
617 throws IOException | 617 throws IOException |
618 { | 618 { |
619 InputStream in = getInputStream(); | 619 InputStream in = getInputStream(); |
620 try | 620 try |
621 { | 621 { |
622 in.skip(start); | 622 in.skip(start); |
623 if (count<0) | 623 if (count<0) |
624 IO.copy(in,out); | 624 IO.copy(in,out); |
625 else | 625 else |
626 IO.copy(in,out,count); | 626 IO.copy(in,out,count); |
627 } | 627 } |
628 finally | 628 finally |
629 { | 629 { |
630 in.close(); | 630 in.close(); |
631 } | 631 } |
632 } | 632 } |
633 | 633 |
634 /* ------------------------------------------------------------ */ | 634 /* ------------------------------------------------------------ */ |
635 public void copyTo(File destination) | 635 public void copyTo(File destination) |
636 throws IOException | 636 throws IOException |
637 { | 637 { |
638 if (destination.exists()) | 638 if (destination.exists()) |
639 throw new IllegalArgumentException(destination+" exists"); | 639 throw new IllegalArgumentException(destination+" exists"); |
640 writeTo(new FileOutputStream(destination),0,-1); | 640 writeTo(new FileOutputStream(destination),0,-1); |
641 } | 641 } |
642 | 642 |
643 /* ------------------------------------------------------------ */ | 643 /* ------------------------------------------------------------ */ |
644 public String getWeakETag() | 644 public String getWeakETag() |
645 { | 645 { |
646 try | 646 StringBuilder b = new StringBuilder(32); |
647 { | 647 b.append("W/\""); |
648 StringBuilder b = new StringBuilder(32); | 648 |
649 b.append("W/\""); | 649 long lhash = lastModified() ^ getName().hashCode() ^ length(); |
650 | 650 byte[] a = new byte[Long.BYTES]; |
651 String name=getName(); | 651 for( int i=0; i<a.length; i++ ) { |
652 int length=name.length(); | 652 a[i] = (byte)lhash; |
653 long lhash=0; | 653 lhash >>= 8; |
654 for (int i=0; i<length;i++) | 654 } |
655 lhash=31*lhash+name.charAt(i); | 655 b.append( Base64.getEncoder().encodeToString(a) ); |
656 | 656 |
657 B64Code.encode(lastModified()^lhash,b); | 657 b.append('"'); |
658 B64Code.encode(length()^lhash,b); | 658 return b.toString(); |
659 b.append('"'); | 659 } |
660 return b.toString(); | 660 |
661 } | 661 /* ------------------------------------------------------------ */ |
662 catch (IOException e) | 662 /** Generate a properly encoded URL from a {@link File} instance. |
663 { | 663 * @param file Target file. |
664 throw new RuntimeException(e); | 664 * @return URL of the target file. |
665 } | 665 * @throws MalformedURLException |
666 } | 666 */ |
667 | 667 public static URL toURL(File file) throws MalformedURLException |
668 /* ------------------------------------------------------------ */ | 668 { |
669 /** Generate a properly encoded URL from a {@link File} instance. | 669 return file.toURI().toURL(); |
670 * @param file Target file. | 670 } |
671 * @return URL of the target file. | |
672 * @throws MalformedURLException | |
673 */ | |
674 public static URL toURL(File file) throws MalformedURLException | |
675 { | |
676 return file.toURI().toURL(); | |
677 } | |
678 } | 671 } |