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