KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > messenger > audit > spi > AuditorImpl


1 /**
2  * $RCSfile: AuditorImpl.java,v $
3  * $Revision: 1.16 $
4  * $Date: 2005/07/14 18:13:40 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.messenger.audit.spi;
13
14 import org.dom4j.DocumentFactory;
15 import org.dom4j.Element;
16 import org.jivesoftware.messenger.Session;
17 import org.jivesoftware.messenger.audit.AuditManager;
18 import org.jivesoftware.messenger.audit.Auditor;
19 import org.jivesoftware.util.LocaleUtils;
20 import org.jivesoftware.util.Log;
21 import org.xmpp.packet.IQ;
22 import org.xmpp.packet.Message;
23 import org.xmpp.packet.Packet;
24 import org.xmpp.packet.Presence;
25
26 import java.io.*;
27 import java.util.Date JavaDoc;
28 import java.util.Queue JavaDoc;
29 import java.util.Timer JavaDoc;
30 import java.util.TimerTask JavaDoc;
31 import java.util.concurrent.LinkedBlockingQueue JavaDoc;
32
33 public class AuditorImpl implements Auditor {
34
35     private AuditManager auditManager;
36     private File currentAuditFile;
37     private Writer writer;
38     private org.jivesoftware.util.XMLWriter xmlWriter;
39     private int maxSize;
40     private long maxCount;
41     private int logTimeout;
42     private boolean closed = false;
43     /**
44      * Directoty (absolute path) where the audit files will be saved.
45      */

46     private String JavaDoc logDir;
47
48     /**
49      * Queue that holds the audited packets that will be later saved to an XML file.
50      */

51     private Queue JavaDoc<AuditPacket> logQueue = new LinkedBlockingQueue JavaDoc<AuditPacket>();
52
53     /**
54      * Timer to save queued logs to the XML file.
55      */

56     private Timer JavaDoc timer = new Timer JavaDoc("Auditor");
57     private SaveQueuedPacketsTask saveQueuedPacketsTask;
58
59     public AuditorImpl(AuditManager manager) {
60         auditManager = manager;
61     }
62
63     public void audit(Packet packet, Session session) {
64         if (auditManager.isEnabled()) {
65             if (packet instanceof Message) {
66                 if (auditManager.isAuditMessage()) {
67                     writePacket(packet, session);
68                 }
69             }
70             else if (packet instanceof Presence) {
71                 if (auditManager.isAuditPresence()) {
72                     writePacket(packet, session);
73                 }
74             }
75             else if (packet instanceof IQ) {
76                 if (auditManager.isAuditIQ()) {
77                     writePacket(packet, session);
78                 }
79             }
80         }
81     }
82
83     public void stop() {
84         // Stop the scheduled task for saving queued packets to the XML file
85
timer.cancel();
86         // Save all remaining queued packets to the XML file
87
saveQueuedPackets();
88         close();
89     }
90
91     private void close() {
92         if (xmlWriter != null) {
93             try {
94                 xmlWriter.flush();
95                 writer.write("</jive>");
96                 xmlWriter.close();
97                 writer = null;
98             }
99             catch (Exception JavaDoc e) {
100                 Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
101             }
102         }
103     }
104
105     private void writePacket(Packet packet, Session session) {
106         if (!closed) {
107             // Add to the logging queue this new entry that will be saved later
108
logQueue.add(new AuditPacket(packet.createCopy(), session));
109         }
110     }
111
112     private void prepareAuditFile() throws IOException {
113         if (currentAuditFile == null || currentAuditFile.length() > maxSize) {
114             rotateFiles();
115         }
116     }
117
118     protected void setMaxValues(int size, int count) {
119         maxSize = size * 1024*1024;
120         maxCount = count;
121     }
122
123     public void setLogTimeout(int newTimeout) {
124         // Cancel any existing task because the timeout has changed
125
if (saveQueuedPacketsTask != null) {
126             saveQueuedPacketsTask.cancel();
127         }
128         this.logTimeout = newTimeout;
129         // Create a new task and schedule it with the new timeout
130
saveQueuedPacketsTask = new SaveQueuedPacketsTask();
131         timer.schedule(saveQueuedPacketsTask, logTimeout, logTimeout);
132
133     }
134
135     public void setLogDir(String JavaDoc logDir) {
136         this.logDir = logDir;
137     }
138
139     public int getQueuedPacketsNumber() {
140         return logQueue.size();
141     }
142
143     private void rotateFiles() throws IOException {
144         close();
145         int i;
146         // Find the next available log file name
147
for (i = 0; maxCount < 1 || i < maxCount; i++) {
148             currentAuditFile = new File(logDir, "jive.audit-" + i + ".log");
149             if (!currentAuditFile.exists()) {
150                 break;
151             }
152         }
153         // Two edge cases, i == 0 (no log files exist) and i == MAX_FILE_COUNT
154
// If i == 0 then the loop above has already set currentAuditFile to
155
// the correct file name, so we only need to setup a file name if i != 0
156
if (i != 0) {
157             if (i == maxCount) {
158                 // We need to delete the last in the series to make room for the next file
159
// the currentAuditFile should be pointing at the last legitimate
160
// file name in the series (i < MAX_FILE_COUNT) so we just delete it
161
// so the previous file can be rotated to it
162
currentAuditFile.delete();
163             }
164             // Rotate the files
165
for (i--; i >= 0; i--) {
166                 String JavaDoc previousName = "jive.audit-" + i + ".log";
167                 File previousFile = new File(logDir, previousName);
168                 previousFile.renameTo(currentAuditFile);
169                 currentAuditFile = new File(logDir, previousName);
170             }
171         }
172
173         writer = new OutputStreamWriter(new FileOutputStream(currentAuditFile), "UTF-8");
174         writer.write("<jive xmlns=\"http://www.jivesoftware.org\">");
175         xmlWriter = new org.jivesoftware.util.XMLWriter(writer);
176     }
177
178     /**
179      * Saves the queued entries to an XML file.
180      */

181     private class SaveQueuedPacketsTask extends TimerTask JavaDoc {
182         public void run() {
183             try {
184                 saveQueuedPackets();
185             }
186             catch (Throwable JavaDoc e) {
187                 Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
188             }
189         }
190     }
191
192     private void saveQueuedPackets() {
193         int batchSize = logQueue.size();
194         for (int index = 0; index < batchSize; index++) {
195             AuditPacket auditPacket = logQueue.poll();
196             if (auditPacket != null) {
197                 try {
198                     prepareAuditFile();
199                     xmlWriter.write(auditPacket.getElement());
200                 }
201                 catch (IOException e) {
202                     Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
203                     // Add again the entry to the queue to save it later
204
logQueue.add(auditPacket);
205                 }
206             }
207         }
208         try {
209             if (xmlWriter != null) {
210                 xmlWriter.flush();
211             }
212         }
213         catch (IOException ioe) {
214
215         }
216     }
217
218     /**
219      * Wrapper on a Packet with information about the packet's status at the moment
220      * when the message was queued.<p>
221      *
222      * The idea is to wrap every packet that is needed to be audited and then add the
223      * wrapper to a queue that will be later processed (i.e. saved to the XML file).
224      */

225     private static class AuditPacket {
226
227         private static DocumentFactory docFactory = DocumentFactory.getInstance();
228
229         private Element element;
230
231         public AuditPacket(Packet packet, Session session) {
232             element = docFactory.createElement("packet", "http://www.jivesoftware.org");
233             if (session.getStreamID() != null) {
234                 element.addAttribute("streamID", session.getStreamID().toString());
235             }
236             switch (session.getStatus()) {
237                 case Session.STATUS_AUTHENTICATED:
238                     element.addAttribute("status", "auth");
239                     break;
240                 case Session.STATUS_CLOSED:
241                     element.addAttribute("status", "closed");
242                     break;
243                 case Session.STATUS_CONNECTED:
244                     element.addAttribute("status", "connected");
245                     // This is a workaround. Since we don't want to have an incorrect FROM attribute
246
// value we need to clean up the FROM attribute. The FROM attribute will contain
247
// an incorrect value since we are setting a fake JID until the user actually
248
// authenticates with the server.
249
packet.setFrom((String JavaDoc) null);
250                     break;
251                 case Session.STATUS_STREAMING:
252                     element.addAttribute("status", "stream");
253                     break;
254                 default:
255                     element.addAttribute("status", "unknown");
256                     break;
257             }
258             element.addAttribute("timestamp", new Date JavaDoc().toString());
259             element.add(packet.getElement());
260         }
261
262         /**
263          * Returns the Element associated with this audit packet.
264          *
265          * @return the Element.
266          */

267         public Element getElement() {
268             return element;
269         }
270     }
271 }
Popular Tags