* @param klass the class set.
*/
public void transformCode(final Context context, final Klass klass) {
m_definition.loadAspects(context.getLoader());
final ClassGen cg = klass.getClassGen();
ClassMetaData classMetaData = BcelMetaDataMaker.createClassMetaData(context.getJavaClass(cg));
// filter caller classes
if (classFilter(classMetaData, cg)) {
return;
}
final Method[] methods = cg.getMethods();
// get the index for the <clinit> method (if there is one)
boolean hasClInitMethod = false;
int clinitIndex = -1;
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals("<clinit>")) {
clinitIndex = i;
hasClInitMethod = true;
break;
}
}
final ConstantPoolGen cpg = cg.getConstantPool();
final String className = cg.getClassName();
final InstructionFactory factory = new InstructionFactory(cg);
final Set callerSideJoinPoints = new HashSet();
Method clInitMethod = null;
final Map methodSequences = new HashMap();
final List newMethods = new ArrayList();
boolean isClassAdvised = false;
boolean isMethodChanged = false;
for (int i = 0; i < methods.length; i++) {
// filter caller methods
if (methodFilterCaller(methods[i])) {
continue;
}
final MethodGen mg = new MethodGen(methods[i], className, cpg);
final InstructionList il = mg.getInstructionList();
if (il == null) {
continue;
}
InstructionHandle ih = il.getStart();
isMethodChanged = false;
// search for all InvokeInstruction instructions and
// inserts the call side pointcuts
while (ih != null) {
final Instruction ins = ih.getInstruction();
if (ins instanceof INVOKESPECIAL ||
ins instanceof INVOKESTATIC ||
ins instanceof INVOKEVIRTUAL) {
final InvokeInstruction invokeInstruction = (InvokeInstruction)ins;
// get the callee method name, signature and class name
final String calleeMethodName = invokeInstruction.getName(cpg);
final String calleeClassName = invokeInstruction.getClassName(cpg);
final String calleeMethodSignature = invokeInstruction.getSignature(cpg);
// filter callee classes
if (!m_definition.inIncludePackage(calleeClassName)) {
ih = ih.getNext();
continue;
}
// filter callee methods
if (methodFilterCallee(calleeMethodName)) {
ih = ih.getNext();
continue;
}
// create the class meta-data
ClassMetaData calleeSideClassMetaData;
try {
JavaClass javaClass = context.getRepository().loadClass(calleeClassName);
calleeSideClassMetaData = BcelMetaDataMaker.createClassMetaData(javaClass);
}
catch (ClassNotFoundException e) {
throw new WrappedRuntimeException(e);
}
// create the method meta-data
MethodMetaData calleeSideMethodMetaData = BcelMetaDataMaker.createMethodMetaData(
invokeInstruction, cpg
);
// is this a caller side method pointcut?
if (m_definition.isPickedOutByCallPointcut(calleeSideClassMetaData, calleeSideMethodMetaData)) {
// get the caller method name and signature
Method method = mg.getMethod();
String callerMethodName = method.getName();
String callerMethodSignature = method.getSignature();
final Type joinPointType = TransformationUtil.CALLER_SIDE_JOIN_POINT_TYPE;
// take care of identification of overloaded methods
// by inserting a sequence number
if (methodSequences.containsKey(calleeMethodName)) {
int sequence = ((Integer)methodSequences.get(calleeMethodName)).intValue();
methodSequences.remove(calleeMethodName);
sequence++;
methodSequences.put(calleeMethodName, new Integer(sequence));
}
else {
methodSequences.put(calleeMethodName, new Integer(1));
}
int methodSequence = ((Integer)methodSequences.get(calleeMethodName)).intValue();
isClassAdvised = true;
isMethodChanged = true;
insertPreAdvice(
il, ih, cg,
calleeMethodName,
methodSequence,
factory,
joinPointType
);
insertPostAdvice(
il, ih.getNext(), cg,
calleeMethodName,
methodSequence,
factory,
joinPointType
);
StringBuffer key = new StringBuffer();
key.append(className);
key.append(TransformationUtil.DELIMITER);
key.append(calleeMethodName);
key.append(TransformationUtil.DELIMITER);
key.append(methodSequence);
// skip the creation of the join point if we already have one
if (!callerSideJoinPoints.contains(key.toString())) {
callerSideJoinPoints.add(key.toString());
addStaticJoinPointField(
cpg, cg, calleeMethodName,
methodSequence, joinPointType
);
if (hasClInitMethod) {
methods[clinitIndex] = createStaticJoinPointField(
cpg, cg,
methods[clinitIndex],
callerMethodName,
calleeClassName,
calleeMethodName,
methodSequence,
callerMethodSignature,
calleeMethodSignature,
factory,
joinPointType,
m_definition.getUuid()
);
}
else if (clInitMethod == null) {
clInitMethod = createClInitMethodWithStaticJoinPointField(
cpg, cg,
callerMethodName,
calleeClassName,
calleeMethodName,
methodSequence,
callerMethodSignature,
calleeMethodSignature,
factory,
joinPointType,
m_definition.getUuid()
);
}
else {
clInitMethod = createStaticJoinPointField(
cpg, cg,
clInitMethod,
callerMethodName,
calleeClassName,
calleeMethodName,
methodSequence,
callerMethodSignature,
calleeMethodSignature,
factory,
joinPointType,
m_definition.getUuid()
);
}
}
}
}
ih = ih.getNext();
}
if (isMethodChanged) {
mg.setMaxStack();
methods[i] = mg.getMethod();
}
}
if (isClassAdvised) {
context.markAsAdvised();
// if we have transformed methods, create the static class field
if (!hasClInitMethod && clInitMethod != null) {
addStaticClassField(cpg, cg);
clInitMethod = createStaticClassField(
cpg, cg,
clInitMethod,
factory
);
newMethods.add(clInitMethod);
}
else {
addStaticClassField(cpg, cg);
methods[clinitIndex] = createStaticClassField(
cpg, cg,
methods[clinitIndex],
factory
);
}
//}//TODO CHECK THIS
// update the old methods
cg.setMethods(methods);
// add the new methods
for (Iterator it = newMethods.iterator(); it.hasNext();) {
Method method = (Method)it.next();
cg.addMethod(method);
}
}//TODO CHECK THIS
}