View Javadoc

1   package net.sf.statsvn.util;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.io.InputStreamReader;
6   import java.util.regex.Matcher;
7   import java.util.regex.Pattern;
8   
9   import net.sf.statcvs.util.LookaheadReader;
10  import net.sf.statsvn.output.SvnConfigurationOptions;
11  
12  /**
13   * Utility class that verifies if the correct version of subversion is used.
14   * 
15   * @author Jean-Philippe Daigle <jpdaigle@softwareengineering.ca>
16   * 
17   * @version $Id: SvnStartupUtils.java 351 2008-03-28 18:46:26Z benoitx $
18   */
19  public final class SvnStartupUtils {
20  	private static final String SVN_VERSION_COMMAND = "svn --version";
21  
22  	private static final String SVN_MINIMUM_VERSION = "1.3.0";
23  
24  	private static final String SVN_MINIMUM_VERSION_DIFF_PER_REV = "1.4.0";
25  
26  	private static final String SVN_VERSION_LINE_PATTERN = ".* [0-9]+\\.[0-9]+\\.[0-9]+.*";
27  
28  	private static final String SVN_VERSION_PATTERN = "[0-9]+\\.[0-9]+\\.[0-9]+";
29  
30  	//  HACK: we "should" parse the output and check for a node named root, but this will work well enough
31  	private static final String SVN_INFO_WITHREPO_LINE_PATTERN = ".*<root>.+</root>.*";
32  
33  	private static final String SVN_REPO_ROOT_NOTFOUND = "Repository root not available - verify that the project was checked out with svn version "
34  	        + SVN_MINIMUM_VERSION + " or above.";
35  
36  	/**
37  	 * A utility class (only static methods) should be final and have
38  	 * a private constructor.
39  	 */
40  	private SvnStartupUtils() {
41  	}
42  
43  	/**
44  	 * Verifies that the current revision of SVN is SVN_MINIMUM_VERSION
45  	 * 
46  	 * @throws SvnVersionMismatchException
47  	 *             if SVN executable not found or version less than
48  	 *             SVN_MINIMUM_VERSION
49  	 * @return the version string
50  	 */
51  	public static synchronized String checkSvnVersionSufficient() throws SvnVersionMismatchException {
52  		ProcessUtils pUtils = null;
53  		try {
54  
55  			pUtils = ProcessUtils.call(SVN_VERSION_COMMAND);
56  			final InputStream istream = pUtils.getInputStream();
57  			final LookaheadReader reader = new LookaheadReader(new InputStreamReader(istream));
58  
59  			while (reader.hasNextLine()) {
60  				final String line = reader.nextLine();
61  				if (line.matches(SVN_VERSION_LINE_PATTERN)) {
62  					// We have our version line
63  					final Pattern pRegex = Pattern.compile(SVN_VERSION_PATTERN);
64  					final Matcher m = pRegex.matcher(line);
65  					if (m.find()) {
66  						final String versionString = line.substring(m.start(), m.end());
67  
68  						// we perform a simple string comparison against the version numbers
69  						if (versionString.compareTo(SVN_MINIMUM_VERSION) >= 0) {
70  							return versionString; // success
71  						} else {
72  							throw new SvnVersionMismatchException(versionString, SVN_MINIMUM_VERSION);
73  						}
74  					}
75  				}
76  			}
77  
78  			if (pUtils.hasErrorOccured()) {
79  				throw new IOException(pUtils.getErrorMessage());
80  			}
81  		} catch (final IOException e) {
82  			SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
83  		} catch (final RuntimeException e) {
84  			SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
85  		} finally {
86  			if (pUtils != null) {
87  				try {
88  					pUtils.close();
89  				} catch (final IOException e) {
90  					SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
91  				}
92  			}
93  		}
94  
95  		throw new SvnVersionMismatchException();
96  	}
97  
98  	/**
99  	 * Verifies that the "svn info" command can return the repository root
100 	 * (info available in svn >= 1.3.0)
101 	 * 
102 	 * @throws SvnVersionMismatchException
103 	 *             if <tt>svn info</tt> failed to provide a non-empty repository root
104 	 */
105 	public static synchronized void checkRepoRootAvailable() throws SvnVersionMismatchException {
106 		ProcessUtils pUtils = null;
107 		try {
108 			final boolean rootOnlyTrue = true;
109 			pUtils = SvnInfoUtils.getSvnInfo(rootOnlyTrue);
110 			final InputStream istream = pUtils.getInputStream();
111 			final LookaheadReader reader = new LookaheadReader(new InputStreamReader(istream));
112 
113 			while (reader.hasNextLine()) {
114 				final String line = reader.nextLine();
115 				if (line.matches(SVN_INFO_WITHREPO_LINE_PATTERN)) {
116 					// We have our <root> element in the svn info AND it's not empty --> checkout performed 
117 					// with a compatible version of subversion client.
118 					istream.close();
119 					return; // success
120 				}
121 			}
122 
123 			if (pUtils.hasErrorOccured()) {
124 				throw new IOException(pUtils.getErrorMessage());
125 			}
126 		} catch (final Exception e) {
127 			SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
128 		} finally {
129 			if (pUtils != null) {
130 				try {
131 					pUtils.close();
132 				} catch (final IOException e) {
133 					SvnConfigurationOptions.getTaskLogger().info(e.getMessage());
134 				}
135 			}
136 		}
137 
138 		throw new SvnVersionMismatchException(SVN_REPO_ROOT_NOTFOUND);
139 
140 	}
141 
142 	public static synchronized boolean checkDiffPerRevPossible(final String version) {
143 		// we perform a simple string comparison against the version numbers
144 		return version.compareTo(SVN_MINIMUM_VERSION_DIFF_PER_REV) >= 0;
145 	}
146 }