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
22
23 package org.apache.james.management;
24
25 import org.apache.oro.text.regex.MalformedPatternException;
26 import org.apache.oro.text.regex.Pattern;
27 import org.apache.oro.text.regex.Perl5Compiler;
28
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.Map;
32
33 /**
34 * immutual collection of filters used to specify which mail should be processed by SpoolManagement
35 * criterias are:
36 * exact state match
37 * headerValue regular expressions match all related headers
38 */
39 public class SpoolFilter {
40
41 public static final String ERROR_STATE = "error";
42
43 public static final SpoolFilter ERRORMAIL_FILTER = new SpoolFilter(ERROR_STATE);
44
45 private String state = null;
46
47 /**
48 * Map<String headerName, String headerValueRegex>
49 */
50 private final Map headerFilters = new HashMap();
51
52 /**
53 * Map<String headerName, Pattern>
54 */
55 private final Map headerFiltersCompiled = new HashMap();
56
57 /**
58 * Construct the SpoolFilter
59 *
60 * @param state the message state on which message the filter should be used
61 * @param header the headername on which the given regex should be used
62 * @param headerValueRegex the regex to use on the value of the given header
63 */
64 public SpoolFilter(String state, String header, String headerValueRegex) {
65 this.state = state;
66 if (header != null) headerFilters.put(header, headerValueRegex);
67 }
68
69 /**
70 * Construct the SpoolFilter
71 *
72 * @param state the message state on which message the filter should be used
73 */
74 public SpoolFilter(String state) {
75 this.state = state;
76 }
77
78 /**
79 * Construct the SpoolFilter
80 *
81 * @param header the headername on which the given regex should be used
82 * @param headerValueRegex the regex to use on the value of the given header
83 */
84 public SpoolFilter(String header, String headerValueRegex) {
85 this.state = null;
86 if (header != null) headerFilters.put(header, headerValueRegex);
87 }
88
89 /**
90 * Construct the SpoolFilter
91 *
92 * @param state the message state on which message the filter should be used
93 * @param headerFilters a Map which contains filters to use
94 */
95 public SpoolFilter(String state, Map headerFilters) {
96 this.state = state;
97 this.headerFilters.putAll(headerFilters);
98 this.headerFilters.remove(null); // NULL is not acceptable here
99 }
100
101 public boolean doFilter() {
102 return doFilterHeader() || doFilterState();
103 }
104
105 /**
106 * Return true if any state was given on init the SpoolFilter
107 *
108 * @return true if state was given on init. False otherwise
109 */
110 public boolean doFilterState() {
111 return state != null;
112 }
113
114 /**
115 * Return true if any filters should be used on the headers
116 *
117 * @return true if filters should be used. False if not
118 */
119 public boolean doFilterHeader() {
120 return headerFilters.size() > 0;
121 }
122
123 /**
124 * Return the message state on which the filter will be used
125 *
126 * @return state the message state
127 */
128 public String getState() {
129 return state;
130 }
131
132 /**
133 * Return an Iterator which contains all headers which should be filtered
134 *
135 * @return headers an Iterator which contains all headers which should be filtered
136 */
137 public Iterator getHeaders() {
138 return headerFilters.keySet().iterator();
139 }
140
141 /**
142 * Return the regex which should be used on the given header.
143 * Return null if the header not exists in the Map
144 *
145 * @param header the headername for which the regex should be retrieven.
146 * @return regex the regex for the given header
147 */
148 public String getHeaderValueRegex(String header) {
149 return (String) headerFilters.get(header);
150 }
151
152 /**
153 * Return the compiled Pattern for the given header.
154 * Return null if the header not exists in the Map
155 *
156 * @param header the header for which the pattern should be returned
157 * @return pattern the Pattern which was compiled for the given header
158 * @throws SpoolManagementException get thrown if an invalid regex is used with the given header
159 */
160 public Pattern getHeaderValueRegexCompiled(String header) throws SpoolManagementException {
161 Perl5Compiler compiler = new Perl5Compiler();
162
163 // try to reuse cached pattern
164 if (headerFiltersCompiled.get(header) != null) return (Pattern)headerFiltersCompiled.get(header);
165
166 String headerValueRegex = getHeaderValueRegex(header);
167 if (headerValueRegex == null) return null;
168 try {
169 Pattern pattern = compiler.compile(headerValueRegex, Perl5Compiler.READ_ONLY_MASK);
170 headerFiltersCompiled.put(header, pattern); // cache
171 return pattern;
172 } catch (MalformedPatternException e) {
173 throw new SpoolManagementException("failed to compile regular expression", e);
174 }
175 }
176
177 }