1 19 package org.netbeans.modules.subversion.client.parser; 20 21 import java.io.BufferedInputStream ; 22 import java.io.BufferedReader ; 23 import java.io.File ; 24 import java.io.IOException ; 25 import java.io.InputStream ; 26 import java.text.ParseException ; 27 import java.util.ArrayList ; 28 import java.util.Date ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.Properties ; 32 import org.openide.ErrorManager; 33 34 38 public class WorkingCopyDetails { 39 static final String FILE_ATTRIBUTE_VALUE = "file"; static final String IS_HANDLED = "handled"; 41 private static final char SLASH_N = '\n'; 42 private static final char SLASH_R = '\r'; 43 44 static final String VERSION_ATTR_KEY = "wc-version"; 45 static final String VERSION_UNKNOWN = ""; 46 static final String VERSION_13 = "1.3"; 47 static final String VERSION_14 = "1.4"; 48 49 private final File file; 50 private final Map <String , String > attributes; 53 private Properties workingSvnProperties = null; 57 private Properties baseSvnProperties = null; 58 59 protected File propertiesFile = null; 60 private File basePropertiesFile = null; 61 private File textBaseFile = null; 62 63 64 private WorkingCopyDetails(File file, Map <String , String > attributes) { 65 this.file = file; 66 this.attributes = attributes; 67 } 68 69 public static WorkingCopyDetails createWorkingCopy(File file, Map <String , String > attributes) { 70 String version = attributes != null ? attributes.get(VERSION_ATTR_KEY) : VERSION_UNKNOWN; 71 if(version != null) { 72 if(version.equals(VERSION_13)) { 73 74 return new WorkingCopyDetails(file, attributes); 75 76 } else if(version.equals(VERSION_14)) { 77 78 return new WorkingCopyDetails(file, attributes) { 79 public boolean propertiesExist() throws IOException { 80 return getAttributes().containsKey("has-props"); } 82 public boolean propertiesModified() throws IOException { 83 return getAttributes().containsKey("has-prop-mods"); } 85 File getPropertiesFile() throws IOException { 86 if (propertiesFile == null) { 87 boolean modified = getBooleanValue("has-prop-mods"); propertiesFile = SvnWcUtils.getPropertiesFile(getFile(), modified ? false : true); 90 } 91 return propertiesFile; 92 } 93 }; 94 95 } else if(version.equals(VERSION_UNKNOWN)) { 96 97 WorkingCopyDetails wcd = new WorkingCopyDetails(file, attributes); 98 if(!wcd.isHandled()) { 99 return wcd; 100 } 101 throw new UnsupportedOperationException ("Unknown SVN working copy version: " + version); 104 } else { 105 106 throw new UnsupportedOperationException ("Unknown SVN working copy version: " + version); 108 } 109 } else { 110 ErrorManager.getDefault().log(ErrorManager.WARNING, "Could not determine the SVN working copy version for " + file + ". Falling back on 1.3"); return new WorkingCopyDetails(file, attributes); 112 } 113 } 114 115 protected Map <String , String > getAttributes() { 116 return attributes; 117 } 118 119 protected File getFile() { 120 return file; 121 } 122 123 public String getValue(String propertyName, String defaultValue) { 124 String returnValue = getValue(propertyName); 125 return returnValue != null ? returnValue : defaultValue; 126 } 127 128 public String getValue(String key) { 129 if(key==null) return null; 130 return getAttributes() != null ? getAttributes().get(key) : null; 131 } 132 133 public long getLongValue(String key) throws LocalSubversionException { 134 try { 135 String value = getValue(key); 136 if(value==null) return -1; 137 return Long.parseLong(value); 138 } catch (NumberFormatException ex) { 139 throw new LocalSubversionException(ex); 140 } 141 } 142 143 public Date getDateValue(String key) throws LocalSubversionException { 144 try { 145 String value = getValue(key); 146 if(value==null || value.equals("")) return null; 147 return SvnWcUtils.parseSvnDate(value); 148 } catch (ParseException ex) { 149 throw new LocalSubversionException(ex); 150 } 151 } 152 153 public boolean getBooleanValue(String key) { 154 String value = getValue(key); 155 if(value==null) return false; 156 return Boolean.valueOf(value).booleanValue(); 157 } 158 159 public boolean isHandled() { 160 return getBooleanValue(IS_HANDLED); 161 } 162 163 public boolean isFile() { 164 return getAttributes() !=null ? FILE_ATTRIBUTE_VALUE.equals(getAttributes().get("kind")) : false; } 166 167 File getPropertiesFile() throws IOException { 168 if (propertiesFile == null) { 169 propertiesFile = SvnWcUtils.getPropertiesFile(file, false); 170 } 171 return propertiesFile; 172 } 173 174 File getBasePropertiesFile() throws IOException { 175 if (basePropertiesFile == null) { 176 basePropertiesFile = SvnWcUtils.getPropertiesFile(file, true); 177 } 178 return basePropertiesFile; 179 } 180 181 private File getTextBaseFile() throws IOException { 182 if (textBaseFile == null) { 183 textBaseFile = SvnWcUtils.getTextBaseFile(file); 184 } 185 return textBaseFile; 186 } 187 188 private Properties getWorkingSvnProperties() throws IOException { 189 if (workingSvnProperties == null) { 190 workingSvnProperties = loadProperties(getPropertiesFile()); 191 } 192 return workingSvnProperties; 193 } 194 195 private Properties getBaseSvnProperties() throws IOException { 196 if (baseSvnProperties == null) { 197 baseSvnProperties = loadProperties(getBasePropertiesFile()); 198 } 199 return baseSvnProperties; 200 } 201 202 public boolean propertiesExist() throws IOException { 203 boolean returnValue = false; 204 File propsFile = getPropertiesFile(); 205 returnValue = propsFile != null ? propsFile.exists() : false; 206 if (returnValue) { 207 InputStream inputStream = new java.io.FileInputStream (propsFile); 209 try { 210 int size = 0; 211 int retval = inputStream.read(); 212 while ((retval != -1) && (size < 5)) { 213 size++; 214 retval = inputStream.read(); 215 } 216 returnValue = (size > 4); 217 } finally { 218 inputStream.close(); 219 } 220 } 221 222 return returnValue; 223 } 224 225 public boolean propertiesModified() throws IOException { 226 File basePropsFile = getPropertiesFile(); 227 File propsFile = getBasePropertiesFile(); 228 229 if ((basePropsFile == null) && (propsFile != null)) { 230 return true; 231 } 232 233 if ((basePropsFile != null) && (propsFile == null)) { 234 return true; 235 } 236 237 if ((basePropsFile == null) && (propsFile == null)) { 238 return false; 239 } 240 241 Properties baseProps = getBaseSvnProperties(); 242 Properties props = getWorkingSvnProperties(); 243 return !(baseProps.equals(props)); 244 } 245 246 private Properties loadProperties(File propsFile) throws IOException { 247 if(propsFile == null || !propsFile.exists()) { 248 return null; 249 } 250 Properties returnValue = new Properties (); 251 BufferedReader fileReader = new BufferedReader (new java.io.FileReader (propsFile)); 252 try { 253 String currentLine = fileReader.readLine(); 254 String propKey = null; 255 String propValue = ""; 256 boolean headerLine = true; 257 while (currentLine != null) { 258 if (!(headerLine)) { 259 if (propKey == null) { 260 propKey = currentLine; 261 } else { 262 propValue = currentLine; 263 returnValue.setProperty(propKey, propValue); 264 propKey = null; 265 propValue = ""; } 267 } 268 headerLine = !(headerLine); 269 currentLine = fileReader.readLine(); 270 } 271 } finally { 272 fileReader.close(); 273 } 274 return returnValue; 275 } 276 277 public boolean textModified() throws IOException { 278 boolean returnValue = false; 279 280 if (file.exists()) { 281 File baseFile = getTextBaseFile(); 282 if ((file == null) && (baseFile != null)) { 283 return true; 284 } 285 286 if ((file != null) && (baseFile == null)) { 287 return true; 288 } 289 290 if ((file == null) && (baseFile == null)) { 291 return false; 292 } 293 294 Properties workingSvnProps = getWorkingSvnProperties(); 295 String value = ""; 296 if(workingSvnProps!=null) { 297 value = workingSvnProps.getProperty("svn:special", "none"); } 299 if (value.equals("*")) { 300 if (isSymbolicLink()) { 301 returnValue = false; 302 } 303 } else { 304 String rawKeywords = workingSvnProps != null ? workingSvnProps.getProperty("svn:keywords") : null; if (rawKeywords != null) { 306 returnValue = isModifiedByLine(rawKeywords.trim()); 307 } else { 308 returnValue = isModifiedByByte(); 309 } 310 } 311 } 312 313 return returnValue; 314 } 315 316 private boolean isSymbolicLink() throws IOException { 317 boolean returnValue = false; 318 319 File baseFile = getTextBaseFile(); 320 if (baseFile != null) { 321 BufferedReader reader = null; 322 try { 323 reader = new BufferedReader (new java.io.FileReader (baseFile)); 324 String firstLine = reader.readLine(); 325 returnValue = firstLine.startsWith("link"); } finally { 327 if (reader != null) { 328 reader.close(); 329 } 330 } 331 } 332 return returnValue; 333 } 334 335 338 private boolean isModifiedByByte() throws IOException { 339 boolean returnValue = false; 340 341 InputStream baseStream = null; 342 InputStream fileStream = null; 343 try { 344 baseStream = new BufferedInputStream (new java.io.FileInputStream (textBaseFile)); 345 fileStream = new BufferedInputStream (new java.io.FileInputStream (file)); 346 347 int baseRetVal = baseStream.read(); 348 int fileRetVal = fileStream.read(); 349 350 while (baseRetVal != -1) { 351 if (baseRetVal != fileRetVal) { 352 boolean isLineEnding = false; 354 if ((SLASH_N == ((char) baseRetVal)) && SLASH_R == ((char) fileRetVal)) { 355 fileRetVal = fileStream.read(); 356 isLineEnding = (SLASH_N == ((char) fileRetVal)); 357 } else if ((SLASH_N == ((char) fileRetVal)) && SLASH_R == ((char) baseRetVal)) { 358 baseRetVal = baseStream.read(); 359 isLineEnding = (SLASH_N == ((char) baseRetVal)); 360 } 361 362 if (!(isLineEnding)) { 363 return true; 364 } 365 } 366 baseRetVal = baseStream.read(); 367 fileRetVal = fileStream.read(); 368 } 369 370 returnValue = (fileRetVal != -1); 373 } finally { 374 if(fileStream != null) { 375 fileStream.close(); 376 } 377 if(baseStream != null) { 378 baseStream.close(); 379 } 380 } 381 382 return returnValue; 383 } 384 385 388 private boolean isModifiedByLine(String rawKeywords) throws IOException { 389 boolean returnValue = false; 390 391 String [] keywords = rawKeywords.split(" "); 392 List <String > keywordsList = new ArrayList <String >(); 393 for (int i = 0; i < keywords.length; i++) { 394 String kw = keywords[i].toLowerCase(); 395 if(kw.equals("date") || kw.equals("lastchangeddate")) { keywordsList.add("LastChangedDate"); keywordsList.add("Date"); } else if(kw.equals("revision") || kw.equals("rev") || kw.equals("lastchangedrevision")) { keywordsList.add("LastChangedRevision"); keywordsList.add("Revision"); keywordsList.add("Rev"); } else if(kw.equals("author") || kw.equals("lastchangedby")) { keywordsList.add("LastChangedBy"); keywordsList.add("Author"); } else if(kw.equals("url") || kw.equals("headurl")) { keywordsList.add("HeadURL"); keywordsList.add("URL"); } else { 409 keywordsList.add(keywords[i]); 410 } 411 } 412 keywords = keywordsList.toArray(new String [keywordsList.size()]); 413 414 BufferedReader baseReader = null; 415 BufferedReader fileReader = null; 416 417 try { 418 baseReader = new BufferedReader (new java.io.FileReader (textBaseFile)); 419 fileReader = new BufferedReader (new java.io.FileReader (file)); 420 421 String baseLine = baseReader.readLine(); 422 String fileLine = fileReader.readLine(); 423 424 while (baseLine != null && fileLine != null) { 425 426 if (!fileLine.equals(baseLine)) { 427 boolean equal = false; 428 for (int i = 0; i < keywords.length; i++) { 429 String headerPattern = "$" + keywords[i]; if(fileLine.indexOf(headerPattern) > -1) { 431 equal = compareKeywordLines(fileLine, baseLine, keywords); 432 break; 433 } 434 } 435 if(!equal) { 436 return true; 437 } 438 } 439 440 baseLine = baseReader.readLine(); 441 fileLine = fileReader.readLine(); 442 } 443 444 returnValue = baseLine != null || fileLine != null; 445 446 } finally { 447 if (fileReader != null) { 448 fileReader.close(); 449 } 450 451 if (baseReader != null) { 452 baseReader.close(); 453 } 454 } 455 456 return returnValue; 457 } 458 459 private boolean compareKeywordLines(String modifiedLine, String baseLine, String [] keywords) { 460 461 int modifiedIdx = 0; 462 for (int fileIdx = 0; fileIdx < baseLine.length(); fileIdx++) { 463 464 if(baseLine.charAt(fileIdx) == '$') { 465 for (int keywordsIdx = 0; keywordsIdx < keywords.length; keywordsIdx++) { 467 468 String keyword = keywords[keywordsIdx]; 470 boolean gotHeader = false; 471 for (int keyIdx = 0; keyIdx < keyword.length(); keyIdx++) { 472 if(fileIdx + keyIdx + 1 > baseLine.length() - 1 || keyword.charAt(keyIdx) != baseLine.charAt(fileIdx + keyIdx + 1)) { 475 gotHeader = false; 476 break; } 478 gotHeader = true; 479 } 480 481 if(gotHeader) { 482 483 fileIdx += keyword.length(); 485 486 if(checkFollowingString(baseLine, fileIdx, "$")) { 488 fileIdx += 1; 489 } else if(checkFollowingString(baseLine, fileIdx, ":$")) { 490 fileIdx += 2; 491 } else { 492 return false; 494 } 495 496 modifiedIdx += keyword.length() + 1; while(++modifiedIdx < modifiedLine.length() && modifiedLine.charAt(modifiedIdx) != '$'); 500 501 if(modifiedIdx >= modifiedLine.length()) { 502 return false; 504 } 505 break; 506 } 507 } 508 } 509 if(modifiedLine.charAt(modifiedIdx) != baseLine.charAt(fileIdx)) { 510 return false; 511 } 512 modifiedIdx++; 513 if(modifiedIdx >= modifiedLine.length()) { 514 return fileIdx == baseLine.length() - 1; 516 } 517 } 518 return modifiedIdx == modifiedLine.length() - 2; 519 } 520 521 private boolean checkFollowingString(String baseLine, int offset, String str) { 522 if(baseLine.length() < offset + str.length()) { 523 return false; 524 } 525 for (int idx = 0; idx < str.length(); idx++) { 526 if(baseLine.charAt(offset + idx + 1) != str.charAt(idx)) { 527 return false; 528 } 529 } 530 return true; 531 } 532 533 } 534 | Popular Tags |