1 package org.apache.maven.scm.provider.bazaar;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.scm.ScmException;
23 import org.apache.maven.scm.ScmFileStatus;
24 import org.apache.maven.scm.log.DefaultLog;
25 import org.apache.maven.scm.provider.bazaar.command.BazaarConstants;
26 import org.apache.maven.scm.provider.bazaar.command.BazaarConsumer;
27 import org.codehaus.plexus.util.cli.Commandline;
28
29 import java.io.File;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33
34
35
36
37
38
39 public class BazaarConfig
40 {
41
42 private static final float BAZAAR_REQ = 0.7f;
43
44 private static final float PYTHON_REQ = 2.4f;
45
46
47 private static final String BAZAAR_VERSION_TAG = "bzr (bazaar-ng) ";
48
49 private static final String BAZAAR_INSTALL_URL = "'http://bazaar-vcs.org/Installation'";
50
51
52 private static final String PYTHON_EXEC = "python";
53
54 private static final String PYTHON_VERSION = "-V";
55
56 private static final String PYTHON_VERSION_TAG = "Python ";
57
58
59 private static final String PARAMIKO = "\"import paramiko\"";
60
61 private static final String CCRYPT = "\"import Crypto\"";
62
63 private static final String CELEMENTREE = "\"import cElementTree\"";
64
65
66 private VersionConsumer bazaarVersion = new VersionConsumer( null );
67
68 private VersionConsumer pythonVersion = new VersionConsumer( null );
69
70 private boolean cElementTree = false;
71
72 private boolean paramiko = false;
73
74 private boolean cCrypt = false;
75
76 BazaarConfig( File workingDir )
77 {
78 try
79 {
80 pythonVersion = getPythonVersion( workingDir );
81 paramiko = checkPyModules( workingDir, PARAMIKO );
82 cCrypt = checkPyModules( workingDir, CCRYPT );
83 cElementTree = checkPyModules( workingDir, CELEMENTREE );
84 bazaarVersion = getBazaarVersion( workingDir );
85 }
86 catch ( ScmException e )
87 {
88
89
90 }
91
92 }
93
94 private boolean checkPyModules( File workingDir, String cmd )
95 {
96 PythonConsumer consumer = new PythonConsumer();
97 int exitCode;
98 try
99 {
100 Commandline cmdLine = buildPythonCmd( workingDir, new String[]{"-c", cmd} );
101 exitCode = BazaarUtils.executeCmd( consumer, cmdLine );
102 }
103 catch ( ScmException e )
104 {
105
106 exitCode = -1;
107 }
108
109 return exitCode == 0 && consumer.getConsumedAndClear().equals( "" );
110 }
111
112
113
114
115 private boolean isInstalled()
116 {
117 return pythonVersion.isVersionOk( PYTHON_REQ ) && bazaarVersion.isVersionOk( BAZAAR_REQ );
118 }
119
120
121
122
123 private boolean isComplete()
124 {
125 return isInstalled() && cElementTree && paramiko && cCrypt;
126 }
127
128 public static VersionConsumer getBazaarVersion( File workingDir )
129 throws ScmException
130 {
131 String[] versionCmd = new String[]{BazaarConstants.VERSION};
132 VersionConsumer consumer = new VersionConsumer( BAZAAR_VERSION_TAG );
133 Commandline cmd = BazaarUtils.buildCmd( workingDir, versionCmd );
134
135
136 BazaarUtils.executeCmd( consumer, cmd );
137
138
139 return consumer;
140 }
141
142 public static VersionConsumer getPythonVersion( File workingDir )
143 throws ScmException
144 {
145 String[] versionCmd = new String[]{PYTHON_VERSION};
146 VersionConsumer consumer = new VersionConsumer( PYTHON_VERSION_TAG );
147 Commandline cmd = buildPythonCmd( workingDir, versionCmd );
148
149
150 BazaarUtils.executeCmd( consumer, cmd );
151
152
153 return consumer;
154 }
155
156 private static Commandline buildPythonCmd( File workingDir, String[] cmdAndArgs )
157 throws ScmException
158 {
159 Commandline cmd = new Commandline();
160 cmd.setExecutable( PYTHON_EXEC );
161 cmd.setWorkingDirectory( workingDir.getAbsolutePath() );
162 cmd.addArguments( cmdAndArgs );
163
164 if ( !workingDir.exists() )
165 {
166 boolean success = workingDir.mkdirs();
167 if ( !success )
168 {
169 String msg = "Working directory did not exist" + " and it couldn't be created: " + workingDir;
170 throw new ScmException( msg );
171 }
172 }
173 return cmd;
174 }
175
176
177
178
179
180 private static class VersionConsumer
181 extends BazaarConsumer
182 {
183
184 private static final Pattern VERSION_PATTERN = Pattern.compile( "[\\d]+.?[\\d]*" );
185
186 private final String versionTag;
187
188 private String versionStr = "NA";
189
190 private float version = -1;
191
192 VersionConsumer( String aVersionTag )
193 {
194 super( new DefaultLog() );
195 this.versionTag = aVersionTag;
196 }
197
198 public void doConsume( ScmFileStatus status, String line )
199 {
200 if ( line.startsWith( versionTag ) )
201 {
202 versionStr = line.substring( versionTag.length() );
203 }
204 }
205
206 String getVersion()
207 {
208 return versionStr;
209 }
210
211 boolean isVersionOk( float min )
212 {
213
214 Matcher matcher = VERSION_PATTERN.matcher( versionStr );
215 if ( matcher.find() )
216 {
217 String subStr = versionStr.substring( matcher.start(), matcher.end() );
218 try
219 {
220 version = Float.valueOf( subStr ).floatValue();
221 }
222 catch ( NumberFormatException e )
223 {
224
225 if ( getLogger().isErrorEnabled() )
226 {
227 getLogger().error( "Regexp for version did not result in a number: " + subStr, e );
228 }
229 }
230 }
231
232 return min <= version;
233 }
234 }
235
236 private static class PythonConsumer
237 extends BazaarConsumer
238 {
239
240 private String consumed = "";
241
242 PythonConsumer()
243 {
244 super( new DefaultLog() );
245 }
246
247 public void doConsume( ScmFileStatus status, String line )
248 {
249 consumed = line;
250 }
251
252 String getConsumedAndClear()
253 {
254 String tmp = consumed;
255 consumed = "";
256 return tmp;
257 }
258 }
259
260 private String getInstalledStr()
261 {
262 if ( isComplete() )
263 {
264 return "valid and complete.";
265 }
266 return ( isInstalled() ? "incomplete. " : "invalid. " ) + "Consult " + BAZAAR_INSTALL_URL;
267 }
268
269 public String toString( File workingDir )
270 {
271 boolean bzrOk = bazaarVersion.isVersionOk( BAZAAR_REQ );
272 boolean pyOk = pythonVersion.isVersionOk( PYTHON_REQ );
273 return "\n Your Bazaar installation seems to be " + getInstalledStr() + "\n Python version: "
274 + pythonVersion.getVersion() + ( pyOk ? " (OK)" : " (May be INVALID)" ) + "\n Bazaar version: "
275 + bazaarVersion.getVersion() + ( bzrOk ? " (OK)" : " (May be INVALID)" ) + "\n Paramiko installed: "
276 + paramiko + " (For remote access eg. sftp) " + "\n cCrypt installed: " + cCrypt
277 + " (For remote access eg. sftp) " + "\n cElementTree installed: " + cElementTree + " (Not mandatory) "
278 + "\n";
279 }
280 }