1 22 package org.jboss.aop; 23 24 import gnu.trove.TLongObjectHashMap; 25 26 import java.lang.reflect.Constructor ; 27 import java.util.ArrayList ; 28 import java.util.Collection ; 29 import java.util.Iterator ; 30 import java.util.WeakHashMap ; 31 32 import javassist.ClassPool; 33 import javassist.CodeConverter; 34 import javassist.CtClass; 35 import javassist.CtField; 36 import javassist.NotFoundException; 37 38 import org.jboss.aop.advice.Interceptor; 39 import org.jboss.aop.instrument.DynamicTransformationObserver; 40 import org.jboss.aop.instrument.HotSwapper; 41 import org.jboss.aop.instrument.Instrumentor; 42 import org.jboss.aop.instrument.InstrumentorFactory; 43 import org.jboss.aop.instrument.JoinpointClassifier; 44 import org.jboss.aop.instrument.JoinpointFullClassifier; 45 import org.jboss.aop.instrument.JoinpointStatusUpdate; 46 47 54 public class HotSwapStrategy implements DynamicAOPStrategy 55 { 56 private HotSwapper hotSwapper; 57 private Collection joinpointUpdates; 58 private Instrumentor instrumentor; 59 60 64 public HotSwapStrategy(HotSwapper hotSwapper) 65 { 66 this.hotSwapper = hotSwapper; 67 this.joinpointUpdates = new ArrayList (); 68 this.instrumentor = InstrumentorFactory.getInstrumentor(AspectManager.instance(), getJoinpointClassifier()); 69 } 70 71 78 public synchronized void interceptorChainsUpdated() 79 { 80 synchronized(joinpointUpdates) 81 { 82 if (!joinpointUpdates.isEmpty()) 83 { 84 instrumentor.interceptorChainsUpdated(new ArrayList (joinpointUpdates), hotSwapper); 85 joinpointUpdates.clear(); 86 } 87 } 88 } 89 90 95 public JoinpointClassifier getJoinpointClassifier() 96 { 97 return new JoinpointFullClassifier(); 98 } 99 100 111 112 116 public DynamicTransformationObserver getDynamicTransformationObserver(CtClass clazz) 117 { 118 return new DynamicTransformationTracker(clazz); 119 } 120 121 125 public InterceptorChainObserver getInterceptorChainObserver(Class clazz) 126 { 127 ClassPool classPool = AspectManager.instance().findClassPool(clazz.getClassLoader()); 128 CtClass ctClass = null; 129 try 130 { 131 ctClass = classPool.get(clazz.getName()); 132 } catch(NotFoundException e) 133 { 134 throw new RuntimeException ("Class " + clazz.getName() + " was not found at class pool."); 135 } 136 return new JoinpointStatusUpdater(ctClass); 137 } 138 139 140 146 private synchronized void newJoinpointUpdate(JoinpointStatusUpdate update) 147 { 148 synchronized(this.joinpointUpdates) 149 { 150 this.joinpointUpdates.add(update); 151 } 152 } 153 154 161 private class DynamicTransformationTracker implements DynamicTransformationObserver 162 { 163 private CtClass clazz; 164 private Collection fieldReads; 165 private Collection fieldWrites; 166 private boolean constructor; 167 168 172 public DynamicTransformationTracker(CtClass clazz) 173 { 174 this.clazz = clazz; 175 this.fieldReads = new ArrayList (); 176 this.fieldWrites = new ArrayList (); 177 this.constructor = false; 178 } 179 180 187 public void fieldReadDynamicalyWrapped(CtField field) 188 { 189 this.fieldReads.add(field); 190 } 191 192 199 public void fieldWriteDynamicalyWrapped(CtField field) 200 { 201 this.fieldWrites.add(field); 202 } 203 204 210 public void constructorDynamicalyWrapped() 211 { 212 this.constructor = true; 213 } 214 215 218 public void transformationFinished(CtClass clazz, CodeConverter converter) 219 { 220 if (constructor || !fieldReads.isEmpty() || !fieldWrites.isEmpty()) 221 { 222 instrumentor.convertProcessedClasses(hotSwapper, clazz, fieldReads, fieldWrites, constructor); 223 } 224 } 225 } 226 227 232 private class JoinpointStatusUpdater implements InterceptorChainObserver 233 { 234 private JoinpointStatusUpdate.ClassJoinpoints newlyAdvised; 235 private JoinpointStatusUpdate.ClassJoinpoints newlyUnadvised; 236 237 private int instanceInterceptors; 238 private WeakHashMap instanceAdvisors; 239 240 private CtClass clazz; 241 private int fields; 242 private int constructors; 243 private int methods; 244 private Interceptor[][] fieldReadInterceptors; 245 private Interceptor[][] fieldWriteInterceptors; 246 private Interceptor[][] constructorInterceptors; 247 private TLongObjectHashMap methodInterceptors; 248 private int[] constructorIndexMap; 249 250 254 public JoinpointStatusUpdater(CtClass clazz) 255 { 256 this.clazz = clazz; 257 this.instanceAdvisors = new WeakHashMap (); 258 } 259 260 264 public synchronized void initialInterceptorChains(Class reflectionClass, Interceptor[][] fieldReadInterceptors, Interceptor[][] fieldWriteInterceptors, 265 Interceptor[][] constructorInterceptors, TLongObjectHashMap methodInterceptors) 266 { 267 Constructor [] declaredConstructors = reflectionClass.getDeclaredConstructors(); 268 constructorIndexMap = new int[declaredConstructors.length]; 269 Collection constructorList = new ArrayList (); 270 int javassistIndex = 0; 271 for (int reflectionIndex = 0; reflectionIndex < declaredConstructors.length; reflectionIndex++) 272 { 273 Class [] params = declaredConstructors[reflectionIndex].getParameterTypes(); 274 if (params.length > 0 && params[params.length-1].getName().equals("javassist.runtime.Inner")) 275 { 276 constructorIndexMap[reflectionIndex] = -1; 277 } 278 else 279 { 280 281 constructorIndexMap[reflectionIndex] = javassistIndex ++ ; 282 } 283 } 284 285 this.fieldReadInterceptors = fieldReadInterceptors; 286 this.fieldWriteInterceptors = fieldWriteInterceptors; 287 this.constructorInterceptors = constructorInterceptors; 288 this.methodInterceptors = methodInterceptors; 289 this.fields = fieldReadInterceptors.length; 290 this.constructors = constructorInterceptors.length; 291 this.methods = methodInterceptors.size(); 292 this.newlyAdvised = new JoinpointStatusUpdate.ClassJoinpoints(fields, constructors, methods); 293 this.newlyUnadvised = new JoinpointStatusUpdate.ClassJoinpoints(fields, constructors, methods); 294 } 295 296 300 public synchronized void interceptorChainsUpdated(Interceptor[][] newFieldReadInterceptors, Interceptor[][] newFieldWriteInterceptors, 301 Interceptor[][] newConstructorInterceptors, TLongObjectHashMap newMethodInterceptors) 302 { 303 if (instanceInterceptors == 0) 304 { 305 long[] methodKeys = methodInterceptors.keys(); 306 for (int i = 0; i < methodKeys.length; i++) 307 { 308 long key = methodKeys[i]; 309 MethodInfo oldMethodInfo = (MethodInfo) methodInterceptors.get(key); 310 MethodInfo newMethodInfo = (MethodInfo) newMethodInterceptors.get(key); 311 if (oldMethodInfo.getInterceptorChain().isEmpty() && !newMethodInfo.getInterceptorChain().isEmpty()) 312 { 313 newlyAdvised.methodExecutions.add(newMethodInfo); 314 } 315 else if (!oldMethodInfo.getInterceptorChain().isEmpty() && newMethodInfo.getInterceptorChain().isEmpty()) 316 { 317 newlyUnadvised.methodExecutions.add(newMethodInfo); 318 } 319 } 320 fillNewStateCollections(fieldReadInterceptors, newFieldReadInterceptors, newlyAdvised.fieldReads, newlyUnadvised.fieldReads, null); 321 fillNewStateCollections(fieldWriteInterceptors, newFieldWriteInterceptors, newlyAdvised.fieldWrites, newlyUnadvised.fieldWrites, null); 322 fillNewStateCollections(constructorInterceptors, newConstructorInterceptors, newlyAdvised.constructorExecutions, newlyUnadvised.constructorExecutions, this.constructorIndexMap); 323 newJoinpointUpdate(this.getJoinpointStatusUpdate()); 324 } 325 this.fieldReadInterceptors = newFieldReadInterceptors; 326 this.fieldWriteInterceptors = newFieldWriteInterceptors; 327 this.constructorInterceptors = newConstructorInterceptors; 328 this.methodInterceptors = newMethodInterceptors; 329 } 330 331 335 public synchronized void instanceInterceptorAdded(InstanceAdvisor instanceAdvisor) 336 { 337 this.instanceInterceptorsAdded(instanceAdvisor, 1); 338 } 339 340 344 public synchronized void instanceInterceptorsAdded(InstanceAdvisor instanceAdvisor, int howMany) 345 { 346 updateInstanceInterceptorsTable(instanceAdvisor, howMany); 347 updateAdvisenessStatus(this.newlyAdvised); 348 this.instanceInterceptors += howMany; 349 HotSwapStrategy.this.interceptorChainsUpdated(); 350 } 351 352 356 public synchronized void instanceInterceptorRemoved(InstanceAdvisor instanceAdvisor) 357 { 358 this.instanceInterceptorsRemoved(instanceAdvisor, 1); 359 } 360 361 365 public synchronized void instanceInterceptorsRemoved(InstanceAdvisor instanceAdvisor, int howMany) 366 { 367 updateInstanceInterceptorsTable(instanceAdvisor, -howMany); 368 this.instanceInterceptors -= howMany; 369 updateAdvisenessStatus(this.newlyUnadvised); 370 HotSwapStrategy.this.interceptorChainsUpdated(); 371 } 372 373 377 public synchronized void allInstanceInterceptorsRemoved(InstanceAdvisor instanceAdvisor) 378 { 379 if (this.instanceAdvisors.containsKey(instanceAdvisor)) 380 { 381 this.instanceAdvisors.remove(instanceAdvisor); 382 } 383 if (this.instanceInterceptors == 0) 384 return; 385 this.instanceInterceptors = 0; 386 for (Iterator iterator = instanceAdvisors.values().iterator(); iterator.hasNext(); ) 387 { 388 Integer interceptors = (Integer ) iterator.next(); 389 instanceInterceptors += interceptors.intValue(); 390 } 391 if (this.instanceInterceptors > 0) 392 return; 393 updateAdvisenessStatus(this.newlyUnadvised); 394 HotSwapStrategy.this.interceptorChainsUpdated(); 395 } 396 397 402 private JoinpointStatusUpdate getJoinpointStatusUpdate() { 403 JoinpointStatusUpdate update = new JoinpointStatusUpdate(); 404 update.clazz = this.clazz; 405 update.newlyAdvisedJoinpoints = this.newlyAdvised; 406 update.newlyUnadvisedJoinpoints = this.newlyUnadvised; 407 this.newlyAdvised = new JoinpointStatusUpdate.ClassJoinpoints(this.fields, this.constructors, this.methods); 408 this.newlyUnadvised = new JoinpointStatusUpdate.ClassJoinpoints(this.fields, this.constructors, this.methods); 409 return update; 410 } 411 412 413 421 private void fillNewStateCollections(Interceptor[][] interceptors, Interceptor[][] newInterceptors, 422 Collection newlyAdvised, Collection newlyUnadvised, int[] indexMap) 423 { 424 if (instanceInterceptors > 0) 425 return; 426 for (int i = 0; i < interceptors.length; i++) { 427 Interceptor[] oldInterceptorsChain = interceptors[i]; 428 Interceptor[] newInterceptorsChain = newInterceptors[i]; 429 boolean interceptedBefore = oldInterceptorsChain != null && oldInterceptorsChain.length > 0; 430 boolean interceptedNow = newInterceptorsChain != null && newInterceptorsChain.length > 0; 431 if (!interceptedBefore && interceptedNow) 432 { 433 if (indexMap != null) 434 { 435 if(indexMap[i] != -1) 436 { 437 newlyAdvised.add(new Integer (indexMap[i])); 438 } 439 } 440 else 441 { 442 newlyAdvised.add(new Integer (i)); 443 } 444 445 } 446 else if (interceptedBefore && !interceptedNow) 447 { 448 if (indexMap != null) 449 { 450 if(indexMap[i] != -1) 451 { 452 newlyUnadvised.add(new Integer (indexMap[i])); 453 } 454 } 455 else 456 { 457 newlyUnadvised.add(new Integer (i)); 458 } 459 } 460 } 461 } 462 463 470 private void updateInstanceInterceptorsTable(InstanceAdvisor instanceAdvisor, int interceptorsAdded) 471 { 472 if (this.instanceAdvisors.containsKey(instanceAdvisor)) 473 { 474 Integer interceptors = (Integer ) instanceAdvisors.get(instanceAdvisor); 475 instanceAdvisors.put(instanceAdvisor, new Integer (interceptors.intValue() + interceptorsAdded)); 476 } 477 else 478 { 479 instanceAdvisors.put(instanceAdvisor, new Integer (interceptorsAdded)); 480 } 481 } 482 483 489 private void updateAdvisenessStatus(JoinpointStatusUpdate.ClassJoinpoints joinpoints) 490 { 491 if (this.instanceInterceptors == 0) 492 { 493 long[] methodKeys = this.methodInterceptors.keys(); 494 for (int i = 0; i < methodKeys.length; i++) 495 { 496 long key = methodKeys[i]; 497 MethodInfo methodInfo = (MethodInfo) this.methodInterceptors.get(key); 498 if (methodInfo.getInterceptorChain().isEmpty()) 499 { 500 joinpoints.methodExecutions.add(methodInfo); 501 } 502 } 503 findUnadvisedJoinpoints(this.fieldReadInterceptors, joinpoints.fieldReads); 504 findUnadvisedJoinpoints(this.fieldWriteInterceptors, joinpoints.fieldWrites); 505 findUnadvisedJoinpoints(this.constructorInterceptors, joinpoints.constructorExecutions); 506 newJoinpointUpdate(getJoinpointStatusUpdate()); 507 } 508 } 509 510 515 private void findUnadvisedJoinpoints(Interceptor[][] interceptors, Collection joinpointsFound) 516 { 517 for (int i = 0; i < interceptors.length; i++) 518 { 519 if (interceptors[i] == null || interceptors[i].length == 0) 520 { 521 joinpointsFound.add(new Integer (i)); 522 } 523 } 524 } 525 } 526 } | Popular Tags |