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.15
Committed: Fri Mar 16 16:47:33 2001 UTC (23 years, 2 months ago) by tdb
Branch: MAIN
Changes since 1.14: +9 -3 lines
Log Message:
Trying to explain what I'm doing better.

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.14 2001/03/16 16:43:50 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.14 $";
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 /**
40 * The default path seperator, here for convienience
41 */
42 private final String sep = File.separator;
43
44 //---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
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 private WebFeeder() {
65 // do something, or nothing.. but must be private
66 // don't need to cleanup latest data
67
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 File alertsDir = new File(rootPath, alertSubDir);
78 if(deleteContents(alertsDir)) {
79 _logger.write(this.toString(), Logger.DEBUG, "Deleted all files and directories from: "+rootPath+sep+alertSubDir);
80 } else {
81 _logger.write(this.toString(), Logger.WARNING, "Failed to delete all files and directories from: "+rootPath+sep+alertSubDir);
82 }
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
89 // set our name and startup
90 setName("client.WebFeeder");
91 start();
92 }
93
94 //---PUBLIC METHODS---
95
96 /**
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 // list the files and delete as appropriate
150 File alertsDir = new File(rootPath, alertSubDir);
151 // get all the hostnames directories
152 File[] contents = alertsDir.listFiles();
153 for(int i=0; i < contents.length; i++) {
154 // get a single directory from the array..
155 File hostdir = contents[i];
156 // ..and check it's a directory
157 if(hostdir.isDirectory()) {
158 // get all the contents of that directory
159 File[] hostdirContents = hostdir.listFiles();
160 for(int j=0; j < hostdirContents.length; j++) {
161 File alertFile = hostdirContents[j];
162 // get the filename..
163 String filename = alertFile.getName();
164 // ..and see if it ends with OK or FINAL
165 if(filename.endsWith(Alert.alertLevels[0]) ||
166 filename.endsWith(Alert.alertLevels[Alert.alertLevels.length-1])) {
167 // it does end with either OK or FINAL
168 // ... 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 if(!alertFile.delete()) {
174 _logger.write(this.toString(), Logger.WARNING, "Failed to delete the following 'old' alert file: "+alertFile.getPath());
175 }
176 }
177 }
178 }
179 }
180 }
181 }
182 }
183
184 /**
185 * Handles an XMLPacket. This will write it out to disk
186 * in an appropriate manner.
187 *
188 * @param packet the XMLPacket to write
189 */
190 public void receiveXMLPacket(XMLPacket packet) {
191 String packetType = packet.getParam("packet.attributes.type");
192 if(packetType == null || !packetType.equals("data")) {
193 // bail out, without warning
194 // this is probably a heartbeat or similar
195 return;
196 }
197 // get config proxy
198 ConfigurationProxy cp = ConfigurationProxy.getInstance();
199 // get file locations
200 String rootPath, latestSubDir, latestFileName;
201 try {
202 rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
203 latestSubDir = cp.getProperty("WebFeeder", "WebFeeder.latestSubDir");
204 latestFileName = cp.getProperty("WebFeeder", "WebFeeder.latestFileName");
205 } catch (PropertyNotFoundException e) {
206 _logger.write(this.toString(), Logger.ERROR, "Failed to get config for Latest Data: "+e);
207 // bail out
208 return;
209 }
210 // get raw data
211 String data = packet.printAll();
212 String hostname = packet.getParam("packet.attributes.machine_name");
213 // set paths
214 File outDir = new File(rootPath, latestSubDir+sep+hostname);
215 File outFile = new File(rootPath, latestSubDir+sep+hostname+sep+latestFileName);
216 // write the data out
217 writeData(outDir, outFile, data);
218 }
219
220 /**
221 * Handles an Alert. This will write it out to disk
222 * in an appropriate manner.
223 *
224 * @param alert the Alert object to write
225 */
226 public void receiveAlert(Alert alert) {
227 // get config proxy
228 ConfigurationProxy cp = ConfigurationProxy.getInstance();
229 // get file locations
230 String rootPath, alertSubDir, alertFileName;
231 try {
232 rootPath = cp.getProperty("WebFeeder", "WebFeeder.rootPath");
233 alertSubDir = cp.getProperty("WebFeeder", "WebFeeder.alertSubDir");
234 alertFileName = cp.getProperty("WebFeeder", "WebFeeder.alertFileName");
235 } catch (PropertyNotFoundException e) {
236 _logger.write(this.toString(), Logger.ERROR, "Failed to get config for Alert Data: "+e);
237 // bail out
238 return;
239 }
240 // get raw data
241 String data = alert.printAll();
242 String hostname = alert.getSource();
243 // set paths
244 File outDir = new File(rootPath, alertSubDir+sep+hostname);
245 String destFile = alertSubDir+sep+hostname+sep+alertFileName+"."+String.valueOf(alert.getInitialAlertTime());
246 File outFile;
247 // check if we're at a special "end case" (OK or FINAL)
248 if(alert.getLevel()==0 || alert.getLevel()==Alert.alertLevels.length-1) {
249 File oldFile = new File(rootPath, destFile);
250 outFile = new File(rootPath, destFile+"."+Alert.alertLevels[alert.getLevel()]);
251 if(!oldFile.renameTo(outFile)) {
252 _logger.write(this.toString(), Logger.WARNING, "Failed to rename old file, "+oldFile.getPath()+" to new file, "+outFile.getPath());
253 }
254 } else {
255 outFile = new File(rootPath, destFile);
256 }
257 // write the data out
258 writeData(outDir, outFile, data);
259 }
260
261 /**
262 * Overrides the {@link java.lang.Object#toString() Object.toString()}
263 * method to provide clean logging (every class should have this).
264 *
265 * This uses the uk.org.iscream.util.FormatName class
266 * to format the toString()
267 *
268 * @return the name of this class and its CVS revision
269 */
270 public String toString() {
271 return FormatName.getName(
272 _name,
273 getClass().getName(),
274 REVISION);
275 }
276
277 //---PRIVATE METHODS---
278
279 /**
280 * Attempts to write "data" to "outFile" in "outDir".
281 *
282 * Performs checks to create the directories, and the file.
283 * Does not "return" anything to indicate failure or success.
284 *
285 * @param outDir the directory to put the file in
286 * @param outFile the filename to put the data in
287 * @param data the String of data to write
288 */
289 private void writeData(File outDir, File outFile, String data) {
290 // try to create directory
291 if(!outDir.exists()) {
292 if(!outDir.mkdirs()) {
293 // didn't exist, and we couldn't make it
294 _logger.write(this.toString(), Logger.ERROR, "Failed to create directory: "+outDir.getPath());
295 // bail out
296 return;
297 }
298 }
299 // directory has been made, check file exists
300 if(!outFile.exists()) {
301 try {
302 outFile.createNewFile();
303 } catch (IOException e) {
304 _logger.write(this.toString(), Logger.ERROR, "Failed to create file: "+e);
305 // bail out
306 return;
307 }
308 }
309 // file should now exist
310 if(outFile.canWrite()) {
311 PrintWriter out;
312 try {
313 out = new PrintWriter(new FileWriter(outFile));
314 out.println(data);
315 out.close();
316 } catch (IOException e) {
317 _logger.write(this.toString(), Logger.ERROR, "Failed to write file: "+e);
318 }
319 }
320 else {
321 _logger.write(this.toString(), Logger.ERROR, "File not writeable: "+outFile.getPath());
322 }
323 }
324
325 /**
326 * Iterates through dir (a directory) and deletes
327 * all files and subdirectories.
328 *
329 * @param dir the directory to clear
330 * @return true if it succeeded
331 */
332 private boolean deleteContents(File dir) {
333 boolean success = true;
334 if(dir.isDirectory()) {
335 // is a directory
336 File[] contents = dir.listFiles();
337 for(int i=0; i < contents.length; i++) {
338 File sub = contents[i];
339 if(sub.isDirectory()) {
340 // lets get recursive
341 success = success & deleteContents(sub);
342 }
343 // it's a file or empty dir
344 success = success & sub.delete();
345 }
346 }
347 else {
348 // not a directory?
349 success=false;
350 }
351 return success;
352 }
353
354 //---ACCESSOR/MUTATOR METHODS---
355
356 //---ATTRIBUTES---
357
358 /**
359 * This is the friendly identifier of the
360 * component this class is running in.
361 * eg, a Filter may be called "filter1",
362 * If this class does not have an owning
363 * component, a name from the configuration
364 * can be placed here. This name could also
365 * be changed to null for utility classes.
366 */
367 private String _name = ClientMain.NAME;
368
369 /**
370 * This holds a reference to the
371 * system logger that is being used.
372 */
373 private Logger _logger = ReferenceManager.getInstance().getLogger();
374
375 //---STATIC ATTRIBUTES---
376
377 /**
378 * A reference to the single instance of this class
379 */
380 private static WebFeeder _instance;
381
382 }