/*
* Copyright (c) 2004, Marco Petris
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of Marco Petris nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.petris.dynamicaspects;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Pattern;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import de.petris.dynamicaspects.classhandler.ClassHandler;
import de.petris.dynamicaspects.util.ClassPatcher;
import de.petris.dynamicaspects.util.Reflection;
/**
* The agent which installs/deinstalls aspects.
*
* @author Marco Petris
* @see de.petris.dynamicaspects.Advice
* @see de.petris.dynamicaspects.PointcutFactory
* @see de.petris.dynamicaspects.AdviceFactory
*/
public class AspectAgent {
// singleton instance
final static AspectAgent AGENT = new AspectAgent();
// the instrumentation instance for redefining classes
private static Instrumentation instrumentation;
// a mapping package name -> List of PackageAspects
static Map<String,List<PackageAspect>> targetPackages;
// a mapping name of class of an advice -> list of its weave types
private static Map<String, List<WeaveType>> adviceClassWeaveTypeMapping;
// a mapping target class -> List of MixIns for the target class
private static Map<String, List<MixIn>> targetclassMixInMapping;
// flag: true indicates that the mixIns have already been installed
private static boolean mixInsInstalled;
// todo: not in use yet
private static List<String> packageList;
private static boolean onErrorAbort;
public static void setOnErrorAbort(boolean onErrorAbort) {
AspectAgent.onErrorAbort = onErrorAbort;
}
/*
* todo: not in use yet
*
* @param packageList
*/
public static void setPackageList(List<String> packageList) {
AspectAgent.packageList = packageList;
}
/**
* The entry point for the java agent
*
* @param options
* @param i
*/
public static void premain(
String options, Instrumentation i ) {
AspectAgent.instrumentation = i;
AspectAgent.packageList = null;
AspectAgent.onErrorAbort = false;
AspectAgent.mixInsInstalled = false;
AspectAgent.targetPackages =
new HashMap<String,List<PackageAspect>>();
AspectAgent.adviceClassWeaveTypeMapping =
new HashMap<String,List<WeaveType>>();
AspectAgent.targetclassMixInMapping =
new HashMap<String,List<MixIn>>();
AspectAgent.instrumentation.addTransformer(
new OnLoadAspectWeaver( targetclassMixInMapping ) );
}
/**
* Installs advices to the given class to all class in the target package at at
* the given pointcut.
*
* @param targetPackage the target package
* @param adviceClass the class of the advices to be installed
* @param joinPointPattern the pointcut
* @param weaveType the weave type for the advices
*/
public static void install(
Package targetPackage,
Class<? extends Advice> adviceClass,
Pattern joinPointPattern,
WeaveType weaveType ) {
String packageName = targetPackage.getName().replace( '.', '/' );
PackageAspect pa = new PackageAspect(
adviceClass, joinPointPattern, weaveType );
// remember the package for all classes which will be loaded in the future
if( !targetPackages.containsKey( packageName ) ) {
Vector<PackageAspect> v = new Vector<PackageAspect>();
v.add( pa );
targetPackages.put( packageName, v );
}
else {
targetPackages.get( packageName ).add( pa );
}
for( Class c : AspectAgent.instrumentation.getAllLoadedClasses() ) {
if( ( c.getPackage() != null )
&& ( c.getPackage().equals( targetPackage ) ) ) {
pa.addWovenClassname( c.getName() );
install( c, adviceClass, joinPointPattern, weaveType );
}
}
}
/**
* Installs the given advice to the given class to all class in the target package at at
* the given pointcut.
*
* @param targetPackage the target package
* @param advice the advice to be installed
* @param joinPointPattern the pointcut
* @param weaveType the weave type for the advices
*/
public static void install(Package targetPackage, Advice advice,
Pattern joinPointPattern, WeaveType weaveType ) {
String packageName = targetPackage.getName().replace('.', '/');
PackageAspect pa = new PackageAspect(
advice, joinPointPattern, weaveType );
// remember the package for all classes which will be loaded in the future
if (!targetPackages.containsKey(packageName)) {
Vector<PackageAspect> v = new Vector<PackageAspect>();
v.add(pa);
targetPackages.put(packageName, v);
} else {
targetPackages.get(packageName).add( pa );
}
for (Class c : AspectAgent.instrumentation.getAllLoadedClasses()) {
if ((c.getPackage() != null)
&& (c.getPackage().equals(targetPackage))) {
pa.addWovenClassname( c.getName() );
install(c, advice, joinPointPattern, weaveType );
}
}
}
/**
* Installs advices to the given class to all class in the target package at at
* the given pointcut using the given factory.
*
* @param targetPackage the target package
* @param factory
* @param joinPointPattern
* @param weaveType
*/
public static void install(Package targetPackage,
AdviceFactory factory, Pattern joinPointPattern, WeaveType weaveType ) {
String packageName = targetPackage.getName().replace('.', '/');
PackageAspect pa = new PackageAspect(
factory, joinPointPattern, weaveType );
if (!targetPackages.containsKey(packageName)) {
Vector<PackageAspect> v = new Vector<PackageAspect>();
v.add( pa );
targetPackages.put(packageName, v);
} else {
targetPackages.get(packageName).add( pa );
}
for (Class c : AspectAgent.instrumentation.getAllLoadedClasses()) {
if ((c.getPackage() != null)
&& (c.getPackage().equals(targetPackage))) {
pa.addWovenClassname( c.getName() );
install(c, factory, joinPointPattern, weaveType );
}
}
}
/**
* Installs an aspect of the given aspectClass to the given target class using the
* given joinpoint pattern and the standard constructor of the aspect.
* <br>For pattern creation see:
* {@link de.petris.dynamicaspects.PointcutFactory PointcutFactory} and
* {@link de.petris.dynamicaspects.util.Reflection Reflection}
*
* @param targetClass the target class
* @param aspectClass the class of the aspect
* @param joinPointPattern the joinpoint pattern
* @throws AspectException in case any exception occurrs
* @see de.petris.dynamicaspects.PointcutFactory
*/
public static void install(
Class targetClass, Class<? extends Advice> aspectClass,
Pattern joinPointPattern, WeaveType weaveType )
throws AspectException {
install(
targetClass, null, aspectClass,
null, joinPointPattern, weaveType );
}
/**
* Installs an aspect returned by the given factory to the given target class using the
* given joinpoint pattern.
* <br>For pattern creation see:
* {@link de.petris.dynamicaspects.PointcutFactory PointcutFactory} and
* {@link de.petris.dynamicaspects.util.Reflection Reflection}
*
* @param targetClass the target class
* @param factory a factory for the aspect
* @param joinPointPattern the joinpoint pattern
* @throws AspectException in case any exception occurrs
* @see de.petris.dynamicaspects.PointcutFactory
*/
public static void install(
Class targetClass, AdviceFactory factory,
Pattern joinPointPattern, WeaveType weaveType )
throws AspectException {
install(
targetClass, null, null,
factory, joinPointPattern, weaveType );
}
/**
* Installs the given aspect to the given target class using the given
* joinpoint pattern.
* <br>For pattern creation see:
* {@link de.petris.dynamicaspects.PointcutFactory PointcutFactory} and
* {@link de.petris.dynamicaspects.util.Reflection Reflection}
*
* @param targetClass the target class
* @param aspect the aspect to be installed
* @param joinPointPattern the joinpoint pattern
* @see de.petris.dynamicaspects.PointcutFactory
* @throws AspectException in case any exception occurrs
*/
static void install(
Class targetClass, Advice aspect,
Pattern joinPointPattern, WeaveType weaveType )
throws AspectException {
install(
targetClass, aspect, null,
null, joinPointPattern, weaveType );
}
/**
* Installs an aspect of the given aspectClass to the given target class using the
* given joinpoint pattern and the standard constructor of the aspect.
* <br>For pattern creation see:
* {@link de.petris.dynamicaspects.PointcutFactory PointcutFactory} and
* {@link de.petris.dynamicaspects.util.Reflection Reflection}
*
* @param targetClass the target class
* @param aspectClass the class of the aspect
* @param joinPointPattern the joinpoint pattern
* @see de.petris.dynamicaspects.PointcutFactory
* @throws AspectException in case any exception occurrs
*/
public static void install(
Class targetClass, Class<? extends Advice> aspectClass,
String joinPointPattern, WeaveType weaveType )
throws AspectException {
Pattern p = Pattern.compile( joinPointPattern );
install(
targetClass, null, aspectClass,
null, p, weaveType );
}
/**
* Installs an aspect returned by the given factory to the given target class using the
* given joinpoint pattern.
* <br>For pattern creation see:
* {@link de.petris.dynamicaspects.PointcutFactory PointcutFactory} and
* {@link de.petris.dynamicaspects.util.Reflection Reflection}
*
* @param targetClass the target class
* @param factory a factory for the aspect
* @param joinPointPattern the joinpoint pattern
* @see de.petris.dynamicaspects.PointcutFactory
* @throws AspectException in case any exception occurrs
*/
public static void install(
Class targetClass, AdviceFactory factory,
String joinPointPattern, WeaveType weaveType )
throws AspectException {
Pattern p = Pattern.compile(joinPointPattern);
install(
targetClass, null,
null, factory, p, weaveType );
}
/**
* Installs the given aspect to the given target class using the given
* joinpoint pattern.
*
* @param targetClass the target class
* @param aspect the aspect to be installed
* @param joinPointPattern the joinpoint pattern
* @throws AspectException in case any exception occurrs
*/
static void install(
Class targetClass, Advice aspect,
String joinPointPattern, WeaveType weaveType )
throws AspectException {
Pattern p = Pattern.compile( joinPointPattern );
install(
targetClass, aspect, null,
null, p, weaveType );
}
/**
* Installs an aspect to the given targetclass using the given joinpoint pattern.
* The aspect to be installed can be given by argument directly or is created either
* by the given class or by the given factory. One of the three
* ( aspect instance, aspect class or aspect factory ) must not be null.
*
* @param targetClass the target class
* @param aspect the instance of the aspect or null
* @param aspectClass the class of the aspect or null
* @param factory the factory for the aspect or null
* @param joinPointPattern the joinpoint pattern
* @throws AspectException in case any exception occurrs
*/
private static void install(
Class targetClass, Advice aspect, Class<? extends Advice> aspectClass,
AdviceFactory factory, Pattern joinPointPattern, WeaveType weaveType )
throws AspectException {
if( checkPackage( aspectClass ) ) {
try {
// JDK1.5 BUG ID: 6191049 ( fixed as 5092850 )
// link class before redefinition:
targetClass.getDeclaredFields();
JavaClass jc = Repository.lookupClass(targetClass.getName());
if( aspect != null ) {
AGENT.applyAspect(
jc, aspect, joinPointPattern, weaveType );
}
else if( aspectClass != null ) {
AGENT.applyAspect(
jc, aspectClass, joinPointPattern, weaveType );
}
else {
AGENT.applyAspect(
jc, factory, joinPointPattern, weaveType );
}
AGENT.redefine(targetClass, jc);
} catch( Exception exc ) {
throw new AspectException( exc );
}
}
}
/**
* Deinstalls all advices of the given class from all target classes of the given package.
*
* @param p the package the target classes
* @param adviceClass the class of the advices
*/
public static void deinstall( Package p , Class<? extends Advice> adviceClass ) {
String packageName = p.getName().replace( '.', '/' );
List<PackageAspect> list = targetPackages.get( packageName );
if( list != null ) {
for( PackageAspect pa : list ) {
if( ( ( pa.getAdviceClass() != null )
&& ( pa.getAdviceClass().getName().equals( adviceClass.getName() ) ) )
||
( pa.getAdvice() != null )
&& ( pa.getAdvice().getClass().getName().equals(
adviceClass.getName() ) ) ) {
pa.removeAspect();
}
}
}
}
/**
* Deinstalls the advice from all target classes of the given package.
*
* @param p the package the target classes
* @param advice the advice to be deinstalled
*/
public static void deinstall( Package p , Advice advice ) {
String packageName = p.getName().replace( '.', '/' );
List<PackageAspect> list = targetPackages.get( packageName );
if( list != null ) {
for( PackageAspect pa : list ) {
if( ( pa.getAdvice() != null )
&& ( pa.getAdvice().equals( advice ) ) ) {
pa.removeAspect();
}
}
}
}
/**
* Deinstalls the aspect instance from the targetClass.
*
* @param targetClass the target class
* @param advice the aspect instance to be installed
* @throws AspectException in case any exception occurrs
*/
public static void deinstall(Class targetClass, Advice advice)
throws AspectException {
try {
JavaClass jc = Repository.lookupClass(targetClass.getName());
AGENT.removeAspect(jc, advice);
AGENT.redefine(targetClass, jc);
} catch( Exception exc ) {
throw new AspectException( exc );
}
}
/**
* Deinstalls aspects of the given aspectClass from the targetClass.
*
* @param targetClass the target class
* @param adviceClass the advice class
* @throws AspectException in case any exception occurrs
*/
public static void deinstall(Class targetClass, Class<? extends Advice> adviceClass )
throws AspectException {
try {
JavaClass jc = Repository.lookupClass(targetClass.getName());
AGENT.removeAspect(jc, adviceClass);
AGENT.redefine(targetClass, jc);
} catch( Exception exc ) {
throw new AspectException( exc );
}
}
/**
* Redefines the given oldClass using the given newClass.
*
* @param oldClass the old class definition
* @param newClass the new class definition
* @throws Throwable in case anything goes wrong
*/
private void redefine( Class oldClass, JavaClass newClass )
throws Exception {
ByteArrayOutputStream byteArrayOs = new ByteArrayOutputStream();
newClass.dump( new DataOutputStream( byteArrayOs ) );
// newClass.dump( oldClass.getName() + "_new.class");
// todo: debug, maybe save feature
instrumentation.redefineClasses(
new ClassDefinition[] {
new ClassDefinition(
oldClass,
byteArrayOs.toByteArray() ) } );
}
/**
* Applies an aspect to the given target class using the given joinpoint pattern
* @param targetClass the target class
* @param factory the factory for the aspect
* @param joinPointPattern the joinpoint pattern
*/
void applyAspect(
JavaClass targetClass, AdviceFactory factory,
Pattern joinPointPattern, WeaveType weaveType ) {
ClassHandler cHandler =
weaveType.getClassHandler( targetClass.getClassName() );
cHandler.setTargetClass(targetClass);
cHandler.install( factory, joinPointPattern );
addAdviceWeaveTypeMapping(
factory.getAdviceClassName(), weaveType );
}
/**
* Applies an aspect to the given target class using the given joinpoint pattern
* @param targetClass the target class
* @param aspectClass the class of the aspect
* @param joinPointPattern the joinpoint pattern
*/
void applyAspect(
JavaClass targetClass, Class<? extends Advice> aspectClass,
Pattern joinPointPattern, WeaveType weaveType ) {
ClassHandler cHandler =
weaveType.getClassHandler( targetClass.getClassName() );
cHandler.setTargetClass(targetClass);
cHandler.install( aspectClass, joinPointPattern );
addAdviceWeaveTypeMapping( aspectClass.getName(), weaveType );
}
/**
* Applies an aspect to the given target class using the given joinpoint pattern
* @param targetClass the target class
* @param aspect the aspect instance
* @param joinPointPattern the joinpoint pattern
*/
void applyAspect(
JavaClass targetClass, Advice aspect,
Pattern joinPointPattern, WeaveType weaveType ) {
ClassHandler cHandler =
weaveType.getClassHandler( targetClass.getClassName() );
cHandler.setTargetClass(targetClass);
cHandler.install( aspect, joinPointPattern );
addAdviceWeaveTypeMapping(
aspect.getClass().getName(), weaveType );
}
/**
* Removes the aspect from the targetClass.
*
* @param targetClass the target class
* @param aspectClass the aspect class
* @throws Throwable in case anything goes wrong
*/
private void removeAspect(
JavaClass targetClass, Class<? extends Advice> aspectClass ) {
List<WeaveType> types =
adviceClassWeaveTypeMapping.get( aspectClass.getName() );
if( types != null ) {
for( WeaveType type : types ) {
ClassHandler cHandler =
type.getClassHandler( targetClass.getClassName() );
cHandler.setTargetClass( targetClass );
cHandler.deinstall( aspectClass );
}
//todo: remove only when all classes have been cleaned
// adviceClassWeaveTypeMapping.remove( aspectClass.getName() );
}
}
/**
* Removes the aspect instance from the targetClass.
*
* @param targetClass the target class
* @param aspect the aspect instance
* @throws Throwable in case anything goes wrong
*/
private void removeAspect(
JavaClass targetClass, Advice aspect ) {
for( WeaveType type :
adviceClassWeaveTypeMapping.get( aspect.getClass().getName() ) ) {
ClassHandler cHandler =
type.getClassHandler( targetClass.getClassName() );
cHandler.setTargetClass( targetClass );
cHandler.deinstall( aspect );
}
adviceClassWeaveTypeMapping.remove( aspect.getClass().getName() );
}
/**
* Checks if the package of the aspectClass belongs to
* the predefined package list.
*
* @param aspectClass the aspect class
* @return true if the package belongs to the list, else false.
*/
private static boolean checkPackage(Class aspectClass) {
if ((packageList != null)
&& !packageList.contains(aspectClass.getPackage().getName())) {
SecurityException se = new SecurityException("the "
+ aspectClass.getPackage()
+ " is not in the predefined package list\n" + " aspect "
+ aspectClass.getName() + " can NOT be installed ");
if (onErrorAbort) {
throw se;
} else {
se.printStackTrace();
}
return false;
}
return true;
}
/**
* Adds the weave type to the advice class.
*
* @param adviceClassName the name of the advice class
* @param type the weaveType
*/
private void addAdviceWeaveTypeMapping(
String adviceClassName, WeaveType type ) {
if( !adviceClassWeaveTypeMapping.containsKey( adviceClassName ) ) {
Vector<WeaveType> v = new Vector<WeaveType>();
v.add( type );
adviceClassWeaveTypeMapping.put( adviceClassName, v );
}
else {
adviceClassWeaveTypeMapping.get(
adviceClassName ).add( type );
}
}
/**
* Adds a MixIn.
*
* @param mixIn the mixIn to be added.
*/
public static void addMixIn( MixIn mixIn ) {
if( mixInsInstalled ) {
throw new AspectException(
"due to restrictions of the " +
"Instrumentation class provided by the JDK " +
"it is not ( yet ) possible to add a mixin " +
"once you have installed MixIns via " +
"installMixIns()-Method call, please add all " +
"mixins prior to installation " );
}
MixInTargets targets =
mixIn.getClass().getAnnotation( MixInTargets.class );
if( targets != null ) {
for( String target : targets.getTargetClassNames() ) {
String nonDottedClassname = target.replace('.', '/' );
if( !targetclassMixInMapping.containsKey(
nonDottedClassname ) ) {
List<MixIn> mixInList = new Vector<MixIn>();
mixInList.add( mixIn );
targetclassMixInMapping.put(
nonDottedClassname, mixInList );
}
else {
targetclassMixInMapping.get(
nonDottedClassname ).add( mixIn );
}
}
}
else {
//todo:
System.out.println( "no targets found" );
}
}
/**
* Installs all added MixIns.
*/
public static void installMixIns() {
mixInsInstalled = true;
for( String target : targetclassMixInMapping.keySet() ) {
try {
Class.forName( target.replace( '/', '.' ) );
}
catch( ClassNotFoundException cfe ) {
throw new AspectException(
"stopping mixIn installation. tried to load class "
+ target,
cfe );
}
}
}
/**
* A onload aspect weaver.
*
* @author Marco Petris
*/
private static class OnLoadAspectWeaver implements ClassFileTransformer {
private Map<String, List<MixIn>> targetclassMixIns;
public OnLoadAspectWeaver( Map<String, List<MixIn>> targetclassMixInMapping ) {
this.targetclassMixIns = targetclassMixInMapping;
}
public byte[] transform(ClassLoader loader, String className,
Class< ? > classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
if ( classBeingRedefined == null ) {
byte[] modifiedBuffer = null;
if( targetclassMixIns.containsKey( className ) ) {
modifiedBuffer = new ClassPatcher(
classfileBuffer, className,
targetclassMixIns.get(
className ) ).patchClass();
}
// todo: should be a regular expression pattern matching
if( ( !targetPackages.isEmpty() )
&& ( targetPackages.containsKey( className.substring(
0, className.lastIndexOf( '/' ) ) ) ) ) {
if( modifiedBuffer == null ) {
modifiedBuffer = classfileBuffer;
}
modifiedBuffer =
applyPackageAspect( modifiedBuffer, className );
}
return modifiedBuffer;
}
return null;
}
/**
* Applies aspects to the class in the buffer with the given name.
*
* @param classfileBuffer the original version of the class
* @param className the name of the class
* @return the new version of the class
*/
private byte[] applyPackageAspect( byte[] classfileBuffer,
String className ) {
JavaClass jc =
Reflection.classForByteArray( classfileBuffer, className );
for( PackageAspect pa :
targetPackages.get(
className.substring(
0, className.lastIndexOf( '/' ) ) ) ) {
pa.applyAspect( jc );
}
return jc.getBytes();
}
}
/**
* An aspect which has been added to a package.
*
* @author Marco Petris
*/
private static class PackageAspect {
private Advice advice;
private Pattern pattern;
private WeaveType type;
private Class<? extends Advice> adviceClass;
private AdviceFactory factory;
private List<String> wovenClasses;
/**
* @param aspect
* @param pattern
*/
public PackageAspect(
Advice advice, Pattern pattern, WeaveType type ) {
super();
this.advice = advice;
this.pattern = pattern;
this.type = type;
this.wovenClasses = new Vector<String>();
}
/**
* @param pattern
* @param aspectClass
*/
public PackageAspect(
Class< ? extends Advice> adviceClass,
Pattern pattern, WeaveType type ) {
super();
this.pattern = pattern;
this.adviceClass = adviceClass;
this.type = type;
this.wovenClasses = new Vector<String>();
}
/**
* @param pattern
* @param factory
*/
public PackageAspect(
AdviceFactory factory,
Pattern pattern, WeaveType type ) {
super();
this.pattern = pattern;
this.factory = factory;
this.type = type;
this.wovenClasses = new Vector<String>();
}
/**
* Applies the package aspect to the target class
* @param jc the target class
*/
public void applyAspect( JavaClass jc ) {
addWovenClassname( jc.getClassName() );
if( advice != null ) {
AGENT.applyAspect( jc, advice, pattern, type );
}
else if( adviceClass != null ) {
AGENT.applyAspect(
jc, adviceClass, pattern, type );
}
else {
AGENT.applyAspect( jc, factory, pattern, type );
}
}
/**
* @param name the name of a woven class
*/
public void addWovenClassname( String name ) {
wovenClasses.add( name );
}
/**
* Removes the package aspect.
*/
public void removeAspect() {
for( String classname : wovenClasses ) {
if( advice != null ) {
AspectAgent.deinstall(
Reflection.classForName( classname ), advice );
}
else if( adviceClass != null ) {
AspectAgent.deinstall(
Reflection.classForName( classname ), adviceClass );
}
}
// todo: this is too simple
wovenClasses.clear();
}
/**
* @return the inner advice, or null
*/
public Advice getAdvice() {
return advice;
}
/**
* @return the class of the advice, or null
*/
public Class< ? extends Advice> getAdviceClass() {
return adviceClass;
}
}
}