1
2
3
4
5
6
7
8
9
10
11
12
13 package org.eclipse.jetty.osgi.boot.internal.webapp;
14
15 import java.io.File;
16 import java.util.HashMap;
17 import java.util.Map;
18
19 import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
20 import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
21 import org.eclipse.jetty.server.Server;
22 import org.eclipse.jetty.server.handler.ContextHandler;
23 import org.eclipse.jetty.util.Scanner;
24 import org.eclipse.jetty.webapp.WebAppContext;
25 import org.osgi.framework.Bundle;
26 import org.osgi.framework.BundleContext;
27 import org.osgi.framework.FrameworkUtil;
28 import org.osgi.framework.ServiceEvent;
29 import org.osgi.framework.ServiceListener;
30 import org.osgi.framework.ServiceReference;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class JettyContextHandlerServiceTracker implements ServiceListener
50 {
51
52 private final WebappRegistrationHelper _helper;
53
54
55 private Map<ServiceReference, ContextHandler> _indexByServiceReference = new HashMap<ServiceReference, ContextHandler>();
56
57
58
59
60
61 private Map<String, ServiceReference> _indexByContextFile = new HashMap<String, ServiceReference>();
62
63
64 private String _osgiContextHomeFolderCanonicalPath;
65
66 private Scanner _scanner;
67
68
69
70
71
72 public JettyContextHandlerServiceTracker(BundleContext context, Server server) throws Exception
73 {
74 _helper = new WebappRegistrationHelper(server);
75 _helper.setup(context,new HashMap<String, String>());
76 File contextHome = _helper.getOSGiContextsHome();
77 if (contextHome != null)
78 {
79 _osgiContextHomeFolderCanonicalPath = contextHome.getCanonicalPath();
80 _scanner = new Scanner();
81 _scanner.setRecursive(true);
82 _scanner.setReportExistingFilesOnStartup(false);
83 _scanner.addListener(new Scanner.DiscreteListener()
84 {
85 public void fileAdded(String filename) throws Exception
86 {
87
88
89
90
91 reloadJettyContextHandler(filename);
92 }
93
94 public void fileChanged(String filename) throws Exception
95 {
96 reloadJettyContextHandler(filename);
97 }
98
99 public void fileRemoved(String filename) throws Exception
100 {
101
102
103
104 reloadJettyContextHandler(filename);
105 }
106 });
107 }
108 }
109
110 public void stop()
111 {
112 if (_scanner != null)
113 {
114 _scanner.stop();
115 }
116
117
118
119 }
120
121
122
123
124
125
126
127 public void serviceChanged(ServiceEvent ev)
128 {
129 ServiceReference sr = ev.getServiceReference();
130 switch (ev.getType())
131 {
132 case ServiceEvent.MODIFIED:
133 case ServiceEvent.UNREGISTERING:
134 {
135 ContextHandler ctxtHandler = unregisterInIndex(ev.getServiceReference());
136 if (ctxtHandler != null && !ctxtHandler.isStopped())
137 {
138 try
139 {
140 _helper.unregister(ctxtHandler);
141 }
142 catch (Exception e)
143 {
144
145 e.printStackTrace();
146 }
147 }
148 }
149 if (ev.getType() == ServiceEvent.UNREGISTERING)
150 {
151 break;
152 }
153 else
154 {
155
156
157 }
158 case ServiceEvent.REGISTERED:
159 {
160 Bundle contributor = sr.getBundle();
161 BundleContext context = FrameworkUtil.getBundle(JettyBootstrapActivator.class).getBundleContext();
162 ContextHandler contextHandler = (ContextHandler)context.getService(sr);
163 if (contextHandler.getServer() != null)
164 {
165
166 return;
167 }
168 if (contextHandler instanceof WebAppContext)
169 {
170 WebAppContext webapp = (WebAppContext)contextHandler;
171 String contextPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
172 if (contextPath == null)
173 {
174 contextPath = webapp.getContextPath();
175 }
176 String webXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_WEB_XML_PATH);
177 if (webXmlPath == null)
178 {
179 webXmlPath = webapp.getDescriptor();
180 }
181 String defaultWebXmlPath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_DEFAULT_WEB_XML_PATH);
182 if (defaultWebXmlPath == null)
183 {
184 defaultWebXmlPath = webapp.getDefaultsDescriptor();
185 }
186 String war = (String)sr.getProperty("war");
187 try
188 {
189 ContextHandler handler = _helper.registerWebapplication(contributor,war,contextPath,(String)sr
190 .getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),(String)sr
191 .getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE),webXmlPath,defaultWebXmlPath);
192 if (handler != null)
193 {
194 registerInIndex(handler,sr);
195 }
196 }
197 catch (Throwable e)
198 {
199 e.printStackTrace();
200 }
201 }
202 else
203 {
204
205 String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
206 if (contextFilePath == null)
207 {
208 throw new IllegalArgumentException("the property contextFilePath is required");
209 }
210 try
211 {
212 ContextHandler handler = _helper.registerContext(contributor,contextFilePath,(String)sr
213 .getProperty(OSGiWebappConstants.SERVICE_PROP_EXTRA_CLASSPATH),(String)sr
214 .getProperty(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE));
215 if (handler != null)
216 {
217 registerInIndex(handler,sr);
218 }
219 }
220 catch (Throwable e)
221 {
222
223 e.printStackTrace();
224 }
225 }
226 }
227 break;
228 }
229 }
230
231 private void registerInIndex(ContextHandler handler, ServiceReference sr)
232 {
233 _indexByServiceReference.put(sr,handler);
234 String key = getSymbolicNameAndContextFileKey(sr);
235 if (key != null)
236 {
237 _indexByContextFile.put(key,sr);
238 }
239 }
240
241
242
243
244
245
246
247 private ContextHandler unregisterInIndex(ServiceReference sr)
248 {
249 ContextHandler handler = _indexByServiceReference.remove(sr);
250 String key = getSymbolicNameAndContextFileKey(sr);
251 if (key != null)
252 {
253 _indexByContextFile.remove(key);
254 }
255 if (handler == null)
256 {
257
258 return null;
259 }
260 return handler;
261 }
262
263
264
265
266
267 private String getSymbolicNameAndContextFileKey(ServiceReference sr)
268 {
269 String contextFilePath = (String)sr.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH);
270 if (contextFilePath != null)
271 {
272 return sr.getBundle().getSymbolicName() + "/" + contextFilePath;
273 }
274 return null;
275 }
276
277
278
279
280
281
282 void reloadJettyContextHandler(String canonicalNameOfFileChanged)
283 {
284 String key = getNormalizedRelativePath(canonicalNameOfFileChanged);
285 if (key == null)
286 {
287 return;
288 }
289 ServiceReference sr = _indexByContextFile.get(key);
290 if (sr == null)
291 {
292
293 return;
294 }
295 serviceChanged(new ServiceEvent(ServiceEvent.MODIFIED,sr));
296 }
297
298
299
300
301
302 private String getNormalizedRelativePath(String canFilename)
303 {
304 if (!canFilename.startsWith(_osgiContextHomeFolderCanonicalPath))
305 {
306
307
308
309 return null;
310 }
311 return canFilename.substring(_osgiContextHomeFolderCanonicalPath.length()).replace('\\','/');
312 }
313
314 }