View Javadoc

1   // ========================================================================
2   // Copyright (c) 2009 Mortbay, 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  //    Greg Wilkins - initial API and implementation
14  // ========================================================================
15  package org.eclipse.jetty.osgi.boot;
16  
17  import java.io.File;
18  import java.io.FilenameFilter;
19  import java.io.IOException;
20  
21  import org.eclipse.jetty.deploy.App;
22  import org.eclipse.jetty.deploy.AppProvider;
23  import org.eclipse.jetty.deploy.DeploymentManager;
24  import org.eclipse.jetty.deploy.providers.ContextProvider;
25  import org.eclipse.jetty.deploy.providers.ScanningAppProvider;
26  import org.eclipse.jetty.server.handler.ContextHandler;
27  import org.eclipse.jetty.util.resource.Resource;
28  
29  /**
30   * AppProvider for OSGi. Supports the configuration of ContextHandlers and
31   * WebApps. Extends the AbstractAppProvider to support the scanning of context
32   * files located outside of the bundles.
33   * <p>
34   * This provider must not be called outside of jetty.boot: it should always be
35   * called via the OSGi service listener.
36   * </p>
37   * <p>
38   * This provider supports the same set of parameters than the WebAppProvider as
39   * it supports the deployment of WebAppContexts. Except for the scanning of the
40   * webapps directory.
41   * </p>
42   */
43  public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
44  {
45  
46      private boolean _extractWars = false;
47      private boolean _parentLoaderPriority = false;
48      private String _defaultsDescriptor;
49      private String _tldBundles;
50  
51      /**
52       * When a context file corresponds to a deployed bundle and is changed we
53       * reload the corresponding bundle.
54       */
55      private static class Filter implements FilenameFilter
56      {
57          OSGiAppProvider _enclosedInstance;
58  
59          public boolean accept(File dir, String name)
60          {
61              if (!new File(dir,name).isDirectory())
62              {
63                  String contextName = getDeployedAppName(name);
64                  if (contextName != null)
65                  {
66                      App app = _enclosedInstance.getDeployedApps().get(contextName);
67                      return app != null;
68                  }
69              }
70              return false;
71          }
72      }
73  
74      /**
75       * @param contextFileName
76       *            for example myContext.xml
77       * @return The context, for example: myContext; null if this was not a
78       *         suitable contextFileName.
79       */
80      private static String getDeployedAppName(String contextFileName)
81      {
82          String lowername = contextFileName.toLowerCase();
83          if (lowername.endsWith(".xml"))
84          {
85              String contextName = contextFileName.substring(0,lowername.length() - ".xml".length());
86              return contextName;
87          }
88          return null;
89      }
90  
91      /**
92       * Default OSGiAppProvider consutructed when none are defined in the
93       * jetty.xml configuration.
94       * 
95       * @param contextsDir
96       */
97      public OSGiAppProvider()
98      {
99          super(new Filter());
100         ((Filter)super._filenameFilter)._enclosedInstance = this;
101     }
102 
103     /**
104      * Default OSGiAppProvider consutructed when none are defined in the
105      * jetty.xml configuration.
106      * 
107      * @param contextsDir
108      */
109     public OSGiAppProvider(File contextsDir) throws IOException
110     {
111         this();
112         setMonitoredDir(Resource.newResource(contextsDir.toURI()));
113     }
114 
115     /**
116      * Returns the ContextHandler that was created by WebappRegistractionHelper
117      * 
118      * @see AppProvider
119      */
120     public ContextHandler createContextHandler(App app) throws Exception
121     {
122         // return pre-created Context
123         if (app.getContextId() != null)
124         {
125             return app.getContextHandler();
126         }
127         // for some reason it was not defined when the App was constructed.
128         // we don't support this situation at this point.
129         // once the WebAppRegistrationHelper is refactored, the code
130         // that creates the ContextHandler will actually be here.
131         throw new IllegalStateException("The App must be passed the " + "instance of the ContextHandler when it is construsted");
132     }
133 
134     /**
135      * @see AppProvider
136      */
137     public void setDeploymentManager(DeploymentManager deploymentManager)
138     {
139         // _manager=deploymentManager;
140         super.setDeploymentManager(deploymentManager);
141     }
142 
143     /**
144      * @param context
145      * @throws Exception
146      */
147     public void addContext(ContextHandler context) throws Exception
148     {
149         // TODO apply configuration specific to this provider
150 
151         // wrap context as an App
152         App app = new App(getDeploymentManager(),this,context.getDisplayName(),context);
153         getDeployedApps().put(context.getDisplayName(),app);
154         getDeploymentManager().addApp(app);
155     }
156 
157     /**
158      * Called by the scanner of the context files directory. If we find the
159      * corresponding deployed App we reload it by returning the App. Otherwise
160      * we return null and nothing happens: presumably the corresponding OSGi
161      * webapp is not ready yet.
162      * 
163      * @return the corresponding already deployed App so that it will be
164      *         reloaded. Otherwise returns null.
165      */
166     @Override
167     protected App createApp(String filename)
168     {
169         // find the corresponding bundle and ContextHandler or WebAppContext
170         // and reload the corresponding App.
171         // see the 2 pass of the refactoring of the WebAppRegistrationHelper.
172         String name = getDeployedAppName(filename);
173         if (name != null)
174         {
175             return getDeployedApps().get(name);
176         }
177         return null;
178     }
179 
180     public void removeContext(ContextHandler context) throws Exception
181     {
182         App app = getDeployedApps().remove(context.getDisplayName());
183         if (app != null)
184         {
185             getDeploymentManager().removeApp(app);
186         }
187     }
188 
189     // //copied from WebAppProvider as the parameters are identical.
190     // //only removed the parameer related to extractWars.
191     /* ------------------------------------------------------------ */
192     /**
193      * Get the parentLoaderPriority.
194      * 
195      * @return the parentLoaderPriority
196      */
197     public boolean isParentLoaderPriority()
198     {
199         return _parentLoaderPriority;
200     }
201 
202     /* ------------------------------------------------------------ */
203     /**
204      * Set the parentLoaderPriority.
205      * 
206      * @param parentLoaderPriority
207      *            the parentLoaderPriority to set
208      */
209     public void setParentLoaderPriority(boolean parentLoaderPriority)
210     {
211         _parentLoaderPriority = parentLoaderPriority;
212     }
213 
214     /* ------------------------------------------------------------ */
215     /**
216      * Get the defaultsDescriptor.
217      * 
218      * @return the defaultsDescriptor
219      */
220     public String getDefaultsDescriptor()
221     {
222         return _defaultsDescriptor;
223     }
224 
225     /* ------------------------------------------------------------ */
226     /**
227      * Set the defaultsDescriptor.
228      * 
229      * @param defaultsDescriptor
230      *            the defaultsDescriptor to set
231      */
232     public void setDefaultsDescriptor(String defaultsDescriptor)
233     {
234         _defaultsDescriptor = defaultsDescriptor;
235     }
236 
237     /**
238      * The context xml directory. In fact it is the directory watched by the
239      * scanner.
240      */
241     public File getContextXmlDirAsFile()
242     {
243         try
244         {
245             Resource monitoredDir = getMonitoredDir();
246             if (monitoredDir == null)
247                 return null;
248             return monitoredDir.getFile();
249         }
250         catch (IOException e)
251         {
252             e.printStackTrace();
253             return null;
254         }
255     }
256 
257     /* ------------------------------------------------------------ */
258     /**
259      * The context xml directory. In fact it is the directory watched by the
260      * scanner.
261      */
262     public String getContextXmlDir()
263     {
264         try
265         {
266             Resource monitoredDir = getMonitoredDir();
267             if (monitoredDir == null)
268                 return null;
269             return monitoredDir.getFile().toURI().toString();
270         }
271         catch (IOException e)
272         {
273             e.printStackTrace();
274             return null;
275         }
276     }
277 
278     /* ------------------------------------------------------------ */
279     /**
280      * Set the directory in which to look for context XML files.
281      * <p>
282      * If a webapp call "foo/" or "foo.war" is discovered in the monitored
283      * directory, then the ContextXmlDir is examined to see if a foo.xml file
284      * exists. If it does, then this deployer will not deploy the webapp and the
285      * ContextProvider should be used to act on the foo.xml file.
286      * 
287      * @see ContextProvider
288      * @param contextsDir
289      */
290     public void setContextXmlDir(String contextsDir)
291     {
292         setMonitoredDir(contextsDir);
293     }
294     
295     /**
296      * @param tldBundles Comma separated list of bundles that contain tld jars
297      * that should be setup on the jetty instances created here.
298      */
299     public void setTldBundles(String tldBundles)
300     {
301     	_tldBundles = tldBundles;
302     }
303     
304     /**
305      * @return The list of bundles that contain tld jars that should be setup
306      * on the jetty instances created here.
307      */
308     public String getTldBundles()
309     {
310     	return _tldBundles;
311     }
312 
313 }