View Javadoc
1   package org.apache.maven.scm.provider.bazaar.command;
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.ScmFileStatus;
23  import org.apache.maven.scm.log.ScmLogger;
24  import org.apache.maven.scm.util.AbstractConsumer;
25  
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  /**
32   * Base consumer to do common parsing for all bazaar commands.
33   * <p/>
34   * More specific: log line each line if debug is enabled, get file status
35   * and detect warnings from bazaar
36   *
37   * @author <a href="mailto:torbjorn@smorgrav.org">Torbjörn Eikli Smörgrav</a>
38   *
39   */
40  public class BazaarConsumer
41      extends AbstractConsumer
42  {
43  
44      /**
45       * A list of known keywords from bazaar
46       */
47      private static final Map<String, ScmFileStatus> IDENTIFIERS = new HashMap<String, ScmFileStatus>();
48  
49      /**
50       * A list of known message prefixes from bazaar
51       */
52      private static final Map<String, String> MESSAGES = new HashMap<String, String>();
53  
54      /**
55       * Number of lines to keep from Std.Err
56       * This size is set to ensure that we capture enough info
57       * but still keeps a low memory footprint.
58       */
59      private static final int MAX_STDERR_SIZE = 10;
60  
61      /**
62       * A list of the MAX_STDERR_SIZE last errors or warnings.
63       */
64      private final List<String> stderr = new ArrayList<String>();
65  
66      static
67      {
68          IDENTIFIERS.put( "added", ScmFileStatus.ADDED );
69          IDENTIFIERS.put( "adding", ScmFileStatus.ADDED );
70          IDENTIFIERS.put( "unknown", ScmFileStatus.UNKNOWN );
71          IDENTIFIERS.put( "modified", ScmFileStatus.MODIFIED );
72          IDENTIFIERS.put( "removed", ScmFileStatus.DELETED );
73          IDENTIFIERS.put( "renamed", ScmFileStatus.RENAMED );
74          MESSAGES.put( "bzr: WARNING:", "WARNING" );
75          MESSAGES.put( "bzr: ERROR:", "ERROR" );
76          MESSAGES.put( "'bzr' ", "ERROR" ); // bzr isn't found in windows path
77      }
78  
79      public BazaarConsumer( ScmLogger logger )
80      {
81          super( logger );
82      }
83  
84      public void doConsume( ScmFileStatus status, String trimmedLine )
85      {
86          //override this
87      }
88  
89      /** {@inheritDoc} */
90      public void consumeLine( String line )
91      {
92          if ( getLogger().isDebugEnabled() )
93          {
94              getLogger().debug( line );
95          }
96          String trimmedLine = line.trim();
97  
98          String statusStr = processInputForKnownIdentifiers( trimmedLine );
99  
100         //If its not a status report - then maybe its a message?
101         if ( statusStr == null )
102         {
103             boolean isMessage = processInputForKnownMessages( trimmedLine );
104             //If it is then its already processed and we can ignore futher processing
105             if ( isMessage )
106             {
107                 return;
108             }
109         }
110         else
111         {
112             //Strip away identifier
113             trimmedLine = trimmedLine.substring( statusStr.length() );
114             trimmedLine = trimmedLine.trim(); //one or more spaces
115         }
116 
117         ScmFileStatus status = statusStr != null ? ( (ScmFileStatus) IDENTIFIERS.get( statusStr.intern() ) ) : null;
118         doConsume( status, trimmedLine );
119     }
120 
121     /**
122      * Warnings and errors is usually printed out in Std.Err, thus for derived consumers
123      * operating on Std.Out this would typically return an empty string.
124      *
125      * @return Return the last lines interpreted as an warning or an error
126      */
127     public String getStdErr()
128     {
129         StringBuilder str = new StringBuilder();
130         for ( String line : stderr )
131         {
132             str.append( line );
133         }
134         return str.toString();
135     }
136 
137     private static String processInputForKnownIdentifiers( String line )
138     {
139         for ( String id : IDENTIFIERS.keySet() )
140         {
141             if ( line.startsWith( id ) )
142             {
143                 return id;
144             }
145         }
146         return null;
147     }
148 
149     private boolean processInputForKnownMessages( String line )
150     {
151         for ( String prefix : MESSAGES.keySet() )
152         {
153             if ( line.startsWith( prefix ) )
154             {
155                 stderr.add( line ); //Add line
156                 if ( stderr.size() > MAX_STDERR_SIZE )
157                 {
158                     stderr.remove( 0 ); //Rotate list
159                 }
160                 String message = line.substring( prefix.length() );
161                 if ( MESSAGES.get( prefix ).equals( "WARNING" ) )
162                 {
163                     if ( getLogger().isWarnEnabled() )
164                     {
165                         getLogger().warn( message );
166                     }
167                 }
168                 else
169                 {
170                     if ( getLogger().isErrorEnabled() )
171                     {
172                         getLogger().error( message );
173                     }
174                 }
175                 return true;
176             }
177         }
178         return false;
179     }
180 }