1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.mortbay.resource;
15
16 import java.io.File;
17 import java.io.FileOutputStream;
18 import java.io.FilterInputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.net.JarURLConnection;
22 import java.net.URL;
23 import java.util.jar.JarEntry;
24 import java.util.jar.JarInputStream;
25
26 import org.mortbay.log.Log;
27 import org.mortbay.util.IO;
28
29
30
31 public class JarResource extends URLResource
32 {
33
34 protected transient JarURLConnection _jarConnection;
35
36
37 JarResource(URL url)
38 {
39 super(url,null);
40 }
41
42
43 JarResource(URL url, boolean useCaches)
44 {
45 super(url, null, useCaches);
46 }
47
48
49 public synchronized void release()
50 {
51 _jarConnection=null;
52 super.release();
53 }
54
55
56 protected boolean checkConnection()
57 {
58 super.checkConnection();
59 try
60 {
61 if (_jarConnection!=_connection)
62 newConnection();
63 }
64 catch(IOException e)
65 {
66 Log.ignore(e);
67 _jarConnection=null;
68 }
69
70 return _jarConnection!=null;
71 }
72
73
74
75
76
77 protected void newConnection() throws IOException
78 {
79 _jarConnection=(JarURLConnection)_connection;
80 }
81
82
83
84
85
86 public boolean exists()
87 {
88 if (_urlString.endsWith("!/"))
89 return checkConnection();
90 else
91 return super.exists();
92 }
93
94
95 public File getFile()
96 throws IOException
97 {
98 return null;
99 }
100
101
102 public InputStream getInputStream()
103 throws java.io.IOException
104 {
105 checkConnection();
106 if (!_urlString.endsWith("!/"))
107 return new FilterInputStream(super.getInputStream())
108 {
109 public void close() throws IOException {this.in=IO.getClosedStream();}
110 };
111
112 URL url = new URL(_urlString.substring(4,_urlString.length()-2));
113 InputStream is = url.openStream();
114 return is;
115 }
116
117
118 public static void extract(Resource resource, File directory, boolean deleteOnExit)
119 throws IOException
120 {
121 if(Log.isDebugEnabled())Log.debug("Extract "+resource+" to "+directory);
122
123
124 String urlString = resource.getURL().toExternalForm().trim();
125 int endOfJarUrl = urlString.indexOf("!/");
126 int startOfJarUrl = (endOfJarUrl >= 0?4:0);
127
128 if (endOfJarUrl < 0)
129 throw new IOException("Not a valid jar url: "+urlString);
130
131 URL jarFileURL = new URL(urlString.substring(startOfJarUrl, endOfJarUrl));
132 String subEntryName = (endOfJarUrl+2 < urlString.length() ? urlString.substring(endOfJarUrl + 2) : null);
133 boolean subEntryIsDir = (subEntryName != null && subEntryName.endsWith("/")?true:false);
134
135 if (Log.isDebugEnabled()) Log.debug("Extracting entry = "+subEntryName+" from jar "+jarFileURL);
136
137 InputStream is = jarFileURL.openConnection().getInputStream();
138 JarInputStream jin = new JarInputStream(is);
139 JarEntry entry;
140 boolean shouldExtract;
141 while((entry=jin.getNextJarEntry())!=null)
142 {
143 String entryName = entry.getName();
144
145 if ((subEntryName != null) && (entryName.startsWith(subEntryName)))
146 {
147
148
149 if (subEntryIsDir)
150 {
151
152
153
154
155 entryName = entryName.substring(subEntryName.length());
156 if (!entryName.equals(""))
157 {
158
159 shouldExtract = true;
160 }
161 else
162 shouldExtract = false;
163 }
164 else
165 shouldExtract = true;
166 }
167 else if ((subEntryName != null) && (!entryName.startsWith(subEntryName)))
168 {
169
170
171 shouldExtract = false;
172 }
173 else
174 {
175
176 shouldExtract = true;
177 }
178
179
180 if (!shouldExtract)
181 {
182 if (Log.isDebugEnabled()) Log.debug("Skipping entry: "+entryName);
183 continue;
184 }
185
186
187 File file=new File(directory,entryName);
188 if (entry.isDirectory())
189 {
190
191 if (!file.exists())
192 file.mkdirs();
193 }
194 else
195 {
196
197 File dir = new File(file.getParent());
198 if (!dir.exists())
199 dir.mkdirs();
200
201
202 FileOutputStream fout = null;
203 try
204 {
205 fout = new FileOutputStream(file);
206 IO.copy(jin,fout);
207 }
208 finally
209 {
210 IO.close(fout);
211 }
212
213
214 if (entry.getTime()>=0)
215 file.setLastModified(entry.getTime());
216 }
217 if (deleteOnExit)
218 file.deleteOnExit();
219 }
220 IO.close(jin);
221 }
222
223
224 public void extract(File directory, boolean deleteOnExit)
225 throws IOException
226 {
227 extract(this,directory,deleteOnExit);
228 }
229 }