1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.apache.james.management.impl;
24
25 import org.apache.avalon.cornerstone.services.store.Store;
26 import org.apache.avalon.framework.configuration.DefaultConfiguration;
27 import org.apache.avalon.framework.container.ContainerUtil;
28 import org.apache.avalon.framework.service.ServiceException;
29 import org.apache.avalon.framework.service.ServiceManager;
30 import org.apache.avalon.framework.service.Serviceable;
31 import org.apache.james.management.SpoolFilter;
32 import org.apache.james.management.SpoolManagementException;
33 import org.apache.james.management.SpoolManagementMBean;
34 import org.apache.james.management.SpoolManagementService;
35 import org.apache.james.services.SpoolRepository;
36 import org.apache.mailet.Mail;
37 import org.apache.mailet.MailAddress;
38 import org.apache.oro.text.regex.Pattern;
39 import org.apache.oro.text.regex.Perl5Matcher;
40
41 import javax.mail.MessagingException;
42 import javax.mail.Address;
43 import javax.mail.internet.MimeMessage;
44 import java.util.ArrayList;
45 import java.util.Collection;
46 import java.util.Date;
47 import java.util.Iterator;
48 import java.util.List;
49
50
51
52
53 public class SpoolManagement implements Serviceable, SpoolManagementService, SpoolManagementMBean {
54
55 private Store mailStore;
56
57
58
59
60
61
62 public void setStore(Store mailStore) {
63 this.mailStore = mailStore;
64 }
65
66
67
68
69 public void service(ServiceManager serviceManager) throws ServiceException {
70 Store mailStore = (Store)serviceManager.lookup(Store.ROLE);
71 setStore(mailStore);
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86 public int moveSpoolItems(String srcSpoolRepositoryURL, String srcState, String dstSpoolRepositoryURL, String dstState, String header, String headerValueRegex)
87 throws SpoolManagementException {
88 SpoolFilter filter = new SpoolFilter(srcState, header, headerValueRegex);
89 try {
90 return moveSpoolItems(srcSpoolRepositoryURL, dstSpoolRepositoryURL, dstState, filter);
91 } catch (Exception e) {
92 throw new SpoolManagementException(e);
93 }
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108 public int moveSpoolItems(String srcSpoolRepositoryURL, String dstSpoolRepositoryURL, String dstState, SpoolFilter filter)
109 throws MessagingException, SpoolManagementException {
110
111 SpoolRepository srcSpoolRepository;
112 SpoolRepository dstSpoolRepository;
113 srcSpoolRepository = getSpoolRepository(srcSpoolRepositoryURL);
114 dstSpoolRepository = getSpoolRepository(dstSpoolRepositoryURL);
115
116
117 Iterator spoolR = srcSpoolRepository.list();
118
119 int count = 0;
120 while (spoolR.hasNext()) {
121 String key = spoolR.next().toString();
122 boolean locked = false;
123 try {
124 locked = srcSpoolRepository.lock(key);
125 } catch (MessagingException e) {
126
127 }
128 if (locked) {
129 Mail m = null;
130 try {
131 m = srcSpoolRepository.retrieve(key);
132 if (filterMatches(m, filter)) {
133 if (dstState != null) {
134 m.setState(dstState);
135 }
136 dstSpoolRepository.store(m);
137 srcSpoolRepository.remove(m);
138 count++;
139 }
140 } catch (MessagingException e) {
141
142 } finally {
143 try {
144 srcSpoolRepository.unlock(key);
145 } catch (MessagingException e) {
146
147 }
148 ContainerUtil.dispose(m);
149 }
150 }
151 }
152
153 return count;
154
155 }
156
157
158
159
160
161
162
163
164
165
166
167 public String[] listSpoolItems(String spoolRepositoryURL, String state, String header, String headerValueRegex)
168 throws SpoolManagementException {
169 return listSpoolItems(spoolRepositoryURL, new SpoolFilter(state, header, headerValueRegex));
170 }
171
172
173
174
175
176
177
178
179
180 public String[] listSpoolItems(String spoolRepositoryURL, SpoolFilter filter) throws SpoolManagementException {
181 List spoolItems;
182 try {
183 spoolItems = getSpoolItems(spoolRepositoryURL, filter);
184 } catch (Exception e) {
185 throw new SpoolManagementException(e);
186 }
187 return (String[]) spoolItems.toArray(new String[]{});
188 }
189
190
191
192
193
194
195
196
197
198 protected boolean filterMatches(Mail mail, SpoolFilter filter) throws SpoolManagementException {
199 if (filter == null || !filter.doFilter()) return true;
200
201 if (filter.doFilterState() && !mail.getState().equalsIgnoreCase(filter.getState())) return false;
202
203 if (filter.doFilterHeader()) {
204
205 Perl5Matcher matcher = new Perl5Matcher();
206
207
208 Iterator headers = filter.getHeaders();
209 while (headers.hasNext()) {
210 String header = (String) headers.next();
211
212 String[] headerValues;
213 try {
214 headerValues = mail.getMessage().getHeader(header);
215 if (headerValues == null) {
216
217 if (header.equalsIgnoreCase("to")) {
218 headerValues = addressesToStrings(mail.getMessage().getRecipients(MimeMessage.RecipientType.TO));
219 }
220 else if (header.equalsIgnoreCase("cc")) {
221 headerValues = addressesToStrings(mail.getMessage().getRecipients(MimeMessage.RecipientType.CC));
222 }
223 else if (header.equalsIgnoreCase("bcc")) {
224 headerValues = addressesToStrings(mail.getMessage().getRecipients(MimeMessage.RecipientType.BCC));
225 }
226 else if (header.equalsIgnoreCase("from")) {
227 headerValues = new String[]{mail.getMessage().getSender().toString()};
228 }
229 }
230 } catch (MessagingException e) {
231 throw new SpoolManagementException("could not filter mail by headers", e);
232 }
233 if (headerValues == null) return false;
234
235 Pattern pattern = filter.getHeaderValueRegexCompiled(header);
236
237
238 boolean matched = false;
239 for (int i = 0; i < headerValues.length; i++) {
240 String headerValue = headerValues[i];
241 if (matcher.matches(headerValue, pattern)) {
242 matched = true;
243 break;
244 }
245 }
246 if (!matched) return false;
247 }
248 }
249
250 return true;
251 }
252
253 private String[] addressesToStrings(Address[] addresses) {
254 if (addresses == null) return null;
255 if (addresses.length == 0) return new String[]{};
256 String[] addressStrings = new String[addresses.length];
257 for (int i = 0; i < addresses.length; i++) {
258 addressStrings[i] = addresses[i].toString();
259 }
260 return addressStrings;
261 }
262
263
264
265
266 public List getSpoolItems(String spoolRepositoryURL, SpoolFilter filter)
267 throws MessagingException, SpoolManagementException {
268 SpoolRepository spoolRepository = getSpoolRepository(spoolRepositoryURL);
269
270 List items = new ArrayList();
271
272
273 Iterator spoolR = spoolRepository.list();
274 while (spoolR.hasNext()) {
275 String key = spoolR.next().toString();
276 Mail m = spoolRepository.retrieve(key);
277
278 if (filterMatches(m, filter)) {
279 StringBuffer itemInfo = new StringBuffer();
280 itemInfo.append("key: ").append(key).append(" sender: ").append(m.getSender()).append(" recipient:");
281 Collection recipients = m.getRecipients();
282 for (Iterator iterator = recipients.iterator(); iterator.hasNext();) {
283 MailAddress mailAddress = (MailAddress) iterator.next();
284 itemInfo.append(" ").append(mailAddress);
285 }
286 items.add(itemInfo.toString());
287 }
288 }
289
290 return items;
291 }
292
293
294
295
296 public int removeSpoolItems(String spoolRepositoryURL, String key, String state, String header, String headerValueRegex)
297 throws SpoolManagementException {
298 return removeSpoolItems(spoolRepositoryURL, key, new SpoolFilter(state, header, headerValueRegex));
299 }
300
301
302
303
304
305
306
307
308
309
310 public int removeSpoolItems(String spoolRepositoryURL, String key, SpoolFilter filter) throws SpoolManagementException {
311 try {
312 return removeSpoolItems(spoolRepositoryURL, key, null, filter);
313 } catch (Exception e) {
314 throw new SpoolManagementException(e);
315 }
316 }
317
318
319
320
321
322 public int removeSpoolItems(String spoolRepositoryURL, String key, List lockingFailures, SpoolFilter filter) throws SpoolManagementException, MessagingException, SpoolManagementException {
323 int count = 0;
324 SpoolRepository spoolRepository = getSpoolRepository(spoolRepositoryURL);
325
326 if (key != null) {
327 count = removeMail(spoolRepository, key, count, lockingFailures, null);
328 } else {
329 Iterator spoolR = spoolRepository.list();
330
331 while (spoolR.hasNext()) {
332 key = (String)spoolR.next();
333 count = removeMail(spoolRepository, key, count, lockingFailures, filter);
334 }
335 }
336 return count;
337 }
338
339 private int removeMail(SpoolRepository spoolRepository, String key, int count, List lockingFailures, SpoolFilter filter) throws MessagingException {
340 try {
341 if (removeMail(spoolRepository, key, filter)) count++;
342 } catch (IllegalStateException e) {
343 lockingFailures.add(key);
344 } catch (SpoolManagementException e) {
345 return count;
346 }
347 return count;
348 }
349
350
351
352
353
354
355
356
357
358
359 public int resendSpoolItems(String spoolRepositoryURL, String key, SpoolFilter filter) throws SpoolManagementException {
360 try {
361 return resendSpoolItems(spoolRepositoryURL, key, null, filter);
362 } catch (Exception e) {
363 throw new SpoolManagementException(e);
364 }
365 }
366
367
368
369
370
371
372
373
374
375
376
377 public int resendSpoolItems(String spoolRepositoryURL, String key, String state, String header, String headerValueRegex) throws SpoolManagementException {
378 return resendSpoolItems(spoolRepositoryURL, key, new SpoolFilter(state, header, headerValueRegex));
379 }
380
381
382
383
384
385 public int resendSpoolItems(String spoolRepositoryURL, String key, List lockingFailures, SpoolFilter filter)
386 throws MessagingException, SpoolManagementException {
387 int count = 0;
388 SpoolRepository spoolRepository = getSpoolRepository(spoolRepositoryURL);
389
390
391 if (key != null) {
392 try {
393 if (resendMail(spoolRepository, key, filter)) count++;
394 } catch (IllegalStateException e) {
395 if (lockingFailures != null) lockingFailures.add(key);
396 }
397 } else {
398
399 Iterator spoolR = spoolRepository.list();
400
401 while (spoolR.hasNext()) {
402 key = spoolR.next().toString();
403 try {
404 if (resendMail(spoolRepository, key, filter)) count++;
405 } catch (IllegalStateException e) {
406 if (lockingFailures != null) lockingFailures.add(key);
407 }
408 }
409 }
410 return count;
411 }
412
413
414
415
416
417
418
419
420
421
422 private boolean resendMail(SpoolRepository spoolRepository, String key, SpoolFilter filter)
423 throws MessagingException, IllegalStateException, SpoolManagementException {
424 if (!spoolRepository.lock(key)) throw new IllegalStateException("locking failure");
425
426
427 Mail m = spoolRepository.retrieve(key);
428
429 if (filterMatches(m, filter)) {
430
431
432 m.setLastUpdated(new Date(0));
433
434
435 spoolRepository.store(m);
436 spoolRepository.unlock(key);
437
438 synchronized (spoolRepository) {
439 spoolRepository.notify();
440 }
441 return true;
442 } else {
443 spoolRepository.unlock(key);
444 return false;
445 }
446 }
447
448
449
450
451
452
453
454
455
456
457 private boolean removeMail(SpoolRepository spoolRepository, String key, SpoolFilter filter)
458 throws MessagingException, SpoolManagementException {
459 if (!spoolRepository.lock(key)) throw new IllegalStateException("locking failure");
460
461 Mail m = spoolRepository.retrieve(key);
462 if (m == null) throw new SpoolManagementException("mail not available having key " + key);
463 if (!filterMatches(m, filter)) return false;
464 ContainerUtil.dispose(m);
465 spoolRepository.remove(key);
466 return true;
467 }
468
469
470
471
472
473
474
475
476 private SpoolRepository getSpoolRepository(String url)
477 throws SpoolManagementException {
478
479 DefaultConfiguration spoolConf = new DefaultConfiguration("spool",
480 "generated:RemoteManager.java");
481 spoolConf.setAttribute("destinationURL", url);
482 spoolConf.setAttribute("type", "SPOOL");
483
484 try {
485 return (SpoolRepository) mailStore.select(spoolConf);
486 } catch (ServiceException e) {
487 throw new SpoolManagementException("Exception while looking up for the repository", e);
488 }
489 }
490
491
492 }