View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.osgi.boot;
20  
21  import java.util.Dictionary;
22  import java.util.HashMap;
23  import java.util.Hashtable;
24  import java.util.Map;
25  
26  import org.eclipse.jetty.deploy.App;
27  import org.eclipse.jetty.deploy.AppProvider;
28  import org.eclipse.jetty.deploy.DeploymentManager;
29  import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
30  import org.eclipse.jetty.server.handler.ContextHandler;
31  import org.eclipse.jetty.util.log.Log;
32  import org.eclipse.jetty.util.log.Logger;
33  import org.osgi.framework.Bundle;
34  import org.osgi.framework.FrameworkUtil;
35  import org.osgi.framework.ServiceReference;
36  import org.osgi.framework.ServiceRegistration;
37  
38  /**
39   * ServiceContextProvider
40   *
41   * Jetty DeploymentManager Provider that is able to deploy ContextHandlers discovered via OSGi as services.
42   * 
43   * 
44   */
45  public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider
46  { 
47      private static final Logger LOG = Log.getLogger(AbstractContextProvider.class);
48      
49      private Map<ServiceReference, App> _serviceMap = new HashMap<ServiceReference, App>();
50      
51      private ServiceRegistration _serviceRegForServices;
52      
53      
54      /**
55       * ServiceApp
56       *
57       *
58       */
59      public class ServiceApp extends OSGiApp
60      {
61          public ServiceApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary properties, String contextFile, String originId)
62          {
63              super(manager, provider, bundle, properties, contextFile, originId);
64          }
65  
66          public ServiceApp(DeploymentManager manager, AppProvider provider, String originId, Bundle bundle, String contextFile)
67          {
68              super(manager, provider, originId, bundle, contextFile);
69          }
70  
71          @Override
72          public void registerAsOSGiService() throws Exception
73          {
74              //not applicable for apps that are already services
75          }
76  
77          @Override
78          protected void deregisterAsOSGiService() throws Exception
79          {
80              //not applicable for apps that are already services
81          }
82      }
83      
84      
85      
86      /* ------------------------------------------------------------ */
87      public ServiceContextProvider(ServerInstanceWrapper wrapper)
88      {
89          super(wrapper);
90      }
91      
92      
93      /* ------------------------------------------------------------ */
94      public boolean serviceAdded (ServiceReference serviceRef, ContextHandler context)
95      {
96          if (context == null || serviceRef == null)
97              return false;
98          
99          if (context instanceof org.eclipse.jetty.webapp.WebAppContext)
100             return false; //the ServiceWebAppProvider will deploy it
101         
102         String watermark = (String)serviceRef.getProperty(OSGiWebappConstants.WATERMARK);
103         if (watermark != null && !"".equals(watermark))
104             return false;  //this service represents a contexthandler that has already been registered as a service by another of our deployers
105         
106         ClassLoader cl = Thread.currentThread().getContextClassLoader();
107         Thread.currentThread().setContextClassLoader(getServerInstanceWrapper().getParentClassLoaderForWebapps());
108         try
109         {
110             //See if there is a context file to apply to this pre-made context
111             String contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
112             if (contextFile == null)
113                 contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); 
114                   
115             String[] keys = serviceRef.getPropertyKeys();
116             Dictionary properties = new Hashtable<String, Object>();
117             if (keys != null)
118             {
119                 for (String key:keys)
120                     properties.put(key, serviceRef.getProperty(key));
121             }
122             Bundle bundle = serviceRef.getBundle();                
123             String originId = bundle.getSymbolicName() + "-" + bundle.getVersion().toString() + "-"+contextFile;
124             ServiceApp app = new ServiceApp(getDeploymentManager(), this, bundle, properties, contextFile, originId);         
125             app.setHandler(context); //set the pre=made ContextHandler instance
126             _serviceMap.put(serviceRef, app);
127             getDeploymentManager().addApp(app);
128             return true;
129         }
130         finally
131         {
132             Thread.currentThread().setContextClassLoader(cl); 
133         }
134     }
135     
136     
137     /* ------------------------------------------------------------ */
138     public boolean serviceRemoved (ServiceReference serviceRef, ContextHandler context)
139     {
140 
141         if (context == null || serviceRef == null)
142             return false;
143         
144         String watermark = (String)serviceRef.getProperty(OSGiWebappConstants.WATERMARK);
145         if (watermark != null && !"".equals(watermark))
146             return false;  //this service represents a contexthandler that will be deregistered as a service by another of our deployers
147         
148         App app = _serviceMap.remove(serviceRef);
149         if (app != null)
150         {
151             getDeploymentManager().removeApp(app);
152             return true;
153         }
154 
155         return false;
156     }
157     
158     
159     
160     /* ------------------------------------------------------------ */
161     @Override
162     protected void doStart() throws Exception
163     {
164         //register as an osgi service for deploying contexts defined in a bundle, advertising the name of the jetty Server instance we are related to
165         Dictionary<String,String> properties = new Hashtable<String,String>();
166         properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, getServerInstanceWrapper().getManagedServerName());
167         
168         //register as an osgi service for deploying contexts, advertising the name of the jetty Server instance we are related to
169         _serviceRegForServices = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(ServiceProvider.class.getName(), this, properties);
170         super.doStart();
171     }
172     
173     /* ------------------------------------------------------------ */
174     @Override
175     protected void doStop() throws Exception
176     {
177         //unregister ourselves 
178         if (_serviceRegForServices != null)
179         {
180             try
181             {
182                 _serviceRegForServices.unregister();
183             }
184             catch (Exception e)
185             {
186                 LOG.warn(e);
187             }
188         }
189         super.doStop();
190     }
191 }