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