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.internal.serverfactory;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Dictionary;
27 import java.util.Enumeration;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.StringTokenizer;
32
33 import org.eclipse.jetty.deploy.AppLifeCycle;
34 import org.eclipse.jetty.deploy.AppProvider;
35 import org.eclipse.jetty.deploy.DeploymentManager;
36 import org.eclipse.jetty.deploy.bindings.StandardStarter;
37 import org.eclipse.jetty.deploy.bindings.StandardStopper;
38 import org.eclipse.jetty.osgi.boot.BundleContextProvider;
39 import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
40 import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
41 import org.eclipse.jetty.osgi.boot.OSGiDeployer;
42 import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
43 import org.eclipse.jetty.osgi.boot.OSGiUndeployer;
44 import org.eclipse.jetty.osgi.boot.ServiceContextProvider;
45 import org.eclipse.jetty.osgi.boot.ServiceWebAppProvider;
46 import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader;
47 import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
48 import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
49 import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
50 import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
51 import org.eclipse.jetty.server.Server;
52 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
53 import org.eclipse.jetty.util.IO;
54 import org.eclipse.jetty.util.log.Log;
55 import org.eclipse.jetty.util.log.Logger;
56 import org.eclipse.jetty.util.resource.Resource;
57 import org.eclipse.jetty.xml.XmlConfiguration;
58 import org.xml.sax.SAXParseException;
59
60
61
62
63
64
65 public class ServerInstanceWrapper
66 {
67
68
69
70
71
72
73 public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
74
75 private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
76
77
78
79 private final String _managedServerName;
80
81
82
83
84 private Server _server;
85
86 private ContextHandlerCollection _ctxtCollection;
87
88
89
90
91
92
93 private ClassLoader _commonParentClassLoaderForWebapps;
94
95 private DeploymentManager _deploymentManager;
96
97
98
99 public ServerInstanceWrapper(String managedServerName)
100 {
101 _managedServerName = managedServerName;
102 }
103
104
105 public String getManagedServerName()
106 {
107 return _managedServerName;
108 }
109
110
111
112
113
114
115
116
117
118 public ClassLoader getParentClassLoaderForWebapps()
119 {
120 return _commonParentClassLoaderForWebapps;
121 }
122
123
124
125
126
127
128 public DeploymentManager getDeploymentManager()
129 {
130 return _deploymentManager;
131 }
132
133
134
135
136
137
138 public Server getServer()
139 {
140 return _server;
141 }
142
143
144
145
146
147 public ContextHandlerCollection getContextHandlerCollection()
148 {
149 return _ctxtCollection;
150 }
151
152
153
154 public void start(Server server, Dictionary props) throws Exception
155 {
156 _server = server;
157 ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
158 try
159 {
160
161
162 ClassLoader libExtClassLoader = null;
163 String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
164
165 List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
166 libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
167
168 if (LOG.isDebugEnabled()) LOG.debug("LibExtClassLoader = "+libExtClassLoader);
169
170 Thread.currentThread().setContextClassLoader(libExtClassLoader);
171
172 configure(server, props);
173
174 init();
175
176 URL[] jarsWithTlds = getJarsWithTlds();
177 _commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
178
179 if (LOG.isDebugEnabled()) LOG.debug("common classloader = "+_commonParentClassLoaderForWebapps);
180
181 server.start();
182 }
183 catch (Exception e)
184 {
185 if (server != null)
186 {
187 try
188 {
189 server.stop();
190 }
191 catch (Exception x)
192 {
193 LOG.ignore(x);
194 }
195 }
196 throw e;
197 }
198 finally
199 {
200 Thread.currentThread().setContextClassLoader(contextCl);
201 }
202 }
203
204
205 public void stop()
206 {
207 try
208 {
209 if (_server.isRunning())
210 {
211 _server.stop();
212 }
213 }
214 catch (Exception e)
215 {
216 LOG.warn(e);
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 private URL[] getJarsWithTlds() throws Exception
244 {
245
246
247
248
249
250
251
252
253
254 ArrayList<URL> res = new ArrayList<URL>();
255 for (WebappRegistrationCustomizer regCustomizer : WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS)
256 {
257 URL[] urls = regCustomizer.getJarsWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
258 for (URL url : urls)
259 {
260 if (!res.contains(url)) res.add(url);
261 }
262 }
263 if (!res.isEmpty())
264 return res.toArray(new URL[res.size()]);
265 else
266 return null;
267 }
268
269
270
271 private void configure(Server server, Dictionary props) throws Exception
272 {
273 String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
274 List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
275 if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
276 Map<String, Object> id_map = new HashMap<String, Object>();
277
278
279 id_map.put("Server", server);
280 id_map.put((String)props.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME), server);
281
282 Map<String, String> properties = new HashMap<String, String>();
283 Enumeration<Object> en = props.keys();
284 while (en.hasMoreElements())
285 {
286 Object key = en.nextElement();
287 Object value = props.get(key);
288 String keyStr = String.valueOf(key);
289 String valStr = String.valueOf(value);
290 properties.put(keyStr, valStr);
291 server.setAttribute(keyStr, valStr);
292 }
293
294 for (URL jettyConfiguration : jettyConfigurations)
295 {
296 InputStream is = null;
297 try
298 {
299
300 Resource r = Resource.newResource(jettyConfiguration);
301 if (!r.exists())
302 {
303 LOG.warn("File does not exist "+r);
304 continue;
305 }
306 is = r.getInputStream();
307 XmlConfiguration config = new XmlConfiguration(is);
308 config.getIdMap().putAll(id_map);
309
310
311
312
313
314 String urlPath = jettyConfiguration.toString();
315 int lastSlash = urlPath.lastIndexOf('/');
316 if (lastSlash > 4)
317 {
318 urlPath = urlPath.substring(0, lastSlash);
319 Map<String, String> properties2 = new HashMap<String, String>(properties);
320 properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
321 config.getProperties().putAll(properties2);
322 }
323 else
324 {
325 config.getProperties().putAll(properties);
326 }
327 config.configure();
328 id_map = config.getIdMap();
329 }
330 catch (SAXParseException saxparse)
331 {
332 LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
333 throw saxparse;
334 }
335 finally
336 {
337 IO.close(is);
338 }
339 }
340
341 }
342
343
344
345
346
347
348
349 private void init()
350 {
351
352 _ctxtCollection = (ContextHandlerCollection) _server.getChildHandlerByClass(ContextHandlerCollection.class);
353
354 if (_ctxtCollection == null)
355 throw new IllegalStateException("ERROR: No ContextHandlerCollection configured in Server");
356
357 List<String> providerClassNames = new ArrayList<String>();
358
359
360 List<DeploymentManager> deployers = _server.getBeans(DeploymentManager.class);
361 if (deployers != null && !deployers.isEmpty())
362 {
363 _deploymentManager = deployers.get(0);
364
365 for (AppProvider provider : _deploymentManager.getAppProviders())
366 {
367 providerClassNames.add(provider.getClass().getName());
368 }
369 }
370 else
371 {
372
373 _deploymentManager = new DeploymentManager();
374 _deploymentManager.setContexts(_ctxtCollection);
375 _server.addBean(_deploymentManager);
376 }
377
378 _deploymentManager.setUseStandardBindings(false);
379 List<AppLifeCycle.Binding> deploymentLifeCycleBindings = new ArrayList<AppLifeCycle.Binding>();
380 deploymentLifeCycleBindings.add(new OSGiDeployer());
381 deploymentLifeCycleBindings.add(new StandardStarter());
382 deploymentLifeCycleBindings.add(new StandardStopper());
383 deploymentLifeCycleBindings.add(new OSGiUndeployer());
384 _deploymentManager.setLifeCycleBindings(deploymentLifeCycleBindings);
385
386 if (!providerClassNames.contains(BundleWebAppProvider.class.getName()))
387 {
388
389 try
390 {
391 BundleWebAppProvider webAppProvider = new BundleWebAppProvider(this);
392 _deploymentManager.addAppProvider(webAppProvider);
393 }
394 catch (Exception e)
395 {
396 LOG.warn(e);
397 }
398 }
399
400 if (!providerClassNames.contains(ServiceWebAppProvider.class.getName()))
401 {
402
403 try
404 {
405 ServiceWebAppProvider webAppProvider = new ServiceWebAppProvider(this);
406 _deploymentManager.addAppProvider(webAppProvider);
407 }
408 catch (Exception e)
409 {
410 LOG.warn(e);
411 }
412 }
413
414 if (!providerClassNames.contains(BundleContextProvider.class.getName()))
415 {
416 try
417 {
418 BundleContextProvider contextProvider = new BundleContextProvider(this);
419 _deploymentManager.addAppProvider(contextProvider);
420 }
421 catch (Exception e)
422 {
423 LOG.warn(e);
424 }
425 }
426
427 if (!providerClassNames.contains(ServiceContextProvider.class.getName()))
428 {
429 try
430 {
431 ServiceContextProvider contextProvider = new ServiceContextProvider(this);
432 _deploymentManager.addAppProvider(contextProvider);
433 }
434 catch (Exception e)
435 {
436 LOG.warn(e);
437 }
438 }
439 }
440
441
442
443
444
445
446
447
448 File getDefaultOSGiContextsHome(File jettyHome)
449 {
450 String jettyContextsHome = System.getProperty("jetty.osgi.contexts.home");
451 if (jettyContextsHome != null)
452 {
453 File contextsHome = new File(jettyContextsHome);
454 if (!contextsHome.exists() || !contextsHome.isDirectory())
455 {
456 throw new IllegalArgumentException("the ${jetty.osgi.contexts.home} '"
457 + jettyContextsHome
458 + " must exist and be a folder");
459 }
460 return contextsHome;
461 }
462 return new File(jettyHome, "/contexts");
463 }
464
465
466
467
468
469 private List<URL> extractResources(String propertyValue)
470 {
471 StringTokenizer tokenizer = new StringTokenizer(propertyValue, ",;", false);
472 List<URL> urls = new ArrayList<URL>();
473 while (tokenizer.hasMoreTokens())
474 {
475 String tok = tokenizer.nextToken();
476 try
477 {
478 urls.add(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(new URL(tok)));
479 }
480 catch (Throwable mfe)
481 {
482 LOG.warn(mfe);
483 }
484 }
485 return urls;
486 }
487
488
489
490
491
492 private List<File> extractFiles(String propertyValue)
493 {
494 StringTokenizer tokenizer = new StringTokenizer(propertyValue, ",;", false);
495 List<File> files = new ArrayList<File>();
496 while (tokenizer.hasMoreTokens())
497 {
498 String tok = tokenizer.nextToken();
499 try
500 {
501 URL url = new URL(tok);
502 url = BundleFileLocatorHelperFactory.getFactory().getHelper().getFileURL(url);
503 if (url.getProtocol().equals("file"))
504 {
505 Resource res = Resource.newResource(url);
506 File folder = res.getFile();
507 if (folder != null)
508 {
509 files.add(folder);
510 }
511 }
512 }
513 catch (Throwable mfe)
514 {
515 LOG.warn(mfe);
516 }
517 }
518 return files;
519 }
520
521 }