View Javadoc

1   package org.eclipse.jetty.policy;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.util.ArrayList;
6   import java.util.List;
7   import java.util.Set;
8   import java.util.concurrent.CountDownLatch;
9   import java.util.concurrent.atomic.AtomicInteger;
10  
11  import org.eclipse.jetty.policy.loader.DefaultPolicyLoader;
12  import org.eclipse.jetty.util.Scanner;
13  import org.eclipse.jetty.util.component.AbstractLifeCycle;
14  
15  /**
16   * PolicyMonitor watches a directory for files ending in the *.policy extension,
17   * loads them and detects when they change.  PolicyGrants are peeped out the
18   * onPolicyChange method to whoever is using this monitor.
19   *
20   */
21  public abstract class PolicyMonitor extends AbstractLifeCycle
22  {    
23  
24      /** 
25       * the directory to be scanned for policy files.
26       */
27      private String _policyDirectory;
28      
29      /** 
30       * instance of the scanner that detects policy files
31       */
32      private Scanner _scanner;
33  
34      /** 
35       * true if updates to policy grants will be pushed through the 
36       * onPolicyChange() method
37       */
38      private boolean _reload = true;
39      
40      /**
41       * scan interval in seconds for policy file changes
42       */
43      private int _scanInterval = 1;
44              
45      /**
46       * specialized listener enabling waitForScan() functionality
47       */
48      private LatchScannerListener _scanningListener;
49      
50      /**
51       * true if the scanner has completed one cycle.
52       */
53      private boolean _initialized = false;
54          
55      /**
56       * record of the number of scans that have been made
57       */
58      private AtomicInteger _scanCount = new AtomicInteger(0);
59      
60      /**
61       * empty constructor
62       */
63      public PolicyMonitor()
64      {
65          
66      }
67      
68      /**
69       * construtor with a predetermined directory to monitor
70       * 
71       * @param directory
72       */
73      public PolicyMonitor( String directory )
74      {
75          this();
76          _policyDirectory = directory;
77      }
78      
79      /**
80       * set the policy directory to scan on a non-running monitor
81       * 
82       * @param directory
83       */
84      public void setPolicyDirectory( String directory )
85      {
86          if (isRunning())
87          {
88              throw new PolicyException("policy monitor is running, unable to set policy directory");
89          }
90          
91          _policyDirectory = directory;
92      }
93      
94      /**
95       * gets the scanner interval
96       * 
97       * @return the scan interval
98       */
99      public int getScanInterval()
100     {
101         return _scanInterval;
102     }
103     
104     /**
105      * sets the scanner interval on a non-running instance of the monitor
106      * 
107      * @param scanInterval in seconds
108      * @see Scanner#setScanInterval(int)
109      */
110     public void setScanInterval( int scanInterval )
111     {
112         if (isRunning())
113         {
114             throw new PolicyException("policy monitor is running, unable to set scan interval");
115         }
116         
117         _scanInterval = scanInterval;
118     }
119     
120     /**
121      * true of the monitor is initialized, meaning that at least one
122      * scan cycle has completed and any policy grants found have been chirped
123      * 
124      * @return true if initialized
125      */
126     public boolean isInitialized()
127     {
128         return _initialized;
129     }
130     
131     /**
132      * gets the number of times the scan has been run
133      * 
134      * @return scan count
135      */
136     public int getScanCount()
137     {
138         return _scanCount.get();
139     }
140     
141     /**
142      * initiates a scan and blocks until it has been completed
143      * 
144      * @throws Exception
145      */
146     public synchronized void waitForScan() throws Exception
147     {
148         // wait for 2 scans for stable files
149         CountDownLatch latch = new CountDownLatch(2);
150         
151        _scanningListener.setScanningLatch(latch);
152        _scanner.scan();
153        latch.await();
154     }  
155     
156     /**
157      * true of reload is enabled, false otherwise
158      * 
159      * @return true if reload is enabled
160      */
161     public boolean isReloadEnabled()
162     {
163         return _reload;
164     }
165 
166     /**
167      * sets the monitor to reload or not, but only if the monitor isn't already running
168      * 
169      * TODO this doesn't really _have_ to be on a non-running monitor
170      * 
171      * @param reload
172      */
173     public void setReload(boolean reload)
174     {
175         if (isRunning())
176         {
177             throw new PolicyException("policy monitor is running, unable to set reload at this time");
178         }
179         
180         _reload = reload;
181     }
182 
183     /**
184      * processes a policy file via the default policy loader and chirps
185      * changes to the onPolicyChange() abstract method
186      * 
187      * @param filename
188      */
189     private void processPolicyFile(String filename)
190     {
191         try
192         {
193             File policyFile = new File(filename);
194 
195             Set<PolicyBlock> policyBlocks = DefaultPolicyLoader.load(new FileInputStream(policyFile),JettyPolicy.getContext());
196 
197             for (PolicyBlock policy : policyBlocks)
198             {
199                 onPolicyChange(policy);
200             }
201         }
202         catch (Exception e)
203         {
204             e.printStackTrace();
205         }
206     }
207 
208     /**
209      * called by the abstract lifecycle to start the monitor
210      */
211     @Override
212     protected void doStart() throws Exception
213     {
214         super.doStart();
215         
216         _scanner = new Scanner();
217 
218         List<File> scanDirs = new ArrayList<File>();
219 
220         scanDirs.add(new File( _policyDirectory ) );
221         
222         //System.out.println("Scanning: " + _policyDirectory );
223         
224         _scanner.addListener(new Scanner.DiscreteListener()
225         {
226 
227             public void fileRemoved(String filename) throws Exception
228             {
229 
230             }
231 
232             /* will trigger when files are changed, not on load time, just when changed */
233             public void fileChanged(String filename) throws Exception
234             {
235                if (_reload && filename.endsWith("policy"))
236                {
237                   // System.out.println("PolicyMonitor: policy file");
238                    processPolicyFile(filename);
239                }
240             }
241 
242             public void fileAdded(String filename) throws Exception
243             {
244                 if (filename.endsWith("policy"))
245                 {
246                    // System.out.println("PolicyMonitor: added policy file");
247                     processPolicyFile(filename);
248                 }
249             }
250         });
251         
252         _scanningListener = new LatchScannerListener();
253         
254         _scanner.addListener(_scanningListener);
255 
256         _scanner.setScanDirs(scanDirs);
257         _scanner.setReportExistingFilesOnStartup(true);
258         _scanner.start();
259         _scanner.setScanInterval(_scanInterval);
260     }
261     
262     /**
263      * called by the abstract life cycle to turn off the monitor
264      */
265     @Override
266     protected void doStop() throws Exception
267     {
268         super.doStop();
269         
270         _scanner.stop();
271     }
272     
273     /**
274      * latch listener that can taken in a countdownlatch and notify other 
275      * blocking threads that the scan has been completed
276      *
277      */
278     private class LatchScannerListener implements Scanner.ScanCycleListener
279     {
280         CountDownLatch _latch;
281         
282         public void scanStarted(int cycle) throws Exception
283         {
284 
285         }
286         
287         public void scanEnded(int cycle) throws Exception
288         {
289             _initialized = true; // just really needed the first time
290             _scanCount.incrementAndGet();
291             if ( _latch != null )
292             {
293                 _latch.countDown();
294             }
295         }
296         
297         public void setScanningLatch( CountDownLatch latch )
298         {
299             _latch = latch;
300         }
301     }
302     
303     /**
304      * implemented by the user of the policy monitor to handle custom logic 
305      * related to the usage of the policy grant instance/s.
306      * 
307      * @param grant
308      */
309     public abstract void onPolicyChange(PolicyBlock grant);
310 }