1 package org.apache.maven.scm.provider.integrity;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import com.mks.api.Command;
23 import com.mks.api.MultiValue;
24 import com.mks.api.Option;
25 import com.mks.api.response.APIException;
26 import com.mks.api.response.Field;
27 import com.mks.api.response.Response;
28 import com.mks.api.response.WorkItem;
29 import com.mks.api.response.WorkItemIterator;
30 import com.mks.api.si.SIModelTypeName;
31
32 import java.util.ArrayList;
33 import java.util.Calendar;
34 import java.util.Collections;
35 import java.util.Comparator;
36 import java.util.Date;
37 import java.util.Hashtable;
38 import java.util.List;
39 import java.util.NoSuchElementException;
40
41
42
43
44
45
46
47
48
49 public class Project
50 {
51 public static final String NORMAL_PROJECT = "Normal";
52
53 public static final String VARIANT_PROJECT = "Variant";
54
55 public static final String BUILD_PROJECT = "Build";
56
57 private String projectName;
58
59 private String projectType;
60
61 private String projectRevision;
62
63 private String fullConfigSyntax;
64
65 private Date lastCheckpoint;
66
67 private APISession api;
68
69
70 public static final Comparator<Member> FILES_ORDER = new Comparator<Member>()
71 {
72 public int compare( Member cmm1, Member cmm2 )
73 {
74 return cmm1.getMemberName().compareToIgnoreCase( cmm2.getMemberName() );
75 }
76 };
77
78
79
80
81
82
83
84
85 public static void validateTag( String tagName )
86 throws Exception
87 {
88 if ( tagName == null || tagName.length() == 0 )
89 {
90 throw new Exception( "The checkpoint label string is empty!" );
91 }
92
93 char ch = tagName.charAt( 0 );
94 if ( !( ( 'A' <= ch && ch <= 'Z' ) || ( 'a' <= ch && ch <= 'z' ) ) )
95 {
96 throw new Exception( "The checkpoint label must start with an alpha character!" );
97 }
98
99 for ( char invalid : "$,.:;/\\@".toCharArray() )
100 {
101 if ( tagName.indexOf( invalid ) >= 0 )
102 {
103 throw new Exception(
104 "The checkpoint label may cannot contain one of the following characters: $ , . : ; / \\ @" );
105 }
106 }
107 }
108
109
110
111
112
113
114
115
116 public Project( APISession api, String configPath )
117 throws APIException
118 {
119
120 this.api = api;
121 try
122 {
123
124 Command siProjectInfoCmd = new Command( Command.SI, "projectinfo" );
125 siProjectInfoCmd.addOption( new Option( "project", configPath ) );
126 api.getLogger().info( "Preparing to execute si projectinfo for " + configPath );
127 Response infoRes = api.runCommand( siProjectInfoCmd );
128
129 WorkItem wi = infoRes.getWorkItems().next();
130
131 Field pjNameFld = wi.getField( "projectName" );
132 Field pjTypeFld = wi.getField( "projectType" );
133 Field pjCfgPathFld = wi.getField( "fullConfigSyntax" );
134 Field pjChkptFld = wi.getField( "lastCheckpoint" );
135
136
137
138 if ( null != pjNameFld && null != pjNameFld.getValueAsString() )
139 {
140 projectName = pjNameFld.getValueAsString();
141 }
142 else
143 {
144 api.getLogger().warn( "Project info did not provide a value for the 'projectName' field!" );
145 projectName = "";
146 }
147
148 if ( null != pjTypeFld && null != pjTypeFld.getValueAsString() )
149 {
150 projectType = pjTypeFld.getValueAsString();
151 if ( isBuild() )
152 {
153
154 Field pjRevFld = wi.getField( "revision" );
155 if ( null != pjRevFld && null != pjRevFld.getItem() )
156 {
157 projectRevision = pjRevFld.getItem().getId();
158 }
159 else
160 {
161 projectRevision = "";
162 api.getLogger().warn( "Project info did not provide a vale for the 'revision' field!" );
163 }
164 }
165 }
166 else
167 {
168 api.getLogger().warn( "Project info did not provide a value for the 'projectType' field!" );
169 projectType = "";
170 }
171
172 if ( null != pjCfgPathFld && null != pjCfgPathFld.getValueAsString() )
173 {
174 fullConfigSyntax = pjCfgPathFld.getValueAsString();
175 }
176 else
177 {
178 api.getLogger().error( "Project info did not provide a value for the 'fullConfigSyntax' field!" );
179 fullConfigSyntax = "";
180 }
181
182 if ( null != pjChkptFld && null != pjChkptFld.getDateTime() )
183 {
184 lastCheckpoint = pjChkptFld.getDateTime();
185 }
186 else
187 {
188 api.getLogger().warn( "Project info did not provide a value for the 'lastCheckpoint' field!" );
189 lastCheckpoint = Calendar.getInstance().getTime();
190 }
191 }
192 catch ( NoSuchElementException nsee )
193 {
194 api.getLogger().error( "Project info did not provide a value for field " + nsee.getMessage() );
195 }
196 }
197
198
199
200
201
202
203 public String getProjectName()
204 {
205 return projectName;
206 }
207
208
209
210
211
212
213 public String getProjectRevision()
214 {
215 return projectRevision;
216 }
217
218
219
220
221
222
223 public boolean isNormal()
224 {
225 if ( projectType.equalsIgnoreCase( NORMAL_PROJECT ) )
226 {
227 return true;
228 }
229 else
230 {
231 return false;
232 }
233 }
234
235
236
237
238
239
240 public boolean isVariant()
241 {
242 if ( projectType.equalsIgnoreCase( VARIANT_PROJECT ) )
243 {
244 return true;
245 }
246 else
247 {
248 return false;
249 }
250 }
251
252
253
254
255
256
257 public boolean isBuild()
258 {
259 if ( projectType.equalsIgnoreCase( BUILD_PROJECT ) )
260 {
261 return true;
262 }
263 else
264 {
265 return false;
266 }
267 }
268
269
270
271
272
273
274 public String getConfigurationPath()
275 {
276 return fullConfigSyntax;
277 }
278
279
280
281
282
283
284 public Date getLastCheckpointDate()
285 {
286 return lastCheckpoint;
287 }
288
289
290
291
292
293
294
295
296 public List<Member> listFiles( String workspaceDir )
297 throws APIException
298 {
299
300 List<Member> memberList = new ArrayList<Member>();
301
302 Hashtable<String, String> pjConfigHash = new Hashtable<String, String>();
303
304 pjConfigHash.put( projectName, fullConfigSyntax );
305
306 String projectRoot = projectName.substring( 0, projectName.lastIndexOf( '/' ) );
307
308
309 Command siViewProjectCmd = new Command( Command.SI, "viewproject" );
310 siViewProjectCmd.addOption( new Option( "recurse" ) );
311 siViewProjectCmd.addOption( new Option( "project", fullConfigSyntax ) );
312 MultiValue mvFields = new MultiValue( "," );
313 mvFields.add( "name" );
314 mvFields.add( "context" );
315 mvFields.add( "memberrev" );
316 mvFields.add( "membertimestamp" );
317 mvFields.add( "memberdescription" );
318 siViewProjectCmd.addOption( new Option( "fields", mvFields ) );
319 api.getLogger().info( "Preparing to execute si viewproject for " + fullConfigSyntax );
320 Response viewRes = api.runCommand( siViewProjectCmd );
321
322
323 WorkItemIterator wit = viewRes.getWorkItems();
324 while ( wit.hasNext() )
325 {
326 WorkItem wi = wit.next();
327 if ( wi.getModelType().equals( SIModelTypeName.SI_SUBPROJECT ) )
328 {
329
330 pjConfigHash.put( wi.getField( "name" ).getValueAsString(), wi.getId() );
331 }
332 else if ( wi.getModelType().equals( SIModelTypeName.MEMBER ) )
333 {
334
335 String parentProject = wi.getField( "parent" ).getValueAsString();
336
337 Member iCMMember = new Member( wi, pjConfigHash.get( parentProject ), projectRoot, workspaceDir );
338
339 memberList.add( iCMMember );
340 }
341 else
342 {
343 api.getLogger().warn( "View project output contains an invalid model type: " + wi.getModelType() );
344 }
345 }
346
347
348 Collections.sort( memberList, FILES_ORDER );
349 return memberList;
350 }
351
352
353
354
355
356
357
358
359
360 public Response checkpoint( String message, String tag )
361 throws APIException
362 {
363
364 api.getLogger().debug( "Checkpointing project " + fullConfigSyntax + " with label '" + tag + "'" );
365
366 Command siCheckpoint = new Command( Command.SI, "checkpoint" );
367 siCheckpoint.addOption( new Option( "recurse" ) );
368
369 siCheckpoint.addOption( new Option( "project", fullConfigSyntax ) );
370
371 siCheckpoint.addOption( new Option( "label", tag ) );
372
373 if ( null != message && message.length() > 0 )
374 {
375 siCheckpoint.addOption( new Option( "description", message ) );
376 }
377
378 return api.runCommand( siCheckpoint );
379 }
380
381
382
383
384
385
386
387
388 public Response createDevPath( String devPath )
389 throws APIException
390 {
391
392 String chkpt = projectRevision;
393 if ( !isBuild() )
394 {
395 Response chkptRes = checkpoint( "Pre-checkpoint for development path " + devPath, devPath + " Baseline" );
396 WorkItem wi = chkptRes.getWorkItem( fullConfigSyntax );
397 chkpt = wi.getResult().getField( "resultant" ).getItem().getId();
398 }
399
400
401 api.getLogger().debug(
402 "Creating development path '" + devPath + "' for project " + projectName + " at revision '" + chkpt + "'" );
403 Command siCreateDevPath = new Command( Command.SI, "createdevpath" );
404 siCreateDevPath.addOption( new Option( "devpath", devPath ) );
405
406 siCreateDevPath.addOption( new Option( "project", projectName ) );
407
408 siCreateDevPath.addOption( new Option( "projectRevision", chkpt ) );
409
410 return api.runCommand( siCreateDevPath );
411 }
412 }
413