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