KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cvsgrab > LocalRepository


1 /*
2  * CVSGrab
3  * Author: Ludovic Claude (ludovicc@users.sourceforge.net)
4  * Distributable under BSD license.
5  */

6 package net.sourceforge.cvsgrab;
7
8 import org.netbeans.lib.cvsclient.admin.AdminHandler;
9 import org.netbeans.lib.cvsclient.admin.Entry;
10 import org.netbeans.lib.cvsclient.command.GlobalOptions;
11
12 import java.io.BufferedInputStream JavaDoc;
13 import java.io.File JavaDoc;
14 import java.io.FileInputStream JavaDoc;
15 import java.io.FileOutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.util.Date JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Vector JavaDoc;
21
22 /**
23  * The local repository where the files are stored on this computer.
24  *
25  * @author Ludovic Claude
26  * @created April 19, 2002
27  * @version 1.0
28  */

29
30 public class LocalRepository {
31     
32     public static final int UPDATE_NEEDED = 1;
33     public static final int UPDATE_NO_CHANGES = 2;
34     public static final int UPDATE_LOCAL_CHANGE = 3;
35     public static final int UPDATE_MERGE_NEEDED = 4;
36     public static final int UPDATE_IMPOSSIBLE = 5;
37     
38     private AdminHandler _handler;
39     private GlobalOptions _globalOptions = new GlobalOptions();
40     /**
41      * The local root of the repository
42      */

43     private File JavaDoc _localRootDir;
44     /**
45      * The local root of the project
46      */

47     private File JavaDoc _localProjectDir;
48     private int _newFiles = 0;
49     private int _updatedFiles = 0;
50     private int _removedFiles = 0;
51     private int _failedUpdates = 0;
52     private boolean _cleanUpdate;
53
54     /**
55      * Constructor for the LocalRepository object
56      *
57      * @param cvsGrab The cvs grabber
58      */

59     public LocalRepository(CVSGrab cvsGrab) {
60         _handler = new CVSGrabAdminHandler(cvsGrab);
61         _globalOptions.setCVSRoot(cvsGrab.getCvsRoot());
62         _globalOptions.setCheckedOutFilesReadOnly(true);
63         _localRootDir = new File JavaDoc(cvsGrab.getDestDir());
64         _cleanUpdate = cvsGrab.isCleanUpdate();
65         _localProjectDir = new File JavaDoc(_localRootDir, cvsGrab.getPackagePath());
66     }
67     
68     /**
69      * Gets the root directory
70      *
71      * @return The rootDirectory value
72      */

73     public File JavaDoc getLocalRootDir() {
74         return _localRootDir;
75     }
76
77     /**
78      * Gets the local directory to use for storing the contents of the remote directory
79      * @param remoteDir The remote directory
80      * @return The local directory
81      */

82     public File JavaDoc getLocalDir(RemoteDirectory remoteDir) {
83         return new File JavaDoc(getLocalRootDir(), remoteDir.getLocalDir());
84     }
85     
86     /**
87      * Gets the local file to use for storing the contents of the remote file
88      * @param remoteFile The remote file
89      * @return The local file
90      */

91     public File JavaDoc getLocalFile(RemoteFile remoteFile) {
92         File JavaDoc dir = getLocalDir(remoteFile.getDirectory());
93         File JavaDoc file = new File JavaDoc(dir, remoteFile.getName());
94         return file;
95     }
96
97     /**
98      * Gets the new file count
99      *
100      * @return The newFileCount value
101      */

102     public int getNewFileCount() {
103         return _newFiles;
104     }
105
106     /**
107      * Gets the updated file count
108      *
109      * @return The updatedFileCount value
110      */

111     public int getUpdatedFileCount() {
112         return _updatedFiles;
113     }
114
115     /**
116      * Gets the removed file count
117      *
118      * @return The deletedFileCount value
119      */

120     public int getRemovedFileCount() {
121         return _removedFiles;
122     }
123
124     /**
125      * Gets the failed update count
126      *
127      * @return The failedUpdates value
128      */

129     public int getFailedUpdateCount() {
130         return _failedUpdates;
131     }
132
133     /**
134      * Gets the cleanUpdate flag.
135      *
136      * @return the cleanUpdate.
137      */

138     public boolean isCleanUpdate() {
139         return _cleanUpdate;
140     }
141     
142     /**
143      * Resets the counters in this class
144      */

145     public void resetFileCounts() {
146         _newFiles = 0;
147         _updatedFiles = 0;
148         _removedFiles = 0;
149         _failedUpdates = 0;
150     }
151
152     /**
153      * Return true if the file needs to be updated
154      *
155      * @param remoteFile The remote file
156      * @return true if the file needs to be loaded from the server
157      */

158     public int checkUpdateStatus(RemoteFile remoteFile) {
159         boolean needUpdate = true;
160         File JavaDoc file = getLocalFile(remoteFile);
161         
162         if (file.exists()) {
163             try {
164                 Entry entry = _handler.getEntry(file);
165                 if (entry == null) {
166                     CVSGrab.getLog().debug("No entry for file " + file);
167                     _failedUpdates++;
168                     return UPDATE_IMPOSSIBLE;
169                 } else {
170                     needUpdate = !remoteFile.getVersion().equals(entry.getRevision());
171                     boolean locallyModified = isLocallyModified(file, entry);
172                     if (locallyModified) {
173                         CVSGrab.getLog().debug("File " + file + " is locally modified");
174                     }
175                     if (needUpdate) {
176                         if (locallyModified) {
177                             CVSGrab.getLog().debug("File " + file + " was modified since last update, cannot upload the new version of this file");
178                             CVSGrab.getLog().debug("Last modified date on disk: " + new Date JavaDoc(file.lastModified()));
179                             CVSGrab.getLog().debug("Last modified date on cvs: " + entry.getLastModified());
180                             // TODO: remove this when the merge functionality works
181
_failedUpdates++;
182                             return UPDATE_MERGE_NEEDED;
183                         } else {
184                             CVSGrab.getLog().debug("New version available on the remote repository for file " + file);
185                             return UPDATE_NEEDED;
186                         }
187                     } else {
188                         if (locallyModified) {
189                             CVSGrab.getLog().debug("File " + file + " was modified since last update, cannot upload the new version of this file");
190                             CVSGrab.getLog().debug("Last modified date on disk: " + new Date JavaDoc(file.lastModified()));
191                             CVSGrab.getLog().debug("Last modified date on cvs: " + entry.getLastModified());
192                         }
193                         return locallyModified ? UPDATE_LOCAL_CHANGE : UPDATE_NO_CHANGES;
194                     }
195                 }
196             } catch (IOException JavaDoc ex) {
197                 // ignore
198
ex.printStackTrace();
199                 _failedUpdates++;
200                 return UPDATE_IMPOSSIBLE;
201             }
202         } else {
203             return UPDATE_NEEDED;
204         }
205     }
206
207     /**
208      * Returns the local version of the remote file
209      * @param remoteFile The remote file
210      * @return The version of the local file, or null if it doesn't exist
211      */

212     public String JavaDoc getLocalVersion(RemoteFile remoteFile) {
213         File JavaDoc file = getLocalFile(remoteFile);
214         
215         if (file.exists()) {
216             try {
217                 Entry entry = _handler.getEntry(file);
218                 if (entry == null) {
219                     return null;
220                 } else {
221                     return entry.getRevision();
222                 }
223             } catch (IOException JavaDoc ex) {
224                 // ignore
225
ex.printStackTrace();
226                 return null;
227             }
228         } else {
229             return null;
230         }
231     }
232     
233     private boolean isLocallyModified(File JavaDoc file, Entry entry) {
234         // Allow a tolerance of 1 minute because on Windows seconds are omitted
235
return (file.lastModified() > entry.getLastModified().getTime() + 60*1000);
236     }
237     
238     /**
239      * Update a file version in the local CVS entries
240      *
241      * @param remoteFile The remote file
242      */

243     // synchronized as it can be accessed from multiple download threads
244
public synchronized void updateFileVersion(RemoteFile remoteFile) {
245         File JavaDoc dir = getLocalDir(remoteFile.getDirectory());
246         File JavaDoc file = getLocalFile(remoteFile);
247         Entry entry = null;
248         Date JavaDoc lastModified = remoteFile.getLastModified();
249         if (lastModified == null) {
250             lastModified = new Date JavaDoc();
251         }
252         try {
253             entry = _handler.getEntry(file);
254             if (entry == null) {
255                 throw new IOException JavaDoc("Entry not found");
256             }
257             entry.setRevision(remoteFile.getVersion());
258             entry.setDate(lastModified);
259             _updatedFiles++;
260         } catch (IOException JavaDoc ex) {
261             boolean binary = remoteFile.isBinary();
262             String JavaDoc lastModifiedStr = Entry.getLastModifiedDateFormatter().format(lastModified);
263             entry = new Entry("/" + remoteFile.getName() + "/" + remoteFile.getVersion() + "/"
264                     + lastModifiedStr + "/" + (binary ? "-kb/" : "/"));
265             _newFiles++;
266         }
267         
268         String JavaDoc localDirectory = WebBrowser.removeFinalSlash(dir.getAbsolutePath());
269         String JavaDoc repositoryPath = remoteFile.getDirectory().getDirectoryPath();
270         try {
271             _handler.updateAdminData(localDirectory, repositoryPath, entry, _globalOptions);
272         } catch (IOException JavaDoc ex) {
273             _failedUpdates++;
274             CVSGrab.getLog().error("Cannot update CVS entry for file " + file, ex);
275             throw new RuntimeException JavaDoc("Cannot update CVS entry for file " + file);
276         }
277     }
278     
279     /**
280      * Backup a remote file that was locally modified
281      *
282      * @param remoteFile The remote file
283      */

284     public void backupFile(RemoteFile remoteFile) {
285         File JavaDoc dir = getLocalDir(remoteFile.getDirectory());
286         File JavaDoc file = getLocalFile(remoteFile);
287         File JavaDoc backupFile = new File JavaDoc(dir, ".#" + remoteFile.getName() + "." + remoteFile.getVersion());
288         CVSGrab.getLog().info("Move " + remoteFile.getName() + " to " + backupFile.getName());
289         //file.renameTo(backupFile);
290
InputStream JavaDoc in = null;
291         FileOutputStream JavaDoc out = null;
292         try {
293             try {
294                 in = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(file));
295                 out = new FileOutputStream JavaDoc(backupFile);
296                 
297                 byte[] buffer = new byte[8 * 1024];
298                 int count = 0;
299                 do {
300                     out.write(buffer, 0, count);
301                     count = in.read(buffer, 0, buffer.length);
302                 } while (count != -1);
303             } finally {
304                 if (out != null) {
305                     out.close();
306                 }
307                 if (in != null) {
308                     in.close();
309                 }
310             }
311         } catch (IOException JavaDoc ex) {
312             _failedUpdates++;
313             ex.printStackTrace();
314             CVSGrab.getLog().error("Cannot create backup for file " + file);
315             throw new RuntimeException JavaDoc("Cannot create backup for file " + file);
316         }
317     }
318
319     /**
320      * Unregister a file from the CVS entries, forcing it to be reloaded next
321      * time the program is run
322      *
323      * @param remoteFile The remote file
324      */

325     public void unregisterFile(RemoteFile remoteFile) {
326         File JavaDoc file = getLocalFile(remoteFile);
327         try {
328             _handler.removeEntry(file);
329             _failedUpdates++;
330         } catch (IOException JavaDoc ex) {
331             ex.printStackTrace();
332             // ignore
333
}
334     }
335
336     /**
337      * Remove the local copies of the files that have been deleted in the remote
338      * repository.
339      *
340      * @param remoteDirectory The remote directory to clean-up
341      */

342     // synchronized as it can be accessed from multiple download threads
343
public synchronized void cleanRemovedFiles(RemoteDirectory remoteDirectory) {
344         try {
345             File JavaDoc dir = getLocalDir(remoteDirectory);
346             Entry dirEntry = _handler.getEntry(dir);
347             Vector JavaDoc dirFiles = new Vector JavaDoc();
348             if (dirEntry == null) {
349                 //System.out.println("Null entries in " + dir);
350
return;
351             }
352             for (Iterator JavaDoc i = _handler.getEntries(dir); i.hasNext(); ) {
353                 Entry cvsFile = (Entry) i.next();
354                 if (cvsFile.isDirectory()) {
355                     continue;
356                 }
357                 dirFiles.add(cvsFile.getName());
358             }
359             RemoteFile[] lastDirFiles = remoteDirectory.getRemoteFiles();
360             for (int i = 0; i < lastDirFiles.length; i++) {
361                 dirFiles.remove(lastDirFiles[i].getName());
362             }
363             _removedFiles += dirFiles.size();
364             for (Iterator JavaDoc i = dirFiles.iterator(); i.hasNext(); ) {
365                 String JavaDoc fileName = (String JavaDoc) i.next();
366                 File JavaDoc file = new File JavaDoc(getLocalDir(remoteDirectory), fileName);
367                 CVSGrab.getLog().debug("Removing " + file);
368                 _handler.removeEntry(file);
369                 file.delete();
370             }
371         } catch (IOException JavaDoc ex) {
372             _failedUpdates++;
373             ex.printStackTrace();
374             CVSGrab.getLog().error("Error while removing files marked for deletion");
375         }
376     }
377
378     /**
379      * Remove any directory that doesn't contain any files
380      */

381     public void pruneEmptyDirectories() throws IOException JavaDoc {
382         pruneEmptyDirectory(_localProjectDir);
383     }
384     
385     /**
386      * Prunes a directory, recursively pruning its subdirectories
387      * @param directory the directory to prune
388      */

389     private boolean pruneEmptyDirectory(File JavaDoc directory) {
390         boolean empty = true;
391
392         final File JavaDoc[] contents = directory.listFiles();
393
394         // should never be null, but just in case...
395
if (contents != null) {
396             for (int i = 0; i < contents.length; i++) {
397                 if (contents[i].isFile()) {
398                     empty = false;
399                 } else {
400                     if (!contents[i].getName().equals("CVS")) { //NOI18N
401
empty = pruneEmptyDirectory(contents[i]);
402                     }
403                 }
404             }
405
406             if (empty) {
407                 // check this is a CVS directory and not some directory the user
408
// has stupidly called CVS...
409
final File JavaDoc entriesFile = new File JavaDoc(directory, "CVS/Entries"); //NOI18N
410
if (entriesFile.exists()) {
411                     final File JavaDoc adminDir = new File JavaDoc(directory, "CVS"); //NOI18N
412
final File JavaDoc[] adminFiles = adminDir.listFiles();
413                     for (int i = 0; i < adminFiles.length; i++) {
414                         adminFiles[i].delete();
415                     }
416                     CVSGrab.getLog().debug("Removing empty directory " + directory);
417                     adminDir.delete();
418                     try {
419                         // Remove the directory from the entries
420
_handler.removeEntry(directory);
421                     } catch (IOException JavaDoc ex) {
422                         _failedUpdates++;
423                         ex.printStackTrace();
424                         CVSGrab.getLog().error("Error while removing empty directory");
425                     }
426                     directory.delete();
427                     _removedFiles++;
428                 }
429             }
430         }
431
432         return empty;
433     }
434
435     /**
436      * Adds a remote directory in the local filesystem, and update the CVS admin entries for that directory.
437      *
438      * @param remoteDir The remote directory
439      */

440     // synchronized as it can be access from the multiple download threads
441
public synchronized void add(RemoteDirectory remoteDir) {
442         File JavaDoc dir = getLocalDir(remoteDir);
443         Entry entry = null;
444         String JavaDoc dirName = WebBrowser.removeFinalSlash(dir.getName());
445         try {
446             entry = _handler.getEntry(dir);
447             if (entry == null) {
448                 throw new IOException JavaDoc("Entry not found");
449             }
450         } catch (IOException JavaDoc ex) {
451             entry = new Entry("D/" + dirName + "////");
452         }
453         
454         String JavaDoc localDirectory = WebBrowser.removeFinalSlash(dir.getParent());
455         String JavaDoc repositoryPath = WebBrowser.removeFinalSlash(remoteDir.getDirectoryPath());
456         int lastSlash = repositoryPath.lastIndexOf('/');
457         if (lastSlash > 0) {
458             repositoryPath = repositoryPath.substring(0, lastSlash);
459         }
460         try {
461             _handler.updateAdminData(localDirectory, repositoryPath, entry, _globalOptions);
462         } catch (IOException JavaDoc ex) {
463             _failedUpdates++;
464             ex.printStackTrace();
465             CVSGrab.getLog().error("Cannot update CVS entry for directory " + dir);
466             throw new RuntimeException JavaDoc("Cannot update CVS entry for directory " + dir);
467         }
468     }
469     
470 }
471
Popular Tags