View Javadoc

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