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 package org.apache.james.transport.matchers;
23
24 import org.apache.mailet.base.GenericMatcher;
25 import org.apache.mailet.Mail;
26
27 import javax.mail.MessagingException;
28 import javax.mail.internet.MimeMessage;
29
30 import java.lang.NumberFormatException;
31
32 import java.util.Collection;
33 import java.util.StringTokenizer;
34
35 /**
36 * <P>Matches mails containing a header with a numeric value whose comparison with the specified value is true.
37 * If the header is missing in the message, there will be <I>no match</I></P>
38 * <P>Configuration string: The headerName, a comparison operator and the numeric headerValue
39 * to compare with, <I>space or tab delimited</I>.</P>
40 * <P>The comparison operators are: <CODE><, <=, ==, >=, ></CODE>;
41 * another set of operators is: <CODE>LT, LE, EQ, GE, GT</CODE>.
42 * Also the following operators are accepted: <CODE>=<, =, =></CODE>.</P>
43 * <P>Example:</P>
44 * <PRE><CODE>
45 * <mailet match="CompareNumericHeaderValue=X-MessageIsSpamProbability > 0.9" class="ToProcessor">
46 * <processor> spam </processor>
47 * </mailet>
48 * </CODE></PRE>
49 *
50 * @version CVS $Revision: 713949 $ $Date: 2008-11-14 07:40:21 +0000 (Fri, 14 Nov 2008) $
51 * @since 2.2.0
52 */
53 public class CompareNumericHeaderValue extends GenericMatcher {
54
55 private String headerName = null;
56
57 private int comparisonOperator;
58 private final static int LT = -2;
59 private final static int LE = -1;
60 private final static int EQ = 0;
61 private final static int GE = +1;
62 private final static int GT = +2;
63
64 private Double headerValue;
65
66 /**
67 * @see org.apache.mailet.GenericMatcher#init()
68 */
69 public void init() throws MessagingException {
70 StringTokenizer st = new StringTokenizer(getCondition(), " \t", false);
71 if (st.hasMoreTokens()) {
72 headerName = st.nextToken().trim();
73 }
74 else {
75 throw new MessagingException("Missing headerName");
76 }
77 if (st.hasMoreTokens()) {
78 String comparisonOperatorString = st.nextToken().trim();
79 if (comparisonOperatorString.equals("<")
80 || comparisonOperatorString.equals("LT")) {
81 comparisonOperator = LT;
82 }
83 else if (comparisonOperatorString.equals("<=")
84 || comparisonOperatorString.equals("=<")
85 || comparisonOperatorString.equals("LE")) {
86 comparisonOperator = LE;
87 }
88 else if (comparisonOperatorString.equals("==")
89 || comparisonOperatorString.equals("=")
90 || comparisonOperatorString.equals("EQ")) {
91 comparisonOperator = EQ;
92 }
93 else if (comparisonOperatorString.equals(">=")
94 || comparisonOperatorString.equals("=>")
95 || comparisonOperatorString.equals("GE")) {
96 comparisonOperator = GE;
97 }
98 else if (comparisonOperatorString.equals(">")
99 || comparisonOperatorString.equals("GT")) {
100 comparisonOperator = GT;
101 }
102 else {
103 throw new MessagingException("Bad comparisonOperator: \"" + comparisonOperatorString + "\"");
104 }
105 }
106 else {
107 throw new MessagingException("Missing comparisonOperator");
108 }
109 if (st.hasMoreTokens()) {
110 String headerValueString = st.nextToken().trim();
111 try {
112 headerValue = Double.valueOf(headerValueString);
113 }
114 catch (NumberFormatException nfe) {
115 throw new MessagingException("Bad header comparison value: \""
116 + headerValueString + "\"", nfe);
117 }
118 }
119 else {
120 throw new MessagingException("Missing headerValue threshold");
121 }
122 }
123
124 /**
125 * @see org.apache.mailet.GenericMatcher#match(Mail)
126 */
127 public Collection match(Mail mail) throws MessagingException {
128 if (headerName == null) {
129 // should never get here
130 throw new IllegalStateException("Null headerName");
131 }
132
133 MimeMessage message = (MimeMessage) mail.getMessage();
134
135 String [] headerArray = message.getHeader(headerName);
136 if (headerArray != null && headerArray.length > 0) {
137 try {
138 int comparison = Double.valueOf(headerArray[0].trim()).compareTo(headerValue);
139 switch (comparisonOperator) {
140 case LT:
141 if (comparison < 0) {
142 return mail.getRecipients();
143 }
144 break;
145 case LE:
146 if (comparison <= 0) {
147 return mail.getRecipients();
148 }
149 break;
150 case EQ:
151 if (comparison == 0) {
152 return mail.getRecipients();
153 }
154 break;
155 case GE:
156 if (comparison >= 0) {
157 return mail.getRecipients();
158 }
159 break;
160 case GT:
161 if (comparison > 0) {
162 return mail.getRecipients();
163 }
164 break;
165 default:
166 // should never get here
167 throw new IllegalStateException("Unknown comparisonOperator" + comparisonOperator);
168 }
169 }
170 catch (NumberFormatException nfe) {
171 throw new MessagingException("Bad header value found in message: \"" + headerArray[0] + "\"", nfe);
172 }
173 }
174
175 return null;
176 }
177 }