KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > subversion > client > parser > WorkingCopyDetails


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.subversion.client.parser;
20
21 import java.io.BufferedInputStream JavaDoc;
22 import java.io.BufferedReader JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.text.ParseException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Date JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Properties JavaDoc;
32 import org.openide.ErrorManager;
33
34 /**
35  *
36  * @author Ed Hillmann
37  */

38 public class WorkingCopyDetails {
39     static final String JavaDoc FILE_ATTRIBUTE_VALUE = "file"; // NOI18
40
static final String JavaDoc IS_HANDLED = "handled";
41     private static final char SLASH_N = '\n';
42     private static final char SLASH_R = '\r';
43
44     static final String JavaDoc VERSION_ATTR_KEY = "wc-version";
45     static final String JavaDoc VERSION_UNKNOWN = "";
46     static final String JavaDoc VERSION_13 = "1.3";
47     static final String JavaDoc VERSION_14 = "1.4";
48
49     private final File JavaDoc file;
50     //These Map stores the values in the SVN entities file
51
//for the file and its parent directory
52
private final Map JavaDoc<String JavaDoc, String JavaDoc> attributes;
53     //private Properties parentProps;
54
//These Properties store the working and base versions of the
55
//SVN properties for the file
56
private Properties JavaDoc workingSvnProperties = null;
57     private Properties JavaDoc baseSvnProperties = null;
58
59     protected File JavaDoc propertiesFile = null;
60     private File JavaDoc basePropertiesFile = null;
61     private File JavaDoc textBaseFile = null;
62
63     /** Creates a new instance of WorkingCopyDetails */
64     private WorkingCopyDetails(File JavaDoc file, Map JavaDoc<String JavaDoc, String JavaDoc> attributes) {
65         this.file = file;
66         this.attributes = attributes;
67     }
68
69     public static WorkingCopyDetails createWorkingCopy(File JavaDoc file, Map JavaDoc<String JavaDoc, String JavaDoc> attributes) {
70         String JavaDoc 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 JavaDoc {
80                         return getAttributes().containsKey("has-props"); // NOI18N
81
}
82                     public boolean propertiesModified() throws IOException JavaDoc {
83                         return getAttributes().containsKey("has-prop-mods"); // NOI18N
84
}
85                     File JavaDoc getPropertiesFile() throws IOException JavaDoc {
86                         if (propertiesFile == null) {
87                             // unchanged properties have only the base file
88
boolean modified = getBooleanValue("has-prop-mods"); // NOI18N
89
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                 // how is this possible?
102
throw new UnsupportedOperationException JavaDoc("Unknown SVN working copy version: " + version); // NOI18N
103

104             } else {
105
106                 throw new UnsupportedOperationException JavaDoc("Unknown SVN working copy version: " + version); // NOI18N
107

108             }
109         } else {
110             ErrorManager.getDefault().log(ErrorManager.WARNING, "Could not determine the SVN working copy version for " + file + ". Falling back on 1.3"); // NOI18N
111
return new WorkingCopyDetails(file, attributes);
112         }
113     }
114
115     protected Map JavaDoc<String JavaDoc, String JavaDoc> getAttributes() {
116         return attributes;
117     }
118     
119     protected File JavaDoc getFile() {
120         return file;
121     }
122     
123     public String JavaDoc getValue(String JavaDoc propertyName, String JavaDoc defaultValue) {
124         String JavaDoc returnValue = getValue(propertyName);
125         return returnValue != null ? returnValue : defaultValue;
126     }
127
128     public String JavaDoc getValue(String JavaDoc key) {
129         if(key==null) return null;
130         return getAttributes() != null ? getAttributes().get(key) : null;
131     }
132
133     public long getLongValue(String JavaDoc key) throws LocalSubversionException {
134         try {
135             String JavaDoc value = getValue(key);
136             if(value==null) return -1;
137             return Long.parseLong(value);
138         } catch (NumberFormatException JavaDoc ex) {
139             throw new LocalSubversionException(ex);
140         }
141     }
142
143     public Date JavaDoc getDateValue(String JavaDoc key) throws LocalSubversionException {
144         try {
145             String JavaDoc value = getValue(key);
146             if(value==null || value.equals("")) return null;
147             return SvnWcUtils.parseSvnDate(value);
148         } catch (ParseException JavaDoc ex) {
149             throw new LocalSubversionException(ex);
150         }
151     }
152
153     public boolean getBooleanValue(String JavaDoc key) {
154         String JavaDoc 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; // NOI18N
165
}
166
167     File JavaDoc getPropertiesFile() throws IOException JavaDoc {
168         if (propertiesFile == null) {
169             propertiesFile = SvnWcUtils.getPropertiesFile(file, false);
170         }
171         return propertiesFile;
172     }
173
174     File JavaDoc getBasePropertiesFile() throws IOException JavaDoc {
175         if (basePropertiesFile == null) {
176             basePropertiesFile = SvnWcUtils.getPropertiesFile(file, true);
177         }
178         return basePropertiesFile;
179     }
180
181     private File JavaDoc getTextBaseFile() throws IOException JavaDoc {
182         if (textBaseFile == null) {
183             textBaseFile = SvnWcUtils.getTextBaseFile(file);
184         }
185         return textBaseFile;
186     }
187
188     private Properties JavaDoc getWorkingSvnProperties() throws IOException JavaDoc {
189         if (workingSvnProperties == null) {
190             workingSvnProperties = loadProperties(getPropertiesFile());
191         }
192         return workingSvnProperties;
193     }
194
195     private Properties JavaDoc getBaseSvnProperties() throws IOException JavaDoc {
196         if (baseSvnProperties == null) {
197             baseSvnProperties = loadProperties(getBasePropertiesFile());
198         }
199         return baseSvnProperties;
200     }
201
202     public boolean propertiesExist() throws IOException JavaDoc {
203         boolean returnValue = false;
204         File JavaDoc propsFile = getPropertiesFile();
205         returnValue = propsFile != null ? propsFile.exists() : false;
206         if (returnValue) {
207             //A size of 4 bytes is equivalent to empty properties
208
InputStream JavaDoc inputStream = new java.io.FileInputStream JavaDoc(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 JavaDoc {
226         File JavaDoc basePropsFile = getPropertiesFile();
227         File JavaDoc 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 JavaDoc baseProps = getBaseSvnProperties();
242         Properties JavaDoc props = getWorkingSvnProperties();
243         return !(baseProps.equals(props));
244     }
245
246     private Properties JavaDoc loadProperties(File JavaDoc propsFile) throws IOException JavaDoc {
247         if(propsFile == null || !propsFile.exists()) {
248             return null;
249         }
250         Properties JavaDoc returnValue = new Properties JavaDoc();
251         BufferedReader JavaDoc fileReader = new BufferedReader JavaDoc(new java.io.FileReader JavaDoc(propsFile));
252         try {
253             String JavaDoc currentLine = fileReader.readLine();
254             String JavaDoc propKey = null;
255             String JavaDoc 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 = ""; // NOI18N
266
}
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 JavaDoc {
278         boolean returnValue = false;
279
280         if (file.exists()) {
281             File JavaDoc 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 JavaDoc workingSvnProps = getWorkingSvnProperties();
295             String JavaDoc value = "";
296             if(workingSvnProps!=null) {
297                 value = workingSvnProps.getProperty("svn:special", "none"); // NOI18N
298
}
299             if (value.equals("*")) {
300         if (isSymbolicLink()) {
301                 returnValue = false;
302         }
303             } else {
304             String JavaDoc rawKeywords = workingSvnProps != null ? workingSvnProps.getProperty("svn:keywords") : null; // NOI18N
305
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 JavaDoc {
317         boolean returnValue = false;
318
319     File JavaDoc baseFile = getTextBaseFile();
320     if (baseFile != null) {
321             BufferedReader JavaDoc reader = null;
322             try {
323                 reader = new BufferedReader JavaDoc(new java.io.FileReader JavaDoc(baseFile));
324             String JavaDoc firstLine = reader.readLine();
325             returnValue = firstLine.startsWith("link"); // NOI18N
326
} finally {
327         if (reader != null) {
328                     reader.close();
329         }
330             }
331         }
332         return returnValue;
333     }
334
335     /**
336      * Assumes that textBaseFile exists
337      */

338     private boolean isModifiedByByte() throws IOException JavaDoc {
339     boolean returnValue = false;
340
341         InputStream JavaDoc baseStream = null;
342         InputStream JavaDoc fileStream = null;
343         try {
344             baseStream = new BufferedInputStream JavaDoc(new java.io.FileInputStream JavaDoc(textBaseFile));
345             fileStream = new BufferedInputStream JavaDoc(new java.io.FileInputStream JavaDoc(file));
346
347             int baseRetVal = baseStream.read();
348             int fileRetVal = fileStream.read();
349
350             while (baseRetVal != -1) {
351                 if (baseRetVal != fileRetVal) {
352                     //Check for line endings... ignore if need be
353
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             //If we're here, then baseRetVal is -1. So, returnValue
371
//should be true is fileRetVal != -1
372
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     /**
386      * Assumes that textBaseFile exists
387      */

388     private boolean isModifiedByLine(String JavaDoc rawKeywords) throws IOException JavaDoc {
389         boolean returnValue = false;
390
391         String JavaDoc[] keywords = rawKeywords.split(" ");
392         List JavaDoc<String JavaDoc> keywordsList = new ArrayList JavaDoc<String JavaDoc>();
393         for (int i = 0; i < keywords.length; i++) {
394             String JavaDoc kw = keywords[i].toLowerCase();
395             if(kw.equals("date") || kw.equals("lastchangeddate")) { // NOI18N
396
keywordsList.add("LastChangedDate"); // NOI18N
397
keywordsList.add("Date"); // NOI18N
398
} else if(kw.equals("revision") || kw.equals("rev") || kw.equals("lastchangedrevision")) { // NOI18N
399
keywordsList.add("LastChangedRevision"); // NOI18N
400
keywordsList.add("Revision"); // NOI18N
401
keywordsList.add("Rev"); // NOI18N
402
} else if(kw.equals("author") || kw.equals("lastchangedby")) { // NOI18N
403
keywordsList.add("LastChangedBy"); // NOI18N
404
keywordsList.add("Author"); // NOI18N
405
} else if(kw.equals("url") || kw.equals("headurl")) { // NOI18N
406
keywordsList.add("HeadURL"); // NOI18N
407
keywordsList.add("URL"); // NOI18N
408
} else {
409                 keywordsList.add(keywords[i]);
410             }
411         }
412         keywords = keywordsList.toArray(new String JavaDoc[keywordsList.size()]);
413         
414         BufferedReader JavaDoc baseReader = null;
415         BufferedReader JavaDoc fileReader = null;
416
417         try {
418             baseReader = new BufferedReader JavaDoc(new java.io.FileReader JavaDoc(textBaseFile));
419             fileReader = new BufferedReader JavaDoc(new java.io.FileReader JavaDoc(file));
420
421             String JavaDoc baseLine = baseReader.readLine();
422             String JavaDoc 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 JavaDoc headerPattern = "$" + keywords[i]; // NOI18N
430
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 JavaDoc modifiedLine, String JavaDoc baseLine, String JavaDoc[] keywords) {
460
461         int modifiedIdx = 0;
462         for (int fileIdx = 0; fileIdx < baseLine.length(); fileIdx++) {
463
464             if(baseLine.charAt(fileIdx) == '$') {
465                 // 1. could be a keyword ...
466
for (int keywordsIdx = 0; keywordsIdx < keywords.length; keywordsIdx++) {
467
468                     String JavaDoc keyword = keywords[keywordsIdx]; // NOI18N
469

470                     boolean gotHeader = false;
471                     for (int keyIdx = 0; keyIdx < keyword.length(); keyIdx++) {
472                         if(fileIdx + keyIdx + 1 > baseLine.length() - 1 || // we are already at the end of the baseline
473
keyword.charAt(keyIdx) != baseLine.charAt(fileIdx + keyIdx + 1)) // the chars are not equal
474
{
475                             gotHeader = false;
476                             break; // 2. it's not a keyword -> try the next one
477
}
478                         gotHeader = true;
479                     }
480                     
481                     if(gotHeader) {
482                         
483                         // base file idx
484
fileIdx += keyword.length();
485                         
486                         // 3. now check if there is somthing like "$", ":$" after the keyword
487
if(checkFollowingString(baseLine, fileIdx, "$")) {
488                             fileIdx += 1;
489                         } else if(checkFollowingString(baseLine, fileIdx, ":$")) {
490                             fileIdx += 2;
491                         } else {
492                             // we are done
493
return false;
494                         }
495                                                 
496                         // 4. it was a correctly closed keyword -> skip the chars until the next '$'
497
// for the modified file - '$Id: '
498
modifiedIdx += keyword.length() + 1; //
499
while(++modifiedIdx < modifiedLine.length() && modifiedLine.charAt(modifiedIdx) != '$');
500
501                         if(modifiedIdx >= modifiedLine.length()) {
502                             // modified line is done but we found a keyword -> wrong
503
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                 // if the modified line is done then must be also the base line done
515
return fileIdx == baseLine.length() - 1;
516             }
517         }
518         return modifiedIdx == modifiedLine.length() - 2;
519     }
520     
521     private boolean checkFollowingString(String JavaDoc baseLine, int offset, String JavaDoc 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