001    /*
002    
003      $Id: CVSManager.java,v 1.12 2003/05/08 10:34:22 culdesac Exp $
004    
005    */
006    
007    package sharpster.daemon.filemanagement;
008    
009    import sharpster.common.*;
010    import sharpster.daemon.SharpsterDaemon;
011    import sharpster.daemon.filemanagement.LocalFileManager;
012    import sharpster.daemon.filemanagement.FileMap;
013    
014    import java.util.LinkedList;
015    import java.util.ListIterator;
016    import java.io.*;
017    
018    /**
019     * Class which handles the local CVS and files stored in it.
020     * It should be used for executing commands to both manipulate and
021     * retrieve information, such as file logs, from the CVS.
022     * This class keeps the whole CVS database checked out under 
023     * <code>m_tempDir</code>, where it puts recieved files before issuing an
024     * update, commit or a similar command.
025     * All methods use the method <code>localDoCVS</code> to perform CVS commands.
026     */
027    
028    public class CVSManager {
029    
030        /**
031         * Temporary directory which can be used by the class.
032         * Should be set up during the initialization of the class.
033         */
034        private String tempDir;
035    
036        /**
037         * Holds the path to the CVS root directory. Should be set up during
038         * the initialization of the class.
039         */
040        private String CVSRoot;
041    
042        /**
043         * This class keeps a reference to the <code>FileKeyManager</code>
044         * in order to be able to update it when files are added and
045         * removed from the CVS.
046         */
047        private FileMap fileMap;
048        
049        
050        /**
051         * Constructs an instance of the class and initializes the member
052         * attributes.
053         */
054        public CVSManager(FileMap fkm, String tempDir) 
055        {
056            fileMap = fkm;
057            this.tempDir = tempDir;
058            this.CVSRoot = sharpster.daemon.SharpsterDaemon.getCVSRoot();
059        }
060        
061        /**
062         * Executes a CVS command. The command attributes contains the
063         * CVS command and any arguments associated with it.
064         * If the command include adding or removing of files,
065         * this method is responsible for updating the <code>fkm</code>
066         * with the changes. The <code>ResponseCollection</code> returned
067         * by the method, holds an array of strings which contains output
068         * from the CVS command.
069         */
070        public ResponseCollection localDoCVS(String command, 
071                                             String workingDirectory) {
072            Runtime runtime = Runtime.getRuntime();
073            String output = new String();
074            String s;
075            
076            ResponseCollection responses = new ResponseCollection();
077            int returnValue=0;
078    
079            try {
080                Process process = runtime.exec("cvs "+command,null,new File(workingDirectory));
081    
082                BufferedReader inReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
083                BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
084    
085                boolean stop = false;
086                boolean trackStdout = true;
087                boolean trackStderr = true;
088                String stdout = new String();
089                String stderr = new String();
090    
091                while(!stop) {
092                    if(trackStdout) {
093                        String stdoutLine = inReader.readLine();
094                        if(stdoutLine == null) trackStdout=false;
095                        else stdout += stdoutLine + "\n";
096                    }       
097                    if(trackStderr) {
098                        String stderrLine = errReader.readLine();
099                        if(stderrLine == null) trackStderr=false;
100                        else stderr += stderrLine + "\n";
101                    }
102                    if(!trackStdout && !trackStderr) stop = true;
103                }                   
104    
105                returnValue = process.waitFor();
106    
107                CVSOutputResponse cvsResp = new CVSOutputResponse();
108                cvsResp.setOrigin("FileManager");
109                cvsResp.setUser(SharpsterDaemon.getPeerName());
110                cvsResp.setError(returnValue!=0);
111                cvsResp.setMessage(stdout + "\n" + stderr);
112                responses.addResponse(cvsResp);
113            }
114            catch(Exception e) {
115                e.printStackTrace();
116            }
117    
118            return responses;    
119        }
120    
121        private void synchronizeRecusive(File root, String cvsLocalPath, FileMap oldFileMap, FileMap newFileMap) {          
122            FileReader fr;
123            BufferedReader inFile;
124            String temp;
125            boolean binary = false;
126    
127            try {                   
128                File[] fileList = root.listFiles();
129                for(int i=0;i<fileList.length;i++) {
130                    String name = fileList[i].getName();
131                    if(name.equals("CVSROOT")) continue;
132                            
133                    if(name.endsWith(",v")) {
134                        name = name.substring(0,name.length()-2);
135                        if(oldFileMap.hasFile(cvsLocalPath+"/"+name)) {
136                            net.jxta.id.ID id = oldFileMap.getID(cvsLocalPath+"/"+name);
137                            newFileMap.addFile(cvsLocalPath+"/"+name,false,oldFileMap.isBinary(id));
138                        }
139                        else {
140                            File file = new File(root.getAbsolutePath(),name+",v");
141                            if(file != null) {
142                                fr = new FileReader(file);
143                                inFile = new BufferedReader(fr);
144                                binary = false;
145                                while((temp=inFile.readLine())!=null) {
146                                    if(temp.startsWith("\n") || temp.startsWith("\r") || temp.startsWith(" ") || temp.equals("")) {
147                                        break;
148                                    }                       
149                                    if(temp.matches("(expand).*(@b@;)\r?\n?")) {
150                                        binary = true;
151                                        break;
152                                    }
153                                }
154                                newFileMap.addFile(cvsLocalPath+"/"+name,false,binary);
155                            }
156                        }   
157                    }
158                    else {
159                        newFileMap.addFile(cvsLocalPath+"/"+name,true,false);
160                        synchronizeRecusive(fileList[i],cvsLocalPath+"/"+name,oldFileMap,newFileMap);
161                    }
162                }
163            }
164            catch(Exception e) {
165            }       
166        }
167    
168        /*private void synchronizeRecusive(File root, FileMap fileMap) {
169            FileReader fr;
170            BufferedReader inFile;
171            String temp;
172            String repository;
173            File tempFile;
174    
175            try {
176                fr = new FileReader(root.getAbsolutePath()+
177                                    File.separator+"CVS"+
178                                    File.separator+"Repository");
179                inFile = new BufferedReader(fr);            
180                temp = inFile.readLine();
181                inFile.close();
182    
183                tempFile = new File(temp);
184                if(tempFile.isAbsolute()) {
185                    String cvsRoot = sharpster.daemon.SharpsterDaemon.getCVSRoot();
186                    repository = temp.substring(cvsRoot.length()+1);
187                }
188                else {
189                    repository = temp;
190                }
191    
192                fr = new FileReader(root.getAbsolutePath()+
193                                    File.separator+"CVS"+
194                                    File.separator+"Entries");
195                inFile = new BufferedReader(fr);            
196    
197                while((temp=inFile.readLine())!=null) {
198                    String[] params = temp.split("(/)");
199                    boolean dir = params[0].equals("D");
200                    boolean bin = false;
201                    if(params.length>4) bin = params[4].equals("-kb");
202                    String path = repository + "/" + params[1];
203                    fileMap.addFile(path,dir,bin);
204                }   
205                
206                inFile.close();
207            }
208            catch(Exception e) {
209                return;
210            }
211    
212            File[] children = root.listFiles();
213            for(int i=0;i<children.length;i++) {
214                if(children[i].isDirectory()) {
215                    synchronizeRecusive(children[i],fileMap);
216                }
217            }
218        }*/
219    
220        public void synchronizeCVS(FileMap fileMap) {
221            File cvsRoot = new File(SharpsterDaemon.getCVSRoot());
222            File[] fileList = cvsRoot.listFiles();
223            
224            FileMap newFileMap = new FileMap();
225            
226            for(int i=0;i<fileList.length;i++) {
227                if(fileList[i].isDirectory()) {
228                    if(fileList[i].isDirectory() && !fileList[i].getName().equals("CVSROOT")) {
229                        newFileMap.addFile(fileList[i].getName(),true,false);
230                        synchronizeRecusive(fileList[i],fileList[i].getName(),fileMap,newFileMap);
231                    }
232                }   
233            }
234            fileMap.merge(newFileMap);
235            
236            /*FileMap newFileMap = new FileMap();
237            File rootPath = new File(workingDirectory);
238            File cvsFolderPath = new File(workingDirectory+File.separator+"CVS");
239            if(cvsFolder == null || !cvsFolder.isDirectory()) return;
240            newFileMap.addFile(rootPath.getName(),true,false);
241            synchronizeRecusive(rootPath,newFileMap);
242            fileMap.merge(newFileMap);*/
243        }
244    
245        /**
246         * Checks out the latest version of the files in <code>files</code>
247         * and puts it in the <code>tempDir</code> directory tree.
248         * The <code>files</code> objects is then completed with the 
249         * checked out files.
250         */
251        public ResponseCollection cvsRun(FileCollection files, String cmd, boolean doVersions) {
252            Runtime runtime = Runtime.getRuntime();
253            String cvsRoot = SharpsterDaemon.getCVSRoot();
254            File cvsTemp = new File(SharpsterDaemon.getCVSTemp());
255            String allFiles = new String();
256            String output = new String();
257            ResponseCollection responses = new ResponseCollection();
258            int returnValue=0;
259            String command;
260    
261            try {
262                for(int i=0;i<files.getFileCount();i++) {
263    
264                    if(doVersions) {
265                        command = "cvs -d " + cvsRoot + " " + cmd 
266                            + " -r" + files.getFile(i).getVersion() 
267                            + " " + files.getFile(i).getFullPath();
268                    }
269                    else {
270                        command = "cvs -d " + cvsRoot + " " + cmd + " " 
271                            + files.getFile(i).getFullPath();
272                    }
273                    System.out.println(command);            
274                    Process process = runtime.exec(command,null,cvsTemp);
275                    
276                    BufferedReader inReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
277                    BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
278    
279                    boolean stop = false;
280                    boolean trackStdout = true;
281                    boolean trackStderr = true;
282                    String stdout = new String();
283                    String stderr = new String();
284    
285                    while(!stop) {
286                        if(trackStdout) {
287                            String stdoutLine = inReader.readLine();
288                            if(stdoutLine == null) trackStdout=false;
289                            else stdout += stdoutLine + "\n";
290                        }   
291                        if(trackStderr) {
292                            String stderrLine = errReader.readLine();
293                            if(stderrLine == null) trackStderr=false;
294                            else stderr += stderrLine + "\n";
295                        }
296                        if(!trackStdout && !trackStderr) stop = true;
297                    }                       
298    
299                    returnValue = process.waitFor();
300                }
301    
302                CVSOutputResponse cvsResp = new CVSOutputResponse();
303                cvsResp.setOrigin("FileManager");
304                cvsResp.setUser(SharpsterDaemon.getPeerName());
305                cvsResp.setError(returnValue!=0);
306                cvsResp.setMessage(output);
307                responses.addResponse(cvsResp);
308            }
309            catch(Exception e) {
310                e.printStackTrace();
311            }
312    
313            return responses;
314        }
315    
316        /**
317         * Updates the given files with possible new changes from the CVS.
318         * The files in <code>files</code> are first stored in the accurate
319         * position in the <code>tempDir</code> directory tree.
320         * Then an update command is issued to the CVS. 
321         * <code>files</code> is then updated with the updated files.
322         */
323        public ResponseCollection updateFiles(FileCollection files) {
324            return new ResponseCollection();
325        }
326    
327        /**
328         * Commits the files to the CVS.
329         * The files in <code>files</code> are first stored in the
330         * <code>tempDir</code> directory tree, 
331         * from where they are commited to the CVS.
332         */
333        public ResponseCollection commitFiles(FileCollection files) {
334            return new ResponseCollection();        
335        }
336    
337        /**
338         * Adds the files to the CVS. This includes also a commit of the
339         * added files. The files in <code>files</code> are first stored in 
340         * the accurate position in the <code>tempDir</code> directory tree,
341         * from where the add and the commit commands are issued.
342         */
343        public ResponseCollection addFiles(FileCollection files) {
344            return new ResponseCollection();        
345        }
346    
347        /**
348         * Removes the files from the CVS.
349         * The method is performed by removing the files specified in 
350         * <code>files</code> in the <code>tempDir</code> directory tree,
351         * and then issuing CVS commands for removing the files and commiting
352         * the remove.
353         */
354        public ResponseCollection removeFiles(FileCollection files) {
355            return new ResponseCollection();        
356        }
357        
358        /**
359         * Translates a local file path to a path in CVS.
360         */
361        public SharedFile translatePath(String path) {
362            String repository, filename, temp, cvsroot;
363            SharedFile file = null;
364                    
365            File cvsFilePath = new File(path);
366            if(!cvsFilePath.exists()) return null;
367    
368            try {
369                    File cvsFileDir = cvsFilePath.getParentFile();
370                    
371                    filename = cvsFilePath.getName();
372            
373                    FileReader fr = new FileReader(cvsFileDir.getAbsolutePath()+
374                                                   File.separator+"CVS"+
375                                                   File.separator+"Repository");
376                    BufferedReader inFile = new BufferedReader(fr);         
377                    
378                    repository = inFile.readLine();
379                    
380                    inFile.close();
381                    
382                    fr = new FileReader(cvsFileDir.getAbsolutePath()+
383                                                   File.separator+"CVS"+
384                                                   File.separator+"Root");
385                    inFile = new BufferedReader(fr);        
386                    
387                    cvsroot = inFile.readLine();
388                    
389                    inFile.close();
390    
391                    if(repository.startsWith(cvsroot)) {
392                        repository = repository.substring(cvsroot.length()+1);
393                    }
394                    
395                    fr = new FileReader(cvsFileDir.getAbsolutePath()+
396                                        File.separator+"CVS"+
397                                        File.separator+"Entries");
398                    inFile = new BufferedReader(fr);        
399                    
400                    while((temp=inFile.readLine())!=null) {
401                        String[] params = temp.split("(/)");
402                        if(params[1].equals(filename)) {
403                            file = new SharedFile();
404                            file.setFileName(filename);
405                            file.setPathInCVS(repository);
406                            if(params.length>2) file.setVersion(params[2]);
407                            Body body = new Body();
408                            body.setBinary(false);
409                            if(params.length>4) body.setBinary(params[4].equals("-kb"));
410                            file.setBody(body);
411                            break;
412                        }
413                    }       
414            
415                    inFile.close();
416            }
417            catch(Exception e) {
418                e.printStackTrace();
419                return null;
420            }
421    
422            return file;
423        }
424    }
425    
426    
427