View Javadoc

1   package org.apache.maven.scm.provider.jazz.command.status;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.scm.ScmFile;
23  import org.apache.maven.scm.ScmFileStatus;
24  import org.apache.maven.scm.log.ScmLogger;
25  import org.apache.maven.scm.provider.ScmProviderRepository;
26  import org.apache.maven.scm.provider.jazz.command.consumer.AbstractRepositoryConsumer;
27  import org.apache.maven.scm.provider.jazz.repository.JazzScmProviderRepository;
28  import org.apache.regexp.RE;
29  import org.apache.regexp.RESyntaxException;
30  
31  import java.util.ArrayList;
32  import java.util.List;
33  
34  /**
35   * Consume the output of the scm command for the "status" operation.
36   * <p/>
37   * It is normally just used to build up a list of ScmFile objects that have
38   * their ScmFileStatus set.
39   * This class has been expanded so that the Workspace, Component and Baseline
40   * are also collected and set back in the JazzScmProviderRepository.
41   * The Workspace and Component names are needed for some other commands (list,
42   * for example), so we can easily get this information here.
43   *
44   * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a>
45   */
46  public class JazzStatusConsumer
47      extends AbstractRepositoryConsumer
48  {
49  // We have have a workspace with no flow targets (it points to itself)
50  //
51  //  Workspace: (1000) "BogusRepositoryWorkspace" <-> (1000) "BogusRepositoryWorkspace"
52  //    Component: (1001) "BogusComponent"
53  //      Baseline: (1128) 27 "BogusTestJazz-3.0.0.40"
54  //      Unresolved:
55  //        d-- /BogusTest/pom.xml.releaseBackup
56  //        d-- /BogusTest/release.properties
57  //
58  // Or, we have have one that does have a flow target (ie a stream or another workspace).
59  //
60  //  Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream"
61  //    Component: (1158) "GPDB" <-> (1157) "GPDBStream"
62  //      Baseline: (1159) 1 "Initial Baseline"
63  //
64  // Note the (%d) numbers are aliases and are only valid for the machine/instance that made the
65  // remote calls to the server. They are not to be shared across machines (ie don't make them global, public
66  // or persistent).
67  //
68  
69      //  Workspace: (1000) "BogusRepositoryWorkspace" <-> (1000) "BogusRepositoryWorkspace"
70      //  Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream"
71      private static final String WORKSPACE_PATTERN = "\\((\\d+)\\) \"(.*)\" <-> \\((\\d+)\\) \"(.*)\"";
72  
73      /**
74       * @see #WORKSPACE_PATTERN
75       */
76      private RE workspaceRegExp;
77  
78      //  Component: (1001) "BogusComponent"
79      private static final String COMPONENT_PATTERN1 = "\\((\\d+)\\) \"(.*)\"";
80  
81      /**
82       * @see #COMPONENT_PATTERN1
83       */
84      private RE componentRegExp1;
85  
86      //  Component: (1158) "GPDB" <-> (1157) "GPDBStream"
87      //  Component: (1002) "FireDragon" <-> (1005) "MavenR3Stream Workspace" (outgoing addition)
88      private static final String COMPONENT_PATTERN2 = "\\((\\d+)\\) \"(.*)\" <.*>";
89  
90      /**
91       * @see #COMPONENT_PATTERN2
92       */
93      private RE componentRegExp2;
94  
95      //  Baseline: (1128) 27 "BogusTestJazz-3.0.0.40"
96      private static final String BASELINE_PATTERN = "\\((\\d+)\\) (\\d+) \"(.*)\"";
97  
98      /**
99       * @see #BASELINE_PATTERN
100      */
101     private RE baselineRegExp;
102 
103     // Additional data we collect. (eye catchers)
104 
105     /**
106      * The "Status" command output line that contains the "Workspace" name.
107      */
108     public static final String STATUS_CMD_WORKSPACE = "Workspace:";
109 
110     /**
111      * The "Status" command output line that contains the "Component" name.
112      */
113     public static final String STATUS_CMD_COMPONENT = "Component:";
114 
115     /**
116      * The "Status" command output line that contains the "Workspace" name.
117      */
118     public static final String STATUS_CMD_BASELINE = "Baseline:";
119 
120     // File Status Commands (eye catchers)
121 
122     /**
123      * The "Status" command status flag for a resource that has been added.
124      */
125     public static final String STATUS_CMD_ADD_FLAG = "a-";
126 
127     /**
128      * The "Status" command status flag for when the content or properties of
129      * a file have been modified, or the properties of a directory have changed.
130      */
131     public static final String STATUS_CMD_CHANGE_FLAG = "-c";
132 
133     /**
134      * The "Status" command status flag for a resource that has been deleted.
135      */
136     public static final String STATUS_CMD_DELETE_FLAG = "d-";
137 
138     /**
139      * The "Status" command status flag for a resource that has been renamed or moved.
140      */
141     public static final String STATUS_CMD_MOVED_FLAG = "m-";
142 
143     /**
144      * A List of ScmFile objects that have their ScmFileStatus set.
145      */
146     private List<ScmFile> fChangedFiles = new ArrayList<ScmFile>();
147 
148     /**
149      * Constructor for our "scm status" consumer.
150      *
151      * @param repo   The JazzScmProviderRepository being used.
152      * @param logger The ScmLogger to use.
153      */
154     public JazzStatusConsumer( ScmProviderRepository repo, ScmLogger logger )
155     {
156         super( repo, logger );
157 
158         try
159         {
160             workspaceRegExp = new RE( WORKSPACE_PATTERN );
161             componentRegExp1 = new RE( COMPONENT_PATTERN1 );
162             componentRegExp2 = new RE( COMPONENT_PATTERN2 );
163             baselineRegExp = new RE( BASELINE_PATTERN );
164         }
165         catch ( RESyntaxException ex )
166         {
167             throw new RuntimeException(
168                 "INTERNAL ERROR: Could not create regexp to parse jazz scm status output. This shouldn't happen. Something is probably wrong with the oro installation.",
169                 ex );
170         }
171     }
172 
173     /**
174      * Process one line of output from the execution of the "scm status" command.
175      *
176      * @param line The line of output from the external command that has been pumped to us.
177      * @see org.codehaus.plexus.util.cli.StreamConsumer#consumeLine(java.lang.String)
178      */
179     public void consumeLine( String line )
180     {
181         super.consumeLine( line );
182         if ( containsWorkspace( line ) )
183         {
184             extractWorkspace( line );
185         }
186         if ( containsComponent( line ) )
187         {
188             extractComponent( line );
189         }
190         if ( containsBaseline( line ) )
191         {
192             extractBaseline( line );
193         }
194         if ( containsStatusFlag( line ) )
195         {
196             extractChangedFile( line );
197         }
198     }
199 
200     private boolean containsWorkspace( String line )
201     {
202         return line.trim().startsWith( STATUS_CMD_WORKSPACE );
203     }
204 
205     private void extractWorkspace( String line )
206     {
207         // With no stream (flow target):
208         //   Workspace: (1000) "BogusRepositoryWorkspace" <-> (1000) "BogusRepositoryWorkspace"
209         // With a stream:
210         //   Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream"
211 
212         if ( workspaceRegExp.match( line ) )
213         {
214             JazzScmProviderRepository jazzRepository = (JazzScmProviderRepository) getRepository();
215 
216             int workspaceAlias = Integer.parseInt( workspaceRegExp.getParen( 1 ) );
217             String workspace = workspaceRegExp.getParen( 2 );
218             int streamAlias = Integer.parseInt( workspaceRegExp.getParen( 3 ) );
219             String stream = workspaceRegExp.getParen( 4 );
220             if ( getLogger().isDebugEnabled() )
221             {
222                 getLogger().debug( "Successfully parsed \"Workspace:\" line:" );
223                 getLogger().debug( "  workspaceAlias = " + workspaceAlias );
224                 getLogger().debug( "  workspace      = " + workspace );
225                 getLogger().debug( "  streamAlias    = " + streamAlias );
226                 getLogger().debug( "  stream         = " + stream );
227             }
228             jazzRepository.setWorkspaceAlias( workspaceAlias );
229             jazzRepository.setWorkspace( workspace );
230             jazzRepository.setFlowTargetAlias( streamAlias );
231             jazzRepository.setFlowTarget( stream );
232         }
233     }
234 
235     private boolean containsComponent( String line )
236     {
237         return line.trim().startsWith( STATUS_CMD_COMPONENT );
238     }
239 
240     private void extractComponent( String line )
241     {
242         // With no stream (flow target):
243         //     Component: (1001) "BogusComponent"
244         // With a stream:
245         //     Component: (1158) "GPDB" <-> (1157) "GPDBStream"
246         // With some additional information:
247         //     Component: (1002) "FireDragon" <-> (1005) "MavenR3Stream Workspace" (outgoing addition)
248 
249         if ( componentRegExp1.match( line ) )
250         {
251             //     Component: (1001) "BogusComponent"
252             JazzScmProviderRepository jazzRepository = (JazzScmProviderRepository) getRepository();
253             int componentAlias = Integer.parseInt( componentRegExp1.getParen( 1 ) );
254             String component = componentRegExp1.getParen( 2 );
255             if ( getLogger().isDebugEnabled() )
256             {
257                 getLogger().debug( "Successfully parsed \"Component:\" line:" );
258                 getLogger().debug( "  componentAlias = " + componentAlias );
259                 getLogger().debug( "  component      = " + component );
260             }
261             jazzRepository.setComponent( component );
262         }
263 
264         if ( componentRegExp2.match( line ) )
265         {
266             //     Component: (1158) "GPDB" <-> (1157) "GPDBStream"
267             JazzScmProviderRepository jazzRepository = (JazzScmProviderRepository) getRepository();
268             int componentAlias = Integer.parseInt( componentRegExp2.getParen( 1 ) );
269             String component = componentRegExp2.getParen( 2 );
270             if ( getLogger().isDebugEnabled() )
271             {
272                 getLogger().debug( "Successfully parsed \"Component:\" line:" );
273                 getLogger().debug( "  componentAlias = " + componentAlias );
274                 getLogger().debug( "  component      = " + component );
275             }
276             jazzRepository.setComponent( component );
277         }
278     }
279 
280     private boolean containsBaseline( String line )
281     {
282         return line.trim().startsWith( STATUS_CMD_BASELINE );
283     }
284 
285     private void extractBaseline( String line )
286     {
287         // Baseline: (1128) 27 "BogusTestJazz-3.0.0.40"
288 
289         if ( baselineRegExp.match( line ) )
290         {
291             JazzScmProviderRepository jazzRepository = (JazzScmProviderRepository) getRepository();
292 
293             int baselineAlias = Integer.parseInt( baselineRegExp.getParen( 1 ) );
294             int baselineId = Integer.parseInt( baselineRegExp.getParen( 2 ) );
295             String baseline = baselineRegExp.getParen( 3 );
296             if ( getLogger().isDebugEnabled() )
297             {
298                 getLogger().debug( "Successfully parsed \"Baseline:\" line:" );
299                 getLogger().debug( "  baselineAlias = " + baselineAlias );
300                 getLogger().debug( "  baselineId    = " + baselineId );
301                 getLogger().debug( "  baseline      = " + baseline );
302             }
303             jazzRepository.setBaseline( baseline );
304         }
305     }
306 
307     private boolean containsStatusFlag( String line )
308     {
309         boolean containsStatusFlag = false;
310 
311         if ( line.trim().length() > 2 )
312         {
313             String flag = line.trim().substring( 0, 2 );
314             if ( STATUS_CMD_ADD_FLAG.equals( flag ) ||
315                 STATUS_CMD_CHANGE_FLAG.equals( flag ) ||
316                 STATUS_CMD_DELETE_FLAG.equals( flag ) )
317             {
318                 containsStatusFlag = true;
319             }
320         }
321         return containsStatusFlag;
322     }
323 
324     private void extractChangedFile( String line )
325     {
326         String flag = line.trim().substring( 0, 2 );
327         String filePath = line.trim().substring( 3 ).trim();
328         ScmFileStatus status = ScmFileStatus.UNKNOWN;
329 
330         if ( STATUS_CMD_ADD_FLAG.equals( flag ) )
331         {
332             status = ScmFileStatus.ADDED;
333         }
334 
335         if ( STATUS_CMD_CHANGE_FLAG.equals( flag ) )
336         {
337             status = ScmFileStatus.MODIFIED;
338         }
339 
340         if ( STATUS_CMD_DELETE_FLAG.equals( flag ) )
341         {
342             status = ScmFileStatus.DELETED;
343         }
344 
345         if ( getLogger().isDebugEnabled() )
346         {
347             getLogger().debug( " Line               : '" + line + "'" );
348             getLogger().debug( " Extracted filePath : '" + filePath + "'" );
349             getLogger().debug( " Extracted     flag : '" + flag + "'" );
350             getLogger().debug( " Extracted   status : '" + status + "'" );
351         }
352 
353         fChangedFiles.add( new ScmFile( filePath, status ) );
354     }
355 
356     public List<ScmFile> getChangedFiles()
357     {
358         return fChangedFiles;
359     }
360 }