1 // ========================================================================
2 // Copyright (c) 2009 Intalio, Inc.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // Contributors:
13 // Hugues Malphettes - initial API and implementation
14 // ========================================================================
15 package org.eclipse.jetty.osgi.boot;
16
17 import java.util.Dictionary;
18 import java.util.Hashtable;
19 import java.util.Properties;
20
21 import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
22 import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServerServiceTracker;
23 import org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper;
24 import org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker;
25 import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
26 import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
27 import org.eclipse.jetty.server.Server;
28 import org.eclipse.jetty.server.handler.ContextHandler;
29 import org.eclipse.jetty.webapp.WebAppContext;
30 import org.osgi.framework.Bundle;
31 import org.osgi.framework.BundleActivator;
32 import org.osgi.framework.BundleContext;
33 import org.osgi.framework.ServiceRegistration;
34 import org.osgi.util.tracker.BundleTracker;
35
36 /**
37 * Experiment: bootstrap jetty's complete distrib from an OSGi bundle. Progress:
38 * <ol>
39 * <li>basic servlet [ok]</li>
40 * <li>basic jetty.xml [ok]</li>
41 * <li>basic jetty.xml and jetty-plus.xml [ok]</li>
42 * <li>basic jsp [ok with modifications]
43 * <ul>
44 * <li>Needed to modify the headers of jdt.core-3.1.1 so that its dependency on
45 * eclipse.runtime, eclipse.resources and eclipse.text are optional. Also we
46 * should depend on the latest jdt.core from eclipse-3.5 not from eclipse-3.1.1
47 * although that will require actual changes to jasper as some internal APIs of
48 * jdt.core have changed.</li>
49 * <li>Modifications to org.mortbay.jetty.jsp-2.1-glassfish: made all imports to
50 * ant, xalan and sun packages optional.</li>
51 * </ul>
52 * </li>
53 * <li>jsp with tag-libs [ok]</li>
54 * <li>test-jndi with atomikos and derby inside ${jetty.home}/lib/ext [ok]</li>
55 * </ul>
56 */
57 public class JettyBootstrapActivator implements BundleActivator
58 {
59
60 private static JettyBootstrapActivator INSTANCE = null;
61
62 public static JettyBootstrapActivator getInstance()
63 {
64 return INSTANCE;
65 }
66
67 private ServiceRegistration _registeredServer;
68 private Server _server;
69 private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
70 private PackageAdminServiceTracker _packageAdminServiceTracker;
71 private BundleTracker _webBundleTracker;
72
73 // private ServiceRegistration _jettyServerFactoryService;
74 private JettyServerServiceTracker _jettyServerServiceTracker;
75
76
77 /**
78 * Setup a new jetty Server, registers it as a service. Setup the Service
79 * tracker for the jetty ContextHandlers that are in charge of deploying the
80 * webapps. Setup the BundleListener that supports the extender pattern for
81 * the jetty ContextHandler.
82 *
83 * @param context
84 */
85 public void start(BundleContext context) throws Exception
86 {
87 INSTANCE = this;
88
89 // track other bundles and fragments attached to this bundle that we
90 // should activate.
91 _packageAdminServiceTracker = new PackageAdminServiceTracker(context);
92
93 _jettyServerServiceTracker = new JettyServerServiceTracker();
94 context.addServiceListener(_jettyServerServiceTracker,"(objectclass=" + Server.class.getName() + ")");
95
96 //Register the Jetty Server Factory as a ManagedServiceFactory:
97 // Properties jettyServerMgdFactoryServiceProps = new Properties();
98 // jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
99 // _jettyServerFactoryService = context.registerService(
100 // ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(),
101 // jettyServerMgdFactoryServiceProps);
102
103 _jettyContextHandlerTracker = new JettyContextHandlerServiceTracker(_jettyServerServiceTracker);
104
105 // the tracker in charge of the actual deployment
106 // and that will configure and start the jetty server.
107 context.addServiceListener(_jettyContextHandlerTracker,"(objectclass=" + ContextHandler.class.getName() + ")");
108
109 //see if we shoult start a default jetty instance right now.
110 DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
111
112 // now ready to support the Extender pattern:
113 _webBundleTracker = new BundleTracker(context,
114 Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
115 _webBundleTracker.open();
116
117 }
118
119 /*
120 * (non-Javadoc)
121 *
122 * @see
123 * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
124 */
125 public void stop(BundleContext context) throws Exception
126 {
127 try
128 {
129
130 if (_webBundleTracker != null)
131 {
132 _webBundleTracker.close();
133 _webBundleTracker = null;
134 }
135 if (_jettyContextHandlerTracker != null)
136 {
137 _jettyContextHandlerTracker.stop();
138 context.removeServiceListener(_jettyContextHandlerTracker);
139 _jettyContextHandlerTracker = null;
140 }
141 if (_jettyServerServiceTracker != null)
142 {
143 _jettyServerServiceTracker.stop();
144 context.removeServiceListener(_jettyServerServiceTracker);
145 _jettyServerServiceTracker = null;
146 }
147 if (_packageAdminServiceTracker != null)
148 {
149 _packageAdminServiceTracker.stop();
150 context.removeServiceListener(_packageAdminServiceTracker);
151 _packageAdminServiceTracker = null;
152 }
153 if (_registeredServer != null)
154 {
155 try
156 {
157 _registeredServer.unregister();
158 }
159 catch (IllegalArgumentException ill)
160 {
161 // already unregistered.
162 }
163 finally
164 {
165 _registeredServer = null;
166 }
167 }
168 // if (_jettyServerFactoryService != null)
169 // {
170 // try
171 // {
172 // _jettyServerFactoryService.unregister();
173 // }
174 // catch (IllegalArgumentException ill)
175 // {
176 // // already unregistered.
177 // }
178 // finally
179 // {
180 // _jettyServerFactoryService = null;
181 // }
182 // }
183
184 }
185 finally
186 {
187 if (_server != null)
188 {
189 _server.stop();
190 }
191 INSTANCE = null;
192 }
193 }
194
195 /**
196 * Helper method that creates a new org.jetty.webapp.WebAppContext and
197 * registers it as an OSGi service. The tracker
198 * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
199 *
200 * @param contributor
201 * The bundle
202 * @param webappFolderPath
203 * The path to the root of the webapp. Must be a path relative to
204 * bundle; either an absolute path.
205 * @param contextPath
206 * The context path. Must start with "/"
207 * @throws Exception
208 */
209 public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
210 {
211 WebAppContext contextHandler = new WebAppContext();
212 Properties dic = new Properties();
213 dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
214 dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
215 contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
216 }
217
218 /**
219 * Helper method that creates a new org.jetty.webapp.WebAppContext and
220 * registers it as an OSGi service. The tracker
221 * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
222 *
223 * @param contributor
224 * The bundle
225 * @param webappFolderPath
226 * The path to the root of the webapp. Must be a path relative to
227 * bundle; either an absolute path.
228 * @param contextPath
229 * The context path. Must start with "/"
230 * @param dic
231 * TODO: parameter description
232 * @throws Exception
233 */
234 public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
235 {
236 WebAppContext contextHandler = new WebAppContext();
237 dic.put(OSGiWebappConstants.SERVICE_PROP_WAR,webappFolderPath);
238 dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH,contextPath);
239 contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
240 }
241
242 /**
243 * Helper method that creates a new skeleton of a ContextHandler and
244 * registers it as an OSGi service. The tracker
245 * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
246 *
247 * @param contributor
248 * The bundle that registers a new context
249 * @param contextFilePath
250 * The path to the file inside the bundle that defines the
251 * context.
252 * @throws Exception
253 */
254 public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
255 {
256 registerContext(contributor,contextFilePath,new Hashtable<String, String>());
257 }
258
259 /**
260 * Helper method that creates a new skeleton of a ContextHandler and
261 * registers it as an OSGi service. The tracker
262 * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
263 *
264 * @param contributor
265 * The bundle that registers a new context
266 * @param contextFilePath
267 * The path to the file inside the bundle that defines the
268 * context.
269 * @param dic
270 * TODO: parameter description
271 * @throws Exception
272 */
273 public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
274 {
275 ContextHandler contextHandler = new ContextHandler();
276 dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH,contextFilePath);
277 dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE,Boolean.TRUE.toString());
278 contributor.getBundleContext().registerService(ContextHandler.class.getName(),contextHandler,dic);
279 }
280
281 public static void unregister(String contextPath)
282 {
283 // todo
284 }
285
286
287 }