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