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;
20
21 import java.io.File;
22 import java.net.URL;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.LinkedHashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.StringTokenizer;
30 import java.util.TreeMap;
31 import java.util.regex.Pattern;
32
33 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
34 import org.eclipse.jetty.osgi.boot.utils.Util;
35 import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
36 import org.eclipse.jetty.util.log.Log;
37 import org.eclipse.jetty.util.log.Logger;
38 import org.eclipse.jetty.util.resource.Resource;
39 import org.eclipse.jetty.util.resource.ResourceCollection;
40 import org.eclipse.jetty.webapp.WebAppContext;
41 import org.eclipse.jetty.webapp.WebInfConfiguration;
42 import org.osgi.framework.Bundle;
43 import org.osgi.framework.FrameworkUtil;
44
45
46
47
48
49
50
51
52 public class OSGiWebInfConfiguration extends WebInfConfiguration
53 {
54 private static final Logger LOG = Log.getLogger(WebInfConfiguration.class);
55
56
57
58
59
60 public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
61
62
63
64 public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
65 public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles";
66 public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @Override
85 public void preConfigure(final WebAppContext context) throws Exception
86 {
87 super.preConfigure(context);
88
89
90
91
92
93
94 String tmp = (String)context.getAttribute(CONTAINER_BUNDLE_PATTERN);
95 Pattern pattern = (tmp==null?null:Pattern.compile(tmp));
96 List<String> names = new ArrayList<String>();
97 tmp = System.getProperty(SYS_PROP_TLD_BUNDLES);
98 if (tmp != null)
99 {
100 StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
101 while (tokenizer.hasMoreTokens())
102 names.add(tokenizer.nextToken());
103 }
104 HashSet<Resource> matchingResources = new HashSet<Resource>();
105 if ( !names.isEmpty() || pattern != null)
106 {
107 Bundle[] bundles = FrameworkUtil.getBundle(OSGiWebInfConfiguration.class).getBundleContext().getBundles();
108
109 for (Bundle bundle : bundles)
110 {
111 LOG.debug("Checking bundle {}:{}", bundle.getBundleId(), bundle.getSymbolicName());
112 if (pattern != null)
113 {
114
115 if (pattern.matcher(bundle.getSymbolicName()).matches())
116 {
117
118 matchingResources.addAll(getBundleAsResource(bundle));
119 }
120 }
121 if (names != null)
122 {
123
124 if (names.contains(bundle.getSymbolicName()))
125 matchingResources.addAll(getBundleAsResource(bundle));
126 }
127 }
128 }
129 for (Resource r:matchingResources)
130 {
131 context.getMetaData().addContainerResource(r);
132 }
133 }
134
135 @Override
136 public void postConfigure(WebAppContext context) throws Exception
137 {
138 context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, null);
139 context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, null);
140 super.postConfigure(context);
141 }
142
143
144
145
146
147
148
149
150 @Override
151 protected List<Resource> findJars (WebAppContext context)
152 throws Exception
153 {
154 List<Resource> mergedResources = new ArrayList<Resource>();
155
156 List<Resource> webInfJars = super.findJars(context);
157 if (webInfJars != null)
158 mergedResources.addAll(webInfJars);
159
160
161 Bundle[] bundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
162 if (bundles != null && bundles.length > 0)
163 {
164 Set<Bundle> fragsAndReqsBundles = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
165 if (fragsAndReqsBundles == null)
166 {
167 fragsAndReqsBundles = new HashSet<Bundle>();
168 context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, fragsAndReqsBundles);
169 }
170
171 Set<Resource> fragsAndReqsResources = (Set<Resource>)context.getAttribute(FRAGMENT_AND_REQUIRED_RESOURCES);
172 if (fragsAndReqsResources == null)
173 {
174 fragsAndReqsResources = new HashSet<Resource>();
175 context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, fragsAndReqsResources);
176 }
177
178 for (Bundle b : bundles)
179 {
180
181 if (b.getState() == Bundle.UNINSTALLED)
182 continue;
183
184
185 fragsAndReqsBundles.add(b);
186 File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(b);
187 Resource r = Resource.newResource(f.toURI());
188
189 fragsAndReqsResources.add(r);
190 mergedResources.add(r);
191 }
192 }
193
194 return mergedResources;
195 }
196
197
198
199
200
201
202
203
204
205 @Override
206 public void configure(WebAppContext context) throws Exception
207 {
208 TreeMap<String, Resource> prependedResourcesPath = new TreeMap<String, Resource>();
209 TreeMap<String, Resource> appendedResourcesPath = new TreeMap<String, Resource>();
210
211 Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
212 if (bundle != null)
213 {
214 Set<Bundle> fragments = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
215 if (fragments != null && !fragments.isEmpty())
216 {
217
218
219
220
221
222
223
224
225
226
227
228
229
230 for (Bundle frag : fragments)
231 {
232 String path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_FRAGMENT_FOLDER_PATH,OSGiWebappConstants.JETTY_WAR_FRAGMENT_RESOURCE_PATH,frag.getHeaders());
233 convertFragmentPathToResource(path, frag, appendedResourcesPath);
234 path = Util.getManifestHeaderValue(OSGiWebappConstants.JETTY_WAR_PATCH_FRAGMENT_FOLDER_PATH, OSGiWebappConstants.JETTY_WAR_PREPEND_FRAGMENT_RESOURCE_PATH, frag.getHeaders());
235 convertFragmentPathToResource(path, frag, prependedResourcesPath);
236 }
237 if (!appendedResourcesPath.isEmpty())
238 {
239 LinkedHashSet<Resource> resources = new LinkedHashSet<Resource>();
240
241 Set<Resource> resourceDirs = (Set<Resource>)context.getAttribute(WebInfConfiguration.RESOURCE_DIRS);
242 if (resourceDirs != null && !resourceDirs.isEmpty())
243 resources.addAll(resourceDirs);
244
245 resources.addAll(appendedResourcesPath.values());
246
247 context.setAttribute(WebInfConfiguration.RESOURCE_DIRS, resources);
248 }
249 }
250 }
251
252 super.configure(context);
253
254
255 if (!prependedResourcesPath.isEmpty())
256 {
257 Resource[] resources = new Resource[1+prependedResourcesPath.size()];
258 System.arraycopy(prependedResourcesPath.values().toArray(new Resource[prependedResourcesPath.size()]), 0, resources, 0, prependedResourcesPath.size());
259 resources[resources.length-1] = context.getBaseResource();
260 context.setBaseResource(new ResourceCollection(resources));
261 }
262 }
263
264
265
266
267
268
269
270 private List<Resource> getBundleAsResource(Bundle bundle)
271 throws Exception
272 {
273 List<Resource> resources = new ArrayList<Resource>();
274
275 File file = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(bundle);
276 if (file.isDirectory())
277 {
278 for (File f : file.listFiles())
279 {
280 if (f.getName().endsWith(".jar") && f.isFile())
281 {
282 resources.add(Resource.newResource(f));
283 }
284 else if (f.isDirectory() && f.getName().equals("lib"))
285 {
286 for (File f2 : file.listFiles())
287 {
288 if (f2.getName().endsWith(".jar") && f2.isFile())
289 {
290 resources.add(Resource.newResource(f));
291 }
292 }
293 }
294 }
295 resources.add(Resource.newResource(file));
296 }
297 else
298 {
299 resources.add(Resource.newResource(file));
300 }
301
302 return resources;
303 }
304
305
306
307
308
309
310
311
312
313 private void convertFragmentPathToResource (String resourcePath, Bundle fragment, Map<String, Resource> resourceMap )
314 throws Exception
315 {
316 if (resourcePath == null)
317 return;
318
319 URL url = fragment.getEntry(resourcePath);
320 if (url == null)
321 {
322 throw new IllegalArgumentException("Unable to locate " + resourcePath
323 + " inside "
324 + " the fragment '"
325 + fragment.getSymbolicName()
326 + "'");
327 }
328 url = BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url);
329 String key = resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath;
330 resourceMap.put(key + ";" + fragment.getSymbolicName(), Resource.newResource(url));
331 }
332 }