1 /*****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20
21 package org.apache.james.postage.result;
22
23 import org.apache.commons.collections.map.HashedMap;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.OutputStreamWriter;
30 import java.io.File;
31 import java.util.ArrayList;
32 import java.util.Date;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.LinkedHashMap;
37
38 public class PostageRunnerResultImpl implements PostageRunnerResult {
39
40 private static Log log = LogFactory.getLog(PostageRunnerResultImpl.class);
41
42 private Map m_matchedMailResults = initMatchedMailResultContainer();
43
44 private final Map m_unmatchedMailResults = new HashedMap();
45
46 private List m_errors = initErrorResultContainer();
47
48 private List m_jvmStatistics = initMatchedJVMStatisticsResultContainer();
49
50 private long m_TimestampFirstResult = -1;
51
52 private long m_TimestampLastResult = -1;
53
54 private long m_matchedMailCounter = 0;
55
56 private long m_validMailCounter = 0;
57
58 private Map m_environmentInfo = new LinkedHashMap();
59
60 public void addNewMailRecord(MailProcessingRecord mailProcessingRecord) {
61
62 if (m_TimestampFirstResult <= 0) m_TimestampFirstResult = System.currentTimeMillis();
63 m_TimestampLastResult = System.currentTimeMillis();
64
65 MailProcessingRecord prevMailProcessingRecord = (MailProcessingRecord)m_unmatchedMailResults.put(mailProcessingRecord.getMailId(), mailProcessingRecord);
66 if (prevMailProcessingRecord != null) {
67 log.error("mail result already contained in unmatched list!");
68 }
69 }
70
71 public synchronized MailProcessingRecord matchMailRecord(MailProcessingRecord mailProcessingRecord) {
72 if (mailProcessingRecord == null) return null;
73 String mailId = mailProcessingRecord.getMailId();
74 if (mailId == null) return null;
75
76 if (m_unmatchedMailResults.containsKey(mailId)) {
77
78 MailProcessingRecord match = (MailProcessingRecord)m_unmatchedMailResults.remove(mailId);
79 log.info("matched test mail having id = " + mailId + " received by queue = " + mailProcessingRecord.getReceivingQueue());
80
81 match.merge(mailProcessingRecord);
82
83 m_matchedMailResults.put(mailId, match);
84 m_matchedMailCounter++;
85 return match;
86 } else if (m_matchedMailResults.containsKey(mailId)) {
87 log.warn("mail already matched for mailId = " + mailId);
88 } else {
89 log.warn("mail match candidate has unknown (purged?) mailId = " + mailId);
90 }
91
92 return null;
93 }
94
95 public void recordValidatedMatch(MailProcessingRecord matchedAndMergedRecord) {
96 if (!m_matchedMailResults.values().contains(matchedAndMergedRecord)) {
97 log.error("cannot record validation result for (already written?) result having id "
98 + matchedAndMergedRecord.getMailId());
99 return;
100 }
101
102 if (matchedAndMergedRecord.isReceivedValid()) m_validMailCounter++;
103 }
104
105 public void addJVMResult(JVMResourcesRecord jvmResourcesRecord) {
106 m_jvmStatistics.add(jvmResourcesRecord);
107 }
108
109 public void setEnvironmentDescription(Map descriptionItems) {
110 m_environmentInfo.putAll(descriptionItems);
111 }
112
113 public long getUnmatchedMails() {
114 return m_unmatchedMailResults.size();
115 }
116
117 public long getMatchedMails() {
118 return m_matchedMailCounter;
119 }
120
121 public long getValidMails() {
122 return m_validMailCounter;
123 }
124
125 public void writeMailResults(OutputStreamWriter outputStreamWriter, boolean flushOnlyMatched) throws IOException {
126 writeMatchedMailResults(outputStreamWriter);
127 if (!flushOnlyMatched) {
128 writeUnmatchedMailResults(outputStreamWriter);
129 writeGeneralData(outputStreamWriter);
130 }
131 }
132
133 private void writeUnmatchedMailResults(OutputStreamWriter outputStreamWriter) throws IOException {
134 writeMailResults(m_unmatchedMailResults, outputStreamWriter);
135 outputStreamWriter.flush();
136 }
137
138 private void writeMatchedMailResults(OutputStreamWriter outputStreamWriter) throws IOException {
139 Map writeResults = m_matchedMailResults;
140 m_matchedMailResults = initMatchedMailResultContainer();
141 writeMailResults(writeResults, outputStreamWriter);
142 outputStreamWriter.flush();
143 }
144
145 private void writeGeneralData(OutputStreamWriter outputStreamWriter) throws IOException {
146 outputStreamWriter.write("start," + m_TimestampFirstResult + "," + new Date(m_TimestampFirstResult) + "\r\n");
147 outputStreamWriter.write("end," + m_TimestampLastResult + "," + new Date(m_TimestampLastResult) + "\r\n");
148 outputStreamWriter.write("current," + System.currentTimeMillis() + "," + new Date() + "\r\n");
149
150 Iterator iterator = m_environmentInfo.keySet().iterator();
151 while (iterator.hasNext()) {
152 String elementName = (String)iterator.next();
153 String elementValue = (String)m_environmentInfo.get(elementName);
154 outputStreamWriter.write(elementName + "," + elementValue + "\r\n");
155 }
156 }
157
158 public long getTimestampFirstResult() {
159 return m_TimestampFirstResult;
160 }
161
162 public long getTimestampLastResult() {
163 return m_TimestampLastResult;
164 }
165
166 public void addError(int errorNumber, String errorMessage) {
167 m_errors.add(new ErrorRecord(errorNumber, errorMessage));
168 }
169
170 public long getErrorCount() {
171 return m_errors.size();
172 }
173
174 private void writeMailResults(Map mailResults, OutputStreamWriter outputStreamWriter) throws IOException {
175 Iterator iterator = mailResults.values().iterator();
176 while (iterator.hasNext()) {
177 MailProcessingRecord record = (MailProcessingRecord)iterator.next();
178 String resultString = record.writeData().toString();
179 outputStreamWriter.write(resultString);
180 }
181 }
182
183 private HashedMap initMatchedMailResultContainer() {
184 return new HashedMap();
185 }
186
187 private List initMatchedJVMStatisticsResultContainer() {
188 return new ArrayList();
189 }
190
191 private List initErrorResultContainer() {
192 return new ArrayList();
193 }
194
195 public void writeResults(String filenameMailResults, String filenameJVMStatistics, String filenameErrors, boolean flushMatchedMailOnly) {
196 if (filenameMailResults != null) writeMailResults(filenameMailResults, flushMatchedMailOnly);
197 if (filenameJVMStatistics != null) writeJVMStatistics(filenameJVMStatistics);
198 if (filenameErrors != null) writeErrors(filenameErrors);
199 }
200
201 public void writeMailResults(String filenameMailResults, boolean flushMatchedMailOnly) {
202 FileOutputStream outputStream = null;
203 OutputStreamWriter outputStreamWriter = null;
204 try {
205 outputStream = new FileOutputStream(filenameMailResults, true);
206 outputStreamWriter = new OutputStreamWriter(outputStream);
207 if (new File(filenameMailResults).length() <= 0) outputStreamWriter.write(MailProcessingRecord.writeHeader().toString());
208 writeMailResults(outputStreamWriter, flushMatchedMailOnly);
209 } catch (IOException e) {
210 log.error("error writing mail results to file " + filenameMailResults, e);
211 } finally {
212 try {
213 if (outputStreamWriter != null) outputStreamWriter.close();
214 if (outputStream != null) outputStream.close();
215 log.info("postage mail results completely written to file " + filenameMailResults);
216 } catch (IOException e) {
217 log.error("error closing stream", e);
218 }
219 }
220 }
221
222 public void writeJVMStatistics(String filenameJVMStatistics) {
223 FileOutputStream outputStream = null;
224 OutputStreamWriter outputStreamWriter = null;
225 try {
226 outputStream = new FileOutputStream(filenameJVMStatistics, true);
227 outputStreamWriter = new OutputStreamWriter(outputStream);
228 if (new File(filenameJVMStatistics).length() <= 0) outputStreamWriter.write(JVMResourcesRecord.writeHeader().toString());
229 writeJVMStatisticsResults(outputStreamWriter);
230 } catch (IOException e) {
231 log.error("error writing JVM statistic results to file " + filenameJVMStatistics, e);
232 } finally {
233 try {
234 if (outputStreamWriter != null) outputStreamWriter.close();
235 if (outputStream != null) outputStream.close();
236 log.info("postage JVM statistic results completely written to file " + filenameJVMStatistics);
237 } catch (IOException e) {
238 log.error("error closing stream", e);
239 }
240 }
241 }
242
243 private void writeJVMStatisticsResults(OutputStreamWriter outputStreamWriter) throws IOException {
244 List unwrittenResults = m_jvmStatistics;
245 m_jvmStatistics = initMatchedJVMStatisticsResultContainer();
246 Iterator iterator = unwrittenResults.iterator();
247 while (iterator.hasNext()) {
248 JVMResourcesRecord record = (JVMResourcesRecord)iterator.next();
249 String resultString = record.writeData().toString();
250 outputStreamWriter.write(resultString);
251 }
252 }
253
254 public void writeErrors(String filenameErrors) {
255 FileOutputStream outputStream = null;
256 OutputStreamWriter outputStreamWriter = null;
257 try {
258 outputStream = new FileOutputStream(filenameErrors, true);
259 outputStreamWriter = new OutputStreamWriter(outputStream);
260
261 if (new File(filenameErrors).length() <= 0) {
262 outputStreamWriter.write("timestamp,number,message\r\n");
263 }
264
265 List unwrittenResults = m_errors;
266 m_errors = initErrorResultContainer();
267 Iterator iterator = unwrittenResults.iterator();
268 while (iterator.hasNext()) {
269 ErrorRecord record = (ErrorRecord)iterator.next();
270
271 StringBuffer resultString = new StringBuffer();
272 resultString.append(record.m_timestamp).append(",");
273 resultString.append(record.m_number).append(",");
274 resultString.append(record.m_message).append(",");
275 resultString.append("\r\n");
276
277 outputStreamWriter.write(resultString.toString());
278 }
279 } catch (IOException e) {
280 log.error("error writing JVM statistic results to file " + filenameErrors, e);
281 } finally {
282 try {
283 if (outputStreamWriter != null) outputStreamWriter.close();
284 if (outputStream != null) outputStream.close();
285 log.info("postage JVM statistic results completely written to file " + filenameErrors);
286 } catch (IOException e) {
287 log.error("error closing stream", e);
288 }
289 }
290 }
291
292 }
293
294 class ErrorRecord {
295 long m_timestamp = -1;
296 int m_number = -1;
297 String m_message = null;
298
299 public ErrorRecord(int m_number, String m_message) {
300 this.m_timestamp = System.currentTimeMillis();
301 this.m_number = m_number;
302 this.m_message = m_message;
303 }
304 }