1 37 package net.sourceforge.cruisecontrol.sourcecontrols; 38 39 import java.io.BufferedReader ; 40 import java.io.IOException ; 41 import java.io.InputStream ; 42 import java.io.InputStreamReader ; 43 import java.text.MessageFormat ; 44 import java.text.ParseException ; 45 import java.text.SimpleDateFormat ; 46 import java.util.ArrayList ; 47 import java.util.Date ; 48 import java.util.Hashtable ; 49 import java.util.Iterator ; 50 import java.util.List ; 51 import java.util.Map ; 52 import java.util.StringTokenizer ; 53 54 import net.sourceforge.cruisecontrol.CruiseControlException; 55 import net.sourceforge.cruisecontrol.Modification; 56 import net.sourceforge.cruisecontrol.SourceControl; 57 import net.sourceforge.cruisecontrol.util.StreamPumper; 58 import net.sourceforge.cruisecontrol.util.ValidationHelper; 59 60 import org.apache.log4j.Logger; 61 62 67 68 public class SnapshotCM implements SourceControl { 69 70 private final SimpleDateFormat inDateFormatter = new SimpleDateFormat ("yyyy.MM.dd.HH.mm.ss"); 71 72 public static final String OUT_DATE_FORMAT = "yyyy/MM/dd HH:mm:ss"; 73 74 private final SimpleDateFormat outDateFormatter = new SimpleDateFormat (OUT_DATE_FORMAT); 75 76 private static final MessageFormat EXECUTABLE = new MessageFormat ("whist -RA -c{0} \"{1}\""); 77 78 private static final String FILE_HEADER = "============================================================="; 79 80 private static final String REVISION_HEADER = "----------------------------"; 81 82 private static final String CHANGE_DELETE = "Delete"; 83 84 85 private static final Logger LOG = Logger.getLogger(SnapshotCM.class); 86 87 private Hashtable props = new Hashtable (); 88 89 private String property; 90 91 private String propertyOnDelete; 92 93 97 private List sourcePaths = new ArrayList (); 98 99 102 public void setProperty(String property) { 103 this.property = property; 104 } 105 106 109 public void setPropertyOnDelete(String propertyOnDelete) { 110 this.propertyOnDelete = propertyOnDelete; 111 } 112 113 public Map getProperties() { 114 return this.props; 115 } 116 117 public void setSourcePaths(String sourcePaths) { 118 StringTokenizer st = new StringTokenizer (sourcePaths, ";"); 119 while (st.hasMoreTokens()) { 120 setSourcePath(st.nextToken()); 121 } 122 } 123 124 public void setSourcePath(String sourcePath) { 125 this.sourcePaths.add(new SourcePath(sourcePath)); 126 } 127 128 public SourcePath createSourcePath() { 129 SourcePath sourcePath = new SourcePath(); 130 this.sourcePaths.add(sourcePath); 131 return sourcePath; 132 } 133 134 137 public void validate() throws CruiseControlException { 138 ValidationHelper.assertFalse(this.sourcePaths.isEmpty(), 139 "'sourcePaths' or 'sourcePath' attribute, or nested sourcepath element(s)" 140 + " is a required attribute for SnapshotCM."); 141 } 142 143 152 public List getModifications(Date lastBuild, Date now) { 153 List modificationList = new ArrayList (); 155 156 String [] parameters = new String [2]; 158 parameters[0] = inDateFormatter.format(lastBuild); 159 160 for (Iterator i = this.sourcePaths.iterator(); i.hasNext(); ) { 161 parameters[1] = ((SourcePath) i.next()).getPath(); 162 163 String command = EXECUTABLE.format(parameters); 164 LOG.info("Running command: " + command); 165 try { 166 Process p = Runtime.getRuntime().exec(command); 167 168 StreamPumper errorPumper = new StreamPumper(p.getErrorStream()); 169 new Thread (errorPumper).start(); 170 171 InputStream input = p.getInputStream(); 172 modificationList.addAll(parseStream(input)); 173 174 p.getInputStream().close(); 175 p.getOutputStream().close(); 176 p.getErrorStream().close(); 177 } catch (Exception e) { 178 LOG.error("Error in executing the SnapshotCM command : ", e); 179 } 180 } 181 182 if (!modificationList.isEmpty() && property != null) { 183 props.put(property, "true"); 184 } 185 186 return modificationList; 187 } 188 189 202 List parseStream(InputStream input) throws IOException { 203 List modifications = new ArrayList (); 204 BufferedReader reader = new BufferedReader (new InputStreamReader (input)); 205 206 StringBuffer sb = new StringBuffer (); 207 208 String line; 209 while ((line = reader.readLine()) != null) { 210 if (line.equals(FILE_HEADER)) { 211 List fileMods = parseEntry(sb.toString()); 212 modifications.addAll(fileMods); 213 sb = new StringBuffer (); 214 } else { 215 sb.append(line); 216 sb.append('\n'); 217 } 218 } 219 List fileMods = parseEntry(sb.toString()); 220 modifications.addAll(fileMods); 221 return modifications; 222 } 223 224 225 257 private List parseEntry(String entry) { 258 List modifications = new ArrayList (); 259 260 StringTokenizer st = new StringTokenizer (entry, "\n"); 261 264 if (st.countTokens() < 13) { 265 return modifications; 266 } 267 268 271 String line = st.nextToken(); 272 String entryname = line.substring(6); 273 String fileName; 274 String folderName; 275 int sep = entryname.lastIndexOf("/"); 276 if (sep == -1) { 277 sep = entryname.lastIndexOf("\\"); 278 } 279 if (sep > -1) { 280 folderName = entryname.substring(0, sep); 281 fileName = entryname.substring(sep + 1); 282 } else { 283 folderName = ""; 284 fileName = entryname; 285 } 286 287 String nextToken; 289 do { 290 nextToken = st.nextToken(); 291 } while (!(nextToken).equals(REVISION_HEADER)); 292 293 296 Modification mod = new Modification("snapshotcm"); 297 mod.createModifiedFile(fileName, folderName); 298 299 while (st.hasMoreTokens()) { 300 line = st.nextToken(); 301 if (line.equals(REVISION_HEADER) || !st.hasMoreTokens()) { 302 if (!line.trim().equals("") && !line.equals(REVISION_HEADER)) { 303 mod.comment += line; 305 } 306 307 modifications.add(mod); 309 mod = new Modification("snapshotcm"); 310 mod.createModifiedFile(fileName, folderName); 311 } else if (line.startsWith("Revision: ")) { int nextSpaceDelimiterIndex = line.indexOf(" ", 10); 313 int endIndex = nextSpaceDelimiterIndex > -1 ? nextSpaceDelimiterIndex : line.length(); 314 mod.revision = line.substring(10, endIndex); 315 } else if (line.startsWith("Date: ")) { try { 317 mod.modifiedTime = outDateFormatter.parse(line.substring(6, line.indexOf("-") - 1)); 318 } catch (ParseException pe) { 319 LOG.warn("Unable to parse date " + line.substring(6, line.indexOf("-") - 1)); 320 mod.modifiedTime = new Date (0); 321 } 322 } else if (line.startsWith("Author: ")) { mod.userName = line.substring(8).trim(); 324 if (mod.userName.indexOf(" ") > -1) { 325 mod.userName = mod.userName.substring(0, mod.userName.indexOf(" ")); 326 } 327 } else if (line.startsWith("Change: ")) { mod.type = line.substring(8).trim(); 329 if (mod.type.equals(CHANGE_DELETE) && propertyOnDelete != null) { 330 props.put(propertyOnDelete, "true"); 331 } 332 } else if (line.startsWith("Snapshot: ")) { 333 } else if (line.startsWith("Used in: ") || line.startsWith(" /")) { 335 338 } else if (!line.trim().equals("")) { 340 mod.comment += line; 342 } 343 } 344 345 return modifications; 346 } 347 348 public static class SourcePath { 349 private String path; 350 351 public SourcePath() { 352 } 353 354 public SourcePath(String path) { 355 this.path = path; 356 } 357 358 public void setPath(String path) { 359 this.path = path; 360 } 361 362 public String getPath() { 363 return this.path; 364 } 365 } 366 } 367 | Popular Tags |