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.deploy.providers;
20  
21  import java.io.File;
22  import java.io.FilenameFilter;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.concurrent.CopyOnWriteArrayList;
30  
31  import org.eclipse.jetty.deploy.App;
32  import org.eclipse.jetty.deploy.AppProvider;
33  import org.eclipse.jetty.deploy.DeploymentManager;
34  import org.eclipse.jetty.util.Scanner;
35  import org.eclipse.jetty.util.annotation.ManagedAttribute;
36  import org.eclipse.jetty.util.annotation.ManagedObject;
37  import org.eclipse.jetty.util.component.AbstractLifeCycle;
38  import org.eclipse.jetty.util.log.Log;
39  import org.eclipse.jetty.util.log.Logger;
40  import org.eclipse.jetty.util.resource.Resource;
41  
42  /**
43   */
44  @ManagedObject("Abstract Provider for loading webapps")
45  public abstract class ScanningAppProvider extends AbstractLifeCycle implements AppProvider
46  {
47      private static final Logger LOG = Log.getLogger(ScanningAppProvider.class);
48  
49      private Map<String, App> _appMap = new HashMap<String, App>();
50  
51      private DeploymentManager _deploymentManager;
52      protected FilenameFilter _filenameFilter;
53      private final List<Resource> _monitored= new CopyOnWriteArrayList<>();
54      private boolean _recursive = false;
55      private int _scanInterval = 10;
56      private Scanner _scanner;
57  
58      /* ------------------------------------------------------------ */
59      private final Scanner.DiscreteListener _scannerListener = new Scanner.DiscreteListener()
60      {
61          @Override
62          public void fileAdded(String filename) throws Exception
63          {
64              ScanningAppProvider.this.fileAdded(filename);
65          }
66  
67          @Override
68          public void fileChanged(String filename) throws Exception
69          {
70              ScanningAppProvider.this.fileChanged(filename);
71          }
72  
73          @Override
74          public void fileRemoved(String filename) throws Exception
75          {
76              ScanningAppProvider.this.fileRemoved(filename);
77          }
78      };
79  
80      /* ------------------------------------------------------------ */
81      protected ScanningAppProvider()
82      {
83      }
84      
85      /* ------------------------------------------------------------ */
86      protected ScanningAppProvider(FilenameFilter filter)
87      {
88          _filenameFilter = filter;
89      }
90  
91      /* ------------------------------------------------------------ */
92      protected void setFilenameFilter(FilenameFilter filter)
93      {
94          if (isRunning())
95              throw new IllegalStateException();
96          _filenameFilter = filter;
97      }
98      
99      /* ------------------------------------------------------------ */
100     /**
101      * @return The index of currently deployed applications.
102      */
103     protected Map<String, App> getDeployedApps()
104     {
105         return _appMap;
106     }
107 
108     /* ------------------------------------------------------------ */
109     /**
110      * Called by the Scanner.DiscreteListener to create a new App object.
111      * Isolated in a method so that it is possible to override the default App
112      * object for specialized implementations of the AppProvider.
113      * 
114      * @param filename
115      *            The file that is the context.xml. It is resolved by
116      *            {@link Resource#newResource(String)}
117      * @return The App object for this particular context definition file.
118      */
119     protected App createApp(String filename)
120     {
121         return new App(_deploymentManager,this,filename);
122     }
123 
124     /* ------------------------------------------------------------ */
125     @Override
126     protected void doStart() throws Exception
127     {
128         if (LOG.isDebugEnabled()) 
129             LOG.debug(this.getClass().getSimpleName() + ".doStart()");
130         if (_monitored.size()==0)
131             throw new IllegalStateException("No configuration dir specified");
132 
133         LOG.info("Deployment monitor " + _monitored + " at interval " + _scanInterval);
134         List<File> files = new ArrayList<>();
135         for (Resource resource:_monitored)
136             files.add(resource.getFile());
137         
138         _scanner = new Scanner();
139         _scanner.setScanDirs(files);
140         _scanner.setScanInterval(_scanInterval);
141         _scanner.setRecursive(_recursive);
142         _scanner.setFilenameFilter(_filenameFilter);
143         _scanner.setReportDirs(true);
144         _scanner.addListener(_scannerListener);
145         _scanner.start();
146     }
147 
148     /* ------------------------------------------------------------ */
149     @Override
150     protected void doStop() throws Exception
151     {
152         if (_scanner!=null)
153         {
154             _scanner.stop();
155             _scanner.removeListener(_scannerListener);
156             _scanner = null;
157         }
158     }
159     
160     /* ------------------------------------------------------------ */
161     protected boolean exists(String path)
162     {
163         return _scanner.exists(path);
164     }
165 
166     /* ------------------------------------------------------------ */
167     protected void fileAdded(String filename) throws Exception
168     {
169         if (LOG.isDebugEnabled()) 
170             LOG.debug("added {}",filename);
171         App app = ScanningAppProvider.this.createApp(filename);
172         if (app != null)
173         {
174             _appMap.put(filename,app);
175             _deploymentManager.addApp(app);
176         }
177     }
178 
179     /* ------------------------------------------------------------ */
180     protected void fileChanged(String filename) throws Exception
181     {
182         if (LOG.isDebugEnabled()) 
183             LOG.debug("changed {}",filename);
184         App app = _appMap.remove(filename);
185         if (app != null)
186         {
187             _deploymentManager.removeApp(app);
188         }
189         app = ScanningAppProvider.this.createApp(filename);
190         if (app != null)
191         {
192             _appMap.put(filename,app);
193             _deploymentManager.addApp(app);
194         }
195     }
196     
197     /* ------------------------------------------------------------ */
198     protected void fileRemoved(String filename) throws Exception
199     {
200         if (LOG.isDebugEnabled()) 
201             LOG.debug("removed {}",filename);
202         App app = _appMap.remove(filename);
203         if (app != null)
204             _deploymentManager.removeApp(app);
205     }
206     
207     /* ------------------------------------------------------------ */
208     /**
209      * Get the deploymentManager.
210      * 
211      * @return the deploymentManager
212      */
213     public DeploymentManager getDeploymentManager()
214     {
215         return _deploymentManager;
216     }
217 
218 
219     /* ------------------------------------------------------------ */
220     public Resource getMonitoredDirResource()
221     {
222         if (_monitored.size()==0)
223             return null;
224         if (_monitored.size()>1)
225             throw new IllegalStateException();
226         return _monitored.get(0);
227     }
228 
229     /* ------------------------------------------------------------ */
230     public String getMonitoredDirName()
231     {
232         Resource resource=getMonitoredDirResource();
233         return resource==null?null:resource.toString();
234     }
235 
236     /* ------------------------------------------------------------ */
237     @ManagedAttribute("scanning interval to detect changes which need reloaded")
238     public int getScanInterval()
239     {
240         return _scanInterval;
241     }
242 
243     /* ------------------------------------------------------------ */
244     @ManagedAttribute("recursive scanning supported")
245     public boolean isRecursive()
246     {
247         return _recursive;
248     }
249 
250     /* ------------------------------------------------------------ */
251     @Override
252     public void setDeploymentManager(DeploymentManager deploymentManager)
253     {
254         _deploymentManager = deploymentManager;
255     }
256     
257     /* ------------------------------------------------------------ */
258     public void setMonitoredResources(List<Resource> resources)
259     {
260         _monitored.clear();
261         _monitored.addAll(resources);
262     }
263     
264     /* ------------------------------------------------------------ */
265     public List<Resource> getMonitoredResources()
266     {
267         return Collections.unmodifiableList(_monitored);
268     }
269     
270     /* ------------------------------------------------------------ */
271     public void setMonitoredDirResource(Resource resource)
272     {
273         setMonitoredResources(Collections.singletonList(resource));
274     }
275 
276     /* ------------------------------------------------------------ */
277     public void addScannerListener(Scanner.Listener listener)
278     {
279         _scanner.addListener(listener);
280     }
281     
282     /* ------------------------------------------------------------ */
283     /**
284      * @param dir
285      *            Directory to scan for context descriptors or war files
286      */
287     public void setMonitoredDirName(String dir)
288     {
289         setMonitoredDirectories(Collections.singletonList(dir));
290     }
291 
292     /* ------------------------------------------------------------ */
293     public void setMonitoredDirectories(Collection<String> directories)
294     {
295         try
296         {
297             List<Resource> resources = new ArrayList<>();
298             for (String dir:directories)
299                 resources.add(Resource.newResource(dir));
300             setMonitoredResources(resources);
301         }
302         catch (Exception e)
303         {
304             throw new IllegalArgumentException(e);
305         }
306     }
307     
308     /* ------------------------------------------------------------ */
309     protected void setRecursive(boolean recursive)
310     {
311         _recursive = recursive;
312     }
313 
314     /* ------------------------------------------------------------ */
315     public void setScanInterval(int scanInterval)
316     {
317         _scanInterval = scanInterval;
318     }
319 }