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.DeploymentManager;
27  import org.eclipse.jetty.util.Scanner;
28  import org.eclipse.jetty.util.component.AbstractLifeCycle;
29  import org.eclipse.jetty.util.log.Log;
30  import org.eclipse.jetty.util.resource.Resource;
31  
32  /**
33   * Abstract for AppProviders that monitor context files. The context file
34   * enables adminsitrators to customize the configuration of a WebAppContext or a
35   * ContextHandler without chaging files inside the packaged application.
36   * <p>
37   * When the context file is changed, the corresponding application is
38   * redeployed.
39   * </p>
40   */
41  public abstract class ScanningAppProvider extends AbstractLifeCycle implements AppProvider
42  {
43      private Map<String, App> _appMap = new HashMap<String, App>();
44  
45      private DeploymentManager _deploymentManager;
46      protected final FilenameFilter _filenameFilter;
47      private Resource _monitoredDir;
48      private boolean _recursive = false;
49      private int _scanInterval = 10;
50      private Scanner _scanner;
51      
52      private final Scanner.DiscreteListener _scannerListener = new Scanner.DiscreteListener()
53      {
54          public void fileAdded(String filename) throws Exception
55          {
56              if (Log.isDebugEnabled()) Log.debug("added ",filename);
57              App app = ScanningAppProvider.this.createApp(filename);
58              if (app != null)
59              {
60                  _appMap.put(filename,app);
61                  _deploymentManager.addApp(app);
62              }
63          }
64  
65          public void fileChanged(String filename) throws Exception
66          {
67              if (Log.isDebugEnabled()) Log.debug("changed ",filename);
68              App app = _appMap.remove(filename);
69              if (app != null)
70              {
71                  _deploymentManager.removeApp(app);
72              }
73              app = ScanningAppProvider.this.createApp(filename);
74              if (app != null)
75              {
76                  _appMap.put(filename,app);
77                  _deploymentManager.addApp(app);
78              }
79          }
80  
81          public void fileRemoved(String filename) throws Exception
82          {
83              if (Log.isDebugEnabled()) Log.debug("removed ",filename);
84              App app = _appMap.remove(filename);
85              if (app != null)
86                  _deploymentManager.removeApp(app);
87          }
88      };
89  
90      protected ScanningAppProvider(FilenameFilter filter)
91      {
92          _filenameFilter = filter;
93      }
94  
95      /**
96       * @return The index of currently deployed applications.
97       */
98      protected Map<String, App> getDeployedApps()
99      {
100         return _appMap;
101     }
102 
103     /**
104      * Called by the Scanner.DiscreteListener to create a new App object.
105      * Isolated in a method so that it is possible to override the default App
106      * object for specialized implementations of the AppProvider.
107      * 
108      * @param filename
109      *            The file that is the context.xml. It is resolved by
110      *            {@link Resource#newResource(String)}
111      * @return The App object for this particular context definition file.
112      */
113     protected App createApp(String filename)
114     {
115         return new App(_deploymentManager,this,filename);
116     }
117 
118     @Override
119     protected void doStart() throws Exception
120     {
121         if (Log.isDebugEnabled()) Log.debug(this.getClass().getSimpleName() + ".doStart()");
122         if (_monitoredDir == null)
123         {
124             throw new IllegalStateException("No configuration dir specified");
125         }
126 
127         File scandir = _monitoredDir.getFile();
128         Log.info("Deployment monitor " + scandir + " at interval " + _scanInterval);
129         _scanner = new Scanner();
130         _scanner.setScanDirs(Collections.singletonList(scandir));
131         _scanner.setScanInterval(_scanInterval);
132         _scanner.setRecursive(_recursive);
133         _scanner.setFilenameFilter(_filenameFilter);
134         _scanner.setReportDirs(true);
135         _scanner.addListener(_scannerListener);
136         _scanner.start();
137     }
138 
139     /* ------------------------------------------------------------ */
140     @Override
141     protected void doStop() throws Exception
142     {
143         _scanner.stop();
144         _scanner.removeListener(_scannerListener);
145         _scanner = null;
146     }
147 
148     /* ------------------------------------------------------------ */
149     /**
150      * Get the deploymentManager.
151      * 
152      * @return the deploymentManager
153      */
154     public DeploymentManager getDeploymentManager()
155     {
156         return _deploymentManager;
157     }
158 
159     /* ------------------------------------------------------------ */
160     public Resource getMonitoredDir()
161     {
162         return _monitoredDir;
163     }
164 
165     /* ------------------------------------------------------------ */
166     public int getScanInterval()
167     {
168         return _scanInterval;
169     }
170 
171     /* ------------------------------------------------------------ */
172     public boolean isRecursive()
173     {
174         return _recursive;
175     }
176 
177     /* ------------------------------------------------------------ */
178     public void setDeploymentManager(DeploymentManager deploymentManager)
179     {
180         _deploymentManager = deploymentManager;
181     }
182 
183     /* ------------------------------------------------------------ */
184 
185     public void setMonitoredDir(Resource contextsDir)
186     {
187         _monitoredDir = contextsDir;
188     }
189 
190     /* ------------------------------------------------------------ */
191     /**
192      * @param dir
193      *            Directory to scan for context descriptors or war files
194      */
195     public void setMonitoredDir(String dir)
196     {
197         try
198         {
199             _monitoredDir = Resource.newResource(dir);
200         }
201         catch (Exception e)
202         {
203             throw new IllegalArgumentException(e);
204         }
205     }
206 
207     /* ------------------------------------------------------------ */
208     protected void setRecursive(boolean recursive)
209     {
210         _recursive = recursive;
211     }
212 
213     /* ------------------------------------------------------------ */
214     public void setScanInterval(int scanInterval)
215     {
216         _scanInterval = scanInterval;
217     }
218 }