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