123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- /* *******************************************************************
- * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Common Public License v1.0
- * which accompanies this distribution and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * Xerox/PARC initial implementation
- * ******************************************************************/
-
-
- package org.aspectj.weaver.bcel;
-
- import java.lang.reflect.Modifier;
- import java.util.*;
-
- import org.apache.bcel.Constants;
- import org.apache.bcel.generic.*;
- import org.aspectj.weaver.*;
- import org.aspectj.weaver.patterns.*;
-
-
- //XXX addLazyMethodGen is probably bad everywhere
- public class BcelTypeMunger extends ConcreteTypeMunger {
-
- public BcelTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) {
- super(munger, aspectType);
- }
-
- public String toString() {
- return "(BcelTypeMunger " + getMunger() + ")";
- }
-
- public boolean munge(BcelClassWeaver weaver) {
- if (munger.getKind() == ResolvedTypeMunger.Field) {
- return mungeNewField(weaver, (NewFieldTypeMunger)munger);
- } else if (munger.getKind() == ResolvedTypeMunger.Method) {
- return mungeNewMethod(weaver, (NewMethodTypeMunger)munger);
- } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) {
- return mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger);
- } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) {
- return mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger);
- } else if (munger.getKind() == ResolvedTypeMunger.Constructor) {
- return mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger);
- } else {
- throw new RuntimeException("unimplemented");
- }
- }
-
-
-
- private boolean mungePrivilegedAccess(
- BcelClassWeaver weaver,
- PrivilegedAccessMunger munger)
- {
- LazyClassGen gen = weaver.getLazyClassGen();
- ResolvedMember member = munger.getMember();
-
- ResolvedTypeX onType = weaver.getWorld().resolve(member.getDeclaringType());
- //System.out.println("munging: " + gen + " with " + member);
- if (onType.equals(gen.getType())) {
- if (member.getKind() == Member.FIELD) {
- //System.out.println("matched: " + gen);
- addFieldGetter(gen, member,
- AjcMemberMaker.privilegedAccessMethodForFieldGet(aspectType, member));
- addFieldSetter(gen, member,
- AjcMemberMaker.privilegedAccessMethodForFieldSet(aspectType, member));
- return true;
- } else if (member.getKind() == Member.METHOD) {
- addMethodDispatch(gen, member,
- AjcMemberMaker.privilegedAccessMethodForMethod(aspectType, member));
- return true;
- } else if (member.getKind() == Member.STATIC_INITIALIZATION) {
- gen.forcePublic();
- return true;
- } else {
- throw new RuntimeException("unimplemented");
- }
- }
- return false;
- }
-
- private void addFieldGetter(
- LazyClassGen gen,
- ResolvedMember field,
- ResolvedMember accessMethod)
- {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- if (field.isStatic()) {
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- field.getName(),
- BcelWorld.makeBcelType(field.getType()), Constants.GETSTATIC));
- } else {
- il.append(fact.ALOAD_0);
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- field.getName(),
- BcelWorld.makeBcelType(field.getType()), Constants.GETFIELD));
- }
- il.append(fact.createReturn(BcelWorld.makeBcelType(field.getType())));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
- }
-
- private void addFieldSetter(
- LazyClassGen gen,
- ResolvedMember field,
- ResolvedMember accessMethod)
- {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- Type fieldType = BcelWorld.makeBcelType(field.getType());
-
- if (field.isStatic()) {
- il.append(fact.createLoad(fieldType, 0));
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- field.getName(),
- fieldType, Constants.PUTSTATIC));
- } else {
- il.append(fact.ALOAD_0);
- il.append(fact.createLoad(fieldType, 1));
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- field.getName(),
- fieldType, Constants.PUTFIELD));
- }
- il.append(fact.createReturn(Type.VOID));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
- }
-
- private void addMethodDispatch(
- LazyClassGen gen,
- ResolvedMember method,
- ResolvedMember accessMethod)
- {
- LazyMethodGen mg = makeMethodGen(gen, accessMethod);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- //Type fieldType = BcelWorld.makeBcelType(field.getType());
- Type[] paramTypes = BcelWorld.makeBcelTypes(method.getParameterTypes());
-
- int pos = 0;
-
- if (!method.isStatic()) {
- il.append(fact.ALOAD_0);
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- il.append(fact.createLoad(paramType, pos));
- pos+=paramType.getSize();
- }
- il.append(Utility.createInvoke(fact, (BcelWorld)aspectType.getWorld(),
- method));
- il.append(fact.createReturn(BcelWorld.makeBcelType(method.getReturnType())));
-
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
- }
-
-
-
- private LazyMethodGen makeMethodGen(LazyClassGen gen, ResolvedMember member) {
- return new LazyMethodGen(
- member.getModifiers(),
- BcelWorld.makeBcelType(member.getReturnType()),
- member.getName(),
- BcelWorld.makeBcelTypes(member.getParameterTypes()),
- TypeX.getNames(member.getExceptions()),
- gen);
- }
-
-
- private FieldGen makeFieldGen(LazyClassGen gen, ResolvedMember member) {
- return new FieldGen(
- member.getModifiers(),
- BcelWorld.makeBcelType(member.getReturnType()),
- member.getName(),
- gen.getConstantPoolGen());
- }
-
-
-
-
- private boolean mungePerObjectInterface(
- BcelClassWeaver weaver,
- PerObjectInterfaceTypeMunger munger)
- {
- LazyClassGen gen = weaver.getLazyClassGen();
-
- if (couldMatch(gen.getType(), munger.getTestPointcut())) {
- FieldGen fg = makeFieldGen(gen,
- AjcMemberMaker.perObjectField(gen.getType(), aspectType));
-
- gen.addField(fg.getField());
-
-
- Type fieldType = BcelWorld.makeBcelType(aspectType);
- LazyMethodGen mg = new LazyMethodGen(
- Modifier.PUBLIC,
- fieldType,
- NameMangler.perObjectInterfaceGet(aspectType),
- new Type[0], new String[0],
- gen);
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- il.append(fact.ALOAD_0);
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.GETFIELD));
- il.append(fact.createReturn(fieldType));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
-
- LazyMethodGen mg1 = new LazyMethodGen(
- Modifier.PUBLIC,
- Type.VOID,
- NameMangler.perObjectInterfaceSet(aspectType),
-
- new Type[]{fieldType,}, new String[0],
- gen);
- InstructionList il1 = new InstructionList();
- il1.append(fact.ALOAD_0);
- il1.append(fact.createLoad(fieldType, 1));
- il1.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.PUTFIELD));
- il1.append(fact.createReturn(Type.VOID));
- mg1.getBody().insert(il1);
-
- gen.addMethodGen(mg1);
-
- gen.addInterface(munger.getInterfaceType());
-
- return true;
- } else {
- return false;
- }
- }
-
- private boolean couldMatch(
- BcelObjectType bcelObjectType,
- Pointcut pointcut) {
- return !bcelObjectType.isInterface();
- }
-
- private boolean mungeNewMethod(BcelClassWeaver weaver, NewMethodTypeMunger munger) {
- ResolvedMember signature = munger.getSignature();
- ResolvedMember dispatchMethod = munger.getDispatchMethod(aspectType);
-
- LazyClassGen gen = weaver.getLazyClassGen();
-
- ResolvedTypeX onType = weaver.getWorld().resolve(signature.getDeclaringType());
- boolean onInterface = onType.isInterface();
-
- if (onType.equals(gen.getType())) {
- ResolvedMember introMethod =
- AjcMemberMaker.interMethod(signature, aspectType, onInterface);
-
- LazyMethodGen mg = makeMethodGen(gen, introMethod);
-
- if (!onInterface && !Modifier.isAbstract(introMethod.getModifiers())) {
- InstructionList body = mg.getBody();
- InstructionFactory fact = gen.getFactory();
- int pos = 0;
-
- if (!signature.isStatic()) {
- body.append(fact.createThis());
- pos++;
- }
- Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(fact.createLoad(paramType, pos));
- pos+=paramType.getSize();
- }
- body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
- body.append(fact.createReturn(BcelWorld.makeBcelType(introMethod.getReturnType())));
- } else {
- //??? this is okay
- //if (!(mg.getBody() == null)) throw new RuntimeException("bas");
- }
-
-
- // XXX make sure to check that we set exceptions properly on this guy.
- weaver.addLazyMethodGen(mg);
-
- Set neededSuperCalls = munger.getSuperMethodsCalled();
-
- for (Iterator iter = neededSuperCalls.iterator(); iter.hasNext(); ) {
- ResolvedMember superMethod = (ResolvedMember) iter.next();
- if (weaver.addDispatchTarget(superMethod)) {
- //System.err.println("super type: " + superMethod.getDeclaringType() + ", " + gen.getType());
- boolean isSuper = !superMethod.getDeclaringType().equals(gen.getType());
- String dispatchName;
- if (isSuper) dispatchName = NameMangler.superDispatchMethod(onType, superMethod.getName());
- else dispatchName = NameMangler.protectedDispatchMethod(onType, superMethod.getName());
- LazyMethodGen dispatcher = makeDispatcher(gen, dispatchName, superMethod, weaver.getWorld(), isSuper);
-
- weaver.addLazyMethodGen(dispatcher);
- }
- }
-
- return true;
- } else if (onInterface && gen.getType().isTopmostImplementor(onType) &&
- !Modifier.isAbstract(signature.getModifiers()))
- {
- ResolvedMember introMethod =
- AjcMemberMaker.interMethod(signature, aspectType, false);
-
- LazyMethodGen mg = makeMethodGen(gen, introMethod);
-
- //
-
- Type[] paramTypes = BcelWorld.makeBcelTypes(introMethod.getParameterTypes());
- Type returnType = BcelWorld.makeBcelType(introMethod.getReturnType());
-
- InstructionList body = mg.getBody();
- InstructionFactory fact = gen.getFactory();
- int pos = 0;
-
- if (!introMethod.isStatic()) {
- body.append(fact.createThis());
- pos++;
- }
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(fact.createLoad(paramType, pos));
- pos+=paramType.getSize();
- }
- body.append(Utility.createInvoke(fact, weaver.getWorld(), dispatchMethod));
- body.append(fact.createReturn(returnType));
- mg.definingType = onType;
-
- weaver.addOrReplaceLazyMethodGen(mg);
-
- return true;
- } else {
- return false;
- }
- }
-
-
- private boolean mungeNewConstructor(
- BcelClassWeaver weaver,
- NewConstructorTypeMunger newConstructorTypeMunger)
- {
- final LazyClassGen currentClass = weaver.getLazyClassGen();
- final InstructionFactory fact = currentClass.getFactory();
-
- ResolvedMember newConstructorMember = newConstructorTypeMunger.getSyntheticConstructor();
- TypeX onType = newConstructorMember.getDeclaringType();
-
-
- if (! onType.equals(currentClass.getType())) return false;
-
- ResolvedMember explicitConstructor = newConstructorTypeMunger.getExplicitConstructor();
- //int declaredParameterCount = newConstructorTypeMunger.getDeclaredParameterCount();
- LazyMethodGen freshConstructor =
- makeMethodGen(currentClass, newConstructorMember);
- currentClass.addMethodGen(freshConstructor);
- //weaver.addLazyMethodGen(freshConstructor);
-
- InstructionList body = freshConstructor.getBody();
-
- // add to body: push arts for call to pre, from actual args starting at 1 (skipping this), going to
- // declared argcount + 1
- TypeX[] declaredParams = newConstructorTypeMunger.getSignature().getParameterTypes();
- Type[] paramTypes = freshConstructor.getArgumentTypes();
- int frameIndex = 1;
- for (int i = 0, len = declaredParams.length; i < len; i++) {
- body.append(fact.createLoad(paramTypes[i], frameIndex));
- frameIndex += paramTypes[i].getSize();
- }
- // do call to pre
- Member preMethod = AjcMemberMaker.preIntroducedConstructor(aspectType, onType, declaredParams);
- body.append(Utility.createInvoke(fact, null, preMethod));
-
- // create a local, and store return pre stuff into it.
- int arraySlot = freshConstructor.allocateLocal(1);
- body.append(fact.createStore(Type.OBJECT, arraySlot));
-
- // put this on the stack
- body.append(fact.ALOAD_0);
-
- // unpack pre args onto stack
- TypeX[] superParamTypes = explicitConstructor.getParameterTypes();
-
- for (int i = 0, len = superParamTypes.length; i < len; i++) {
- body.append(fact.createLoad(Type.OBJECT, arraySlot));
- body.append(Utility.createConstant(fact, i));
- body.append(fact.createArrayLoad(Type.OBJECT));
- body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(superParamTypes[i])));
- }
-
- // call super/this
-
- body.append(Utility.createInvoke(fact, null, explicitConstructor));
-
- // put this back on the stack
-
- body.append(fact.ALOAD_0);
-
- // unpack params onto stack
- Member postMethod = AjcMemberMaker.postIntroducedConstructor(aspectType, onType, declaredParams);
- TypeX[] postParamTypes = postMethod.getParameterTypes();
-
- for (int i = 1, len = postParamTypes.length; i < len; i++) {
- body.append(fact.createLoad(Type.OBJECT, arraySlot));
- body.append(Utility.createConstant(fact, superParamTypes.length + i-1));
- body.append(fact.createArrayLoad(Type.OBJECT));
- body.append(Utility.createConversion(fact, Type.OBJECT, BcelWorld.makeBcelType(postParamTypes[i])));
- }
-
- // call post
- body.append(Utility.createInvoke(fact, null, postMethod));
-
- // don't forget to return!!
-
- body.append(fact.RETURN);
-
- return true;
- }
-
-
- private static LazyMethodGen makeDispatcher(
- LazyClassGen onGen,
- String dispatchName,
- ResolvedMember superMethod,
- BcelWorld world,
- boolean isSuper)
- {
- Type[] paramTypes = BcelWorld.makeBcelTypes(superMethod.getParameterTypes());
- Type returnType = BcelWorld.makeBcelType(superMethod.getReturnType());
-
- LazyMethodGen mg =
- new LazyMethodGen(
- Modifier.PUBLIC,
- returnType,
- dispatchName,
- paramTypes,
- TypeX.getNames(superMethod.getExceptions()),
- onGen);
- InstructionList body = mg.getBody();
-
- // assert (!superMethod.isStatic())
- InstructionFactory fact = onGen.getFactory();
- int pos = 0;
-
- body.append(fact.createThis());
- pos++;
- for (int i = 0, len = paramTypes.length; i < len; i++) {
- Type paramType = paramTypes[i];
- body.append(fact.createLoad(paramType, pos));
- pos+=paramType.getSize();
- }
- if (isSuper) {
- body.append(Utility.createSuperInvoke(fact, world, superMethod));
- } else {
- body.append(Utility.createInvoke(fact, world, superMethod));
- }
- body.append(fact.createReturn(returnType));
-
- return mg;
- }
-
- private boolean mungeNewField(BcelClassWeaver weaver, NewFieldTypeMunger munger) {
- ResolvedMember initMethod = munger.getInitMethod(aspectType);
-
- LazyClassGen gen = weaver.getLazyClassGen();
- ResolvedMember field = munger.getSignature();
-
-
- ResolvedTypeX onType = weaver.getWorld().resolve(field.getDeclaringType());
- boolean onInterface = onType.isInterface();
-
- if (onType.equals(gen.getType())) {
- if (onInterface) {
- LazyMethodGen mg = makeMethodGen(gen,
- AjcMemberMaker.interFieldInterfaceGetter(field, onType, aspectType));
- gen.addMethodGen(mg);
-
- LazyMethodGen mg1 = makeMethodGen(gen,
- AjcMemberMaker.interFieldInterfaceSetter(field, onType, aspectType));
- gen.addMethodGen(mg1);
- } else {
- weaver.addInitializer(this);
- FieldGen fg = makeFieldGen(gen,
- AjcMemberMaker.interFieldClassField(field, aspectType));
- gen.addField(fg.getField());
- }
- return true;
- } else if (onInterface && gen.getType().isTopmostImplementor(onType)) {
- // wew know that we can't be static since we don't allow statics on interfaces
- if (field.isStatic()) throw new RuntimeException("unimplemented");
- weaver.addInitializer(this);
- //System.err.println("impl body on " + gen.getType() + " for " + munger);
- Type fieldType = BcelWorld.makeBcelType(field.getType());
-
- FieldGen fg = makeFieldGen(gen,
- AjcMemberMaker.interFieldInterfaceField(field, onType, aspectType));
- gen.addField(fg.getField());
-
- //this uses a shadow munger to add init method to constructors
- //weaver.getShadowMungers().add(makeInitCallShadowMunger(initMethod));
-
- LazyMethodGen mg = makeMethodGen(gen,
- AjcMemberMaker.interFieldInterfaceGetter(field, gen.getType(), aspectType));
- InstructionList il = new InstructionList();
- InstructionFactory fact = gen.getFactory();
- if (field.isStatic()) {
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.GETSTATIC));
- } else {
- il.append(fact.ALOAD_0);
- il.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.GETFIELD));
- }
- il.append(fact.createReturn(fieldType));
- mg.getBody().insert(il);
-
- gen.addMethodGen(mg);
-
- LazyMethodGen mg1 = makeMethodGen(gen,
- AjcMemberMaker.interFieldInterfaceSetter(field, gen.getType(), aspectType));
- InstructionList il1 = new InstructionList();
- if (field.isStatic()) {
- il1.append(fact.createLoad(fieldType, 0));
- il1.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.PUTSTATIC));
- } else {
- il1.append(fact.ALOAD_0);
- il1.append(fact.createLoad(fieldType, 1));
- il1.append(fact.createFieldAccess(
- gen.getClassName(),
- fg.getName(),
- fieldType, Constants.PUTFIELD));
- }
- il1.append(fact.createReturn(Type.VOID));
- mg1.getBody().insert(il1);
-
- gen.addMethodGen(mg1);
-
- return true;
- } else {
- return false;
- }
- }
- }
|