View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.Constants;
35  import org.osgi.framework.FrameworkUtil;
36  import org.osgi.framework.ServiceReference;
37  import org.osgi.framework.ServiceRegistration;
38  
39  /**
40   * ServiceContextProvider
41   *
42   * Jetty DeploymentManager Provider that is able to deploy ContextHandlers discovered via OSGi as services.
43   * 
44   * 
45   */
46  public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider
47  { 
48      private static final Logger LOG = Log.getLogger(AbstractContextProvider.class);
49      
50      private Map<ServiceReference, App> _serviceMap = new HashMap<ServiceReference, App>();
51      
52      private ServiceRegistration _serviceRegForServices;
53      
54      
55      /**
56       * ServiceApp
57       *
58       *
59       */
60      public class ServiceApp extends OSGiApp
61      {
62          public ServiceApp(DeploymentManager manager, AppProvider provider, Bundle bundle, Dictionary properties, String contextFile, String originId)
63          {
64              super(manager, provider, bundle, properties, contextFile, originId);
65          }
66  
67          public ServiceApp(DeploymentManager manager, AppProvider provider, String originId, Bundle bundle, String contextFile)
68          {
69              super(manager, provider, originId, bundle, contextFile);
70          }
71  
72          @Override
73          public void registerAsOSGiService() throws Exception
74          {
75              //not applicable for apps that are already services
76          }
77  
78          @Override
79          protected void deregisterAsOSGiService() throws Exception
80          {
81              //not applicable for apps that are already services
82          }
83      }
84      
85      
86      
87      /* ------------------------------------------------------------ */
88      public ServiceContextProvider(ServerInstanceWrapper wrapper)
89      {
90          super(wrapper);
91      }
92      
93      
94      /* ------------------------------------------------------------ */
95      public boolean serviceAdded (ServiceReference serviceRef, ContextHandler context)
96      {
97          if (context == null || serviceRef == null)
98              return false;
99          
100         if (context instanceof org.eclipse.jetty.webapp.WebAppContext)
101             return false; //the ServiceWebAppProvider will deploy it
102         
103         String watermark = (String)serviceRef.getProperty(OSGiWebappConstants.WATERMARK);
104         if (watermark != null && !"".equals(watermark))
105             return false;  //this service represents a contexthandler that has already been registered as a service by another of our deployers
106         
107         ClassLoader cl = Thread.currentThread().getContextClassLoader();
108         Thread.currentThread().setContextClassLoader(getServerInstanceWrapper().getParentClassLoaderForWebapps());
109         try
110         {
111             //See if there is a context file to apply to this pre-made context
112             String contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.JETTY_CONTEXT_FILE_PATH);
113             if (contextFile == null)
114                 contextFile = (String)serviceRef.getProperty(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH); 
115                   
116             String[] keys = serviceRef.getPropertyKeys();
117             Dictionary properties = new Hashtable<String, Object>();
118             if (keys != null)
119             {
120                 for (String key:keys)
121                     properties.put(key, serviceRef.getProperty(key));
122             }
123             Bundle bundle = serviceRef.getBundle();                
124             String originId = bundle.getSymbolicName() + "-" + bundle.getVersion().toString() + "-"+(contextFile!=null?contextFile:serviceRef.getProperty(Constants.SERVICE_ID));
125             ServiceApp app = new ServiceApp(getDeploymentManager(), this, bundle, properties, contextFile, originId);         
126             app.setHandler(context); //set the pre=made ContextHandler instance
127             _serviceMap.put(serviceRef, app);
128             getDeploymentManager().addApp(app);
129             return true;
130         }
131         finally
132         {
133             Thread.currentThread().setContextClassLoader(cl); 
134         }
135     }
136     
137     
138     /* ------------------------------------------------------------ */
139     public boolean serviceRemoved (ServiceReference serviceRef, ContextHandler context)
140     {
141 
142         if (context == null || serviceRef == null)
143             return false;
144         
145         String watermark = (String)serviceRef.getProperty(OSGiWebappConstants.WATERMARK);
146         if (watermark != null && !"".equals(watermark))
147             return false;  //this service represents a contexthandler that will be deregistered as a service by another of our deployers
148         
149         App app = _serviceMap.remove(serviceRef);
150         if (app != null)
151         {
152             getDeploymentManager().removeApp(app);
153             return true;
154         }
155 
156         return false;
157     }
158     
159     
160     
161     /* ------------------------------------------------------------ */
162     @Override
163     protected void doStart() throws Exception
164     {
165         //register as an osgi service for deploying contexts defined in a bundle, advertising the name of the jetty Server instance we are related to
166         Dictionary<String,String> properties = new Hashtable<String,String>();
167         properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, getServerInstanceWrapper().getManagedServerName());
168         
169         //register as an osgi service for deploying contexts, advertising the name of the jetty Server instance we are related to
170         _serviceRegForServices = FrameworkUtil.getBundle(this.getClass()).getBundleContext().registerService(ServiceProvider.class.getName(), this, properties);
171         super.doStart();
172     }
173     
174     /* ------------------------------------------------------------ */
175     @Override
176     protected void doStop() throws Exception
177     {
178         //unregister ourselves 
179         if (_serviceRegForServices != null)
180         {
181             try
182             {
183                 _serviceRegForServices.unregister();
184             }
185             catch (Exception e)
186             {
187                 LOG.warn(e);
188             }
189         }
190         super.doStop();
191     }
192 }