1 package org.testng; 2 3 import java.io.PrintStream; 4 import java.io.PrintWriter; 5 import java.text.DateFormat; 6 import java.text.ParseException; 7 import java.text.SimpleDateFormat; 8 import java.util.Calendar; 9 import java.util.Date; 10 11 /** 12 * A {@link SkipException} extension that transforms a skipped method 13 * into a failed method based on a time trigger. 14 * <p/> 15 * By default the time format is yyyy/MM/dd (according to {@code SimpleDateFormat}). 16 * You can customize this by using the specialized constructors. Suppported date 17 * formats are according to the {@code SimpleDateFormat}. 18 * 19 * @author <a href='mailto:the[dot]mindstorm[at]gmail[dot]com'>Alex Popescu</a> 20 * @since 5.6 21 */ 22 public class TimeBombSkipException extends SkipException { 23 private static final long serialVersionUID = -8599821478834048537L; 24 private static final SimpleDateFormat SDF= new SimpleDateFormat("yyyy/MM/dd"); 25 private Calendar m_expireDate; 26 private DateFormat m_inFormat= SDF; 27 private DateFormat m_outFormat= SDF; 28 29 /** 30 * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>. 31 * The format used for date comparison is <tt>yyyy/MM/dd</tt> 32 * @param msg exception message 33 * @param expirationDate time limit after which the SKIP becomes a FAILURE 34 */ 35 public TimeBombSkipException(String msg, Date expirationDate) { 36 super(msg); 37 initExpireDate(expirationDate); 38 } 39 40 /** 41 * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>. 42 * The <tt>format</tt> parameter wiil be used for performing the time comparison. 43 * @param msg exception message 44 * @param expirationDate time limit after which the SKIP becomes a FAILURE 45 * @param format format for the time comparison 46 */ 47 public TimeBombSkipException(String msg, Date expirationDate, String format) { 48 super(msg); 49 m_inFormat= new SimpleDateFormat(format); 50 m_outFormat= new SimpleDateFormat(format); 51 initExpireDate(expirationDate); 52 } 53 54 /** 55 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 56 * in the format <tt>yyyy/MM/dd</tt>. 57 * @param msg exception message 58 * @param date time limit after which the SKIP becomes a FAILURE 59 */ 60 public TimeBombSkipException(String msg, String date) { 61 super(msg); 62 initExpireDate(date); 63 } 64 65 /** 66 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 67 * in the specified format <tt>format</tt>. The same format is used 68 * when performing the time comparison. 69 * @param msg exception message 70 * @param date time limit after which the SKIP becomes a FAILURE 71 * @param format format of the passed in <tt>date</tt> and of the time comparison 72 */ 73 public TimeBombSkipException(String msg, String date, String format) { 74 this(msg, date, format, format); 75 } 76 77 /** 78 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 79 * in the specified format <tt>inFormat</tt>. The <tt>outFormat</tt> will be 80 * used to perform the time comparison and display. 81 * @param msg exception message 82 * @param date time limit after which the SKIP becomes a FAILURE 83 * @param inFormat format of the passed in <tt>date</tt> 84 * @param outFormat format of the time comparison 85 */ 86 public TimeBombSkipException(String msg, String date, String inFormat, String outFormat) { 87 super(msg); 88 m_inFormat= new SimpleDateFormat(inFormat); 89 m_outFormat= new SimpleDateFormat(outFormat); 90 initExpireDate(date); 91 } 92 93 /** 94 * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>. 95 * The format used for date comparison is <tt>yyyy/MM/dd</tt> 96 * @param msg exception message 97 * @param expirationDate time limit after which the SKIP becomes a FAILURE 98 * @param cause the cause (which is saved for later retrieval by the 99 * {@link #getCause()} method). (A <tt>null</tt> value is 100 * permitted, and indicates that the cause is nonexistent or 101 * unknown.) 102 */ 103 public TimeBombSkipException(String msg, Date expirationDate, Throwable cause) { 104 super(msg, cause); 105 initExpireDate(expirationDate); 106 } 107 108 /** 109 * Creates a {@code TimeBombedSkipException} using the <tt>expirationDate</tt>. 110 * The <tt>format</tt> parameter wiil be used for performing the time comparison. 111 * @param msg exception message 112 * @param expirationDate time limit after which the SKIP becomes a FAILURE 113 * @param format format for the time comparison 114 * @param cause the cause (which is saved for later retrieval by the 115 * {@link #getCause()} method). (A <tt>null</tt> value is 116 * permitted, and indicates that the cause is nonexistent or 117 * unknown.) 118 */ 119 public TimeBombSkipException(String msg, Date expirationDate, String format, Throwable cause) { 120 super(msg, cause); 121 m_inFormat= new SimpleDateFormat(format); 122 m_outFormat= new SimpleDateFormat(format); 123 initExpireDate(expirationDate); 124 } 125 126 /** 127 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 128 * in the format <tt>yyyy/MM/dd</tt>. 129 * @param msg exception message 130 * @param date time limit after which the SKIP becomes a FAILURE 131 * @param cause the cause (which is saved for later retrieval by the 132 * {@link #getCause()} method). (A <tt>null</tt> value is 133 * permitted, and indicates that the cause is nonexistent or 134 * unknown.) 135 */ 136 public TimeBombSkipException(String msg, String date, Throwable cause) { 137 super(msg, cause); 138 initExpireDate(date); 139 } 140 141 /** 142 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 143 * in the specified format <tt>format</tt>. The same format is used 144 * when performing the time comparison. 145 * @param msg exception message 146 * @param date time limit after which the SKIP becomes a FAILURE 147 * @param format format of the passed in <tt>date</tt> and of the time comparison 148 * @param cause the cause (which is saved for later retrieval by the 149 * {@link #getCause()} method). (A <tt>null</tt> value is 150 * permitted, and indicates that the cause is nonexistent or 151 * unknown.) 152 */ 153 public TimeBombSkipException(String msg, String date, String format, Throwable cause) { 154 this(msg, date, format, format, cause); 155 } 156 157 /** 158 * Creates a {@code TimeBombedSkipException} using the <tt>date</tt> 159 * in the specified format <tt>inFormat</tt>. The <tt>outFormat</tt> will be 160 * used to perform the time comparison and display. 161 * @param msg exception message 162 * @param date time limit after which the SKIP becomes a FAILURE 163 * @param inFormat format of the passed in <tt>date</tt> 164 * @param outFormat format of the time comparison 165 * @param cause the cause (which is saved for later retrieval by the 166 * {@link #getCause()} method). (A <tt>null</tt> value is 167 * permitted, and indicates that the cause is nonexistent or 168 * unknown.) 169 */ 170 public TimeBombSkipException(String msg, String date, String inFormat, String outFormat, Throwable cause) { 171 super(msg, cause); 172 m_inFormat= new SimpleDateFormat(inFormat); 173 m_outFormat= new SimpleDateFormat(outFormat); 174 initExpireDate(date); 175 } 176 177 private void initExpireDate(Date expireDate) { 178 m_expireDate= Calendar.getInstance(); 179 m_expireDate.setTime(expireDate); 180 } 181 182 private void initExpireDate(String date) { 183 try { 184 // SimpleDateFormat is not thread-safe, and m_inFormat 185 // is, by default, connected to the static SDF variable 186 synchronized( m_inFormat ){ 187 Date d = m_inFormat.parse(date); 188 initExpireDate(d); 189 } 190 } 191 catch(ParseException pex) { 192 throw new TestNGException("Cannot parse date:" + date + " using pattern: " + m_inFormat, pex); 193 } 194 } 195 196 @Override 197 public boolean isSkip() { 198 if (null == m_expireDate) { 199 return false; 200 } 201 202 try { 203 Calendar now= Calendar.getInstance(); 204 Date nowDate= m_inFormat.parse(m_inFormat.format(now.getTime())); 205 now.setTime(nowDate); 206 207 return !now.after(m_expireDate); 208 } 209 catch(ParseException pex) { 210 throw new TestNGException("Cannot compare dates."); 211 } 212 } 213 214 @Override 215 public String getMessage() { 216 if(isSkip()) { 217 return super.getMessage(); 218 } 219 else { 220 return super.getMessage() + "; Test must have been enabled by: " + m_outFormat.format(m_expireDate.getTime()); 221 } 222 } 223 224 @Override 225 public void printStackTrace(PrintStream s) { 226 reduceStackTrace(); 227 super.printStackTrace(s); 228 } 229 230 @Override 231 public void printStackTrace(PrintWriter s) { 232 reduceStackTrace(); 233 super.printStackTrace(s); 234 } 235 } 236