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.net.JarURLConnection;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.util.ArrayList;
27 import java.util.Enumeration;
28 import java.util.List;
29 import java.util.jar.JarEntry;
30 import java.util.jar.JarFile;
31
32 import org.eclipse.jetty.util.log.Log;
33 import org.eclipse.jetty.util.log.Logger;
34
35
36 class JarFileResource extends JarResource
37 {
38 private static final Logger LOG = Log.getLogger(JarFileResource.class);
39 private JarFile _jarFile;
40 private File _file;
41 private String[] _list;
42 private JarEntry _entry;
43 private boolean _directory;
44 private String _jarUrl;
45 private String _path;
46 private boolean _exists;
47
48
49 JarFileResource(URL url)
50 {
51 super(url);
52 }
53
54
55 JarFileResource(URL url, boolean useCaches)
56 {
57 super(url, useCaches);
58 }
59
60
61
62 @Override
63 public synchronized void release()
64 {
65 _list=null;
66 _entry=null;
67 _file=null;
68
69 if ( _jarFile != null )
70 {
71 try
72 {
73 _jarFile.close();
74 }
75 catch ( IOException ioe )
76 {
77 LOG.ignore(ioe);
78 }
79 }
80
81 _jarFile=null;
82 super.release();
83 }
84
85
86 @Override
87 protected boolean checkConnection()
88 {
89 try
90 {
91 super.checkConnection();
92 }
93 finally
94 {
95 if (_jarConnection==null)
96 {
97 _entry=null;
98 _file=null;
99 _jarFile=null;
100 _list=null;
101 }
102 }
103 return _jarFile!=null;
104 }
105
106
107
108 @Override
109 protected synchronized void newConnection()
110 throws IOException
111 {
112 super.newConnection();
113
114 _entry=null;
115 _file=null;
116 _jarFile=null;
117 _list=null;
118
119 int sep = _urlString.indexOf("!/");
120 _jarUrl=_urlString.substring(0,sep+2);
121 _path=_urlString.substring(sep+2);
122 if (_path.length()==0)
123 _path=null;
124 _jarFile=_jarConnection.getJarFile();
125 _file=new File(_jarFile.getName());
126 }
127
128
129
130
131
132
133 @Override
134 public boolean exists()
135 {
136 if (_exists)
137 return true;
138
139 if (_urlString.endsWith("!/"))
140 {
141
142 String file_url=_urlString.substring(4,_urlString.length()-2);
143 try{return newResource(file_url).exists();}
144 catch(Exception e) {LOG.ignore(e); return false;}
145 }
146
147 boolean check=checkConnection();
148
149
150 if (_jarUrl!=null && _path==null)
151 {
152
153 _directory=check;
154 return true;
155 }
156 else
157 {
158
159 JarFile jarFile=null;
160 if (check)
161
162 jarFile=_jarFile;
163 else
164 {
165
166 try
167 {
168 JarURLConnection c=(JarURLConnection)((new URL(_jarUrl)).openConnection());
169 c.setUseCaches(getUseCaches());
170 jarFile=c.getJarFile();
171 }
172 catch(Exception e)
173 {
174 LOG.ignore(e);
175 }
176 }
177
178
179 if (jarFile!=null && _entry==null && !_directory)
180 {
181
182 Enumeration<JarEntry> e=jarFile.entries();
183 while(e.hasMoreElements())
184 {
185 JarEntry entry = (JarEntry) e.nextElement();
186 String name=entry.getName().replace('\\','/');
187
188
189 if (name.equals(_path))
190 {
191 _entry=entry;
192
193 _directory=_path.endsWith("/");
194 break;
195 }
196 else if (_path.endsWith("/"))
197 {
198 if (name.startsWith(_path))
199 {
200 _directory=true;
201 break;
202 }
203 }
204 else if (name.startsWith(_path) && name.length()>_path.length() && name.charAt(_path.length())=='/')
205 {
206 _directory=true;
207 break;
208 }
209 }
210
211 if (_directory && !_urlString.endsWith("/"))
212 {
213 _urlString+="/";
214 try
215 {
216 _url=new URL(_urlString);
217 }
218 catch(MalformedURLException ex)
219 {
220 LOG.warn(ex);
221 }
222 }
223 }
224 }
225
226 _exists= ( _directory || _entry!=null);
227 return _exists;
228 }
229
230
231
232
233
234
235
236
237 @Override
238 public boolean isDirectory()
239 {
240 return _urlString.endsWith("/") || exists() && _directory;
241 }
242
243
244
245
246
247 @Override
248 public long lastModified()
249 {
250 if (checkConnection() && _file!=null)
251 {
252 if (exists() && _entry!=null)
253 return _entry.getTime();
254 return _file.lastModified();
255 }
256 return -1;
257 }
258
259
260 @Override
261 public synchronized String[] list()
262 {
263 if (isDirectory() && _list==null)
264 {
265 List<String> list = null;
266 try
267 {
268 list = listEntries();
269 }
270 catch (Exception e)
271 {
272
273
274
275
276
277
278 LOG.warn("Retrying list:"+e);
279 LOG.debug(e);
280 release();
281 list = listEntries();
282 }
283
284 if (list != null)
285 {
286 _list=new String[list.size()];
287 list.toArray(_list);
288 }
289 }
290 return _list;
291 }
292
293
294
295 private List<String> listEntries ()
296 {
297 checkConnection();
298
299 ArrayList<String> list = new ArrayList<String>(32);
300 JarFile jarFile=_jarFile;
301 if(jarFile==null)
302 {
303 try
304 {
305 JarURLConnection jc=(JarURLConnection)((new URL(_jarUrl)).openConnection());
306 jc.setUseCaches(getUseCaches());
307 jarFile=jc.getJarFile();
308 }
309 catch(Exception e)
310 {
311
312 e.printStackTrace();
313 LOG.ignore(e);
314 }
315 }
316
317 Enumeration<JarEntry> e=jarFile.entries();
318 String dir=_urlString.substring(_urlString.indexOf("!/")+2);
319 while(e.hasMoreElements())
320 {
321 JarEntry entry = e.nextElement();
322 String name=entry.getName().replace('\\','/');
323 if(!name.startsWith(dir) || name.length()==dir.length())
324 {
325 continue;
326 }
327 String listName=name.substring(dir.length());
328 int dash=listName.indexOf('/');
329 if (dash>=0)
330 {
331
332
333 if (dash==0 && listName.length()==1)
334 continue;
335
336
337 if (dash==0)
338 listName=listName.substring(dash+1, listName.length());
339 else
340 listName=listName.substring(0,dash+1);
341
342 if (list.contains(listName))
343 continue;
344 }
345
346 list.add(listName);
347 }
348
349 return list;
350 }
351
352
353
354
355
356
357
358
359
360 @Override
361 public long length()
362 {
363 if (isDirectory())
364 return -1;
365
366 if (_entry!=null)
367 return _entry.getSize();
368
369 return -1;
370 }
371
372
373
374
375
376
377
378 @Override
379 public String encode(String uri)
380 {
381 return uri;
382 }
383
384
385
386
387
388
389
390
391 public static Resource getNonCachingResource (Resource resource)
392 {
393 if (!(resource instanceof JarFileResource))
394 return resource;
395
396 JarFileResource oldResource = (JarFileResource)resource;
397
398 JarFileResource newResource = new JarFileResource(oldResource.getURL(), false);
399 return newResource;
400
401 }
402
403
404
405
406
407
408
409
410 @Override
411 public boolean isContainedIn (Resource resource)
412 throws MalformedURLException
413 {
414 String string = _urlString;
415 int index = string.indexOf("!/");
416 if (index > 0)
417 string = string.substring(0,index);
418 if (string.startsWith("jar:"))
419 string = string.substring(4);
420 URL url = new URL(string);
421 return url.sameFile(resource.getURL());
422 }
423 }
424
425
426
427
428
429
430
431