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