ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/client/WebFeeder.java
Revision: 1.16
Committed: Mon Mar 19 21:30:30 2001 UTC (23 years, 2 months ago) by tdb
Branch: MAIN
Changes since 1.15: +14 -3 lines
Log Message:
Now cleans up empty host directories on the alert pages.

File Contents

# User Rev Content
1 tdb 1.1 //---PACKAGE DECLARATION---
2 tdb 1.7 package uk.org.iscream.client;
3 tdb 1.1
4     //---IMPORTS---
5 tdb 1.7 import uk.org.iscream.componentmanager.*;
6     import uk.org.iscream.core.*;
7     import uk.org.iscream.util.*;
8 tdb 1.2 import java.io.*;
9 tdb 1.1
10     /**
11     * Provides a feed to the webpage system.
12     *
13 tdb 1.11 * !! There may also be need to have a Thread to grab any
14     * !! required config (groups, "nice names, etc) and dump
15     * !! that to a file.
16 tdb 1.9 *
17 tdb 1.2 * @author $Author: tdb1 $
18 tdb 1.16 * @version $Id: WebFeeder.java,v 1.15 2001/03/16 16:47:33 tdb1 Exp $
19 tdb 1.1 */
20 tdb 1.11 public class WebFeeder extends Thread {
21 tdb 1.1
22     //---FINAL ATTRIBUTES---
23    
24     /**
25     * The current CVS revision of this class
26     */
27 tdb 1.16 public static final String REVISION = "$Revision: 1.15 $";
28 tdb 1.11
29     /**
30     * Default check period in seconds (30 minutes)
31     */
32     public final int DEFAULT_CHECK_PERIOD = 1800;
33    
34     /**
35     * Delete alerts older than this in seconds, default.
36     */
37     public final int DEFAULT_AGE = 3600;
38 tdb 1.1
39 tdb 1.14 /**
40     * The default path seperator, here for convienience
41     */
42     private final String sep = File.separator;
43    
44 tdb 1.1 //---STATIC METHODS---
45    
46     /**
47     * Return a reference to the single class.
48     * Construct it if it does not already exist, otherwise just return the reference.
49     */
50     public static WebFeeder getInstance() {
51     if (_instance == null){
52     _instance = new WebFeeder();
53     }
54     return _instance;
55     }
56    
57     //---CONSTRUCTORS---
58 tdb 1.11
59     /**
60     * Construct a new WebFeeder. This will also wipe out any
61     * old Alerts, as these can't be carried from one session
62     * until the next.
63     */
64 tdb 1.1 private WebFeeder() {
65     // do something, or nothing.. but must be private
66 tdb 1.8 // don't need to cleanup latest data
67 tdb 1.9
68     // -- cleanup old alerts
69     // get config proxy
70     ConfigurationProxy cp = ConfigurationProxy.getInstance();
71     // get file locations
72     String rootPath, alertSubDir, alertFileName;
73     try {
74     // work out where things are
75     rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
76     alertSubDir = cp.getProperty("WebFeeder", "WebFeeder.alertSubDir");
77 tdb 1.12 File alertsDir = new File(rootPath, alertSubDir);
78 tdb 1.10 if(deleteContents(alertsDir)) {
79 tdb 1.14 _logger.write(this.toString(), Logger.DEBUG, "Deleted all files and directories from: "+rootPath+sep+alertSubDir);
80 tdb 1.10 } else {
81 tdb 1.14 _logger.write(this.toString(), Logger.WARNING, "Failed to delete all files and directories from: "+rootPath+sep+alertSubDir);
82 tdb 1.9 }
83     // cleanup complete
84     } catch (PropertyNotFoundException e) {
85     _logger.write(this.toString(), Logger.ERROR, "Failed to cleanup on construction, due to failing to get config for Alert Data: "+e);
86     // just leave it at that
87     }
88 tdb 1.11
89     // set our name and startup
90     setName("client.WebFeeder");
91     start();
92 tdb 1.1 }
93    
94     //---PUBLIC METHODS---
95    
96 tdb 1.11 /**
97     * Thread loop, will check at intervals for any files
98     * that need to be "cleaned up". This will normally
99     * be OK and FINAL alerts that have been around for longer
100     * than a specified period of time.
101     */
102     public void run() {
103     boolean running = true;
104     // get config proxy
105     ConfigurationProxy cp = ConfigurationProxy.getInstance();
106     // loop round
107     while(running) {
108     // get our check period
109     int checkPeriod = 0;
110     try {
111     checkPeriod = Integer.parseInt(cp.getProperty("WebFeeder", "WebFeeder.checkPeriod"));
112     } catch (NumberFormatException e) {
113     checkPeriod = DEFAULT_CHECK_PERIOD;
114     _logger.write(toString(), Logger.WARNING, "Erronous WebFeeder.checkPeriod value in configuration using default of " + checkPeriod + " seconds");
115     } catch (PropertyNotFoundException e) {
116     checkPeriod = DEFAULT_CHECK_PERIOD;
117     _logger.write(toString(), Logger.WARNING, "WebFeeder.checkPeriod value unavailable using default of " + checkPeriod + " seconds");
118     }
119     // wait for the check period
120     try {
121     Thread.sleep(checkPeriod * 1000);
122     } catch (InterruptedException e) {
123     }
124    
125     // get alerts directory
126     String rootPath, alertSubDir, alertFileName;
127     try {
128     rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
129     alertSubDir = cp.getProperty("WebFeeder", "WebFeeder.alertSubDir");
130     alertFileName = cp.getProperty("WebFeeder", "WebFeeder.alertFileName");
131     } catch (PropertyNotFoundException e) {
132     _logger.write(this.toString(), Logger.ERROR, "Failed to get config for Alert Data: "+e);
133     // bail out
134     continue;
135     }
136    
137     // get the "age" barrier
138     int deleteOlderThan = 0;
139     try {
140     deleteOlderThan = Integer.parseInt(cp.getProperty("WebFeeder", "WebFeeder.alertDeleteOlderThan"));
141     } catch (NumberFormatException e) {
142     deleteOlderThan = DEFAULT_AGE;
143     _logger.write(toString(), Logger.WARNING, "Erronous WebFeeder.alertDeleteOlderThan value in configuration using default of " + deleteOlderThan + " seconds");
144     } catch (PropertyNotFoundException e) {
145     deleteOlderThan = DEFAULT_AGE;
146     _logger.write(toString(), Logger.WARNING, "WebFeeder.alertDeleteOlderThan value unavailable using default of " + deleteOlderThan + " seconds");
147     }
148    
149 tdb 1.12 // list the files and delete as appropriate
150     File alertsDir = new File(rootPath, alertSubDir);
151 tdb 1.15 // get all the hostnames directories
152 tdb 1.11 File[] contents = alertsDir.listFiles();
153     for(int i=0; i < contents.length; i++) {
154 tdb 1.15 // get a single directory from the array..
155 tdb 1.11 File hostdir = contents[i];
156 tdb 1.15 // ..and check it's a directory
157 tdb 1.12 if(hostdir.isDirectory()) {
158 tdb 1.15 // get all the contents of that directory
159 tdb 1.12 File[] hostdirContents = hostdir.listFiles();
160     for(int j=0; j < hostdirContents.length; j++) {
161     File alertFile = hostdirContents[j];
162 tdb 1.15 // get the filename..
163 tdb 1.12 String filename = alertFile.getName();
164 tdb 1.15 // ..and see if it ends with OK or FINAL
165 tdb 1.12 if(filename.endsWith(Alert.alertLevels[0]) ||
166     filename.endsWith(Alert.alertLevels[Alert.alertLevels.length-1])) {
167 tdb 1.15 // it does end with either OK or FINAL
168 tdb 1.12 // ... so we can check it for deletion
169     long lastModified = alertFile.lastModified();
170     long age = System.currentTimeMillis() - lastModified;
171     if(age > ((long) deleteOlderThan*1000)) {
172     // it's also older than our age to delete older than
173 tdb 1.16 if(alertFile.delete()) {
174     // do a quick check to see if the directory is now empty
175     File[] newHostdirContents = hostdir.listFiles();
176     if(newHostdirContents.length == 0) {
177     // it does seem to be, try and delete it
178     // this will fail anyway if files still remain
179     if(!hostdir.delete()) {
180     _logger.write(this.toString(), Logger.WARNING, "Failed to delete the following empty host directory: "+hostdir.getPath());
181     }
182     }
183     }
184     else {
185 tdb 1.12 _logger.write(this.toString(), Logger.WARNING, "Failed to delete the following 'old' alert file: "+alertFile.getPath());
186     }
187 tdb 1.11 }
188     }
189     }
190     }
191     }
192     }
193     }
194 tdb 1.1
195 tdb 1.11 /**
196     * Handles an XMLPacket. This will write it out to disk
197     * in an appropriate manner.
198     *
199     * @param packet the XMLPacket to write
200     */
201 tdb 1.1 public void receiveXMLPacket(XMLPacket packet) {
202 tdb 1.4 String packetType = packet.getParam("packet.attributes.type");
203     if(packetType == null || !packetType.equals("data")) {
204     // bail out, without warning
205     // this is probably a heartbeat or similar
206     return;
207     }
208 tdb 1.2 // get config proxy
209     ConfigurationProxy cp = ConfigurationProxy.getInstance();
210     // get file locations
211     String rootPath, latestSubDir, latestFileName;
212     try {
213     rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
214     latestSubDir = cp.getProperty("WebFeeder", "WebFeeder.latestSubDir");
215     latestFileName = cp.getProperty("WebFeeder", "WebFeeder.latestFileName");
216     } catch (PropertyNotFoundException e) {
217     _logger.write(this.toString(), Logger.ERROR, "Failed to get config for Latest Data: "+e);
218     // bail out
219     return;
220     }
221     // get raw data
222     String data = packet.printAll();
223 tdb 1.3 String hostname = packet.getParam("packet.attributes.machine_name");
224 tdb 1.2 // set paths
225 tdb 1.14 File outDir = new File(rootPath, latestSubDir+sep+hostname);
226     File outFile = new File(rootPath, latestSubDir+sep+hostname+sep+latestFileName);
227 tdb 1.11 // write the data out
228     writeData(outDir, outFile, data);
229 tdb 1.1 }
230    
231 tdb 1.11 /**
232     * Handles an Alert. This will write it out to disk
233     * in an appropriate manner.
234     *
235     * @param alert the Alert object to write
236     */
237 tdb 1.1 public void receiveAlert(Alert alert) {
238 tdb 1.5 // get config proxy
239     ConfigurationProxy cp = ConfigurationProxy.getInstance();
240     // get file locations
241     String rootPath, alertSubDir, alertFileName;
242     try {
243     rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
244     alertSubDir = cp.getProperty("WebFeeder", "WebFeeder.alertSubDir");
245     alertFileName = cp.getProperty("WebFeeder", "WebFeeder.alertFileName");
246     } catch (PropertyNotFoundException e) {
247     _logger.write(this.toString(), Logger.ERROR, "Failed to get config for Alert Data: "+e);
248     // bail out
249     return;
250     }
251     // get raw data
252     String data = alert.printAll();
253     String hostname = alert.getSource();
254     // set paths
255 tdb 1.14 File outDir = new File(rootPath, alertSubDir+sep+hostname);
256     String destFile = alertSubDir+sep+hostname+sep+alertFileName+"."+String.valueOf(alert.getInitialAlertTime());
257 tdb 1.9 File outFile;
258     // check if we're at a special "end case" (OK or FINAL)
259     if(alert.getLevel()==0 || alert.getLevel()==Alert.alertLevels.length-1) {
260 tdb 1.12 File oldFile = new File(rootPath, destFile);
261     outFile = new File(rootPath, destFile+"."+Alert.alertLevels[alert.getLevel()]);
262 tdb 1.9 if(!oldFile.renameTo(outFile)) {
263     _logger.write(this.toString(), Logger.WARNING, "Failed to rename old file, "+oldFile.getPath()+" to new file, "+outFile.getPath());
264     }
265     } else {
266 tdb 1.13 outFile = new File(rootPath, destFile);
267 tdb 1.9 }
268 tdb 1.11 // write the data out
269     writeData(outDir, outFile, data);
270     }
271    
272     /**
273     * Overrides the {@link java.lang.Object#toString() Object.toString()}
274     * method to provide clean logging (every class should have this).
275     *
276     * This uses the uk.org.iscream.util.FormatName class
277     * to format the toString()
278     *
279     * @return the name of this class and its CVS revision
280     */
281     public String toString() {
282     return FormatName.getName(
283     _name,
284     getClass().getName(),
285     REVISION);
286     }
287    
288     //---PRIVATE METHODS---
289    
290     /**
291     * Attempts to write "data" to "outFile" in "outDir".
292     *
293     * Performs checks to create the directories, and the file.
294     * Does not "return" anything to indicate failure or success.
295     *
296     * @param outDir the directory to put the file in
297     * @param outFile the filename to put the data in
298     * @param data the String of data to write
299     */
300     private void writeData(File outDir, File outFile, String data) {
301 tdb 1.5 // try to create directory
302     if(!outDir.exists()) {
303     if(!outDir.mkdirs()) {
304     // didn't exist, and we couldn't make it
305     _logger.write(this.toString(), Logger.ERROR, "Failed to create directory: "+outDir.getPath());
306     // bail out
307     return;
308     }
309     }
310     // directory has been made, check file exists
311     if(!outFile.exists()) {
312     try {
313     outFile.createNewFile();
314     } catch (IOException e) {
315     _logger.write(this.toString(), Logger.ERROR, "Failed to create file: "+e);
316     // bail out
317     return;
318     }
319     }
320     // file should now exist
321     if(outFile.canWrite()) {
322     PrintWriter out;
323     try {
324 tdb 1.8 out = new PrintWriter(new FileWriter(outFile));
325 tdb 1.5 out.println(data);
326     out.close();
327     } catch (IOException e) {
328     _logger.write(this.toString(), Logger.ERROR, "Failed to write file: "+e);
329     }
330     }
331     else {
332     _logger.write(this.toString(), Logger.ERROR, "File not writeable: "+outFile.getPath());
333     }
334 tdb 1.1 }
335 tdb 1.10
336     /**
337     * Iterates through dir (a directory) and deletes
338     * all files and subdirectories.
339     *
340     * @param dir the directory to clear
341     * @return true if it succeeded
342     */
343     private boolean deleteContents(File dir) {
344     boolean success = true;
345     if(dir.isDirectory()) {
346     // is a directory
347     File[] contents = dir.listFiles();
348     for(int i=0; i < contents.length; i++) {
349     File sub = contents[i];
350     if(sub.isDirectory()) {
351     // lets get recursive
352     success = success & deleteContents(sub);
353     }
354     // it's a file or empty dir
355     success = success & sub.delete();
356     }
357     }
358     else {
359     // not a directory?
360     success=false;
361     }
362     return success;
363     }
364    
365 tdb 1.1 //---ACCESSOR/MUTATOR METHODS---
366    
367     //---ATTRIBUTES---
368    
369     /**
370     * This is the friendly identifier of the
371     * component this class is running in.
372     * eg, a Filter may be called "filter1",
373     * If this class does not have an owning
374     * component, a name from the configuration
375     * can be placed here. This name could also
376     * be changed to null for utility classes.
377     */
378     private String _name = ClientMain.NAME;
379    
380     /**
381     * This holds a reference to the
382     * system logger that is being used.
383     */
384     private Logger _logger = ReferenceManager.getInstance().getLogger();
385    
386     //---STATIC ATTRIBUTES---
387    
388     /**
389     * A reference to the single instance of this class
390     */
391     private static WebFeeder _instance;
392    
393     }