1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jetty.util.resource;
14
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.FilterInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.JarURLConnection;
21 import java.net.URL;
22 import java.util.jar.JarEntry;
23 import java.util.jar.JarInputStream;
24 import java.util.jar.Manifest;
25
26 import org.eclipse.jetty.util.IO;
27 import org.eclipse.jetty.util.log.Log;
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 if ((subEntryName != null) && (entryName.startsWith(subEntryName)))
145 {
146
147
148 if (subEntryIsDir)
149 {
150
151
152
153
154 entryName = entryName.substring(subEntryName.length());
155 if (!entryName.equals(""))
156 {
157
158 shouldExtract = true;
159 }
160 else
161 shouldExtract = false;
162 }
163 else
164 shouldExtract = true;
165 }
166 else if ((subEntryName != null) && (!entryName.startsWith(subEntryName)))
167 {
168
169
170 shouldExtract = false;
171 }
172 else
173 {
174
175 shouldExtract = true;
176 }
177
178
179 if (!shouldExtract)
180 {
181 if (Log.isDebugEnabled()) Log.debug("Skipping entry: "+entryName);
182 continue;
183 }
184
185
186 File file=new File(directory,entryName);
187 if (entry.isDirectory())
188 {
189
190 if (!file.exists())
191 file.mkdirs();
192 }
193 else
194 {
195
196 File dir = new File(file.getParent());
197 if (!dir.exists())
198 dir.mkdirs();
199
200
201 FileOutputStream fout = null;
202 try
203 {
204 fout = new FileOutputStream(file);
205 IO.copy(jin,fout);
206 }
207 finally
208 {
209 IO.close(fout);
210 }
211
212
213 if (entry.getTime()>=0)
214 file.setLastModified(entry.getTime());
215 }
216 if (deleteOnExit)
217 file.deleteOnExit();
218 }
219
220 if ((subEntryName == null) || (subEntryName != null && subEntryName.equalsIgnoreCase("META-INF/MANIFEST.MF")))
221 {
222 Manifest manifest = jin.getManifest();
223 if (manifest != null)
224 {
225 File metaInf = new File (directory, "META-INF");
226 metaInf.mkdir();
227 File f = new File(metaInf, "MANIFEST.MF");
228 FileOutputStream fout = new FileOutputStream(f);
229 manifest.write(fout);
230 fout.close();
231 }
232 }
233 IO.close(jin);
234 }
235
236
237 public void extract(File directory, boolean deleteOnExit)
238 throws IOException
239 {
240 extract(this,directory,deleteOnExit);
241 }
242 }