001package 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 022import java.io.File; 023import java.util.ArrayList; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.maven.scm.ScmFile; 029import org.apache.maven.scm.ScmFileStatus; 030import org.apache.maven.scm.log.ScmLogger; 031import org.codehaus.plexus.util.cli.StreamConsumer; 032 033/** 034 * @author <a href="mailto:dantran@gmail.com">Dan T. Tran</a> 035 * 036 */ 037public 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}