View Javadoc

1   // ========================================================================
2   // Copyright (c) Webtide LLC
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   //
8   // The Eclipse Public License is available at 
9   // http://www.eclipse.org/legal/epl-v10.html
10  //
11  // The Apache License v2.0 is available at
12  // http://www.apache.org/licenses/LICENSE-2.0.txt
13  //
14  // You may elect to redistribute this code under either of these licenses. 
15  // ========================================================================
16  package org.eclipse.jetty.deploy.providers;
17  
18  import java.io.File;
19  import java.io.FilenameFilter;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import org.eclipse.jetty.deploy.App;
25  import org.eclipse.jetty.deploy.AppProvider;
26  import org.eclipse.jetty.deploy.ConfigurationManager;
27  import org.eclipse.jetty.deploy.DeploymentManager;
28  import org.eclipse.jetty.deploy.util.FileID;
29  import org.eclipse.jetty.server.handler.ContextHandler;
30  import org.eclipse.jetty.util.Scanner;
31  import org.eclipse.jetty.util.URIUtil;
32  import org.eclipse.jetty.util.component.AbstractLifeCycle;
33  import org.eclipse.jetty.util.log.Log;
34  import org.eclipse.jetty.util.resource.Resource;
35  import org.eclipse.jetty.webapp.WebAppContext;
36  import org.eclipse.jetty.xml.XmlConfiguration;
37  
38  /**
39   * AppProvider for Monitoring directories for contexts.
40   * 
41   * A Context may either be a WAR, a directory or an XML descriptor.
42   */
43  public abstract class MonitoredDirAppProvider extends AbstractLifeCycle implements AppProvider
44  {
45      class MonitoredFilenameFilter implements FilenameFilter
46      {
47          public boolean accept(File file, String name)
48          {
49              if (!file.exists())
50                  return false;
51              
52              String lowername = name.toLowerCase();
53  
54              if (_acceptContextXmlFiles && !file.isDirectory() && lowername.endsWith(".xml"))
55              {
56                  return true;
57              }
58  
59              if (_acceptWarFiles && !file.isDirectory() && lowername.endsWith(".war"))
60              {
61                  return true;
62              }
63              
64              if (_acceptDirectories && file.isDirectory())
65              {
66                  return true;
67              }
68  
69              return false;
70          }
71      }
72  
73      private boolean _acceptContextXmlFiles = true;
74      private boolean _acceptWarFiles = true;
75      private boolean _acceptDirectories = true;
76      private Resource _monitoredDir;
77      private Scanner _scanner;
78      private int _scanInterval = 10;
79      private boolean _recursive = false;
80      private boolean _extractWars = false;
81      private boolean _parentLoaderPriority = false;
82      private String _defaultsDescriptor;
83      private DeploymentManager _deploymentManager;
84      private FilenameFilter _filenamefilter;
85      private ConfigurationManager _configurationManager;
86      
87      private final Scanner.DiscreteListener _scannerListener = new Scanner.DiscreteListener()
88      {
89          public void fileAdded(String filename) throws Exception
90          {
91              if (Log.isDebugEnabled()) Log.debug("added ",  filename);
92              addConfiguredContextApp(filename);
93          }
94  
95          public void fileChanged(String filename) throws Exception
96          {
97              System.err.println("changed "+filename);
98              // TODO should this not be an add/remove?
99              if (Log.isDebugEnabled()) Log.debug("changed ",  filename);
100             addConfiguredContextApp(filename);
101         }
102 
103         public void fileRemoved(String filename) throws Exception
104         {
105             if (Log.isDebugEnabled()) Log.debug("removed ",  filename);
106             
107             // TODO: How to determine ID from filename that doesn't exist?
108             // TODO: we probably need a map from discovered filename to resulting App
109         }
110     };
111     
112     public MonitoredDirAppProvider()
113     {
114         _filenamefilter = new MonitoredFilenameFilter();
115     }
116 
117     protected MonitoredDirAppProvider(boolean xml,boolean war, boolean dir)
118     {
119         _acceptContextXmlFiles=xml;
120         _acceptWarFiles=war;
121         _acceptDirectories=dir;
122         _filenamefilter = new MonitoredFilenameFilter();
123     }
124 
125     protected MonitoredDirAppProvider(FilenameFilter filter, boolean xml,boolean war, boolean dir)
126     {
127         _acceptContextXmlFiles=xml;
128         _acceptWarFiles=war;
129         _acceptDirectories=dir;
130         _filenamefilter = filter;
131     }
132     
133     private App addConfiguredContextApp(String filename)
134     {
135         App app = new App(_deploymentManager,this,filename);
136         _deploymentManager.addApp(app);
137         return app;
138     }
139 
140     /* ------------------------------------------------------------ */
141     /** Create a context Handler for an App instance.
142      * This method can create a {@link ContextHandler} from a context XML file
143      * or a {@link WebAppContext} from a WAR file or directory, depending on the 
144      * settings of the accept fields.
145      * @see #setAcceptContextXmlFiles(boolean)
146      * @see #setAcceptWarFiles(boolean)
147      * @see #setAcceptDirectories(boolean)
148      * @see org.eclipse.jetty.deploy.AppProvider#createContextHandler(org.eclipse.jetty.deploy.App)
149      */
150     public ContextHandler createContextHandler(final App app) throws Exception
151     {
152         Resource resource = Resource.newResource(app.getOriginId());
153         File file=resource.getFile();
154         
155         if (!resource.exists())
156             throw new IllegalStateException("App resouce does not exist "+resource);
157 
158         if (_acceptContextXmlFiles &&  FileID.isXmlFile(file))
159         {
160             // TODO - it is a bit wierd that this ignores 
161             // _defaultsDescriptor, _extractWars and _parentLoaderPriority
162             // This reflects that there really is the common base for Context
163             // and WebApp deployers should probably not have these bits in them
164             
165             XmlConfiguration xmlc = new XmlConfiguration(resource.getURL());
166             Map props = new HashMap();
167             props.put("Server",_deploymentManager.getServer());
168             if (getConfigurationManager() != null)
169                 props.putAll(getConfigurationManager().getProperties());
170             xmlc.setProperties(props);
171             return (ContextHandler)xmlc.configure();
172         }
173 
174         String context = file.getName();
175         
176         if (_acceptWarFiles && FileID.isWebArchiveFile(file))
177         {
178             // Context Path is the same as the archive.
179             context = context.substring(0,context.length() - 4);
180         }
181         else if (_acceptDirectories && file.isDirectory())
182         {
183             // must be a directory
184         }
185         else
186             throw new IllegalStateException("unable to create ContextHandler for "+app);
187 
188         
189         // special case of archive (or dir) named "root" is / context
190         if (context.equalsIgnoreCase("root") || context.equalsIgnoreCase("root/"))
191             context = URIUtil.SLASH;
192 
193         // Ensure "/" is Prepended to all context paths.
194         if (context.charAt(0) != '/')
195             context = "/" + context;
196 
197         // Ensure "/" is Not Trailing in context paths.
198         if (context.endsWith("/") && context.length() > 0)
199             context = context.substring(0,context.length() - 1);
200 
201         WebAppContext wah = new WebAppContext();
202         wah.setContextPath(context);
203         wah.setWar(file.getAbsolutePath());
204         if (_defaultsDescriptor != null)
205             wah.setDefaultsDescriptor(_defaultsDescriptor);
206         wah.setExtractWAR(_extractWars);
207         wah.setParentLoaderPriority(_parentLoaderPriority);
208 
209         return wah;
210         
211     }
212 
213     @Override
214     protected void doStart() throws Exception
215     {
216         if (_monitoredDir == null)
217         {
218             throw new IllegalStateException("No configuration dir specified");
219         }
220 
221         File scandir = _monitoredDir.getFile();
222         Log.info("Deployment monitor " + scandir+ " at interval "+_scanInterval);
223         _scanner=new Scanner();
224         _scanner.setScanDirs(Collections.singletonList(scandir));
225         _scanner.setScanInterval(_scanInterval);
226         _scanner.setRecursive(_recursive);
227         _scanner.setFilenameFilter(_filenamefilter);
228         _scanner.setReportDirs(_acceptDirectories);
229         _scanner.addListener(_scannerListener);
230         _scanner.start();
231     }
232 
233     @Override
234     protected void doStop() throws Exception
235     {
236         _scanner.stop();
237         _scanner.removeListener(_scannerListener);
238         _scanner=null;
239     }
240 
241     public ConfigurationManager getConfigurationManager()
242     {
243         return _configurationManager;
244     }
245 
246     public String getDefaultsDescriptor()
247     {
248         return _defaultsDescriptor;
249     }
250 
251     /* ------------------------------------------------------------ */
252     /** Get the deploymentManager.
253      * @return the deploymentManager
254      */
255     public DeploymentManager getDeploymentManager()
256     {
257         return _deploymentManager;
258     }
259 
260     public Resource getMonitoredDir()
261     {
262         return _monitoredDir;
263     }
264 
265     public int getScanInterval()
266     {
267         return _scanInterval;
268     }
269 
270     /* ------------------------------------------------------------ */
271     /** Get the acceptContextXmlFiles.
272      * @return the acceptContextXmlFiles
273      */
274     public boolean isAcceptContextXmlFiles()
275     {
276         return _acceptContextXmlFiles;
277     }
278 
279     /* ------------------------------------------------------------ */
280     /** Get the acceptDirectories.
281      * @return the acceptDirectories
282      */
283     public boolean isAcceptDirectories()
284     {
285         return _acceptDirectories;
286     }
287 
288     /* ------------------------------------------------------------ */
289     /** Get the acceptWarFiles.
290      * @return the acceptWarFiles
291      */
292     public boolean isAcceptWarFiles()
293     {
294         return _acceptWarFiles;
295     }
296 
297     public boolean isExtractWars()
298     {
299         return _extractWars;
300     }
301 
302     public boolean isParentLoaderPriority()
303     {
304         return _parentLoaderPriority;
305     }
306 
307     public boolean isRecursive()
308     {
309         return _recursive;
310     }
311 
312     public void setAcceptContextXmlFiles(boolean flag)
313     {
314         if (isRunning())
315             throw new IllegalStateException();
316         _acceptContextXmlFiles = flag;
317     }
318 
319     public void setAcceptDirectories(boolean flag)
320     {
321         if (isRunning())
322             throw new IllegalStateException();
323         _acceptDirectories = flag;
324     }
325 
326     public void setAcceptWarFiles(boolean flag)
327     {
328         if (isRunning())
329             throw new IllegalStateException();
330         _acceptWarFiles = flag;
331     }
332 
333     public void setConfigurationManager(ConfigurationManager configurationManager)
334     {
335         _configurationManager = configurationManager;
336     }
337 
338     public void setDefaultsDescriptor(String defaultsDescriptor)
339     {
340         _defaultsDescriptor = defaultsDescriptor;
341     }
342 
343     public void setDeploymentManager(DeploymentManager deploymentManager)
344     {
345         _deploymentManager = deploymentManager;
346     }
347 
348     public void setExtractWars(boolean extractWars)
349     {
350         _extractWars = extractWars;
351     }
352 
353     public void setMonitoredDir(Resource contextsDir)
354     {
355         _monitoredDir = contextsDir;
356     }
357 
358     /**
359      * @param dir
360      *            Directory to scan for context descriptors or war files
361      */
362     public void setMonitoredDir(String dir)
363     {
364         try
365         {
366             _monitoredDir = Resource.newResource(dir);
367         }
368         catch (Exception e)
369         {
370             throw new IllegalArgumentException(e);
371         }
372     }
373     
374     public void setParentLoaderPriority(boolean parentLoaderPriority)
375     {
376         _parentLoaderPriority = parentLoaderPriority;
377     }
378 
379     public void setRecursive(boolean recursive)
380     {
381         _recursive = recursive;
382     }
383 
384     public void setScanInterval(int scanInterval)
385     {
386         _scanInterval = scanInterval;
387     }
388 }