1 37 package net.sourceforge.cruisecontrol.sourcecontrols; 38 39 import net.sourceforge.cruisecontrol.CruiseControlException; 40 import net.sourceforge.cruisecontrol.SourceControl; 41 import net.sourceforge.cruisecontrol.util.ValidationHelper; 42 import net.sourceforge.cruisecontrol.util.StreamPumper; 43 44 import org.apache.log4j.Logger; 45 46 import java.io.BufferedReader ; 47 import java.io.File ; 48 import java.io.IOException ; 49 import java.io.InputStream ; 50 import java.io.InputStreamReader ; 51 import java.text.ParseException ; 52 import java.text.SimpleDateFormat ; 53 import java.util.ArrayList ; 54 import java.util.Arrays ; 55 import java.util.Date ; 56 import java.util.Hashtable ; 57 import java.util.List ; 58 import java.util.Map ; 59 import java.util.StringTokenizer ; 60 import java.util.Vector ; 61 62 71 public class ClearCase implements SourceControl { 72 private static final int DEFAULT = 0; 73 private static final int DISABLED = 1; 74 private static final int ENABLED = 2; 75 76 private static final Logger LOG = Logger.getLogger(ClearCase.class); 77 78 private Hashtable properties = new Hashtable (); 79 80 private String property; 81 82 85 private String viewPath; 86 87 90 private String branch; 91 private int recursive = DEFAULT; private int all = DEFAULT; 94 97 private final SimpleDateFormat inDateFormatter = 98 new SimpleDateFormat ("dd-MMMM-yyyy.HH:mm:ss"); 99 100 103 private final SimpleDateFormat outDateFormatter = 104 new SimpleDateFormat ("yyyyMMdd.HHmmss"); 105 106 109 static final String DELIMITER = "#~#"; 110 111 115 static final String END_OF_STRING_DELIMITER = "@#@#@#@#@#@#@#@#@#@#@#@"; 116 117 122 public void setViewpath(String path) { 123 viewPath = new File (path).getAbsolutePath(); 125 } 126 127 132 public void setBranch(String branch) { 133 this.branch = branch; 134 } 135 136 139 public void setRecursive(boolean recursive) { 140 this.recursive = recursive ? ENABLED : DISABLED; 141 } 142 143 144 157 public void setAll(boolean all) { 158 this.all = all ? ENABLED : DISABLED; 159 160 if (this.recursive == DEFAULT && all) { 161 this.recursive = DISABLED; 162 } 163 } 164 165 public void setProperty(String property) { 166 this.property = property; 167 } 168 169 public Map getProperties() { 170 return properties; 171 } 172 173 public void validate() throws CruiseControlException { 174 ValidationHelper.assertIsSet(branch, "branch", this.getClass()); 175 ValidationHelper.assertIsSet(viewPath, "viewpath", this.getClass()); 176 if (recursive == ENABLED && all == ENABLED) { 177 ValidationHelper.fail("'recursive' and 'all' are mutually exclusive attributes for ClearCase"); 178 } 179 } 180 181 190 public List getModifications(Date lastBuild, Date now) { 191 String lastBuildDate = inDateFormatter.format(lastBuild); 192 String nowDate = inDateFormatter.format(now); 193 properties.put("clearcaselastbuild", lastBuildDate); 194 properties.put("clearcasenow", nowDate); 195 196 207 String command = "cleartool lshistory"; 208 209 if (branch != null) { 210 command += " -branch " + branch; 211 } 212 213 if (recursive == DEFAULT || recursive == ENABLED) { 214 command += " -r"; 215 } else if (all == ENABLED) { 216 command += " -all"; 217 } 218 219 command += " -nco -since " + lastBuildDate; 220 command += " -fmt %u" 221 + DELIMITER 222 + "%Nd" 223 + DELIMITER 224 + "%En" 225 + DELIMITER 226 + "%Vn" 227 + DELIMITER 228 + "%o" 229 + DELIMITER 230 + "!%l" 231 + DELIMITER 232 + "!%a" 233 + DELIMITER 234 + "%Nc" 235 + END_OF_STRING_DELIMITER 236 + "\\n"; 237 238 File root = new File (viewPath); 239 240 LOG.info("ClearCase: getting modifications for " + viewPath); 241 242 LOG.debug("Command to execute : " + command); 243 List modifications = null; 244 try { 245 Process p = Runtime.getRuntime().exec(command, null, root); 246 247 StreamPumper errorPumper = new StreamPumper(p.getErrorStream()); 248 new Thread (errorPumper).start(); 249 250 InputStream input = p.getInputStream(); 251 modifications = parseStream(input); 252 253 p.waitFor(); 254 p.getInputStream().close(); 255 p.getOutputStream().close(); 256 p.getErrorStream().close(); 257 } catch (Exception e) { 258 LOG.error("Error in executing the Clear Case command : ", e); 259 } 260 261 if (modifications == null) { 262 modifications = new ArrayList (); 263 } 264 265 return modifications; 266 } 267 268 276 List parseStream(InputStream input) throws IOException { 277 ArrayList modifications = new ArrayList (); 278 BufferedReader reader = new BufferedReader (new InputStreamReader (input)); 279 String ls = System.getProperty("line.separator"); 280 281 String line; 282 String lines = ""; 283 284 while ((line = reader.readLine()) != null) { 285 if (!lines.equals("")) { 286 lines += ls; 287 } 288 lines += line; 289 ClearCaseModification mod = null; 290 if (lines.indexOf(END_OF_STRING_DELIMITER) > -1) { 291 mod = parseEntry(lines.substring(0, lines.indexOf(END_OF_STRING_DELIMITER))); 292 lines = ""; 293 } 294 if (mod != null) { 295 modifications.add(mod); 296 } 297 } 298 return modifications; 299 } 300 301 309 private ClearCaseModification parseEntry(String line) { 310 LOG.debug("parsing entry: " + line); 311 String [] tokens = tokeniseEntry(line); 312 if (tokens == null) { 313 return null; 314 } 315 String username = tokens[0].trim(); 316 317 String timeStamp = tokens[1].trim(); 318 String elementName = tokens[2].trim(); 319 String version = tokens[3].trim(); 320 String operationType = tokens[4].trim(); 321 322 String labelList = tokens[5].substring(1).trim(); 323 Vector labels = extractLabelsList(labelList); 324 325 String attributeList = tokens[6].substring(1).trim(); 326 Hashtable attributes = extractAttributesMap(attributeList); 327 328 String comment = tokens[7].trim(); 329 330 if (operationType.equals("mkbranch") || operationType.equals("rmbranch")) { 332 return null; 333 } 334 335 if (elementName.indexOf("@@") >= 0) { 337 return null; 338 } 339 340 ClearCaseModification mod = new ClearCaseModification(); 341 342 mod.userName = username; 343 mod.revision = version; 344 345 String folderName, fileName; 346 int sep = elementName.lastIndexOf(File.separator); 347 if (sep > -1) { 348 folderName = elementName.substring(0, sep); 349 fileName = elementName.substring(sep + 1); 350 } else { 351 folderName = null; 352 fileName = elementName; 353 } 354 ClearCaseModification.ModifiedFile modfile = mod.createModifiedFile(fileName, folderName); 355 356 try { 357 mod.modifiedTime = outDateFormatter.parse(timeStamp); 358 } catch (ParseException e) { 359 mod.modifiedTime = null; 360 } 361 362 modfile.action = operationType; 363 modfile.revision = version; 364 365 mod.type = "clearcase"; 366 mod.labels = labels; 367 mod.attributes = attributes; 368 369 mod.comment = comment; 370 371 if (property != null) { 372 properties.put(property, "true"); 373 } 374 375 377 return mod; 378 } 379 380 private String [] tokeniseEntry(String line) { 381 int maxTokens = 8; 382 int minTokens = maxTokens - 1; String [] tokens = new String [maxTokens]; 384 Arrays.fill(tokens, ""); 385 int tokenIndex = 0; 386 for (int oldIndex = 0, index = line.indexOf(DELIMITER, 0); true; 387 oldIndex = index + DELIMITER.length(), index = line.indexOf(DELIMITER, oldIndex), tokenIndex++) { 388 if (tokenIndex > maxTokens) { 389 LOG.debug("Too many tokens; skipping entry"); 390 return null; 391 } 392 if (index == -1) { 393 tokens[tokenIndex] = line.substring(oldIndex); 394 break; 395 } else { 396 tokens[tokenIndex] = line.substring(oldIndex, index); 397 } 398 } 399 if (tokenIndex < minTokens) { 400 LOG.debug("Not enough tokens; skipping entry"); 401 return null; 402 } 403 return tokens; 404 } 405 406 410 private Hashtable extractAttributesMap(String attributeList) { 411 Hashtable attributes = null; 412 if (attributeList.length() > 0) { 413 attributes = new Hashtable (); 414 StringTokenizer attrST = new StringTokenizer (attributeList, "(), "); 415 while (attrST.hasMoreTokens()) { 416 String attr = attrST.nextToken(); 417 int idx = attr.indexOf('='); 418 if (idx > 0) { 419 String attrName = attr.substring(0, idx); 420 String attrValue = attr.substring(idx + 1); 421 if (attrValue.startsWith("\"")) { 422 attrValue = attrValue.substring(1, attrValue.length() - 1); 423 } 424 attributes.put(attrName, attrValue); 425 } 426 } 427 } 428 return attributes; 429 } 430 431 435 private Vector extractLabelsList(String labelList) { 436 Vector labels = null; 437 if (labelList.length() > 0) { 438 labels = new Vector (); 439 StringTokenizer labelST = new StringTokenizer (labelList, "(), "); 440 while (labelST.hasMoreTokens()) { 441 labels.add(labelST.nextToken().trim()); 442 } 443 } 444 return labels; 445 } 446 } 447 | Popular Tags |