package org.revisionfilter.utils.rcs; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IFile; import org.revisionfilter.utils.console.RevisionFilterConsoleFactory; import org.revisionfilter.utils.rcs.impl.DiffEngine; import org.revisionfilter.utils.rcs.impl.LineOffsetEngine; import org.revisionfilter.utils.rcs.impl.LineOffsetEngine.OffsetLineMapping; /** * Wrap another revision control system and cache all results. The cache cannot * be reset, the caller must create a new instance. */ public class CachedLineChangeSystem { private final IRevisionSystem system; private final Map<String, Set<Integer>> cachedDirtyLines = new ConcurrentHashMap<String, Set<Integer>>(); private final Map<String, List<OffsetLineMapping>> cachedLineOffsets = new ConcurrentHashMap<String, List<OffsetLineMapping>>(); /** * cTor for a specific type of backend * * @param type */ public CachedLineChangeSystem(IRevisionSystem wrappedSystem) { system = wrappedSystem; } public Set<Integer> getDirtyLines(IFile file) { Set<Integer> dirtyLines = new HashSet<Integer>(); // Firewall args if ((file != null) && (file.getLocation() != null)) { // Check cache String absoluteFileName = file.getLocation().toOSString(); dirtyLines = cachedDirtyLines.get(absoluteFileName); if (dirtyLines == null) { // Compute dirty lines try { // Get source strings InputStream fileStream = file.getContents(); String fileString = getFileContents(fileStream); String baseFileString = system.getBaseFileContents(file); // Compute dirty lines dirtyLines = DiffEngine.getDirtyLines(fileString, baseFileString); cachedDirtyLines.put(absoluteFileName, dirtyLines); } catch (Exception ex) { // Throw away RevisionFilterConsoleFactory.outputLine(ex.toString()); ex.printStackTrace(); } } } return dirtyLines; } /** * @param file * @return Map from string offset to line number */ public List<OffsetLineMapping> getLineOffsets(IFile file) { List<OffsetLineMapping> lineOffsets = new LinkedList<OffsetLineMapping>(); // Firewall args if ((file != null) && (file.getLocation() != null)) { // Check cache String absoluteFileName = file.getLocation().toOSString(); lineOffsets = cachedLineOffsets.get(absoluteFileName); if (lineOffsets == null) { // Computer line offsets try { // Get source string InputStream fileStream = file.getContents(); String fileString = getFileContents(fileStream); // Compute line offsets lineOffsets = LineOffsetEngine.computeLineOffsets(fileString); cachedLineOffsets.put(absoluteFileName, lineOffsets); } catch (Exception ex) { // Throw away RevisionFilterConsoleFactory.outputLine(ex.toString()); ex.printStackTrace(); } } } return lineOffsets; } public static String getFileContents(InputStream fileStream) throws IOException { StringBuffer fileString = new StringBuffer(); Reader fileReader = new InputStreamReader(fileStream); int charsRead; char[] inputBuf = new char[512]; while ((charsRead = fileReader.read(inputBuf)) != -1) { fileString.append(inputBuf, 0, charsRead); } return fileString.toString(); } }