001 /* 002 * Cobertura - http://cobertura.sourceforge.net/ 003 * 004 * Copyright (C) 2010 Piotr Tabor 005 * 006 * Note: This file is dual licensed under the GPL and the Apache 007 * Source License (so that it can be used from both the main 008 * Cobertura classes and the ant tasks). 009 * 010 * Cobertura is free software; you can redistribute it and/or modify 011 * it under the terms of the GNU General Public License as published 012 * by the Free Software Foundation; either version 2 of the License, 013 * or (at your option) any later version. 014 * 015 * Cobertura is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of 017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 018 * General Public License for more details. 019 * 020 * You should have received a copy of the GNU General Public License 021 * along with Cobertura; if not, write to the Free Software 022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 023 * USA 024 */ 025 026 package net.sourceforge.cobertura.coveragedata; 027 028 import java.util.Map; 029 import java.util.Map.Entry; 030 import java.util.concurrent.ConcurrentHashMap; 031 import java.util.concurrent.atomic.AtomicInteger; 032 033 import net.sourceforge.cobertura.coveragedata.countermaps.AtomicCounterMap; 034 import net.sourceforge.cobertura.coveragedata.countermaps.CounterMap; 035 036 public class TouchCollector implements HasBeenInstrumented{ 037 038 private static final CounterMap<LineTouchData> touchedLines=new AtomicCounterMap<LineTouchData>(); 039 private static final CounterMap<SwitchTouchData> switchTouchData=new AtomicCounterMap<SwitchTouchData>(); 040 private static final CounterMap<JumpTouchData> jumpTouchData=new AtomicCounterMap<JumpTouchData>(); 041 042 private static AtomicInteger lastClassId=new AtomicInteger(1); 043 private static final Map<String,Integer> class2classId=new ConcurrentHashMap<String, Integer>(); 044 private static final Map<Integer,String> classId2class=new ConcurrentHashMap<Integer,String>(); 045 046 static{ 047 ProjectData.initialize(); 048 } 049 050 private static final int registerClassData(String name){ 051 Integer res=class2classId.get(name); 052 if (res==null){ 053 int new_id=lastClassId.incrementAndGet(); 054 class2classId.put(name, new_id); 055 classId2class.put(new_id, name); 056 return new_id; 057 } 058 return res; 059 } 060 061 /** 062 * This method is only called by code that has been instrumented. It 063 * is not called by any of the Cobertura code or ant tasks. 064 */ 065 public static final void touchSwitch(String classId,int lineNumber, int switchNumber, int branch) { 066 switchTouchData.incrementValue(new SwitchTouchData(registerClassData(classId),lineNumber, switchNumber, branch)); 067 } 068 069 /** 070 * This method is only called by code that has been instrumented. It 071 * is not called by any of the Cobertura code or ant tasks. 072 */ 073 public static final void touch(String classId,int lineNumber) { 074 touchedLines.incrementValue(new LineTouchData(registerClassData(classId), lineNumber)); 075 } 076 077 /** 078 * This method is only called by code that has been instrumented. It 079 * is not called by any of the Cobertura code or ant tasks. 080 */ 081 public static final void touchJump(String classId,int lineNumber, int branchNumber, boolean branch) { 082 jumpTouchData.incrementValue(new JumpTouchData(registerClassData(classId),lineNumber, branchNumber, branch)); 083 } 084 085 private static class LineTouchData implements HasBeenInstrumented{ 086 int classId,lineNumber; 087 public LineTouchData(int classId,int lineNumber) { 088 this.classId=classId; 089 this.lineNumber=lineNumber; 090 } 091 @Override 092 public int hashCode() { 093 final int prime = 31; 094 int result = 1; 095 result = prime * result + classId; 096 result = prime * result + lineNumber; 097 return result; 098 } 099 @Override 100 public boolean equals(Object obj) { 101 if (this == obj) 102 return true; 103 if (obj == null) 104 return false; 105 if (getClass() != obj.getClass()) 106 return false; 107 LineTouchData other = (LineTouchData) obj; 108 if (classId != other.classId) 109 return false; 110 if (lineNumber != other.lineNumber) 111 return false; 112 return true; 113 } 114 } 115 116 private static class SwitchTouchData extends LineTouchData implements HasBeenInstrumented{ 117 int switchNumber, branch; 118 119 public SwitchTouchData(int classId,int lineNumber, int switchNumber, int branch) { 120 super(classId,lineNumber); 121 this.switchNumber=switchNumber; 122 this.branch=branch; 123 } 124 125 @Override 126 public int hashCode() { 127 final int prime = 31; 128 int result = super.hashCode(); 129 result = prime * result + branch; 130 result = prime * result + switchNumber; 131 return result; 132 } 133 134 @Override 135 public boolean equals(Object obj) { 136 if (this == obj) 137 return true; 138 if (!super.equals(obj)) 139 return false; 140 if (getClass() != obj.getClass()) 141 return false; 142 SwitchTouchData other = (SwitchTouchData) obj; 143 if (branch != other.branch) 144 return false; 145 if (switchNumber != other.switchNumber) 146 return false; 147 return true; 148 } 149 } 150 151 private static class JumpTouchData extends LineTouchData implements HasBeenInstrumented{ 152 int branchNumber; 153 boolean branch; 154 public JumpTouchData(int classId,int lineNumber, int branchNumber, boolean branch) { 155 super(classId, lineNumber); 156 this.branchNumber=branchNumber; 157 this.branch=branch; 158 } 159 @Override 160 public int hashCode() { 161 final int prime = 31; 162 int result = super.hashCode(); 163 result = prime * result + (branch ? 1231 : 1237); 164 result = prime * result + branchNumber; 165 return result; 166 } 167 @Override 168 public boolean equals(Object obj) { 169 if (this == obj) 170 return true; 171 if (!super.equals(obj)) 172 return false; 173 if (getClass() != obj.getClass()) 174 return false; 175 JumpTouchData other = (JumpTouchData) obj; 176 if (branch != other.branch) 177 return false; 178 if (branchNumber != other.branchNumber) 179 return false; 180 return true; 181 } 182 } 183 184 185 public static synchronized void applyTouchesOnProjectData(ProjectData projectData){ 186 System.out.println("Flushing results..."); 187 Map<LineTouchData,Integer> touches=touchedLines.getFinalStateAndCleanIt(); 188 for(Entry<LineTouchData, Integer> touch:touches.entrySet()){ 189 if(touch.getValue()>0){ 190 getClassFor(touch.getKey(),projectData).touch(touch.getKey().lineNumber,touch.getValue()); 191 } 192 } 193 194 Map<SwitchTouchData,Integer> switchTouches=switchTouchData.getFinalStateAndCleanIt(); 195 for(Entry<SwitchTouchData, Integer> touch:switchTouches.entrySet()){ 196 if(touch.getValue()>0){ 197 getClassFor(touch.getKey(),projectData).touchSwitch( 198 touch.getKey().lineNumber, 199 touch.getKey().switchNumber, 200 touch.getKey().branch,touch.getValue()); 201 } 202 } 203 204 Map<JumpTouchData,Integer> jumpTouches=jumpTouchData.getFinalStateAndCleanIt(); 205 for(Entry<JumpTouchData, Integer> touch:jumpTouches.entrySet()){ 206 if(touch.getValue()>0){ 207 getClassFor(touch.getKey(),projectData).touchJump( 208 touch.getKey().lineNumber, 209 touch.getKey().branchNumber, 210 touch.getKey().branch,touch.getValue()); 211 } 212 } 213 System.out.println("Flushing results done"); 214 } 215 216 private static ClassData getClassFor(LineTouchData key,ProjectData projectData) { 217 // System.out.println("\nLooking for:"+key.classId+"\n"); 218 return projectData.getOrCreateClassData(classId2class.get(key.classId)); 219 } 220 221 }