001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.reporters;
020:
021: import java.io.Serializable;
022: import java.util.Properties;
023: import java.util.StringTokenizer;
024: import java.util.Vector;
025:
026: import javax.mail.Message;
027: import javax.mail.MessagingException;
028: import javax.mail.Session;
029: import javax.mail.Transport;
030: import javax.mail.internet.AddressException;
031: import javax.mail.internet.InternetAddress;
032: import javax.mail.internet.MimeMessage;
033: import javax.swing.event.ChangeEvent;
034: import javax.swing.event.ChangeListener;
035:
036: import org.apache.jmeter.samplers.SampleResult;
037: import org.apache.jmeter.testelement.AbstractTestElement;
038: import org.apache.jmeter.util.JMeterUtils;
039: import org.apache.jorphan.logging.LoggingManager;
040: import org.apache.log.Logger;
041:
042: /**
043: * The model for a MailerVisualizer.
044: *
045: */
046: public class MailerModel extends AbstractTestElement implements
047: Serializable {
048:
049: private static final Logger log = LoggingManager
050: .getLoggerForClass();
051:
052: private static final String MAIL_SMTP_HOST = "mail.smtp.host"; //$NON-NLS-1$
053:
054: private long failureCount = 0;
055:
056: private long successCount = 0;
057:
058: private boolean failureMsgSent = false;
059:
060: private boolean siteDown = false;
061:
062: private boolean successMsgSent = false;
063:
064: private static final String FROM_KEY = "MailerModel.fromAddress"; //$NON-NLS-1$
065:
066: private static final String TO_KEY = "MailerModel.addressie"; //$NON-NLS-1$
067:
068: private static final String HOST_KEY = "MailerModel.smtpHost"; //$NON-NLS-1$
069:
070: private static final String SUCCESS_SUBJECT = "MailerModel.successSubject"; //$NON-NLS-1$
071:
072: private static final String FAILURE_SUBJECT = "MailerModel.failureSubject"; //$NON-NLS-1$
073:
074: private static final String FAILURE_LIMIT_KEY = "MailerModel.failureLimit"; //$NON-NLS-1$
075:
076: private static final String SUCCESS_LIMIT_KEY = "MailerModel.successLimit"; //$NON-NLS-1$
077:
078: private static final String DEFAULT_LIMIT = "2"; //$NON-NLS-1$
079:
080: /** The listener for changes. */
081: transient ChangeListener changeListener;
082:
083: /**
084: * Constructs a MailerModel.
085: */
086: public MailerModel() {
087: super ();
088:
089: setProperty(SUCCESS_LIMIT_KEY, JMeterUtils.getPropDefault(
090: "mailer.successlimit", DEFAULT_LIMIT)); //$NON-NLS-1$
091: setProperty(FAILURE_LIMIT_KEY, JMeterUtils.getPropDefault(
092: "mailer.failurelimit", DEFAULT_LIMIT)); //$NON-NLS-1$
093: }
094:
095: public void addChangeListener(ChangeListener list) {
096: changeListener = list;
097: }
098:
099: public Object clone() {
100: MailerModel m = (MailerModel) super .clone();
101: m.changeListener = changeListener;
102: return m;
103: }
104:
105: /**
106: * Returns wether there had been more failures than acceptable.
107: *
108: * @return a boolean value indicating whether the limit of acceptable
109: * failures has been reached.
110: */
111: public synchronized boolean isFailing() {
112: return (failureCount > getFailureLimit());
113: }
114:
115: public void notifyChangeListeners() {
116: if (changeListener != null) {
117: changeListener.stateChanged(new ChangeEvent(this ));
118: }
119: }
120:
121: /**
122: * Gets a Vector of String-objects. Each String is one mail-address of the
123: * addresses-String set by <code>setToAddress(str)</code>. The addresses
124: * must be seperated by commas. Only String-objects containing a "@" are
125: * added to the returned Vector.
126: *
127: * @return a Vector of String-objects wherein each String represents a
128: * mail-address.
129: */
130: public synchronized Vector getAddressVector() {
131: String theAddressie = getToAddress();
132: Vector addressVector = new Vector();
133:
134: if (theAddressie != null) {
135: String addressSep = ","; //$NON-NLS-1$
136:
137: StringTokenizer next = new StringTokenizer(theAddressie,
138: addressSep);
139:
140: while (next.hasMoreTokens()) {
141: String theToken = next.nextToken().trim();
142:
143: if (theToken.indexOf("@") > 0) { //$NON-NLS-1$
144: addressVector.addElement(theToken);
145: }
146: }
147: } else {
148: return new Vector(0);
149: }
150:
151: return addressVector;
152: }
153:
154: /**
155: * Adds a SampleResult. If SampleResult represents a change concerning the
156: * failure/success of the sampling a message might be send to the addressies
157: * according to the settings of <code>successCount</code> and
158: * <code>failureCount</code>.
159: *
160: * @param sample
161: * the SampleResult encapsulating informations about the last
162: * sample.
163: */
164: public synchronized void add(SampleResult sample) {
165:
166: // -1 is the code for a failed sample.
167: //
168: if (!sample.isSuccessful()) {
169: failureCount++;
170: successCount = 0;
171: } else {
172: successCount++;
173: }
174:
175: if (this .isFailing() && !siteDown && !failureMsgSent) {
176: // Send the mail ...
177: Vector addressVector = getAddressVector();
178:
179: if (addressVector.size() != 0) {
180: try {
181: sendMail(getFromAddress(), addressVector,
182: getFailureSubject(), "URL Failed: "
183: + sample.getSampleLabel(),
184: getSmtpHost());
185: } catch (Exception e) {
186: log.error("Problem sending mail", e);
187: }
188: siteDown = true;
189: failureMsgSent = true;
190: successCount = 0;
191: successMsgSent = false;
192: }
193: }
194:
195: if (siteDown && (sample.getTime() != -1) && !successMsgSent) {
196: // Send the mail ...
197: if (successCount > getSuccessLimit()) {
198: Vector addressVector = getAddressVector();
199:
200: try {
201: sendMail(getFromAddress(), addressVector,
202: getSuccessSubject(), "URL Restarted: "
203: + sample.getSampleLabel(),
204: getSmtpHost());
205: } catch (Exception e) {
206: log.error("Problem sending mail", e);
207: }
208: siteDown = false;
209: successMsgSent = true;
210: failureCount = 0;
211: failureMsgSent = false;
212: }
213: }
214:
215: if (successMsgSent && failureMsgSent) {
216: clear();
217: }
218: notifyChangeListeners();
219: }
220:
221: /**
222: * Resets the state of this object to its default. But: This method does not
223: * reset any mail-specific attributes (like sender, mail-subject...) since
224: * they are independent of the sampling.
225: */
226: public synchronized void clear() {// TODO: should this be clearData()?
227: failureCount = 0;
228: successCount = 0;
229: siteDown = false;
230: successMsgSent = false;
231: failureMsgSent = false;
232: notifyChangeListeners();
233: }
234:
235: /**
236: * Returns a String-representation of this object. Returns always
237: * "E-Mail-Notification". Might be enhanced in future versions to return
238: * some kind of String-representation of the mail-parameters (like sender,
239: * addressies, smtpHost...).
240: *
241: * @return A String-representation of this object.
242: */
243: public String toString() {
244: return "E-Mail Notification";
245: }
246:
247: /**
248: * Sends a mail with the given parameters using SMTP.
249: *
250: * @param from
251: * the sender of the mail as shown in the mail-client.
252: * @param vEmails
253: * all receivers of the mail. The receivers are seperated by
254: * commas.
255: * @param subject
256: * the subject of the mail.
257: * @param attText
258: * the message-body.
259: * @param smtpHost
260: * the smtp-server used to send the mail.
261: */
262: public synchronized void sendMail(String from, Vector vEmails,
263: String subject, String attText, String smtpHost)
264: throws AddressException, MessagingException {
265: String host = smtpHost;
266: boolean debug = Boolean.valueOf(host).booleanValue();
267: // InetAddress remote = InetAddress.getByName(host);
268:
269: InternetAddress[] address = new InternetAddress[vEmails.size()];
270:
271: for (int k = 0; k < vEmails.size(); k++) {
272: address[k] = new InternetAddress(vEmails.elementAt(k)
273: .toString());
274: }
275:
276: // create some properties and get the default Session
277: Properties props = new Properties();
278:
279: props.put(MAIL_SMTP_HOST, host);
280: Session session = Session.getDefaultInstance(props, null);
281: // N.B. properties are only used when the default session is first
282: // created
283: // so check if the mail host needs to be reset...
284: props = session.getProperties();
285: if (!host.equalsIgnoreCase(props.getProperty(MAIL_SMTP_HOST))) {
286: props.setProperty(MAIL_SMTP_HOST, host);
287: }
288:
289: session.setDebug(debug);
290:
291: // create a message
292: Message msg = new MimeMessage(session);
293:
294: msg.setFrom(new InternetAddress(from));
295: msg.setRecipients(Message.RecipientType.TO, address);
296: msg.setSubject(subject);
297: msg.setText(attText);
298: Transport.send(msg);
299: }
300:
301: public synchronized void sendTestMail() throws AddressException,
302: MessagingException {
303: String to = getToAddress();
304: String from = getFromAddress();
305: String subject = "Testing mail-addresses";
306: String smtpHost = getSmtpHost();
307: String attText = "JMeter-Testmail" + "\n" + "To: " + to + "\n"
308: + "From: " + from + "\n" + "Via: " + smtpHost + "\n"
309: + "Fail Subject: " + getFailureSubject() + "\n"
310: + "Success Subject: " + getSuccessSubject();
311:
312: log.info(attText);
313:
314: Vector destination = new Vector();
315: destination.add(to);
316:
317: sendMail(from, destination, subject, attText, smtpHost);
318: log.info("Test mail sent successfully!!");
319: }
320:
321: // ////////////////////////////////////////////////////////////
322: //
323: // setter/getter - JavaDoc-Comments not needed...
324: //
325: // ////////////////////////////////////////////////////////////
326:
327: public void setToAddress(String str) {
328: setProperty(TO_KEY, str);
329: }
330:
331: public void setFromAddress(String str) {
332: setProperty(FROM_KEY, str);
333: }
334:
335: public void setSmtpHost(String str) {
336: setProperty(HOST_KEY, str);
337: }
338:
339: public void setFailureSubject(String str) {
340: setProperty(FAILURE_SUBJECT, str);
341: }
342:
343: public void setSuccessSubject(String str) {
344: setProperty(SUCCESS_SUBJECT, str);
345: }
346:
347: public void setSuccessLimit(String limit) {
348: setProperty(SUCCESS_LIMIT_KEY, limit);
349: }
350:
351: // private void setSuccessCount(long count)
352: // {
353: // this.successCount = count;
354: // }
355:
356: public void setFailureLimit(String limit) {
357: setProperty(FAILURE_LIMIT_KEY, limit);
358: }
359:
360: // private void setFailureCount(long count)
361: // {
362: // this.failureCount = count;
363: // }
364:
365: public String getToAddress() {
366: return getPropertyAsString(TO_KEY);
367: }
368:
369: public String getFromAddress() {
370: return getPropertyAsString(FROM_KEY);
371: }
372:
373: public String getSmtpHost() {
374: return getPropertyAsString(HOST_KEY);
375: }
376:
377: public String getFailureSubject() {
378: return getPropertyAsString(FAILURE_SUBJECT);
379: }
380:
381: public String getSuccessSubject() {
382: return getPropertyAsString(SUCCESS_SUBJECT);
383: }
384:
385: public long getSuccessLimit() {
386: return getPropertyAsLong(SUCCESS_LIMIT_KEY);
387: }
388:
389: public long getSuccessCount() {
390: return successCount;
391: }
392:
393: public long getFailureLimit() {
394: return getPropertyAsLong(FAILURE_LIMIT_KEY);
395: }
396:
397: public long getFailureCount() {
398: return this.failureCount;
399: }
400: }
|