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 }