1 12 package org.eclipse.team.internal.ccvs.core.client.listeners; 13 14 import java.text.*; 15 import java.util.*; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 import org.eclipse.core.runtime.IStatus; 19 import org.eclipse.osgi.util.NLS; 20 import org.eclipse.team.internal.ccvs.core.*; 21 import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener; 22 import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; 23 import org.eclipse.team.internal.ccvs.core.util.Util; 24 25 29 public class LogListener extends CommandOutputListener { 30 31 34 private static final String LOG_TIMESTAMP_FORMAT_OLD= "yyyy/MM/dd HH:mm:ss zzz"; private static final String LOG_TIMESTAMP_FORMAT= "yyyy-MM-dd HH:mm:ss zzz"; private static final Locale LOG_TIMESTAMP_LOCALE= Locale.US; 37 private final DateFormat LOG_DATE_FORMATTER_OLD = new SimpleDateFormat(LOG_TIMESTAMP_FORMAT_OLD, LOG_TIMESTAMP_LOCALE); 38 private final DateFormat LOG_DATE_FORMATTER = new SimpleDateFormat(LOG_TIMESTAMP_FORMAT, LOG_TIMESTAMP_LOCALE); 39 40 private static final String NOTHING_KNOWN_ABOUT = "nothing known about "; 43 private final int DONE = 4; 45 private final int COMMENT = 3; 46 private final int REVISION = 2; 47 private final int SYMBOLIC_NAMES = 1; 48 private final int BEGIN = 0; 49 50 public final static String BRANCH_REVISION = "branchRevision"; 53 private RemoteFile currentFile; 55 private int state = BEGIN; 56 private StringBuffer comment; 57 private String fileState; 58 private String revision; 59 private String author; 60 private String creationDate; 61 private List versions = new ArrayList(); 62 63 private final ILogEntryListener listener; 64 65 68 public LogListener(ILogEntryListener listener) { 69 this.listener = listener; 70 } 71 72 public LogListener(RemoteFile file, ILogEntryListener listener) { 73 this(listener); 74 this.currentFile = file; 75 } 76 77 private String getRelativeFilePath(ICVSRepositoryLocation location, String fileName) { 78 if (fileName.endsWith(",v")) { fileName = fileName.substring(0, fileName.length() - 2); 80 } 81 fileName = Util.removeAtticSegment(fileName); 82 String rootDirectory = location.getRootDirectory(); 83 if (fileName.startsWith(rootDirectory)) { 84 try { 85 fileName = Util.getRelativePath(rootDirectory, fileName); 86 } catch (CVSException e) { 87 CVSProviderPlugin.log(e); 88 return null; 89 } 90 } 91 return fileName; 92 } 93 94 public IStatus errorLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) { 95 String serverMessage = getServerMessage(line, location); 96 if (serverMessage != null) { 97 if (serverMessage.startsWith(NOTHING_KNOWN_ABOUT)) { 100 return new CVSStatus(IStatus.ERROR, CVSStatus.DOES_NOT_EXIST, line, commandRoot); 101 } 102 } 103 return OK; 104 } 105 106 public IStatus messageLine(String line, ICVSRepositoryLocation location, ICVSFolder commandRoot, IProgressMonitor monitor) { 107 switch (state) { 110 case BEGIN: 111 if (line.startsWith("RCS file: ")) { String fileName = getRelativeFilePath(location, line.substring(10).trim()); 114 if (fileName == null) { 115 currentFile = null; 116 handleInvalidFileName(location, fileName); 117 } else { 118 if (currentFile == null || !currentFile.getRepositoryRelativePath().equals(fileName)) { 119 beginFile(location, fileName); 121 } 122 } 123 } else if (line.startsWith("symbolic names:")) { state = SYMBOLIC_NAMES; 125 } else if (line.startsWith("revision ")) { revision = line.substring(9); 127 state = REVISION; 128 } else if (line.startsWith("total revisions:")){ int indexOfSelectedRevisions = line.lastIndexOf("selected revisions: "); String selectedRevisions = line.substring(indexOfSelectedRevisions + 20).trim(); 135 if (selectedRevisions.equals("0")){ state = COMMENT; 138 revision = BRANCH_REVISION; 139 comment = new StringBuffer (); 140 } 141 } 142 break; 143 case SYMBOLIC_NAMES: 144 if (line.startsWith("keyword substitution:")) { state = BEGIN; 146 } else { 147 int firstColon = line.indexOf(':'); 148 String tagName = line.substring(1, firstColon); 149 String tagRevision = line.substring(firstColon + 2); 150 versions.add(new VersionInfo(tagRevision, tagName)); 151 } 152 break; 153 case REVISION: 154 int endOfDateIndex = line.indexOf(';', 6); 157 creationDate = line.substring(6, endOfDateIndex) + " GMT"; 159 int endOfAuthorIndex = line.indexOf(';', endOfDateIndex + 1); 161 author = line.substring(endOfDateIndex + 11, endOfAuthorIndex); 162 163 fileState = line.substring(endOfAuthorIndex + 10, line.indexOf(';', endOfAuthorIndex + 1)); 165 comment = new StringBuffer (); 166 state = COMMENT; 167 break; 168 case COMMENT: 169 if (line.startsWith("branches:")) break; if (line.equals("=============================================================================") || line.equals("----------------------------")) { state = DONE; 174 break; 175 } 176 if (comment == null) 178 break; 179 180 if (comment.length() != 0) comment.append('\n'); 181 comment.append(line); 182 break; 183 } 184 if (state == DONE) { 185 List thisRevisionTags = new ArrayList(3); 187 List revisionVersions = new ArrayList(3); 189 for (Iterator i = versions.iterator(); i.hasNext();) { 190 VersionInfo version = (VersionInfo) i.next(); 191 String tagName = version.getTagName(); 192 String tagRevision = version.getTagRevision(); 193 194 if (tagRevision.equals(revision) || 195 revision.equals(BRANCH_REVISION)) { 196 int type = version.isBranch() ? CVSTag.BRANCH : CVSTag.VERSION; 197 thisRevisionTags.add(new CVSTag(tagName, type)); 198 if (revision.equals(BRANCH_REVISION)){ 199 revisionVersions.add(tagRevision); 201 } 202 } 203 } 204 Date date = null; 205 if (creationDate != null) 206 date = convertFromLogTime(creationDate); 207 208 if (currentFile != null) { 209 LogEntry entry = new LogEntry(currentFile, revision, author, date, 210 comment.toString(), fileState, (CVSTag[]) thisRevisionTags.toArray(new CVSTag[thisRevisionTags.size()]), (String []) revisionVersions.toArray(new String [revisionVersions.size()])); 211 addEntry(entry); 212 } 213 state = BEGIN; 214 } 215 return OK; 216 } 217 218 protected void beginFile(ICVSRepositoryLocation location, String fileName) { 219 currentFile = RemoteFile.create(fileName, location); 220 versions.clear(); 221 } 222 223 protected void addEntry(LogEntry entry) { 224 listener.handleLogEntryReceived(entry); 225 } 226 227 protected void handleInvalidFileName(ICVSRepositoryLocation location, String badFilePath) { 228 CVSProviderPlugin.log(IStatus.WARNING, "Invalid file path '" + badFilePath + "' received from " + location.toString(), null); } 230 231 235 private Date convertFromLogTime(String modTime) { 236 DateFormat format = LOG_DATE_FORMATTER; 237 if (modTime.length() > 4 && modTime.charAt(4) == '/') 239 format = LOG_DATE_FORMATTER_OLD; 240 241 try { 242 return format.parse(modTime); 243 } catch (ParseException e) { 244 return null; 246 } 247 } 248 249 private static class VersionInfo { 250 private final String version; 251 private final boolean isBranch; 252 private String tagRevision; 253 private final String tagName; 254 255 public VersionInfo(String version, String tagName) { 256 this.version = version; 257 this.tagName = tagName; 258 this.isBranch = isBranchTag(version); 259 tagRevision = version; 260 if (isBranch) { 261 int lastDot = version.lastIndexOf('.'); 262 if (lastDot == -1) { 263 CVSProviderPlugin.log(IStatus.ERROR, 264 NLS.bind(CVSMessages.LogListener_invalidRevisionFormat, new String [] { tagName, version }), null); 265 } else { 266 if (version.charAt(lastDot - 1) == '0' && version.charAt(lastDot - 2) == '.') { 267 lastDot = lastDot - 2; 268 } 269 tagRevision = version.substring(0, lastDot); 270 } 271 } 272 } 273 274 public String getVersion() { 275 return this.version; 276 } 277 278 public String getTagName() { 279 return this.tagName; 280 } 281 282 public String getTagRevision() { 283 return this.tagRevision; 284 } 285 286 public boolean isBranch() { 287 return isBranch; 288 } 289 290 293 private boolean isBranchTag(String tagName) { 294 int numberOfDots = 0; 296 int lastDot = 0; 297 for (int i = 0; i < tagName.length(); i++) { 298 if (tagName.charAt(i) == '.') { 299 numberOfDots++; 300 lastDot = i; 301 } 302 } 303 if ((numberOfDots % 2) == 0) return true; 304 if (numberOfDots == 1) return false; 305 306 if (tagName.charAt(lastDot - 1) == '0' && tagName.charAt(lastDot - 2) == '.') return true; 308 return false; 309 } 310 } 311 } 312 | Popular Tags |