1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.osgi.boot.utils.internal;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Method;
25 import java.net.URI;
26 import java.net.URL;
27 import java.net.URLConnection;
28 import java.net.URLDecoder;
29 import java.util.ArrayList;
30 import java.util.Enumeration;
31 import java.util.zip.ZipFile;
32
33 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
34 import org.eclipse.jetty.util.URIUtil;
35 import org.eclipse.jetty.util.resource.PathResource;
36 import org.eclipse.jetty.util.resource.Resource;
37 import org.osgi.framework.Bundle;
38
39
40
41
42
43
44
45 public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
46 {
47
48
49
50
51
52
53 private static Field BUNDLE_ENTRY_FIELD = null;
54
55 private static Field FILE_FIELD = null;
56
57 private static Field BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = null;
58
59
60
61
62 private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;
63
64 private static final String[] FILE_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry","org.eclipse.osgi.storage.bundlefile.FileBundleEntry"};
65 private static final String[] ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry","org.eclipse.osgi.storage.bundlefile.ZipBundleEntry"};
66 private static final String[] DIR_ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry","org.eclipse.osgi.storage.bundlefile.DirZipBundleEntry"};
67 private static final String[] BUNDLE_URL_CONNECTION_CLASSES = {"org.eclipse.osgi.framework.internal.core.BundleURLConnection", "org.eclipse.osgi.storage.url.BundleURLConnection"};
68
69
70 public static boolean match (String name, String... names)
71 {
72 if (name == null || names == null)
73 return false;
74 boolean matched = false;
75 for (int i=0; i< names.length && !matched; i++)
76 if (name.equals(names[i]))
77 matched = true;
78 return matched;
79 }
80
81
82
83
84
85
86
87
88
89
90
91 public File getBundleInstallLocation(Bundle bundle) throws Exception
92 {
93
94
95
96 URL url = bundle.getEntry("/META-INF/MANIFEST.MF");
97
98 if (url.getProtocol().equals("file"))
99 {
100
101
102
103 return new PathResource(url).getFile().getParentFile().getParentFile();
104 }
105 else if (url.getProtocol().equals("bundleentry"))
106 {
107
108
109
110
111 URLConnection con = url.openConnection();
112 con.setUseCaches(Resource.getDefaultUseCaches());
113
114
115
116
117
118
119 if (BUNDLE_ENTRY_FIELD == null)
120 {
121 BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
122 BUNDLE_ENTRY_FIELD.setAccessible(true);
123 }
124 Object bundleEntry = BUNDLE_ENTRY_FIELD.get(con);
125
126 if (match(bundleEntry.getClass().getName(), FILE_BUNDLE_ENTRY_CLASSES))
127 {
128 if (FILE_FIELD == null)
129 {
130 FILE_FIELD = bundleEntry.getClass().getDeclaredField("file");
131 FILE_FIELD.setAccessible(true);
132 }
133 File f = (File) FILE_FIELD.get(bundleEntry);
134 return f.getParentFile().getParentFile();
135 }
136 else if (match(bundleEntry.getClass().getName(), ZIP_BUNDLE_ENTRY_CLASSES))
137 {
138 url = bundle.getEntry("/");
139
140 con = url.openConnection();
141 con.setDefaultUseCaches(Resource.getDefaultUseCaches());
142
143 if (BUNDLE_ENTRY_FIELD == null)
144 {
145 BUNDLE_ENTRY_FIELD = con.getClass().getDeclaredField("bundleEntry");
146 BUNDLE_ENTRY_FIELD.setAccessible(true);
147 }
148 bundleEntry = BUNDLE_ENTRY_FIELD.get(con);
149 if (BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY == null)
150 {
151 BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY = bundleEntry.getClass().getDeclaredField("bundleFile");
152 BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY.setAccessible(true);
153 }
154 Object zipBundleFile = BUNDLE_FILE_FIELD_FOR_DIR_ZIP_BUNDLE_ENTRY.get(bundleEntry);
155 if (ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE == null)
156 {
157 ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = zipBundleFile.getClass().getDeclaredField("zipFile");
158 ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.setAccessible(true);
159 }
160 ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
161 return new File(zipFile.getName());
162 }
163 else if (match (bundleEntry.getClass().getName(), DIR_ZIP_BUNDLE_ENTRY_CLASSES))
164 {
165
166
167 }
168 }
169 else if ("bundle".equals(url.getProtocol()))
170 {
171
172 String location = bundle.getLocation();
173 if (location.startsWith("file:/"))
174 {
175 URI uri = new URI(URIUtil.encodePath(location));
176 return new File(uri);
177 }
178 else if (location.startsWith("file:"))
179 {
180
181
182
183 File res = new File(location.substring("file:".length()));
184 if (!res.exists()) { return null;
185
186
187
188
189
190
191
192
193
194
195
196 }
197 return res;
198 }
199 else if (location.startsWith("reference:file:"))
200 {
201 location = URLDecoder.decode(location.substring("reference:".length()), "UTF-8");
202 File file = new File(location.substring("file:".length()));
203 return file;
204 }
205 }
206 return null;
207 }
208
209
210
211
212
213
214
215
216
217 public File getFileInBundle(Bundle bundle, String path) throws Exception
218 {
219 if (path != null && path.length() > 0 && path.charAt(0) == '/')
220 {
221 path = path.substring(1);
222 }
223 File bundleInstall = getBundleInstallLocation(bundle);
224 File webapp = path != null && path.length() != 0 ? new File(bundleInstall, path) : bundleInstall;
225 if (!webapp.exists()) { throw new IllegalArgumentException("Unable to locate " + path
226 + " inside "
227 + bundle.getSymbolicName()
228 + " ("
229 + (bundleInstall != null ? bundleInstall.getAbsolutePath() : " no_bundle_location ")
230 + ")"); }
231 return webapp;
232 }
233
234
235
236
237
238
239
240
241
242
243 public Enumeration<URL> findEntries(Bundle bundle, String entryPath)
244 {
245 int last = entryPath.lastIndexOf('/');
246 String path = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(0, last) : "/";
247 if (!path.startsWith("/"))
248 {
249 path = "/" + path;
250 }
251 String pattern = last != -1 && last < entryPath.length() - 2 ? entryPath.substring(last + 1) : entryPath;
252 Enumeration<URL> enUrls = bundle.findEntries(path, pattern, false);
253 return enUrls;
254 }
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270 public File[] locateJarsInsideBundle(Bundle bundle) throws Exception
271 {
272 File jasperLocation = getBundleInstallLocation(bundle);
273 if (jasperLocation.isDirectory())
274 {
275
276 ArrayList<File> urls = new ArrayList<File>();
277 for (File f : jasperLocation.listFiles())
278 {
279 if (f.getName().endsWith(".jar") && f.isFile())
280 {
281 urls.add(f);
282 }
283 else if (f.isDirectory() && f.getName().equals("lib"))
284 {
285 for (File f2 : jasperLocation.listFiles())
286 {
287 if (f2.getName().endsWith(".jar") && f2.isFile())
288 {
289 urls.add(f2);
290 }
291 }
292 }
293 }
294 return urls.toArray(new File[urls.size()]);
295 }
296 else
297 {
298 return new File[] { jasperLocation };
299 }
300 }
301
302
303
304
305
306 private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
307
308 private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
309
310
311
312
313
314
315
316
317
318
319
320 public URL getLocalURL(URL url)
321 throws Exception
322 {
323 if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
324 {
325
326 URLConnection conn = url.openConnection();
327 conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
328 if (BUNDLE_URL_CONNECTION_getLocalURL == null && match(conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
329 {
330 BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
331 BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
332 }
333 if (BUNDLE_URL_CONNECTION_getLocalURL != null) { return (URL) BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn, null); }
334 }
335 return url;
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351 public URL getFileURL(URL url) throws Exception
352
353 {
354 if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
355 {
356
357 URLConnection conn = url.openConnection();
358 conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
359 if (BUNDLE_URL_CONNECTION_getFileURL == null
360 &&
361 match (conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
362 {
363 BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
364 BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
365 }
366 if (BUNDLE_URL_CONNECTION_getFileURL != null) { return (URL) BUNDLE_URL_CONNECTION_getFileURL.invoke(conn, null); }
367
368 }
369 return url;
370 }
371
372 }