1 37 package net.sourceforge.cruisecontrol.sourcecontrols; 38 39 import java.io.BufferedReader ; 40 import java.io.FileReader ; 41 import java.text.ParseException ; 42 import java.text.SimpleDateFormat ; 43 import java.util.ArrayList ; 44 import java.util.Date ; 45 import java.util.Hashtable ; 46 import java.util.List ; 47 import java.util.Locale ; 48 import java.util.Map ; 49 50 import net.sourceforge.cruisecontrol.CruiseControlException; 51 import net.sourceforge.cruisecontrol.Modification; 52 import net.sourceforge.cruisecontrol.SourceControl; 53 import net.sourceforge.cruisecontrol.util.ValidationHelper; 54 55 import org.apache.log4j.Logger; 56 57 73 public class VssJournal implements SourceControl { 74 75 private static final Logger LOG = Logger.getLogger(VssJournal.class); 76 77 private String dateFormat; 78 private String timeFormat; 79 private SimpleDateFormat vssDateTimeFormat; 80 private boolean overridenDateFormat = false; 81 82 private String ssDir = "$/"; 83 private String journalFile; 84 85 private Hashtable properties = new Hashtable (); 86 private String property; 87 private String propertyOnDelete; 88 89 private Date lastBuild; 90 91 private ArrayList modifications = new ArrayList (); 92 93 public VssJournal() { 94 dateFormat = "MM/dd/yy"; 95 timeFormat = "hh:mma"; 96 constructVssDateTimeFormat(); 97 } 98 102 public void setSsDir(String s) { 103 StringBuffer sb = new StringBuffer (); 104 if (!s.startsWith("$")) { 105 sb.append("$"); 106 } 107 if (s.endsWith("/")) { 108 sb.append(s.substring(0, s.length() - 1)); 109 } else { 110 sb.append(s); 111 } 112 this.ssDir = sb.toString(); 113 } 114 115 120 public void setJournalFile(String journalFile) { 121 this.journalFile = journalFile; 122 } 123 124 130 public void setProperty(String property) { 131 this.property = property; 132 } 133 134 139 public void setPropertyOnDelete(String propertyOnDelete) { 140 this.propertyOnDelete = propertyOnDelete; 141 } 142 143 151 public void setDateFormat(String format) { 152 dateFormat = format; 153 overridenDateFormat = true; 154 constructVssDateTimeFormat(); 155 } 156 157 165 public void setTimeFormat(String format) { 166 timeFormat = format; 167 constructVssDateTimeFormat(); 168 } 169 170 private void constructVssDateTimeFormat() { 171 vssDateTimeFormat = new SimpleDateFormat (dateFormat + " " + timeFormat, Locale.US); 172 } 173 174 175 178 protected void setLastBuildDate(Date lastBuild) { 179 this.lastBuild = lastBuild; 180 } 181 182 public Map getProperties() { 183 return properties; 184 } 185 186 public void validate() throws CruiseControlException { 187 ValidationHelper.assertIsSet(journalFile, "journalfile", this.getClass()); 188 ValidationHelper.assertIsSet(ssDir, "ssdir", this.getClass()); 189 } 190 191 194 public List getModifications(Date lastBuild, Date now) { 195 this.lastBuild = lastBuild; 196 modifications.clear(); 197 198 try { 199 final BufferedReader br = new BufferedReader (new FileReader (journalFile)); 200 try { 201 String s = br.readLine(); 202 while (s != null) { 203 ArrayList entry = new ArrayList (); 204 entry.add(s); 205 s = br.readLine(); 206 while (s != null && !s.equals("")) { 207 entry.add(s); 208 s = br.readLine(); 209 } 210 Modification mod = handleEntry(entry); 211 if (mod != null) { 212 modifications.add(mod); 213 } 214 215 if ("".equals(s)) { 216 s = br.readLine(); 217 } 218 } 219 } finally { 220 br.close(); 221 } 222 } catch (Exception e) { 223 LOG.warn(e); 224 } 225 226 if (property != null && modifications.size() > 0) { 227 properties.put(property, "true"); 228 } 229 230 LOG.info("Found " + modifications.size() + " modified files"); 231 return modifications; 232 } 233 234 239 protected Modification handleEntry(List historyEntry) { 240 Modification mod = new Modification("vss"); 241 String nameAndDateLine = (String ) historyEntry.get(2); 242 mod.userName = parseUser(nameAndDateLine); 243 mod.modifiedTime = parseDate(nameAndDateLine); 244 245 String folderLine = (String ) historyEntry.get(0); 246 String fileLine = (String ) historyEntry.get(3); 247 boolean setPropertyOnDelete = false; 248 249 if (!isInSsDir(folderLine)) { 250 return null; 252 } else if (isBeforeLastBuild(mod.modifiedTime)) { 253 return null; 255 } else if (fileLine.startsWith("Labeled")) { 256 return null; 258 } else if (fileLine.startsWith("Checked in")) { 259 String fileName = substringFromLastSlash(folderLine); 260 String folderName = substringToLastSlash(folderLine); 261 Modification.ModifiedFile modfile = mod.createModifiedFile(fileName, folderName); 262 263 modfile.action = "checkin"; 264 mod.comment = parseComment(historyEntry); 265 } else if (fileLine.indexOf(" renamed to ") > -1) { 266 mod.comment = parseComment(historyEntry); 270 271 String fileName = fileLine.substring(0, fileLine.indexOf(" ")); 272 273 Modification.ModifiedFile modfile = mod.createModifiedFile(fileName, folderLine); 274 modfile.action = "delete"; 275 setPropertyOnDelete = true; 276 277 } else if (fileLine.indexOf(" moved to ") > -1) { 278 mod.comment = parseComment(historyEntry); 282 String fileName = fileLine.substring(0, fileLine.indexOf(" ")); 283 284 Modification.ModifiedFile modfile = mod.createModifiedFile(fileName, folderLine); 285 modfile.action = "delete"; 286 setPropertyOnDelete = true; 287 288 } else { 289 String fileName = fileLine.substring(0, fileLine.lastIndexOf(" ")); 290 Modification.ModifiedFile modfile = mod.createModifiedFile(fileName, folderLine); 291 292 mod.comment = parseComment(historyEntry); 293 294 if (fileLine.endsWith("added")) { 295 modfile.action = "add"; 296 } else if (fileLine.endsWith("deleted")) { 297 modfile.action = "delete"; 298 setPropertyOnDelete = true; 299 } else if (fileLine.endsWith("recovered")) { 300 modfile.action = "recover"; 301 } else if (fileLine.endsWith("shared")) { 302 modfile.action = "branch"; 303 } 304 } 305 306 if (propertyOnDelete != null && setPropertyOnDelete) { 307 properties.put(propertyOnDelete, "true"); 308 } 309 310 if (property != null) { 311 properties.put(property, "true"); 312 } 313 return mod; 314 } 315 316 322 private String parseComment(List a) { 323 StringBuffer comment = new StringBuffer (); 324 for (int i = 4; i < a.size(); i++) { 325 comment.append(a.get(i)).append(" "); 326 } 327 return comment.toString().trim(); 328 } 329 330 342 public Date parseDate(String nameAndDateLine) { 343 String dateString = nameAndDateLine.substring( 345 nameAndDateLine.indexOf("Date:") + 5, 346 nameAndDateLine.indexOf("Time:")).trim(); 347 348 String timeString = nameAndDateLine.substring( 349 nameAndDateLine.indexOf("Time:") + 5).trim(); 350 351 if (!overridenDateFormat) { 352 int indexOfColon = dateString.indexOf("/:"); 354 if (indexOfColon != -1) { 355 dateString = dateString.substring(0, indexOfColon) 356 + dateString.substring(indexOfColon, indexOfColon + 2).replace(':', '0') 357 + dateString.substring(indexOfColon + 2); 358 } 359 360 } 361 StringBuffer dateToParse = new StringBuffer (); 362 dateToParse.append(dateString); 363 dateToParse.append(" "); 364 dateToParse.append(timeString); 365 if (!overridenDateFormat) { 366 dateToParse.append("m"); 370 } 371 try { 372 return vssDateTimeFormat.parse(dateToParse.toString()); 373 374 } catch (ParseException pe) { 375 LOG.error("Could not parse date in VssJournal file : " + dateToParse.toString(), pe); 376 } 377 return null; 378 } 379 380 386 public String parseUser(String userLine) { 387 final int startOfUserName = 6; 388 389 try { 390 return userLine.substring(startOfUserName, userLine.indexOf("Date: ") - 1).trim(); 391 } catch (StringIndexOutOfBoundsException e) { 392 LOG.error("Unparsable string was: " + userLine); 393 throw e; 394 } 395 396 } 397 398 402 public String substringFromLastSlash(String input) { 403 int lastSlashPos = input.lastIndexOf("/"); 404 if (lastSlashPos > 0 && lastSlashPos + 1 <= input.length()) { 405 return input.substring(lastSlashPos + 1); 406 } 407 408 return input; 409 } 410 411 415 public String substringToLastSlash(String input) { 416 int lastSlashPos = input.lastIndexOf("/"); 417 if (lastSlashPos > 0) { 418 return input.substring(0, lastSlashPos); 419 } 420 421 return input; 422 } 423 424 427 protected boolean isInSsDir(String path) { 428 boolean isInDir = (path.toLowerCase().startsWith(ssDir.toLowerCase())); 429 if (isInDir) { 430 if (ssDir.equalsIgnoreCase(path) || ('/' == path.charAt(ssDir.length())) || "$/".equalsIgnoreCase(ssDir)) { 435 } else { 437 isInDir = false; 439 } 440 } 441 return isInDir; 442 } 443 444 447 protected boolean isBeforeLastBuild(Date date) { 448 return date.before(lastBuild); 449 } 450 } 451 | Popular Tags |