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.11
Committed: Thu Mar 15 14:30:55 2001 UTC (23 years, 2 months ago) by tdb
Branch: MAIN
Changes since 1.10: +155 -65 lines
Log Message:
Added support for deleting old alert files.

File Contents

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