1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package org.apache.jmeter.reporters; 20 21 import java.io.Serializable; 22 import java.util.Properties; 23 import java.util.StringTokenizer; 24 import java.util.Vector; 25 26 import javax.mail.Message; 27 import javax.mail.MessagingException; 28 import javax.mail.Session; 29 import javax.mail.Transport; 30 import javax.mail.internet.AddressException; 31 import javax.mail.internet.InternetAddress; 32 import javax.mail.internet.MimeMessage; 33 import javax.swing.event.ChangeEvent; 34 import javax.swing.event.ChangeListener; 35 36 import org.apache.jmeter.samplers.SampleResult; 37 import org.apache.jmeter.testelement.AbstractTestElement; 38 import org.apache.jmeter.util.JMeterUtils; 39 import org.apache.jorphan.logging.LoggingManager; 40 import org.apache.log.Logger; 41 42 /** 43 * The model for a MailerVisualizer. 44 * 45 */ 46 public class MailerModel extends AbstractTestElement implements Serializable { 47 48 private static final long serialVersionUID = 233L; 49 50 private static final Logger log = LoggingManager.getLoggerForClass(); 51 52 private static final String MAIL_SMTP_HOST = "mail.smtp.host"; //$NON-NLS-1$ 53 54 private long failureCount = 0; 55 56 private long successCount = 0; 57 58 private boolean failureMsgSent = false; 59 60 private boolean siteDown = false; 61 62 private boolean successMsgSent = false; 63 64 private static final String FROM_KEY = "MailerModel.fromAddress"; //$NON-NLS-1$ 65 66 private static final String TO_KEY = "MailerModel.addressie"; //$NON-NLS-1$ 67 68 private static final String HOST_KEY = "MailerModel.smtpHost"; //$NON-NLS-1$ 69 70 private static final String SUCCESS_SUBJECT = "MailerModel.successSubject"; //$NON-NLS-1$ 71 72 private static final String FAILURE_SUBJECT = "MailerModel.failureSubject"; //$NON-NLS-1$ 73 74 private static final String FAILURE_LIMIT_KEY = "MailerModel.failureLimit"; //$NON-NLS-1$ 75 76 private static final String SUCCESS_LIMIT_KEY = "MailerModel.successLimit"; //$NON-NLS-1$ 77 78 private static final String DEFAULT_LIMIT = "2"; //$NON-NLS-1$ 79 80 /** The listener for changes. */ 81 transient ChangeListener changeListener; 82 83 /** 84 * Constructs a MailerModel. 85 */ 86 public MailerModel() { 87 super(); 88 89 setProperty(SUCCESS_LIMIT_KEY, JMeterUtils.getPropDefault("mailer.successlimit", DEFAULT_LIMIT)); //$NON-NLS-1$ 90 setProperty(FAILURE_LIMIT_KEY, JMeterUtils.getPropDefault("mailer.failurelimit", DEFAULT_LIMIT)); //$NON-NLS-1$ 91 } 92 93 public void addChangeListener(ChangeListener list) { 94 changeListener = list; 95 } 96 97 public Object clone() { 98 MailerModel m = (MailerModel) super.clone(); 99 m.changeListener = changeListener; 100 return m; 101 } 102 103 public void notifyChangeListeners() { 104 if (changeListener != null) { 105 changeListener.stateChanged(new ChangeEvent(this)); 106 } 107 } 108 109 /** 110 * Gets a Vector of String-objects. Each String is one mail-address of the 111 * addresses-String set by <code>setToAddress(str)</code>. The addresses 112 * must be seperated by commas. Only String-objects containing a "@" are 113 * added to the returned Vector. 114 * 115 * @return a Vector of String-objects wherein each String represents a 116 * mail-address. 117 */ 118 public Vector getAddressVector() { 119 String addressees = getToAddress(); 120 Vector addressVector = new Vector(); 121 122 if (addressees != null) { 123 124 StringTokenizer next = new StringTokenizer(addressees, ","); //$NON-NLS-1$ 125 126 while (next.hasMoreTokens()) { 127 String theToken = next.nextToken().trim(); 128 129 if (theToken.indexOf("@") > 0) { //$NON-NLS-1$ 130 addressVector.addElement(theToken); 131 } else { 132 log.warn("Ignored unexpected e-mail address: "+theToken); 133 } 134 } 135 } 136 137 return addressVector; 138 } 139 140 /** 141 * Adds a SampleResult. If SampleResult represents a change concerning the 142 * failure/success of the sampling a message might be send to the addressies 143 * according to the settings of <code>successCount</code> and 144 * <code>failureCount</code>. 145 * 146 * @param sample 147 * the SampleResult encapsulating informations about the last 148 * sample. 149 */ 150 public synchronized void add(SampleResult sample) { 151 152 // -1 is the code for a failed sample. 153 // 154 if (!sample.isSuccessful()) { 155 failureCount++; 156 successCount = 0; 157 } else { 158 successCount++; 159 } 160 161 if ((failureCount > getFailureLimit()) && !siteDown && !failureMsgSent) { 162 // Send the mail ... 163 Vector addressVector = getAddressVector(); 164 165 if (addressVector.size() != 0) { 166 try { 167 sendMail(getFromAddress(), addressVector, getFailureSubject(), "URL Failed: " 168 + sample.getSampleLabel(), getSmtpHost()); 169 } catch (Exception e) { 170 log.error("Problem sending mail", e); 171 } 172 siteDown = true; 173 failureMsgSent = true; 174 successCount = 0; 175 successMsgSent = false; 176 } 177 } 178 179 if (siteDown && (sample.getTime() != -1) && !successMsgSent) { 180 // Send the mail ... 181 if (successCount > getSuccessLimit()) { 182 Vector addressVector = getAddressVector(); 183 184 try { 185 sendMail(getFromAddress(), addressVector, getSuccessSubject(), "URL Restarted: " 186 + sample.getSampleLabel(), getSmtpHost()); 187 } catch (Exception e) { 188 log.error("Problem sending mail", e); 189 } 190 siteDown = false; 191 successMsgSent = true; 192 failureCount = 0; 193 failureMsgSent = false; 194 } 195 } 196 197 if (successMsgSent && failureMsgSent) { 198 clear(); 199 } 200 notifyChangeListeners(); 201 } 202 203 /** 204 * Resets the state of this object to its default. But: This method does not 205 * reset any mail-specific attributes (like sender, mail-subject...) since 206 * they are independent of the sampling. 207 */ 208 public synchronized void clear() {// TODO: should this be clearData()? 209 failureCount = 0; 210 successCount = 0; 211 siteDown = false; 212 successMsgSent = false; 213 failureMsgSent = false; 214 notifyChangeListeners(); 215 } 216 217 /** 218 * Returns a String-representation of this object. Returns always 219 * "E-Mail-Notification". Might be enhanced in future versions to return 220 * some kind of String-representation of the mail-parameters (like sender, 221 * addressies, smtpHost...). 222 * 223 * @return A String-representation of this object. 224 */ 225 public String toString() { 226 return "E-Mail Notification"; 227 } 228 229 /** 230 * Sends a mail with the given parameters using SMTP. 231 * 232 * @param from 233 * the sender of the mail as shown in the mail-client. 234 * @param vEmails 235 * all receivers of the mail. The receivers are seperated by 236 * commas. 237 * @param subject 238 * the subject of the mail. 239 * @param attText 240 * the message-body. 241 * @param smtpHost 242 * the smtp-server used to send the mail. 243 */ 244 public synchronized void sendMail(String from, Vector vEmails, String subject, String attText, String smtpHost) 245 throws AddressException, MessagingException { 246 String host = smtpHost; 247 boolean debug = Boolean.valueOf(host).booleanValue(); 248 // InetAddress remote = InetAddress.getByName(host); 249 250 InternetAddress[] address = new InternetAddress[vEmails.size()]; 251 252 for (int k = 0; k < vEmails.size(); k++) { 253 address[k] = new InternetAddress(vEmails.elementAt(k).toString()); 254 } 255 256 // create some properties and get the default Session 257 Properties props = new Properties(); 258 259 props.put(MAIL_SMTP_HOST, host); 260 Session session = Session.getDefaultInstance(props, null); 261 // N.B. properties are only used when the default session is first 262 // created 263 // so check if the mail host needs to be reset... 264 props = session.getProperties(); 265 if (!host.equalsIgnoreCase(props.getProperty(MAIL_SMTP_HOST))) { 266 props.setProperty(MAIL_SMTP_HOST, host); 267 } 268 269 session.setDebug(debug); 270 271 // create a message 272 Message msg = new MimeMessage(session); 273 274 msg.setFrom(new InternetAddress(from)); 275 msg.setRecipients(Message.RecipientType.TO, address); 276 msg.setSubject(subject); 277 msg.setText(attText); 278 Transport.send(msg); 279 } 280 281 public synchronized void sendTestMail() throws AddressException, MessagingException { 282 String to = getToAddress(); 283 String from = getFromAddress(); 284 String subject = "Testing mail-addresses"; 285 String smtpHost = getSmtpHost(); 286 String attText = "JMeter-Testmail" + "\n" + "To: " + to + "\n" + "From: " + from + "\n" + "Via: " + smtpHost 287 + "\n" + "Fail Subject: " + getFailureSubject() + "\n" + "Success Subject: " + getSuccessSubject(); 288 289 log.info(attText); 290 291 sendMail(from, getAddressVector(), subject, attText, smtpHost); 292 log.info("Test mail sent successfully!!"); 293 } 294 295 // //////////////////////////////////////////////////////////// 296 // 297 // setter/getter - JavaDoc-Comments not needed... 298 // 299 // //////////////////////////////////////////////////////////// 300 301 public void setToAddress(String str) { 302 setProperty(TO_KEY, str); 303 } 304 305 public void setFromAddress(String str) { 306 setProperty(FROM_KEY, str); 307 } 308 309 public void setSmtpHost(String str) { 310 setProperty(HOST_KEY, str); 311 } 312 313 public void setFailureSubject(String str) { 314 setProperty(FAILURE_SUBJECT, str); 315 } 316 317 public void setSuccessSubject(String str) { 318 setProperty(SUCCESS_SUBJECT, str); 319 } 320 321 public void setSuccessLimit(String limit) { 322 setProperty(SUCCESS_LIMIT_KEY, limit); 323 } 324 325 // private void setSuccessCount(long count) 326 // { 327 // this.successCount = count; 328 // } 329 330 public void setFailureLimit(String limit) { 331 setProperty(FAILURE_LIMIT_KEY, limit); 332 } 333 334 // private void setFailureCount(long count) 335 // { 336 // this.failureCount = count; 337 // } 338 339 public String getToAddress() { 340 return getPropertyAsString(TO_KEY); 341 } 342 343 public String getFromAddress() { 344 return getPropertyAsString(FROM_KEY); 345 } 346 347 public String getSmtpHost() { 348 return getPropertyAsString(HOST_KEY); 349 } 350 351 public String getFailureSubject() { 352 return getPropertyAsString(FAILURE_SUBJECT); 353 } 354 355 public String getSuccessSubject() { 356 return getPropertyAsString(SUCCESS_SUBJECT); 357 } 358 359 public long getSuccessLimit() { 360 return getPropertyAsLong(SUCCESS_LIMIT_KEY); 361 } 362 363 public long getSuccessCount() { 364 return successCount; 365 } 366 367 public long getFailureLimit() { 368 return getPropertyAsLong(FAILURE_LIMIT_KEY); 369 } 370 371 public long getFailureCount() { 372 return this.failureCount; 373 } 374 }