KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > deployer > Deployer


1 /**************************************************************************************
2  * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3  * http://aspectwerkz.codehaus.org *
4  * ---------------------------------------------------------------------------------- *
5  * The software in this package is published under the terms of the LGPL license *
6  * a copy of which has been included with this distribution in the license.txt file. *
7  **************************************************************************************/

8 package org.codehaus.aspectwerkz.transform.inlining.deployer;
9
10 import java.util.Iterator JavaDoc;
11 import java.util.HashSet JavaDoc;
12 import java.util.Set JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14 import java.io.InputStream JavaDoc;
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 /**
40  * Manages deployment and undeployment of aspects. Aspects can be deployed and undeployed into a running system(s).
41  * <p/>
42  * Supports annotation defined and XML defined aspects.
43  *
44  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
45  */

46 public class Deployer {
47
48     /**
49      * Deploys an annotation defined aspect.
50      * <p/>
51      * Deploys the aspect in all systems in the class loader that has loaded the aspect class.
52      * <p/>
53      * <b>CAUTION</b>: use a to own risk, the aspect might have a wider scope than your set of instrumented join points,
54      * then the aspect will not be applied to all intended points, to play safe -
55      * use <code>deploy(final Class aspect, final DeploymentScope deploymentScope)</code>
56      *
57      * @param aspect the aspect class
58      * @return a unique deployment handle for this deployment
59      */

60     public static DeploymentHandle deploy(final Class JavaDoc aspect) {
61         return deploy(aspect, DeploymentScope.MATCH_ALL);
62     }
63
64     /**
65      * Deploys an annotation defined aspect.
66      * <p/>
67      * Deploys the aspect in all systems in the class loader that has loaded the aspect class.
68      * <p/>
69      * <b>CAUTION</b>: use a to own risk, the aspect might have a wider scope than your set of instrumented join points,
70      * then the aspect will not be applied to all intended points, to play safe -
71      * use <code>deploy(final Class aspect, final DeploymentScope preparedPointcut)</code>
72      *
73      * @param aspectClassName the aspect class name
74      * @return a unique deployment handle for this deployment
75      */

76     public static DeploymentHandle deploy(final String JavaDoc aspectClassName) {
77         return deploy(aspectClassName, DeploymentScope.MATCH_ALL);
78     }
79
80     /**
81      * Deploys an annotation defined aspect.
82      * <p/>
83      * Deploys the aspect in all systems in the class loader that is specified.
84      * <p/>
85      * <b>CAUTION</b>: use a to own risk, the aspect might have a wider scope than your set of instrumented join points,
86      * then the aspect will not be applied to all intended points, to play safe -
87      * use <code>deploy(final Class aspect, final DeploymentScope preparedPointcut)</code>
88      *
89      * @param aspect the aspect class
90      * @param deployLoader
91      * @return a unique deployment handle for this deployment
92      */

93     public static DeploymentHandle deploy(final Class JavaDoc aspect, final ClassLoader JavaDoc deployLoader) {
94         return deploy(aspect, DeploymentScope.MATCH_ALL, deployLoader);
95     }
96
97     /**
98      * Deploys an annotation defined aspect.
99      * <p/>
100      * Deploys the aspect in all systems in the class loader that is specified.
101      * <p/>
102      * <b>CAUTION</b>: use a to own risk, the aspect might have a wider scope than your set of instrumented join points,
103      * then the aspect will not be applied to all intended points, to play safe -
104      * use <code>deploy(final Class aspect, final DeploymentScope preparedPointcut)</code>
105      *
106      * @param aspectClassName the aspect class name
107      * @param deployLoader
108      * @return a unique deployment handle for this deployment
109      */

110     public static DeploymentHandle deploy(final String JavaDoc aspectClassName, final ClassLoader JavaDoc deployLoader) {
111         return deploy(aspectClassName, DeploymentScope.MATCH_ALL, deployLoader);
112     }
113
114     /**
115      * Deploys an annotation defined aspect in the scope defined by the prepared pointcut.
116      * <p/>
117      * Deploys the aspect in all systems in the class loader that has loaded the aspect class.
118      *
119      * @param aspect the aspect class
120      * @param deploymentScope
121      * @return a unique deployment handle for this deployment
122      */

123     public static DeploymentHandle deploy(final Class JavaDoc aspect, final DeploymentScope deploymentScope) {
124         return deploy(aspect, deploymentScope, Thread.currentThread().getContextClassLoader());
125     }
126
127     /**
128      * Deploys an annotation defined aspect in the scope defined by the prepared pointcut.
129      * <p/>
130      * Deploys the aspect in all systems in the class loader that has loaded the aspect class.
131      *
132      * @param aspectClassName the aspect class name
133      * @param deploymentScope
134      * @return a unique deployment handle for this deployment
135      */

136     public static DeploymentHandle deploy(final String JavaDoc aspectClassName, final DeploymentScope deploymentScope) {
137         return deploy(aspectClassName, deploymentScope, Thread.currentThread().getContextClassLoader());
138     }
139
140     /**
141      * TODO allow deployment in other systems than virtual system?
142      * <p/>
143      * Deploys an annotation defined aspect in the scope defined by the prepared pointcut.
144      * <p/>
145      * Deploys the aspect in the class loader that is specified.
146      *
147      * @param aspect the aspect class
148      * @param deployLoader the loader to deploy the aspect in
149      * @param deploymentScope the prepared pointcut
150      * @return a unique deployment handle for this deployment
151      */

152     public static DeploymentHandle deploy(final Class JavaDoc aspect,
153                                           final DeploymentScope deploymentScope,
154                                           final ClassLoader JavaDoc deployLoader) {
155         if (aspect == null) {
156             throw new IllegalArgumentException JavaDoc("aspect to deploy can not be null");
157         }
158         if (deploymentScope == null) {
159             throw new IllegalArgumentException JavaDoc("prepared pointcut can not be null");
160         }
161         if (deployLoader == null) {
162             throw new IllegalArgumentException JavaDoc("class loader to deploy aspect in can not be null");
163         }
164
165         final String JavaDoc className = aspect.getName();
166         return deploy(className, deploymentScope, deployLoader);
167
168     }
169
170     /**
171      * Deploys an annotation defined aspect in the scope defined by the prepared pointcut.
172      * <p/>
173      * Deploys the aspect in the class loader that is specified.
174      *
175      * @param className
176      * @param deploymentScope
177      * @param deployLoader
178      * @return
179      */

180     public synchronized static DeploymentHandle deploy(final String JavaDoc className,
181                                                        final DeploymentScope deploymentScope,
182                                                        final ClassLoader JavaDoc deployLoader) {
183         logDeployment(className, deployLoader);
184
185         Class JavaDoc aspectClass = null;
186         try {
187             aspectClass = Class.forName(className, false, deployLoader);
188         } catch (ClassNotFoundException JavaDoc e) {
189             throw new RuntimeException JavaDoc(
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         // create a new aspect def and fill it up with the annotation def from the aspect class
199
final SystemDefinition systemDef = SystemDefinitionContainer.getVirtualDefinitionAt(deployLoader);
200         final AspectDefinition newAspectDef = new AspectDefinition(className, aspectClassInfo, systemDef);
201         final Set JavaDoc newExpressions = getNewExpressionsForAspect(
202                 aspectClass, newAspectDef, systemDef, deploymentScope, deploymentHandle
203         );
204
205         redefine(newExpressions);
206         return deploymentHandle;
207     }
208
209     /**
210      * Deploys an XML defined aspect in the scope defined by the prepared pointcut.
211      * <p/>
212      * If the aspect class has annotations, those will be read but the XML definition will override the
213      * annotation definition.
214      * <p/>
215      * Deploys the aspect in the class loader that has loaded the aspect.
216      *
217      * @param aspect the aspect class
218      * @param xmlDef
219      * @return
220      */

221     public static DeploymentHandle deploy(final Class JavaDoc aspect, final String JavaDoc xmlDef) {
222         return deploy(aspect, xmlDef, DeploymentScope.MATCH_ALL);
223     }
224
225     /**
226      * Deploys an XML defined aspect in the scope defined by the prepared pointcut.
227      * <p/>
228      * If the aspect class has annotations, those will be read but the XML definition will override the
229      * annotation definition.
230      * <p/>
231      * Deploys the aspect in the class loader that has loaded the aspect.
232      *
233      * @param aspect the aspect class
234      * @param xmlDef
235      * @param deploymentScope
236      * @return
237      */

238     public static DeploymentHandle deploy(final Class JavaDoc aspect,
239                                           final String JavaDoc xmlDef,
240                                           final DeploymentScope deploymentScope) {
241         return deploy(aspect, xmlDef, deploymentScope, aspect.getClassLoader());
242     }
243
244     /**
245      * Deploys an XML defined aspect in the scope defined by the prepared pointcut.
246      * <p/>
247      * If the aspect class has annotations, those will be read but the XML definition will override the
248      * annotation definition.
249      * <p/>
250      * Deploys the aspect in the class loader that is specified.
251      *
252      * @param aspect the aspect class
253      * @param xmlDef
254      * @param deployLoader
255      * @return
256      */

257     public static DeploymentHandle deploy(final Class JavaDoc aspect, final String JavaDoc xmlDef, final ClassLoader JavaDoc deployLoader) {
258         return deploy(aspect, xmlDef, DeploymentScope.MATCH_ALL, deployLoader);
259     }
260
261     /**
262      * TODO allow deployment in other systems than virtual system?
263      * <p/>
264      * Deploys an XML defined aspect in the scope defined by the prepared pointcut.
265      * <p/>
266      * If the aspect class has annotations, those will be read but the XML definition will override the
267      * annotation definition.
268      * <p/>
269      * Deploys the aspect in the class loader that is specified.
270      *
271      * @param aspect the aspect class
272      * @param deploymentScope
273      * @param xmlDef
274      * @param deployLoader
275      * @return
276      */

277     public synchronized static DeploymentHandle deploy(final Class JavaDoc aspect,
278                                                        final String JavaDoc xmlDef,
279                                                        final DeploymentScope deploymentScope,
280                                                        final ClassLoader JavaDoc deployLoader) {
281         if (aspect == null) {
282             throw new IllegalArgumentException JavaDoc("aspect to deploy can not be null");
283         }
284         if (deploymentScope == null) {
285             throw new IllegalArgumentException JavaDoc("prepared pointcut can not be null");
286         }
287         if (xmlDef == null) {
288             throw new IllegalArgumentException JavaDoc("xml definition can not be null");
289         }
290         if (deployLoader == null) {
291             throw new IllegalArgumentException JavaDoc("class loader to deploy aspect in can not be null");
292         }
293         final String JavaDoc 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 JavaDoc 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     /**
314      * Undeploys an aspect from the same loader that has loaded the class.
315      *
316      * @param aspect the aspect class
317      */

318     public static void undeploy(final Class JavaDoc aspect) {
319         undeploy(aspect, aspect.getClassLoader());
320     }
321
322     /**
323      * Undeploys an aspect from a specific class loader.
324      *
325      * @param aspect the aspect class
326      * @param loader the loader that you want to undeploy the aspect from
327      */

328     public static void undeploy(final Class JavaDoc aspect, final ClassLoader JavaDoc loader) {
329         if (aspect == null) {
330             throw new IllegalArgumentException JavaDoc("aspect to undeploy can not be null");
331         }
332         if (loader == null) {
333             throw new IllegalArgumentException JavaDoc("loader to undeploy aspect from can not be null");
334         }
335         undeploy(aspect.getName(), loader);
336     }
337
338     /**
339      * Undeploys an aspect from a specific class loader.
340      *
341      * @param className the aspect class name
342      * @param loader the loader that you want to undeploy the aspect from
343      */

344     public static void undeploy(final String JavaDoc className, final ClassLoader JavaDoc loader) {
345         logUndeployment(className, loader);
346
347         //TODO: this one should acquire lock or something
348

349         // lookup only in the given classloader scope
350
// since the system hierarchy holds reference, they will see the change
351
Set JavaDoc systemDefs = SystemDefinitionContainer.getDefinitionsAt(loader);
352
353         for (Iterator JavaDoc 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 JavaDoc newExpressions = new HashSet JavaDoc();
359                 for (Iterator JavaDoc it2 = aspectDef.getAdviceDefinitions().iterator(); it2.hasNext();) {
360                     AdviceDefinition adviceDef = (AdviceDefinition) it2.next();
361                     ExpressionInfo oldExpression = adviceDef.getExpressionInfo();
362                     if (oldExpression == null) { // if null, then already undeployed
363
continue;
364                     }
365                     adviceDef.setExpressionInfo(null);
366                     newExpressions.add(oldExpression);
367                 }
368                 redefine(newExpressions);
369             }
370         }
371     }
372
373     /**
374      * Undeploys an aspect in the same way that it has been deployed in in the previous deploy event
375      * defined by the deployment handle.
376      *
377      * @param deploymentHandle the handle to the previous deployment event
378      */

379     public static void undeploy(final DeploymentHandle deploymentHandle) {
380         if (deploymentHandle == null) {
381             throw new IllegalArgumentException JavaDoc("deployment handle can not be null");
382         }
383
384         deploymentHandle.revertChanges();
385
386         final Class JavaDoc aspectClass = deploymentHandle.getAspectClass();
387         if (aspectClass == null) {
388             return; // already undeployed
389
}
390         undeploy(aspectClass);
391     }
392
393     /**
394      * Redefines all join points that are affected by the system redefinition.
395      *
396      * @param expressions the expressions that will pick out the join points that are affected
397      */

398     private static void redefine(final Set JavaDoc expressions) {
399         final Set JavaDoc allMatchingJoinPoints = new HashSet JavaDoc();
400         for (Iterator JavaDoc itExpr = expressions.iterator(); itExpr.hasNext();) {
401             ExpressionInfo expression = (ExpressionInfo) itExpr.next();
402             Set JavaDoc matchingJoinPoints = JoinPointFactory.getJoinPointsMatching(expression);
403             allMatchingJoinPoints.addAll(matchingJoinPoints);
404         }
405
406         final ChangeSet changeSet = new ChangeSet();
407         for (Iterator JavaDoc 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     /**
420      * Do the redefinition of the existing join point and the compilation of the new join point.
421      *
422      * @param changeSet
423      */

424     private static void doRedefine(final ChangeSet changeSet) {
425         for (Iterator JavaDoc it = changeSet.getElements().iterator(); it.hasNext();) {
426             compileNewJoinPoint((ChangeSet.Element) it.next());
427         }
428         redefineInitialJoinPoints(changeSet);
429     }
430
431     /**
432      * Compiles a completely new join point instance based on the new redefined model.
433      *
434      * @param changeSetElement the change set item
435      */

436     private static void compileNewJoinPoint(final ChangeSet.Element changeSetElement) {
437         final CompilationInfo compilationInfo = changeSetElement.getCompilationInfo();
438         final MatchingJoinPointInfo joinPointInfo = changeSetElement.getJoinPointInfo();
439         final ClassLoader JavaDoc 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(), // copy the reference since it is the same
446
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     /**
457      * Redefines the intial (weaved in) join point to delegate to the newly compiled "real" join point which is
458      * based on the new redefined model.
459      *
460      * @param changeSet the change set
461      */

462     private static void redefineInitialJoinPoints(final ChangeSet changeSet) {
463         // TODO type should be pluggable
464
RedefinerFactory.newRedefiner(RedefinerFactory.Type.HOTSWAP).redefine(changeSet);
465     }
466
467     /**
468      * Returns a set with the new expressions for the advice in the aspect to deploy.
469      *
470      * @param aspectClass s * @param newAspectDef
471      * @param systemDef
472      * @param deploymentScope
473      * @param deploymentHandle
474      * @return a set with the new expressions
475      */

476     private static Set JavaDoc getNewExpressionsForAspect(final Class JavaDoc aspectClass,
477                                                   final AspectDefinition newAspectDef,
478                                                   final SystemDefinition systemDef,
479                                                   final DeploymentScope deploymentScope,
480                                                   final DeploymentHandle deploymentHandle) {
481         final ClassLoader JavaDoc aspectLoader = aspectClass.getClassLoader();
482         final String JavaDoc 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             // if in def already reuse some of the settings that can have been overridded by XML def
493
newAspectDef.setContainerClassName(aspectDef.getContainerClassName());
494             newAspectDef.setDeploymentModel(aspectDef.getDeploymentModel());
495         }
496
497         systemDef.addAspectOverwriteIfExists(newAspectDef);
498
499         final Set JavaDoc newExpressions = new HashSet JavaDoc();
500         for (Iterator JavaDoc 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     /**
516      * Imports a class from one class loader to another one.
517      *
518      * @param clazz the class to import
519      * @param toLoader the loader to import to
520      */

521     private static void importClassIntoLoader(final Class JavaDoc clazz, final ClassLoader JavaDoc toLoader) {
522         final ClassLoader JavaDoc fromLoader = clazz.getClassLoader();
523         if (toLoader == fromLoader) {
524             return;
525         }
526         final String JavaDoc className = clazz.getName();
527         try {
528             Class.forName(className, false, toLoader);
529         } catch (ClassNotFoundException JavaDoc cnfe) {
530             try {
531                 InputStream JavaDoc 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 JavaDoc e) {
540                         ;
541                     }
542                 }
543                 Class JavaDoc klass = Class.forName("java.lang.ClassLoader", false, toLoader);
544                 Method JavaDoc method = klass.getDeclaredMethod(
545                         "defineClass",
546                         new Class JavaDoc[]{String JavaDoc.class, byte[].class, int.class, int.class}
547                 );
548                 method.setAccessible(true);
549                 Object JavaDoc[] args = new Object JavaDoc[]{
550                     clazz.getName(), bytes, new Integer JavaDoc(0), new Integer JavaDoc(bytes.length)
551                 };
552                 method.invoke(toLoader, args);
553                 method.setAccessible(false);
554             } catch (Exception JavaDoc e) {
555                 throw new RuntimeException JavaDoc(
556                         new StringBuffer JavaDoc().append("could not deploy aspect [").
557                         append(className).append("] in class loader [").append(toLoader)
558                         .append(']').toString()
559                 );
560             }
561         }
562     }
563
564     /**
565      * Logs undeployment.
566      * <p/>
567      * TODO unified way or at least format for logging
568      *
569      * @param className
570      * @param loader
571      */

572     private static void logUndeployment(final String JavaDoc className, final ClassLoader JavaDoc loader) {
573         System.out.println(
574                 new StringBuffer JavaDoc().append("Deployer::INFO - undeploying aspect [").
575                 append(className).append("] from class loader [").
576                 append(loader).append(']').toString()
577         );
578     }
579
580     /**
581      * Logs deployment.
582      * <p/>
583      * TODO unified way or at least format for logging
584      *
585      * @param className
586      * @param loader
587      */

588     private static void logDeployment(final String JavaDoc className, final ClassLoader JavaDoc loader) {
589         System.out.println(
590                 new StringBuffer JavaDoc().append("Deployer::INFO - deploying aspect [").
591                 append(className).append("] in class loader [").
592                 append(loader).append(']').toString()
593         );
594     }
595 }
596
Popular Tags