View Javadoc

1   /**
2    * Copyright 2005-2006 the original author or authors.
3    *
4    * Licensed under the Gnu General Pubic License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    *
8    *      http://www.opensource.org/licenses/gpl-license.php
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13   * See the Gnu General Public License for more details.
14   */
15  package org.figure8.join.services.vcs;
16  
17  import org.figure8.join.util.CVSCrypt;
18  import org.figure8.join.util.LogUtil;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.tools.ant.Project;
22  import org.apache.tools.ant.types.Environment;
23  import org.apache.tools.ant.types.Commandline;
24  import org.apache.tools.ant.taskdefs.Execute;
25  
26  import java.io.File;
27  import java.io.FileReader;
28  import java.io.FileWriter;
29  import java.io.PrintWriter;
30  import java.io.BufferedReader;
31  /**
32   * Implementation of <code>VCSAccessor</code> for CVS system. This implementation
33   * uses the cvs.exe client configured on the execution machine. This later should
34   * be in the PATH environment variable (or equivalent).
35   * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
36   * @version $Revision: 1.3 $
37   */
38  public class CVSAccessor extends AbstractVCSAccessor{
39  
40     // Static -------------------------------------------------------------------
41  
42     /** Get a commons logger */
43     private static final Log log = LogUtil.getLog(CVSAccessor.class);
44  
45     /** Constant for the CVS pserver protocol */
46     public static final String PSERVER_PROTOCOL = "pserver";
47     /** Constant for the CVS checkout command */
48     public static final String CHECKOUT_COMMAND = "checkout";
49  
50  
51     // Constructors -------------------------------------------------------------
52  
53     /** Creates a new instance of CVSAccessor */
54     public CVSAccessor(){
55        // Default protocol is pserver.
56        setProtocol(PSERVER_PROTOCOL);
57     }
58  
59     
60     // Implementation of VCSAccessor --------------------------------------------
61  
62     /**
63      * Login onto configuration management system.
64      * @throws VCSAccessException if login is not successfull
65      */
66     public void login() throws VCSAccessException{
67        // Check CVSROOT presence.
68        if (rootRepository == null || rootRepository.length() == 0){
69           log.error("CVS rootRepository must be set to perform login !");
70           throw new VCSAccessException("rootRepository (CVSROOT) must be set to perform login");
71        }
72  
73        // Perform login if protocol is pserver.
74        if (protocol == null || protocol.equals(PSERVER_PROTOCOL)){
75           if (password == null){
76              log.error("CVS password must be set when using pserver protocol");
77              throw new VCSAccessException("password must be set when using pserver protocol");
78           }
79  
80           // Read CVS password file.
81           File passFile = new File(System.getProperty("cygwin.user.home",
82                                      System.getProperty("user.home")) + File.separatorChar + ".cvspass");
83           if (log.isDebugEnabled())
84              log.debug("CVS password file is " + passFile.getPath());
85  
86           // Login consists in writing the crypted password into .cvspass file for the CVSROOT.
87           PrintWriter writer = null;
88           BufferedReader reader = null;
89           try{
90              StringBuffer buffer = new StringBuffer();
91  
92              // If password file already exists, keep the other passwords.
93              if (passFile.exists()){
94                 reader = new BufferedReader(new FileReader(passFile));
95  
96                 String line = null;
97                 while ((line = reader.readLine()) != null){
98                    if (!line.startsWith(rootRepository))
99                       buffer.append(line).append(System.getProperty("line.separator"));
100                }
101             }
102 
103             String pwdfile = buffer.toString() + rootRepository + " A" + CVSCrypt.crypt(password);
104             writer = new PrintWriter(new FileWriter(passFile));
105             writer.println(pwdfile);
106          }
107          catch (Exception e){
108             // Log some diagnostic messages before propagating.
109             log.error("Exception while writing the CVS password file for root " + rootRepository);
110             log.error("The exception message is the following: " + e.getMessage());
111             throw new VCSAccessException("Exception while writing the CVS password file.", e);
112          }
113          finally{
114             // Close reader and writer.
115             try {reader.close();}
116             catch (Exception e){
117                /* Do nothing here. */
118             }
119             try {writer.close();}
120             catch (Exception e){
121                // Log and propagate exception.
122                log.error("IOException while closing writer for CVS password file for root " + rootRepository);
123                throw new VCSAccessException("IOException while closing CVS password file");
124             }
125          }
126       }
127    }
128 
129    /**
130     * Perform a checkout command (or equivalent) on the VCS using a specified
131     * baseline <b>tag</b>. Extracted files are stored within <b>destDirectory</b>
132     * @param tag Baseline tag for retrieving module from VCS
133     * @param destDirectory Path of the destination directory where to put extracted files
134     * @throws VCSAccessException if cehckout command is not successfull
135     */
136    public void checkout(String tag, String destDirectory) throws VCSAccessException{
137       if (log.isInfoEnabled()){
138          log.info("Performing checkout command on CVS repository: '" + rootRepository + "'");
139          log.info("Tag to retrieve on module '" + module + "' is " + tag);
140       }
141 
142       // Create and configure command line.
143       Commandline c = new Commandline();
144       c.setExecutable("cvs");
145       c.createArgument(true).setLine(CHECKOUT_COMMAND);
146 
147       // Check CVSROOT presence.
148       if (rootRepository == null || rootRepository.length() == 0){
149          log.error("CVS rootRepository must be set to perform checkout");
150          throw new VCSAccessException("rootRepository (CVSROOT) must be set to perform checkout");
151       }
152 
153       c.createArgument(true).setLine("-d" + rootRepository);
154 
155       // Add tag information.
156       if (tag != null && tag.length() > 0)
157          c.createArgument().setLine("-r" + tag);
158 
159       // Add module information.
160       if (module != null && module.length() > 0)
161          c.createArgument().setLine(module);
162 
163       // Check destination directory.
164       if (destDirectory == null || destDirectory.length() == 0){
165          log.error("CVS destDirectory must be set to perform checkout");
166          throw new VCSAccessException("destDirectory must be set to perform checkout");
167       }
168       File dest = new File(destDirectory);
169       if (!dest.isDirectory()){
170          try {dest.mkdirs();}
171          catch (Exception e){
172             throw new VCSAccessException("IOException while creating destination directory");
173          }
174       }
175 
176       // Create execution environment.
177       Environment env = new Environment();
178 
179       File passFile = new File(System.getProperty("cygwin.user.home",
180                                  System.getProperty("user.home")) + File.separatorChar + ".cvspass");
181       Environment.Variable var = new Environment.Variable();
182       var.setKey("CVS_PASSFILE");
183       var.setValue(String.valueOf(passFile));
184       env.addVariable(var);
185 
186       // Create execution flow.
187       Execute exe = new Execute(getExecuteStreamHandler(), null);
188       exe.setAntRun(new Project());
189       exe.setWorkingDirectory(dest);
190       exe.setCommandline(c.getCommandline());
191       exe.setEnvironment(env.getVariables());
192 
193       int returnCode = -1;
194 
195       try{
196          if (log.isDebugEnabled())
197             log.debug("Checkout command line is: " + c.getCommandline());
198          // Execute checkout command here.
199          returnCode = exe.execute();
200       }
201       catch (Exception e){
202          log.error("CVS checkout execution on '" + rootRepository + "' throws an exception");
203          log.error("Here's the exception message: " + e.getMessage());
204          throw new VCSAccessException("Exception during checkout command on '" + rootRepository + "': " + e.getMessage());
205       }
206 
207       log.info("CVS checkout return code is: " + returnCode);
208       // Return code is 0 when everything is ok.
209       if (returnCode != 0)
210          throw new VCSAccessException("CVS ckeckout command return abnormally ...");
211    }
212 
213    /**
214     * Logout from configuration management system.
215     * @throws VCSAccessException if logout is not successfull
216     */
217    public void logout() throws VCSAccessException{
218       // No logout in CVS.
219    }
220 }