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