1 8 package org.codehaus.aspectwerkz.transform.inlining.deployer; 9 10 import java.util.Iterator ; 11 import java.util.HashSet ; 12 import java.util.Set ; 13 import java.lang.reflect.Method ; 14 import java.io.InputStream ; 15 16 import org.codehaus.aspectwerkz.expression.ExpressionInfo; 17 import org.codehaus.aspectwerkz.definition.AspectDefinition; 18 import org.codehaus.aspectwerkz.definition.SystemDefinition; 19 import org.codehaus.aspectwerkz.definition.SystemDefinitionContainer; 20 import org.codehaus.aspectwerkz.definition.AdviceDefinition; 21 import org.codehaus.aspectwerkz.definition.DeploymentScope; 22 import org.codehaus.aspectwerkz.definition.XmlParser; 23 import org.codehaus.aspectwerkz.definition.DocumentParser; 24 import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer; 25 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointManager; 26 import org.codehaus.aspectwerkz.annotation.AspectAnnotationParser; 27 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 28 import org.codehaus.aspectwerkz.reflect.impl.java.JavaClassInfo; 29 import org.codehaus.aspectwerkz.reflect.ClassInfo; 30 import org.codehaus.aspectwerkz.exception.DefinitionException; 31 import org.codehaus.aspectwerkz.transform.inlining.compiler.MatchingJoinPointInfo; 32 import org.codehaus.aspectwerkz.transform.inlining.compiler.JoinPointFactory; 33 import org.codehaus.aspectwerkz.transform.inlining.compiler.CompilationInfo; 34 import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager; 35 import org.objectweb.asm.ClassReader; 36 import org.dom4j.Document; 37 import org.dom4j.DocumentException; 38 39 46 public class Deployer { 47 48 60 public static DeploymentHandle deploy(final Class aspect) { 61 return deploy(aspect, DeploymentScope.MATCH_ALL); 62 } 63 64 76 public static DeploymentHandle deploy(final String aspectClassName) { 77 return deploy(aspectClassName, DeploymentScope.MATCH_ALL); 78 } 79 80 93 public static DeploymentHandle deploy(final Class aspect, final ClassLoader deployLoader) { 94 return deploy(aspect, DeploymentScope.MATCH_ALL, deployLoader); 95 } 96 97 110 public static DeploymentHandle deploy(final String aspectClassName, final ClassLoader deployLoader) { 111 return deploy(aspectClassName, DeploymentScope.MATCH_ALL, deployLoader); 112 } 113 114 123 public static DeploymentHandle deploy(final Class aspect, final DeploymentScope deploymentScope) { 124 return deploy(aspect, deploymentScope, Thread.currentThread().getContextClassLoader()); 125 } 126 127 136 public static DeploymentHandle deploy(final String aspectClassName, final DeploymentScope deploymentScope) { 137 return deploy(aspectClassName, deploymentScope, Thread.currentThread().getContextClassLoader()); 138 } 139 140 152 public static DeploymentHandle deploy(final Class aspect, 153 final DeploymentScope deploymentScope, 154 final ClassLoader deployLoader) { 155 if (aspect == null) { 156 throw new IllegalArgumentException ("aspect to deploy can not be null"); 157 } 158 if (deploymentScope == null) { 159 throw new IllegalArgumentException ("prepared pointcut can not be null"); 160 } 161 if (deployLoader == null) { 162 throw new IllegalArgumentException ("class loader to deploy aspect in can not be null"); 163 } 164 165 final String className = aspect.getName(); 166 return deploy(className, deploymentScope, deployLoader); 167 168 } 169 170 180 public synchronized static DeploymentHandle deploy(final String className, 181 final DeploymentScope deploymentScope, 182 final ClassLoader deployLoader) { 183 logDeployment(className, deployLoader); 184 185 Class aspectClass = null; 186 try { 187 aspectClass = Class.forName(className, false, deployLoader); 188 } catch (ClassNotFoundException e) { 189 throw new RuntimeException ( 190 "could not load class [" + className + "] in class loader [" + deployLoader + "]" 191 ); 192 } 193 194 final DeploymentHandle deploymentHandle = new DeploymentHandle(aspectClass, deployLoader); 195 196 final ClassInfo aspectClassInfo = JavaClassInfo.getClassInfo(aspectClass); 197 198 final SystemDefinition systemDef = SystemDefinitionContainer.getVirtualDefinitionAt(deployLoader); 200 final AspectDefinition newAspectDef = new AspectDefinition(className, aspectClassInfo, systemDef); 201 final Set newExpressions = getNewExpressionsForAspect( 202 aspectClass, newAspectDef, systemDef, deploymentScope, deploymentHandle 203 ); 204 205 redefine(newExpressions); 206 return deploymentHandle; 207 } 208 209 221 public static DeploymentHandle deploy(final Class aspect, final String xmlDef) { 222 return deploy(aspect, xmlDef, DeploymentScope.MATCH_ALL); 223 } 224 225 238 public static DeploymentHandle deploy(final Class aspect, 239 final String xmlDef, 240 final DeploymentScope deploymentScope) { 241 return deploy(aspect, xmlDef, deploymentScope, aspect.getClassLoader()); 242 } 243 244 257 public static DeploymentHandle deploy(final Class aspect, final String xmlDef, final ClassLoader deployLoader) { 258 return deploy(aspect, xmlDef, DeploymentScope.MATCH_ALL, deployLoader); 259 } 260 261 277 public synchronized static DeploymentHandle deploy(final Class aspect, 278 final String xmlDef, 279 final DeploymentScope deploymentScope, 280 final ClassLoader deployLoader) { 281 if (aspect == null) { 282 throw new IllegalArgumentException ("aspect to deploy can not be null"); 283 } 284 if (deploymentScope == null) { 285 throw new IllegalArgumentException ("prepared pointcut can not be null"); 286 } 287 if (xmlDef == null) { 288 throw new IllegalArgumentException ("xml definition can not be null"); 289 } 290 if (deployLoader == null) { 291 throw new IllegalArgumentException ("class loader to deploy aspect in can not be null"); 292 } 293 final String className = aspect.getName(); 294 logDeployment(className, deployLoader); 295 296 final DeploymentHandle deploymentHandle = new DeploymentHandle(aspect, deployLoader); 297 298 final SystemDefinition systemDef = SystemDefinitionContainer.getVirtualDefinitionAt(deployLoader); 299 try { 300 final Document document = XmlParser.createDocument(xmlDef); 301 final AspectDefinition newAspectDef = DocumentParser.parseAspectDefinition(document, systemDef, aspect); 302 final Set newExpressions = getNewExpressionsForAspect( 303 aspect, newAspectDef, systemDef, deploymentScope, deploymentHandle 304 ); 305 306 redefine(newExpressions); 307 } catch (DocumentException e) { 308 throw new DefinitionException("XML definition for aspect is not well-formed: " + xmlDef); 309 } 310 return deploymentHandle; 311 } 312 313 318 public static void undeploy(final Class aspect) { 319 undeploy(aspect, aspect.getClassLoader()); 320 } 321 322 328 public static void undeploy(final Class aspect, final ClassLoader loader) { 329 if (aspect == null) { 330 throw new IllegalArgumentException ("aspect to undeploy can not be null"); 331 } 332 if (loader == null) { 333 throw new IllegalArgumentException ("loader to undeploy aspect from can not be null"); 334 } 335 undeploy(aspect.getName(), loader); 336 } 337 338 344 public static void undeploy(final String className, final ClassLoader loader) { 345 logUndeployment(className, loader); 346 347 349 Set systemDefs = SystemDefinitionContainer.getDefinitionsAt(loader); 352 353 for (Iterator it = systemDefs.iterator(); it.hasNext();) { 354 SystemDefinition systemDef = (SystemDefinition) it.next(); 355 final AspectDefinition aspectDef = systemDef.getAspectDefinition(className); 356 if (aspectDef != null) { 357 358 final Set newExpressions = new HashSet (); 359 for (Iterator it2 = aspectDef.getAdviceDefinitions().iterator(); it2.hasNext();) { 360 AdviceDefinition adviceDef = (AdviceDefinition) it2.next(); 361 ExpressionInfo oldExpression = adviceDef.getExpressionInfo(); 362 if (oldExpression == null) { continue; 364 } 365 adviceDef.setExpressionInfo(null); 366 newExpressions.add(oldExpression); 367 } 368 redefine(newExpressions); 369 } 370 } 371 } 372 373 379 public static void undeploy(final DeploymentHandle deploymentHandle) { 380 if (deploymentHandle == null) { 381 throw new IllegalArgumentException ("deployment handle can not be null"); 382 } 383 384 deploymentHandle.revertChanges(); 385 386 final Class aspectClass = deploymentHandle.getAspectClass(); 387 if (aspectClass == null) { 388 return; } 390 undeploy(aspectClass); 391 } 392 393 398 private static void redefine(final Set expressions) { 399 final Set allMatchingJoinPoints = new HashSet (); 400 for (Iterator itExpr = expressions.iterator(); itExpr.hasNext();) { 401 ExpressionInfo expression = (ExpressionInfo) itExpr.next(); 402 Set matchingJoinPoints = JoinPointFactory.getJoinPointsMatching(expression); 403 allMatchingJoinPoints.addAll(matchingJoinPoints); 404 } 405 406 final ChangeSet changeSet = new ChangeSet(); 407 for (Iterator it = allMatchingJoinPoints.iterator(); it.hasNext();) { 408 final MatchingJoinPointInfo joinPointInfo = (MatchingJoinPointInfo) it.next(); 409 410 final CompilationInfo compilationInfo = joinPointInfo.getCompilationInfo(); 411 compilationInfo.incrementRedefinitionCounter(); 412 413 changeSet.addElement(new ChangeSet.Element(compilationInfo, joinPointInfo)); 414 } 415 416 doRedefine(changeSet); 417 } 418 419 424 private static void doRedefine(final ChangeSet changeSet) { 425 for (Iterator it = changeSet.getElements().iterator(); it.hasNext();) { 426 compileNewJoinPoint((ChangeSet.Element) it.next()); 427 } 428 redefineInitialJoinPoints(changeSet); 429 } 430 431 436 private static void compileNewJoinPoint(final ChangeSet.Element changeSetElement) { 437 final CompilationInfo compilationInfo = changeSetElement.getCompilationInfo(); 438 final MatchingJoinPointInfo joinPointInfo = changeSetElement.getJoinPointInfo(); 439 final ClassLoader loader = joinPointInfo.getJoinPointClass().getClassLoader(); 440 final AdviceInfoContainer newAdviceContainer = JoinPointManager.getAdviceInfoContainerForJoinPoint( 441 joinPointInfo.getExpressionContext(), 442 loader 443 ); 444 final CompilationInfo.Model redefinedModel = new CompilationInfo.Model( 445 compilationInfo.getInitialModel().getEmittedJoinPoint(), newAdviceContainer, 447 compilationInfo.getRedefinitionCounter(), 448 compilationInfo.getInitialModel().getThisClassInfo() 449 ); 450 JoinPointFactory.compileJoinPointAndAttachToClassLoader(redefinedModel, loader); 451 452 compilationInfo.setRedefinedModel(redefinedModel); 453 JoinPointFactory.addCompilationInfo(joinPointInfo.getJoinPointClass(), compilationInfo); 454 } 455 456 462 private static void redefineInitialJoinPoints(final ChangeSet changeSet) { 463 RedefinerFactory.newRedefiner(RedefinerFactory.Type.HOTSWAP).redefine(changeSet); 465 } 466 467 476 private static Set getNewExpressionsForAspect(final Class aspectClass, 477 final AspectDefinition newAspectDef, 478 final SystemDefinition systemDef, 479 final DeploymentScope deploymentScope, 480 final DeploymentHandle deploymentHandle) { 481 final ClassLoader aspectLoader = aspectClass.getClassLoader(); 482 final String aspectName = aspectClass.getName(); 483 484 final ClassInfo classInfo = AsmClassInfo.getClassInfo(aspectName, aspectLoader); 485 486 AspectModelManager.defineAspect(classInfo, newAspectDef, aspectLoader); 487 488 AspectAnnotationParser.parse(classInfo, newAspectDef, aspectLoader); 489 490 AspectDefinition aspectDef = systemDef.getAspectDefinition(aspectName); 491 if (aspectDef != null) { 492 newAspectDef.setContainerClassName(aspectDef.getContainerClassName()); 494 newAspectDef.setDeploymentModel(aspectDef.getDeploymentModel()); 495 } 496 497 systemDef.addAspectOverwriteIfExists(newAspectDef); 498 499 final Set newExpressions = new HashSet (); 500 for (Iterator it2 = newAspectDef.getAdviceDefinitions().iterator(); it2.hasNext();) { 501 AdviceDefinition adviceDef = (AdviceDefinition) it2.next(); 502 ExpressionInfo oldExpression = adviceDef.getExpressionInfo(); 503 if (oldExpression == null) { 504 continue; 505 } 506 deploymentHandle.registerDefinitionChange(adviceDef, oldExpression); 507 508 final ExpressionInfo newExpression = deploymentScope.newExpressionInfo(oldExpression); 509 adviceDef.setExpressionInfo(newExpression); 510 newExpressions.add(newExpression); 511 } 512 return newExpressions; 513 } 514 515 521 private static void importClassIntoLoader(final Class clazz, final ClassLoader toLoader) { 522 final ClassLoader fromLoader = clazz.getClassLoader(); 523 if (toLoader == fromLoader) { 524 return; 525 } 526 final String className = clazz.getName(); 527 try { 528 Class.forName(className, false, toLoader); 529 } catch (ClassNotFoundException cnfe) { 530 try { 531 InputStream stream = null; 532 byte[] bytes; 533 try { 534 stream = fromLoader.getResourceAsStream(className.replace('.', '/') + ".class"); 535 bytes = new ClassReader(stream).b; 536 } finally { 537 try { 538 stream.close(); 539 } catch (Exception e) { 540 ; 541 } 542 } 543 Class klass = Class.forName("java.lang.ClassLoader", false, toLoader); 544 Method method = klass.getDeclaredMethod( 545 "defineClass", 546 new Class []{String .class, byte[].class, int.class, int.class} 547 ); 548 method.setAccessible(true); 549 Object [] args = new Object []{ 550 clazz.getName(), bytes, new Integer (0), new Integer (bytes.length) 551 }; 552 method.invoke(toLoader, args); 553 method.setAccessible(false); 554 } catch (Exception e) { 555 throw new RuntimeException ( 556 new StringBuffer ().append("could not deploy aspect ["). 557 append(className).append("] in class loader [").append(toLoader) 558 .append(']').toString() 559 ); 560 } 561 } 562 } 563 564 572 private static void logUndeployment(final String className, final ClassLoader loader) { 573 System.out.println( 574 new StringBuffer ().append("Deployer::INFO - undeploying aspect ["). 575 append(className).append("] from class loader ["). 576 append(loader).append(']').toString() 577 ); 578 } 579 580 588 private static void logDeployment(final String className, final ClassLoader loader) { 589 System.out.println( 590 new StringBuffer ().append("Deployer::INFO - deploying aspect ["). 591 append(className).append("] in class loader ["). 592 append(loader).append(']').toString() 593 ); 594 } 595 } 596 | Popular Tags |