001 package org.apache.maven.scm.provider.starteam.command.diff;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.io.File;
023 import java.util.ArrayList;
024 import java.util.HashMap;
025 import java.util.List;
026 import java.util.Map;
027
028 import org.apache.maven.scm.ScmFile;
029 import org.apache.maven.scm.ScmFileStatus;
030 import org.apache.maven.scm.log.ScmLogger;
031 import org.codehaus.plexus.util.cli.StreamConsumer;
032
033 /**
034 * @author <a href="mailto:dantran@gmail.com">Dan T. Tran</a>
035 *
036 */
037 public class StarteamDiffConsumer
038 implements StreamConsumer
039 {
040 private static final String WORKING_DIR_TOKEN = "(working dir: ";
041
042 private static final String PATCH_SEPARATOR_TOKEN = "--------------";
043
044 private static final String REVISION_TOKEN = " Revision: ";
045
046 private static final String ONDISK_TOKEN = " (on disk)";
047
048 private static final String ADDED_LINE_TOKEN = "+";
049
050 private static final String REMOVED_LINE_TOKEN = "-";
051
052 private static final String UNCHANGED_LINE_TOKEN = " ";
053
054 private ScmLogger logger;
055
056 @SuppressWarnings( "unused" )
057 private String currentDir = "";
058
059 private boolean diffBlockProcessingStarted = false;
060
061 private boolean revisionBlockStarted = false;
062
063 private String currentFile;
064
065 private StringBuilder currentDifference;
066
067 private List<ScmFile> changedFiles = new ArrayList<ScmFile>();
068
069 private Map<String,CharSequence> differences = new HashMap<String,CharSequence>();
070
071 private StringBuilder patch = new StringBuilder();
072
073 // ----------------------------------------------------------------------
074 //
075 // ----------------------------------------------------------------------
076
077 public StarteamDiffConsumer( ScmLogger logger, File workingDirectory )
078 {
079 this.logger = logger;
080 }
081
082 // ----------------------------------------------------------------------
083 // StreamConsumer Implementation
084 // ----------------------------------------------------------------------
085
086 /** {@inheritDoc} */
087 public void consumeLine( String line )
088 {
089 int pos = 0;
090
091 if ( logger.isDebugEnabled() )
092 {
093 logger.debug( line );
094 }
095
096 patch.append( line ).append( "\n" );
097
098 if ( line.trim().length() == 0 )
099 {
100 return;
101 }
102
103 if ( ( pos = line.indexOf( WORKING_DIR_TOKEN ) ) != -1 )
104 {
105 processGetDir( line, pos );
106
107 return;
108 }
109
110 if ( line.startsWith( PATCH_SEPARATOR_TOKEN ) )
111 {
112 diffBlockProcessingStarted = !diffBlockProcessingStarted;
113
114 if ( diffBlockProcessingStarted )
115 {
116 if ( revisionBlockStarted )
117 {
118 throw new IllegalStateException( "Missing second Revision line or local copy line " );
119 }
120 }
121
122 return;
123 }
124
125 if ( ( pos = line.indexOf( REVISION_TOKEN ) ) != -1 )
126 {
127 if ( revisionBlockStarted )
128 {
129 revisionBlockStarted = false;
130 }
131 else
132 {
133 extractCurrentFile( line, pos );
134
135 revisionBlockStarted = true;
136 }
137
138 return;
139 }
140
141 if ( ( pos = line.indexOf( ONDISK_TOKEN ) ) != -1 )
142 {
143 if ( revisionBlockStarted )
144 {
145 revisionBlockStarted = false;
146 }
147 else
148 {
149 throw new IllegalStateException( "Working copy line found at the wrong state " );
150 }
151
152 return;
153 }
154
155 if ( !diffBlockProcessingStarted )
156 {
157 if ( logger.isWarnEnabled() )
158 {
159 logger.warn( "Unparseable line: '" + line + "'" );
160 }
161
162 return;
163 }
164
165 if ( line.startsWith( ADDED_LINE_TOKEN ) || line.startsWith( REMOVED_LINE_TOKEN )
166 || line.startsWith( UNCHANGED_LINE_TOKEN ) )
167 {
168 // add to buffer
169 currentDifference.append( line ).append( "\n" );
170 }
171 else
172 {
173 if ( logger.isWarnEnabled() )
174 {
175 logger.warn( "Unparseable line: '" + line + "'" );
176 }
177 }
178 }
179
180 /**
181 * Process the current input line in the Get Directory
182 *
183 * @param line a line of text from the Starteam log output
184 */
185 private void processGetDir( String line, int pos )
186 {
187 String dirPath = line.substring( pos + WORKING_DIR_TOKEN.length(), line.length() - 1 ).replace( '\\', '/' );
188
189 this.currentDir = dirPath;
190 }
191
192 private void extractCurrentFile( String line, int pos )
193 {
194 currentFile = line.substring( 0, pos );
195
196 changedFiles.add( new ScmFile( currentFile, ScmFileStatus.MODIFIED ) );
197
198 currentDifference = new StringBuilder();
199
200 differences.put( currentFile, currentDifference );
201 }
202
203 public List<ScmFile> getChangedFiles()
204 {
205 return changedFiles;
206 }
207
208 public Map<String,CharSequence> getDifferences()
209 {
210 return differences;
211 }
212
213 public String getPatch()
214 {
215 return patch.toString();
216 }
217
218 }