/* * Cobertura - http://cobertura.sourceforge.net/ * * Copyright (C) 2010 Piotr Tabor * * Note: This file is dual licensed under the GPL and the Apache * Source License (so that it can be used from both the main * Cobertura classes and the ant tasks). * * Cobertura is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Cobertura is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cobertura; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ package net.sourceforge.cobertura.coveragedata; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import net.sourceforge.cobertura.coveragedata.countermaps.AtomicCounterMap; import net.sourceforge.cobertura.coveragedata.countermaps.CounterMap; public class TouchCollector implements HasBeenInstrumented{ private static final CounterMap<LineTouchData> touchedLines=new AtomicCounterMap<LineTouchData>(); private static final CounterMap<SwitchTouchData> switchTouchData=new AtomicCounterMap<SwitchTouchData>(); private static final CounterMap<JumpTouchData> jumpTouchData=new AtomicCounterMap<JumpTouchData>(); private static AtomicInteger lastClassId=new AtomicInteger(1); private static final Map<String,Integer> class2classId=new ConcurrentHashMap<String, Integer>(); private static final Map<Integer,String> classId2class=new ConcurrentHashMap<Integer,String>(); // We can handle dumping of data manually. No ShutDownHook required // static{ // ProjectData.initialize(); // } private static final int registerClassData(String name){ Integer res=class2classId.get(name); if (res==null){ int new_id=lastClassId.incrementAndGet(); class2classId.put(name, new_id); classId2class.put(new_id, name); return new_id; } return res; } /** * This method is only called by code that has been instrumented. It * is not called by any of the Cobertura code or ant tasks. */ public static final void touchSwitch(String classId,int lineNumber, int switchNumber, int branch) { switchTouchData.incrementValue(new SwitchTouchData(registerClassData(classId),lineNumber, switchNumber, branch)); } /** * This method is only called by code that has been instrumented. It * is not called by any of the Cobertura code or ant tasks. */ public static final void touch(String classId,int lineNumber) { touchedLines.incrementValue(new LineTouchData(registerClassData(classId), lineNumber)); } /** * This method is only called by code that has been instrumented. It * is not called by any of the Cobertura code or ant tasks. */ public static final void touchJump(String classId,int lineNumber, int branchNumber, boolean branch) { jumpTouchData.incrementValue(new JumpTouchData(registerClassData(classId),lineNumber, branchNumber, branch)); } private static class LineTouchData implements HasBeenInstrumented{ int classId,lineNumber; public LineTouchData(int classId,int lineNumber) { this.classId=classId; this.lineNumber=lineNumber; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + classId; result = prime * result + lineNumber; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; LineTouchData other = (LineTouchData) obj; if (classId != other.classId) return false; if (lineNumber != other.lineNumber) return false; return true; } } private static class SwitchTouchData extends LineTouchData implements HasBeenInstrumented{ int switchNumber, branch; public SwitchTouchData(int classId,int lineNumber, int switchNumber, int branch) { super(classId,lineNumber); this.switchNumber=switchNumber; this.branch=branch; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + branch; result = prime * result + switchNumber; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; SwitchTouchData other = (SwitchTouchData) obj; if (branch != other.branch) return false; if (switchNumber != other.switchNumber) return false; return true; } } private static class JumpTouchData extends LineTouchData implements HasBeenInstrumented{ int branchNumber; boolean branch; public JumpTouchData(int classId,int lineNumber, int branchNumber, boolean branch) { super(classId, lineNumber); this.branchNumber=branchNumber; this.branch=branch; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (branch ? 1231 : 1237); result = prime * result + branchNumber; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; JumpTouchData other = (JumpTouchData) obj; if (branch != other.branch) return false; if (branchNumber != other.branchNumber) return false; return true; } } public static synchronized void applyTouchesOnProjectData(ProjectData projectData){ //System.out.println("Flushing results..."); Map<LineTouchData,Integer> touches=touchedLines.getFinalStateAndCleanIt(); for(Entry<LineTouchData, Integer> touch:touches.entrySet()){ if(touch.getValue()>0){ getClassFor(touch.getKey(),projectData).touch(touch.getKey().lineNumber,touch.getValue()); } } Map<SwitchTouchData,Integer> switchTouches=switchTouchData.getFinalStateAndCleanIt(); for(Entry<SwitchTouchData, Integer> touch:switchTouches.entrySet()){ if(touch.getValue()>0){ getClassFor(touch.getKey(),projectData).touchSwitch( touch.getKey().lineNumber, touch.getKey().switchNumber, touch.getKey().branch,touch.getValue()); } } Map<JumpTouchData,Integer> jumpTouches=jumpTouchData.getFinalStateAndCleanIt(); for(Entry<JumpTouchData, Integer> touch:jumpTouches.entrySet()){ if(touch.getValue()>0){ getClassFor(touch.getKey(),projectData).touchJump( touch.getKey().lineNumber, touch.getKey().branchNumber, touch.getKey().branch,touch.getValue()); } } //System.out.println("Flushing results done"); } private static ClassData getClassFor(LineTouchData key,ProjectData projectData) { // System.out.println("\nLooking for:"+key.classId+"\n"); return projectData.getOrCreateClassData(classId2class.get(key.classId)); } }