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 package org.apache.jsieve.util.check;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.List;
27
28 import javax.mail.MessagingException;
29 import javax.mail.internet.MimeMessage;
30
31 import org.apache.jsieve.ConfigurationManager;
32 import org.apache.jsieve.exception.SieveException;
33 import org.apache.jsieve.mail.ActionFileInto;
34 import org.apache.jsieve.mail.ActionKeep;
35 import org.apache.jsieve.mail.ActionRedirect;
36 import org.apache.jsieve.mail.ActionReject;
37 import org.apache.jsieve.parser.generated.ParseException;
38
39 /**
40 * Checks a <code>sieve</code> script by executing it against a given mail and
41 * reporting the results.
42 */
43 public class ScriptChecker {
44
45 private final ScriptCheckMailAdapter adapter;
46
47 public ScriptChecker() {
48 adapter = new ScriptCheckMailAdapter();
49 }
50
51 /**
52 * Checks the <code>sieve</code> script contained in the given file by
53 * executing it against the given message.
54 *
55 * @param message
56 * <code>File</code> containing the mail message to be fed to
57 * the script, not null
58 * @param script
59 * <code>File</code> containing the script to be checked
60 * @return <code>Results</code> of that execution
61 * @throws IOException
62 * @throws MessageException
63 */
64 public Results check(final File message, final File script)
65 throws IOException, MessagingException {
66 final FileInputStream messageStream = new FileInputStream(message);
67 final FileInputStream scriptStream = new FileInputStream(script);
68 final Results results = check(messageStream, scriptStream);
69 return results;
70 }
71
72 /**
73 * Checks the <code>sieve</code> script contained in the given file by
74 * executing it against the given message.
75 *
76 * @param script
77 * <code>InputStream</code>, not null
78 * @return <code>Results</code> of the check, not null
79 * @throws IOException
80 * @throws MessagingException
81 */
82 public Results check(final InputStream message, final InputStream script)
83 throws IOException, MessagingException {
84 MimeMessage mimeMessage = new MimeMessage(null, message);
85 adapter.setMail(mimeMessage);
86 Results results;
87 try {
88 new ConfigurationManager().build().interpret(adapter, script);
89 final List executedActions = adapter.getExecutedActions();
90 results = new Results(executedActions);
91 } catch (ParseException e) {
92 e.printStackTrace();
93 results = new Results(e);
94 } catch (SieveException e) {
95 e.printStackTrace();
96 results = new Results(e);
97 }
98 return results;
99 }
100
101 /**
102 * Contains results of script execution.
103 */
104 public final static class Results {
105 private final boolean pass;
106
107 private final Exception exception;
108
109 private final List actionsExecuted;
110
111 public Results(final Exception ex) {
112 this.exception = ex;
113 pass = false;
114 actionsExecuted = null;
115 }
116
117 public Results(final List actions) {
118 this.pass = true;
119 exception = null;
120 this.actionsExecuted = actions;
121 }
122
123 /**
124 * Is this a pass?
125 *
126 * @return true if the script executed without error, false if errors
127 * were encountered
128 */
129 public boolean isPass() {
130 return pass;
131 }
132
133 /**
134 * Gets the exception which was thrown during execution.
135 *
136 * @return <code>Exception</code> or null if no exception was thrown
137 */
138 public Exception getException() {
139 return exception;
140 }
141
142 /**
143 * Gets the actions executed by the script.
144 *
145 * @return <code>List</code> of actions or null if the script failed
146 */
147 public List getActionsExecuted() {
148 return actionsExecuted;
149 }
150
151 /**
152 * Is the <code>n<code>'th action a <code>FileInto</code>
153 * with given destination?
154 * @param destination <code>String</code> destination for the file into
155 * @param n index to check
156 * @return true if the <code>n<code>'th action is a <code>FileInto</code>
157 * with given destination
158 */
159 public boolean isActionFileInto(String destination, int n) {
160 boolean result = false;
161 Object action = actionsExecuted.get(n);
162 if (action != null && action instanceof ActionFileInto) {
163 ActionFileInto actionFileInto = (ActionFileInto) action;
164 result = destination.equals(actionFileInto.getDestination());
165 }
166 return result;
167 }
168
169 /**
170 * Is the <code>n<code>'th action a <code>Redirect</code>
171 * with given address?
172 * @param address <code>String</code> redirect address
173 * @param n index to check
174 * @return true if the <code>n<code>'th action is a <code>Redirect</code>
175 * with given redirect address
176 */
177 public boolean isActionRedirect(String address, int n) {
178 boolean result = false;
179 Object action = actionsExecuted.get(n);
180 if (action != null && action instanceof ActionRedirect) {
181 ActionRedirect actionRedirect = (ActionRedirect) action;
182 result = address.equals(actionRedirect.getAddress());
183 }
184 return result;
185 }
186
187 /**
188 * Is the <code>n<code>'th action a <code>Reject</code>
189 * with given message?
190 * @param message <code>String</code> rejection message
191 * @param n index to check
192 * @return true if the <code>n<code>'th action is a <code>Reject</code>
193 * with given reject message
194 */
195 public boolean isActionReject(String message, int n) {
196 boolean result = false;
197 Object action = actionsExecuted.get(n);
198 if (action != null && action instanceof ActionReject) {
199 ActionReject actionReject = (ActionReject) action;
200 result = message.equals(actionReject.getMessage());
201 }
202 return result;
203 }
204
205 /**
206 * Is the <code>n<code>'th action a <code>Keep</code>?
207 * @param n index to check
208 * @return true if the <code>n<code>'th action is a <code>Keep</code>
209 */
210 public boolean isActionKeep(int n) {
211 boolean result = false;
212 Object action = actionsExecuted.get(n);
213 if (action != null && action instanceof ActionKeep) {
214 result = true;
215 }
216 return result;
217 }
218
219 /**
220 * Prints out details of results.
221 */
222 public String toString() {
223 StringBuffer buffer = new StringBuffer("Results: ");
224 if (pass) {
225 buffer.append("PASS");
226 } else {
227 buffer.append("FAIL: ");
228 if (exception != null) {
229 if (exception instanceof ParseException) {
230 buffer.append("Cannot parse script");
231 } else {
232 buffer.append("Cannot excute script");
233 }
234 buffer.append(exception.getMessage());
235 }
236 }
237 return buffer.toString();
238 }
239
240 }
241 }