1 37 38 package net.sourceforge.cruisecontrol; 39 40 import net.sourceforge.cruisecontrol.util.ValidationHelper; 41 42 import org.apache.log4j.Logger; 43 import org.apache.oro.io.GlobFilenameFilter; 44 import org.apache.oro.text.MalformedCachePatternException; 45 import org.jdom.Element; 46 47 import java.io.File ; 48 import java.text.DateFormat ; 49 import java.util.ArrayList ; 50 import java.util.Date ; 51 import java.util.Hashtable ; 52 import java.util.Iterator ; 53 import java.util.List ; 54 import java.util.StringTokenizer ; 55 56 61 public class ModificationSet { 62 63 private boolean lieOnIsModified = false; 64 private static final Logger LOG = Logger.getLogger(ModificationSet.class); 65 private static final int ONE_SECOND = 1000; 66 67 private List modifications = new ArrayList (); 68 private List sourceControls = new ArrayList (); 69 private int quietPeriod = 60 * ONE_SECOND; 70 private Date timeOfCheck; 71 private final DateFormat formatter = DateFormatFactory.getDateFormat(); 72 73 76 private List ignoreFiles; 77 78 83 public void setQuietPeriod(int seconds) { 84 quietPeriod = seconds * ONE_SECOND; 85 } 86 87 94 public void setIgnoreFiles(String filePatterns) throws CruiseControlException { 95 if (filePatterns != null) { 96 StringTokenizer st = new StringTokenizer (filePatterns, ","); 97 ignoreFiles = new ArrayList (); 98 while (st.hasMoreTokens()) { 99 String pattern = st.nextToken(); 100 try { 102 ignoreFiles.add (new GlobFilenameFilter(pattern)); 103 } catch (MalformedCachePatternException e) { 104 throw new CruiseControlException("Invalid filename pattern '" + pattern + "'", e); 105 } 106 } 107 } 108 } 109 110 protected List getIgnoreFiles() { 111 return this.ignoreFiles; 112 } 113 114 115 public void addSourceControl(SourceControl sourceControl) { 116 add(sourceControl); 117 } 118 119 public void add(SourceControl sourceControl) { 120 sourceControls.add(sourceControl); 121 } 122 123 public List getSourceControls() { 124 return sourceControls; 125 } 126 127 protected boolean isLastModificationInQuietPeriod(Date timeOfCheck, List modificationList) { 128 long lastModificationTime = getLastModificationMillis(modificationList); 129 final long quietPeriodStart = timeOfCheck.getTime() - quietPeriod; 130 final boolean modificationInFuture = new Date ().getTime() < lastModificationTime; 131 if (modificationInFuture) { 132 LOG.warn("A modification has been detected in the future. Building anyway."); 133 } 134 return (quietPeriodStart <= lastModificationTime) && !modificationInFuture; 135 } 136 137 protected long getLastModificationMillis(List modificationList) { 138 Date timeOfLastModification = new Date (0); 139 Iterator iterator = modificationList.iterator(); 140 while (iterator.hasNext()) { 141 Object object = iterator.next(); 142 Modification modification = null; 143 if (object instanceof Modification) { 144 modification = (Modification) object; 145 } 146 if (object instanceof Element) { 147 Element element = (Element) object; 148 modification = new Modification("unknown"); 149 modification.fromElement(element, formatter); 150 } 151 if (modification != null) { 152 Date modificationDate = modification.modifiedTime; 153 if (modificationDate.after(timeOfLastModification)) { 154 timeOfLastModification = modificationDate; 155 } 156 } 157 } 158 LOG.debug("Last modification: " + formatter.format(timeOfLastModification)); 159 return timeOfLastModification.getTime(); 160 } 161 162 protected long getQuietPeriodDifference(Date now, List modificationList) { 163 long diff = quietPeriod - (now.getTime() - getLastModificationMillis(modificationList)); 164 return Math.max(0, diff); 165 } 166 167 172 public Hashtable getProperties() { 173 Hashtable table = new Hashtable (); 174 for (Iterator iter = sourceControls.iterator(); iter.hasNext();) { 175 SourceControl control = (SourceControl) iter.next(); 176 table.putAll(control.getProperties()); 177 } 178 return table; 179 } 180 181 184 public Element getModifications(Date lastBuild) { 185 Element modificationsElement; 186 do { 187 timeOfCheck = new Date (); 188 modifications = new ArrayList (); 189 Iterator sourceControlIterator = sourceControls.iterator(); 190 while (sourceControlIterator.hasNext()) { 191 SourceControl sourceControl = (SourceControl) sourceControlIterator.next(); 192 modifications.addAll(sourceControl.getModifications(lastBuild, timeOfCheck)); 193 } 194 195 filterIgnoredModifications(modifications); 197 198 if (modifications.size() > 0) { 199 LOG.info( 200 modifications.size() 201 + ((modifications.size() > 1) 202 ? " modifications have been detected." 203 : " modification has been detected.")); 204 } 205 modificationsElement = new Element("modifications"); 206 Iterator modificationIterator = modifications.iterator(); 207 while (modificationIterator.hasNext()) { 208 Object object = modificationIterator.next(); 209 if (object instanceof Element) { 210 modificationsElement.addContent(((Element) object).detach()); 211 } else { 212 Modification modification = (Modification) object; 213 Element modificationElement = (modification).toElement(formatter); 214 modification.log(formatter); 215 modificationsElement.addContent(modificationElement); 216 } 217 } 218 219 if (isLastModificationInQuietPeriod(timeOfCheck, modifications)) { 220 LOG.info("A modification has been detected in the quiet period. "); 221 if (LOG.isDebugEnabled()) { 222 final Date quietPeriodStart = new Date (timeOfCheck.getTime() - quietPeriod); 223 LOG.debug(formatter.format(quietPeriodStart) + " <= Quiet Period <= " 224 + formatter.format(timeOfCheck)); 225 } 226 Date now = new Date (); 227 long timeToSleep = getQuietPeriodDifference(now, modifications); 228 LOG.info("Sleeping for " + (timeToSleep / 1000) + " seconds before retrying."); 229 try { 230 Thread.sleep(timeToSleep); 231 } catch (InterruptedException e) { 232 LOG.error(e); 233 } 234 } 235 } while (isLastModificationInQuietPeriod(timeOfCheck, modifications)); 236 237 238 return modificationsElement; 239 } 240 241 244 protected void filterIgnoredModifications (List modifications) { 245 if (this.ignoreFiles != null) { 246 for (Iterator iterator = modifications.iterator(); iterator.hasNext(); ) { 247 Object object = iterator.next(); 248 Modification modification = null; 249 if (object instanceof Modification) { 250 modification = (Modification) object; 251 } else if (object instanceof Element) { 252 Element element = (Element) object; 253 modification = new Modification(); 254 modification.fromElement(element, formatter); 255 } 256 257 if (isIgnoredModification(modification)) { 258 iterator.remove(); 259 } 260 } 261 } 262 } 263 264 private boolean isIgnoredModification(Modification modification) { 265 File file; 266 if (modification.getFolderName() == null) { 267 if (modification.getFileName() == null) { 268 return false; 269 } else { 270 file = new File (modification.getFileName()); 271 } 272 } else { 273 file = new File (modification.getFolderName(), modification.getFileName()); 274 } 275 String path = file.toString(); 276 277 if (File.separatorChar == '\\') { 280 path = path.replace('\\', '/'); 281 } 282 283 for (Iterator iterator = ignoreFiles.iterator(); iterator.hasNext(); ) { 284 GlobFilenameFilter pattern = (GlobFilenameFilter) iterator.next(); 285 286 if (pattern.accept(file, path)) { 289 return true; 290 } 291 } 292 return false; 293 } 294 295 public Date getTimeOfCheck() { 296 return timeOfCheck; 297 } 298 299 public boolean isModified() { 300 return (!modifications.isEmpty()) || lieOnIsModified; 301 } 302 303 public void validate() throws CruiseControlException { 304 ValidationHelper.assertFalse(sourceControls.isEmpty(), 305 "modificationset element requires at least one nested source control element"); 306 } 307 308 int getQuietPeriod() { 309 return quietPeriod; 310 } 311 312 public void setRequireModification(boolean isModifiedAccurate) { 313 lieOnIsModified = !isModifiedAccurate; 314 } 315 } 316 | Popular Tags |