1 26 27 package net.sourceforge.groboutils.codecoverage.v2.compiler; 28 29 import java.util.HashMap ; 30 import java.util.HashSet ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.List ; 34 import java.util.Map ; 35 import java.util.Set ; 36 37 import org.apache.bcel.generic.BranchInstruction; 38 import org.apache.bcel.generic.CodeExceptionGen; 39 import org.apache.bcel.generic.InstructionHandle; 40 import org.apache.bcel.generic.InstructionTargeter; 41 import org.apache.bcel.generic.LineNumberGen; 42 import org.apache.bcel.generic.LocalVariableGen; 43 import org.apache.bcel.generic.MethodGen; 44 import org.apache.bcel.generic.ObjectType; 45 46 47 57 class ModifiedTargeters 58 { 59 private static final org.apache.log4j.Logger LOG = 60 org.apache.log4j.Logger.getLogger( ModifiedTargeters.class ); 61 private MethodGen methGen; 62 private Map startToCodeException = new HashMap (); 63 66 private Map handlerToCodeException = new HashMap (); 67 private List myCegs = new LinkedList (); 68 private InstructionHandle lastInstruction; 69 70 private static class MyCEG 71 { 72 private InstructionHandle origStartPC; 73 private InstructionHandle newStartPC; 74 75 private InstructionHandle origEndPC; 76 private InstructionHandle newEndPC; 77 78 private InstructionHandle origHandlerPC; 79 private InstructionHandle newHandlerPC; 80 81 private ObjectType type; 82 83 public MyCEG( InstructionHandle s, InstructionHandle e, 84 InstructionHandle h, ObjectType t ) 85 { 86 this.type = t; 87 this.origStartPC = s; 88 this.origEndPC = e; 89 this.origHandlerPC = h; 90 91 if (t == null) 92 { 93 LOG.debug( ">> Found null object type in CodeExceptionGen" ); 94 } 95 } 96 97 98 public CodeExceptionGen addCodeException( MethodGen mg ) 99 { 100 InstructionHandle sp = this.newStartPC; 101 InstructionHandle ep = this.newEndPC; 102 InstructionHandle hp = this.newHandlerPC; 103 104 if (sp == null) 105 { 106 sp = this.origStartPC; 107 } 108 if (ep == null) 109 { 110 ep = this.origEndPC; 111 } 112 if (hp == null) 113 { 114 hp = this.origHandlerPC; 115 } 116 LOG.debug( "Changing exception handler for type "+this.type+ 117 ": moved from (start = "+this.origStartPC+ 118 ", end = "+this.origEndPC+", handler = "+this.origHandlerPC+ 119 ") to (start = "+sp+", end = "+ep+", handler = "+hp+")" ); 120 return mg.addExceptionHandler( sp, ep, hp, this.type ); 121 } 122 123 124 public void setStartPC( InstructionHandle h ) 125 { 126 if (this.newStartPC == null) 127 { 128 LOG.debug( "Updating internal start PC for exception "+ 129 this.type+" to point to "+h ); 130 this.newStartPC = h; 131 } 132 } 133 134 142 143 144 public void setHandlerPC( InstructionHandle h ) 145 { 146 if (this.newHandlerPC == null) 147 { 148 LOG.debug( "Updating internal handler PC for exception "+ 149 this.type+" to point to "+h ); 150 this.newHandlerPC = h; 151 } 152 } 153 } 154 155 157 ModifiedTargeters( MethodGen mg ) 158 { 159 if (mg == null) 160 { 161 throw new IllegalArgumentException ("no null args"); 162 } 163 this.methGen = mg; 164 165 CodeExceptionGen ceg[] = mg.getExceptionHandlers(); 167 for (int i = 0; i < ceg.length; ++i) 168 { 169 MyCEG ceg2 = new MyCEG( ceg[i].getStartPC(), ceg[i].getEndPC(), 170 ceg[i].getHandlerPC(), ceg[i].getCatchType() ); 171 this.myCegs.add( ceg2 ); 172 putList( this.startToCodeException, ceg2.origStartPC, ceg2 ); 173 176 putList( this.handlerToCodeException, ceg2.origHandlerPC, ceg2 ); 177 } 178 179 Iterator list = mg.getInstructionList().iterator(); 181 while (list.hasNext()) 182 { 183 this.lastInstruction = (InstructionHandle)list.next(); 184 } 185 } 186 187 188 189 190 195 public void insertProbe( InstructionHandle instr, InstructionHandle probe ) 196 { 197 206 207 InstructionTargeter [] its = instr.getTargeters(); 208 if (its != null) 209 { 210 for (int j = 0; j < its.length; j++) 211 { 212 LOG.debug( "Found for instruction "+instr+" targeter "+ 213 its[j] ); 214 215 220 if (its[j] instanceof LineNumberGen) 221 { 222 LOG.debug( "Updating line number to point to probe "+ 223 probe ); 224 ((LineNumberGen)its[j]).setInstruction( probe ); 225 } 226 else 227 if (its[j] instanceof LocalVariableGen) 228 { 229 if (instr.equals( ((LocalVariableGen)its[j]).getStart() )) 233 { 234 LOG.debug( 235 "Updating local variable start to point to probe "+ 236 probe ); 237 ((LocalVariableGen)its[j]).setStart( probe ); 238 } 239 } 240 else 241 if (its[j] instanceof CodeExceptionGen) 242 { 243 LOG.debug( "Ignoring CodeExceptionGen" ); 245 } 246 else 247 if (its[j] instanceof BranchInstruction) 248 { 249 LOG.debug( "Updating branch instruction to point to probe "+ 252 probe ); 253 ((BranchInstruction)its[j]).updateTarget( 254 instr, probe ); 255 } 256 else 257 { 258 throw new IllegalStateException ( 259 "Unexpected targeter type (" + 260 its[j].getClass().getName() + 261 ") for instruction " + instr ); 262 } 263 } 264 } 265 266 Iterator iter = getList( this.startToCodeException, instr ); 269 while (iter.hasNext()) 270 { 271 MyCEG mceg = (MyCEG)iter.next(); 272 mceg.setStartPC( probe ); 273 } 274 275 iter = getList( this.handlerToCodeException, instr ); 278 while (iter.hasNext()) 279 { 280 MyCEG mceg = (MyCEG)iter.next(); 281 mceg.setHandlerPC( probe ); 282 } 283 } 284 285 286 362 363 364 369 public void update() 370 { 371 this.methGen.removeExceptionHandlers(); 372 Iterator iter = this.myCegs.iterator(); 373 while (iter.hasNext()) 374 { 375 ((MyCEG)iter.next()).addCodeException( this.methGen ); 376 } 377 } 378 379 380 private void putList( Map map, Object key, Object value ) 381 { 382 Set s = (Set )map.get( key ); 383 if (s == null) 384 { 385 s = new HashSet (); 386 map.put( key, s ); 387 } 388 s.add( value ); 389 } 390 391 392 395 private Iterator getList( Map map, Object key ) 396 { 397 Set s = (Set )map.get( key ); 398 if (s == null) 399 { 400 s = new HashSet (); 401 } 402 return s.iterator(); 403 } 404 } 405 406 | Popular Tags |