001: // Copyright © 2006-2007 ASERT. Released under the Canoo Webtest license.
002: package com.canoo.webtest.plugins.emailtest;
003:
004: import java.util.ArrayList;
005: import java.util.List;
006: import java.util.StringTokenizer;
007:
008: import javax.mail.Address;
009: import javax.mail.Folder;
010: import javax.mail.Message;
011: import javax.mail.MessagingException;
012: import javax.mail.internet.MimeMessage;
013:
014: import org.apache.commons.lang.StringUtils;
015:
016: /**
017: * Abstract class used by email steps needing to select one or more messages.
018: *
019: * @author Paul King
020: */
021: public abstract class AbstractSelectStep extends AbstractStoreStep {
022: private String fSubject;
023: private String fFrom;
024: private String fTo;
025: private String fCc;
026: private String fReplyTo;
027:
028: /**
029: * Sets the Subject field.
030: *
031: * @param value The Subject field
032: * @webtest.parameter required="no"
033: * description="The email Subject header field."
034: */
035: public void setSubject(final String value) {
036: fSubject = value;
037: }
038:
039: public String getSubject() {
040: return fSubject;
041: }
042:
043: /**
044: * Sets the From field.
045: *
046: * @param value The From field
047: * @webtest.parameter required="no"
048: * description="The email From header field."
049: */
050: public void setFrom(final String value) {
051: fFrom = value;
052: }
053:
054: public String getFrom() {
055: return fFrom;
056: }
057:
058: /**
059: * Sets the To field.
060: *
061: * @param value The To field
062: * @webtest.parameter required="no"
063: * description="The email To header field."
064: */
065: public void setTo(final String value) {
066: fTo = value;
067: }
068:
069: public String getTo() {
070: return fTo;
071: }
072:
073: /**
074: * Sets the Cc field.
075: *
076: * @param value The Cc field
077: * @webtest.parameter required="no"
078: * description="The email Cc header field."
079: */
080: public void setCc(final String value) {
081: fCc = value;
082: }
083:
084: public String getCc() {
085: return fCc;
086: }
087:
088: /**
089: * Sets the ReplyTo field.
090: *
091: * @param value The ReplyTo field
092: * @webtest.parameter required="no"
093: * description="The email ReplyTo header field."
094: */
095: public void setReplyTo(final String value) {
096: fReplyTo = value;
097: }
098:
099: public String getReplyTo() {
100: return fReplyTo;
101: }
102:
103: protected Message[] retrieveMatchingMessages(final Folder folder)
104: throws MessagingException {
105: final Message[] messages = getHelper().getMessages(folder);
106: // For efficiency
107: if (noMatchCriteria()) {
108: return messages;
109: }
110: final List result = new ArrayList();
111: for (int message = 0; message < messages.length; message++) {
112: if (messageMatches(messages[message])) {
113: result.add(messages[message]);
114: }
115: }
116: return (Message[]) result.toArray(new Message[] {});
117: }
118:
119: private boolean noMatchCriteria() {
120: return StringUtils.isEmpty(getSubject())
121: && StringUtils.isEmpty(getFrom())
122: && StringUtils.isEmpty(getTo())
123: && StringUtils.isEmpty(getCc())
124: && StringUtils.isEmpty(getReplyTo());
125: }
126:
127: boolean messageMatches(final Message message)
128: throws MessagingException {
129: if (!doMatch(getFrom(), message.getFrom()[0].toString())) {
130: return false;
131: }
132: if (!doMatch(getSubject(), message.getSubject())) {
133: return false;
134: }
135: if (!doMatchMultiple(getReplyTo(), message.getReplyTo())) {
136: return false;
137: }
138: if (!doMatchMultiple(getCc(), message
139: .getRecipients(MimeMessage.RecipientType.CC))) {
140: return false;
141: }
142: return doMatchMultiple(getTo(), message
143: .getRecipients(MimeMessage.RecipientType.TO));
144: }
145:
146: static boolean doMatch(final String expected, String actual) {
147: actual = StringUtils.defaultString(actual, ""); // catch null
148:
149: // semantics are: if no expectation then match
150: if (StringUtils.isEmpty(expected)) {
151: return true;
152: }
153:
154: if (isRegexMatch(expected)) {
155: return getVerifier(true).verifyStrings(
156: expected.substring(1, expected.length() - 1),
157: actual);
158: }
159: return getVerifier(false).verifyStrings(expected, actual);
160: }
161:
162: static boolean doMatchMultiple(final String expected,
163: final Address[] actuals) {
164: // semantics are: if no expectation then match
165: if (StringUtils.isEmpty(expected)) {
166: return true;
167: }
168: final StringTokenizer expectedTokens = new StringTokenizer(
169: expected, ",");
170: while (expectedTokens.hasMoreTokens()) {
171: final String expectedToken = expectedTokens.nextToken()
172: .trim();
173: boolean hasMatched = false;
174: for (int i = 0; i < actuals.length; i++) {
175: final Address actual = actuals[i];
176: hasMatched = doMatch(expectedToken, actual.toString());
177: if (hasMatched) {
178: break;
179: }
180: }
181: if (!hasMatched) {
182: return false;
183: }
184: }
185: return true;
186: }
187:
188: protected static boolean isRegexMatch(final String expected) {
189: return expected.startsWith("/") && expected.endsWith("/")
190: && expected.length() > 1;
191: }
192: }
|