blob: 5e5844f0455258822e485b1745c9c02e605f1771 [file] [log] [blame]
/**********************************************************************
* This file is part of the "Object Teams Runtime Environment"
*
* Copyright 2002-2009 Berlin Institute of Technology, Germany.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* $Id: StaticSliceBaseTransformation.java 23408 2010-02-03 18:07:35Z stephan $
*
* Please visit http://www.objectteams.org for updates and contact.
*
* Contributors:
* Berlin Institute of Technology - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otre;
import org.apache.bcel.classfile.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.*;
import org.eclipse.objectteams.otre.util.*;
/**
* Adds to base classes with callin bindings what can be literally pasted in:
*
* Fields:
* protected static Team[] _OT$activeTeams;
* protected static int[] _OT$activeTeamIDs;
* Methods:
* public static void _OT$addTeam(Team team, in team_id)
* public static void _OT$removeTeam(Team team)
* Static initialization (adds clinit method, if not yet presented):
* _OT$activeTeams = new Team[0];
* _OT$activeTeamIDs = new int[0];
*
*
* @version $Id: StaticSliceBaseTransformation.java 23408 2010-02-03 18:07:35Z stephan $
* @author Christine Hundt
* @author Stephan Herrmann
*/
public class StaticSliceBaseTransformation
extends ObjectTeamsTransformation
{
static final String _OT_ACTIVE_TEAMS= "_OT$activeTeams"; //$NON-NLS-1$
static final String _OT_ACTIVE_TEAM_IDS= "_OT$activeTeamIDs"; //$NON-NLS-1$
public StaticSliceBaseTransformation(ClassLoader loader, SharedState state) { super(loader, state); }
public void doTransformCode(ClassGen cg) {
if (cg.isInterface())
return; // can't add implementation
// IMPLICIT_INHERITANCE
String class_name = cg.getClassName();
if (!CallinBindingManager.isBoundBaseClass(class_name)
/*&& !CallinBindingManager.containsBoundBaseInterface(cg.getInterfaceNames())*/)
return; //only (base-)classes with callin bindings need this addition
/*// this only works if teams are only added at the root bound base class
if (CallinBindingManager.isBoundBaseClass(cg.getSuperclassName()))
continue; // team infrastructur already added by super class
*/
if (CallinBindingManager.hasBoundBaseParent(class_name))
return; // team infrastructure already has been added to a super class
ConstantPoolGen cpg = cg.getConstantPool();
factory = new InstructionFactory(cpg);
addStaticInitializations(cg, cpg);
}
/**
* @param ce
* @param cg
*/
public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
String class_name = cg.getClassName();
ConstantPoolGen cpg = cg.getConstantPool();
checkReadClassAttributes(ce, cg, class_name, cpg);
if (cg.isInterface())
return; // can't add implementation
if (state.interfaceTransformedClasses.contains(class_name))
return; // class has already been transformed by this transformer
// IMPLICIT_INHERITANCE
if (!CallinBindingManager.isBoundBaseClass(class_name)
/*&& !CallinBindingManager.containsBoundBaseInterface(cg.getInterfaceNames())*/)
return; //only (base-)classes with callin bindings need this addition
/*// this only works if teams are only added at the root bound base class
if (CallinBindingManager.isBoundBaseClass(cg.getSuperclassName()))
continue; // team infrastructur already added by super class
*/
if (CallinBindingManager.hasBoundBaseParent(class_name))
return; // team infrastructure already has been added to a super class
if(logging) printLogMessage("StaticSliceBaseTransformer transforms "+ class_name);
if(CallinBindingManager.isRole(class_name)) {
addImplicitSubclassNotificationInfrastructure(ce, cg);
}
// addition of the fields '_OT$activeTeams' and '_OT$activeTeamIDs':
int accessFlags = Constants.ACC_PROTECTED | Constants.ACC_STATIC;
FieldGen activeTeamsField = new FieldGen(accessFlags, teamArray, _OT_ACTIVE_TEAMS, cpg);
ce.addField(activeTeamsField.getField(), cg);
// generated global variable: protected static Team[] _OT$activeTeams;
FieldGen activeTeamIDsField = new FieldGen(accessFlags, intArray, _OT_ACTIVE_TEAM_IDS, cpg);
ce.addField(activeTeamIDsField.getField(), cg);
// generated global variable: protected static int[] _OT$activeTeamIDs;
factory = new InstructionFactory(cpg);
// implementation of method '_OT$addTeam'
ce.addMethod(genAddTeam(class_name, cg.getMajor(), cpg).getMethod(), cg);
// implementation of method '_OT$removeTeam':
ce.addMethod(genRemoveTeam(class_name, cg.getMajor(), cpg).getMethod(), cg);
// implementation of the static class initialization method '<clinit>':
/* Adding static initializations requires the addition of the clinit method, if not yet presented.
* This requires synchronization with other transformers (TeamInterfaceImplementer)
* which may do the same this. This is done via 'TeamIdDispenser.clinitAdded(class_name)'.
*/
Method clinit = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V");
if (clinit != null || TeamIdDispenser.clinitAdded(class_name, loader)) {
// the clinit-Method only has to be extended by the code transformation of this transformer
state.interfaceTransformedClasses.add(class_name);
return;
}
InstructionList il = new InstructionList();
MethodGen clinitMethod = new MethodGen(Constants.ACC_STATIC,
Type.VOID,
Type.NO_ARGS,
new String[] { },
Constants.STATIC_INITIALIZER_NAME, class_name,
il, cpg);
il.append(InstructionFactory.createReturn(Type.VOID));
clinitMethod.setMaxStack();
clinitMethod.setMaxLocals();
ce.addMethod(clinitMethod.getMethod(), cg);
/***********************************************************************************************************/
il.dispose();
state.interfaceTransformedClasses.add(class_name);
}
/* Code to be generated:
public static void _OT$addTeam(Team team, int teamID)
{
int l;
// Second part of the "if" below: Avoid duplicate entry of the same team.
// Assumption (see r17473): this strategy assumes that a team instance
// can only be duplicated directly after the first registration.
// Reason: registerAtBases() calling addTeam() for multiple sub-bases
// which share the same _OT$activateTeams et al fields from a common super-base.
if((l = _OT$activeTeams.length) != 0 && _OT$activeTeams[0] == team)
{
return;
} else
{
Team newTeams[] = new Team[l + 1];
int newTeamIDs[] = new int[l + 1];
System.arraycopy(_OT$activeTeams, 0, newTeams, 1, l);
System.arraycopy(_OT$activeTeamIDs, 0, newTeamIDs, 1, l);
_OT$activeTeams = newTeams;
_OT$activeTeamIDs = newTeamIDs;
_OT$activeTeams[0] = team;
_OT$activeTeamIDs[0] = teamID;
return;
}
}
*/
private MethodGen genAddTeam(String class_name, int major, ConstantPoolGen cpg) {
LocalVariableGen lg;
InstructionList il;
il = new InstructionList();
MethodGen addTeamMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNCHRONIZED,
Type.VOID,
new Type[] { teamType, Type.INT },
new String[] { "team", "teamID" },
"_OT$addTeam", class_name,
il, cpg);
// synchronized (BaseClass.class) {
int monitor = addClassMonitorEnter(addTeamMethod, il, class_name, major, cpg).first;
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ARRAYLENGTH());
lg = addTeamMethod.addLocalVariable("l", Type.INT, null, null);
int l = lg.getIndex();
il.append(new DUP());
lg.setStart(il.append(InstructionFactory.createStore(Type.INT, l)));
// generated: int l = _OT$activeTeams.length;
// add duplication check:
BranchHandle emptyArray =
il.append(new IFEQ(null));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ICONST(0));
il.append(InstructionFactory.createArrayLoad(teamType));
il.append(new ALOAD(0));
BranchHandle noDuplication =
il.append(new IF_ACMPNE(null));
GOTO earlyExit = new GOTO(null);
il.append(earlyExit);
InstructionHandle skipReturn = il.append(new NOP());
emptyArray.setTarget(skipReturn);
noDuplication.setTarget(skipReturn);
// generated: if (l > 0 && _OT$activeTeams[0] == team ) return;
lg = addTeamMethod.addLocalVariable("newTeams", teamArray, null, null);
int newTeams = lg.getIndex();
il.append(InstructionFactory.createLoad(Type.INT, l));
il.append(new ICONST(1));
il.append(new IADD());
il.append((Instruction)factory.createNewArray(teamType, (short)1));
//this are very strange (but necessary!?) casts...
lg.setStart(il.append(InstructionFactory.createStore(teamArray, newTeams)));
// generated: Team[] newTeams = new Team[l+1];
lg = addTeamMethod.addLocalVariable("newTeamIDs", intArray, null, null);
int newTeamIDs = lg.getIndex();
il.append(InstructionFactory.createLoad(Type.INT, l));
il.append(new ICONST(1));
il.append(new IADD());
il.append((Instruction)factory.createNewArray(Type.INT, (short)1));
//this are very strange (but necessary!?) casts...
lg.setStart(il.append(InstructionFactory.createStore(intArray, newTeamIDs)));
// generated: int[] newTeamIDs = new int[l+1];
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ICONST(0));
il.append(InstructionFactory.createLoad(teamArray, newTeams));
il.append(new ICONST(1));
il.append(InstructionFactory.createLoad(Type.INT, l));
ObjectType object = new ObjectType("java.lang.Object");
il.append(factory.createInvoke("java.lang.System", "arraycopy",
Type.VOID,
new Type[] {object, Type.INT, object, Type.INT, Type.INT },
Constants.INVOKESTATIC));
// generated: System.arraycopy(_OT$activeTeams, 0, newTeams, 1, l);
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
il.append(new ICONST(0));
il.append(InstructionFactory.createLoad(intArray, newTeamIDs));
il.append(new ICONST(1));
il.append(InstructionFactory.createLoad(Type.INT, l));
il.append(factory.createInvoke("java.lang.System", "arraycopy",
Type.VOID,
new Type[] {object, Type.INT, object, Type.INT, Type.INT },
Constants.INVOKESTATIC));
// generated: System.arraycopy(_OT$activeTeamIDs, 0, newTeamIDs, 1, l);
il.append(InstructionFactory.createLoad(teamArray, newTeams));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC));
// generated: _OT$activeTeams = newTeams;
il.append(InstructionFactory.createLoad(intArray, newTeamIDs));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC));
// generated: _OT$activeTeamIDs = newTeamIDs;
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ICONST(0));
il.append(new ALOAD(0));
il.append(InstructionFactory.createArrayStore(teamType));
// generated: _OT$activeTeams[0] = team;
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
il.append(new ICONST(0));
il.append(new ILOAD(1));
il.append(InstructionFactory.createArrayStore(Type.INT));
// generated: _OT$activeTeamIDs[0] = teamID;
if (CallinBindingManager.isRole(class_name)) {
il.append(new ALOAD(0));
il.append(new ILOAD(1));
il.append(factory.createInvoke(class_name, "_OT$activateNotify", Type.VOID, new Type[] { teamType, Type.INT }, Constants.INVOKESTATIC));
// generated: _OT$activateNotify(team, teamID);
}
// No more access to array fields, release monitor:
InstructionHandle exitSequence =
il.append(InstructionFactory.createLoad(Type.OBJECT, monitor));
il.append(new MONITOREXIT());
earlyExit.setTarget(exitSequence);
il.append(InstructionFactory.createReturn(Type.VOID));
addTeamMethod.setMaxStack();
addTeamMethod.setMaxLocals();
addTeamMethod.removeNOPs();
return addTeamMethod;
}
/* Code to be generated:
public static void _OT$removeTeam(Team team)
{
int l;
if((l = _OT$activeTeams.length) == 0)
return;
boolean found = false;
int newLen= l-1;
Team newTeams[] = new Team[newLen];
int newTeamIDs[] = new int[newLen];
for(int i = 0; i < l; i++)
if(!found)
{
if(_OT$activeTeams[i] == team)
{
found = true;
} else if (i<newLen) { // coded as: jump if (newLen<=i)
{
newTeams[i] = _OT$activeTeams[i];
newTeamIDs[i] = _OT$activeTeamIDs[i];
}
} else
{
newTeams[i - 1] = _OT$activeTeams[i];
newTeamIDs[i - 1] = _OT$activeTeamIDs[i];
}
if(found)
{
_OT$activeTeams = newTeams;
_OT$activeTeamIDs = newTeamIDs;
}
}
*/
private MethodGen genRemoveTeam(String class_name, int major, ConstantPoolGen cpg)
{
LocalVariableGen lg;
InstructionList il;
int l;
BranchHandle emptyArray;
int newTeams;
int newTeamIDs;
il = new InstructionList();
MethodGen removeTeamMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNCHRONIZED,
Type.VOID,
new Type[] { teamType },
new String[] { "team" },
"_OT$removeTeam", class_name,
il, cpg);
// synchronized (BaseClass.class) {
int monitor = addClassMonitorEnter(removeTeamMethod, il, class_name, major, cpg).first;
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ARRAYLENGTH());
lg = removeTeamMethod.addLocalVariable("l", Type.INT, null, null);
//int l = lg.getIndex();
l = lg.getIndex();
il.append(new DUP());
lg.setStart(il.append(InstructionFactory.createStore(Type.INT, l)));
// generated: int l = _OT$activeTeams.length;
emptyArray = il.append(new IFNE(null));
GOTO earlyExit = new GOTO(null);
il.append(earlyExit);
emptyArray.setTarget(il.append(new NOP()));
// generated: if (l == 0) return;
lg = removeTeamMethod.addLocalVariable("found", Type.BOOLEAN, null, null);
int found = lg.getIndex();
il.append(new ICONST(0));
lg.setStart(il.append(InstructionFactory.createStore(Type.BOOLEAN, found)));
// generated: boolean found = false;
lg = removeTeamMethod.addLocalVariable("newTeams", teamArray, null, null);
newTeams = lg.getIndex();
il.append(InstructionFactory.createLoad(Type.INT, l));
// [SH]: variable newLen
LocalVariableGen lgNewLen= removeTeamMethod.addLocalVariable("newLen", Type.INT, il.getEnd(), null);
il.append(new ICONST(1));
il.append(new ISUB());
// [SH] store for later use:
il.append(new DUP());
il.append(InstructionFactory.createStore(Type.INT, lgNewLen.getIndex()));
// [HS] generated: "newLen= l-1;"
il.append((Instruction)factory.createNewArray(teamType, (short)1));
lg.setStart(il.append(InstructionFactory.createStore(teamArray, newTeams)));
// generated: Team[] newTeams = new Team[newLen];
lg = removeTeamMethod.addLocalVariable("newTeamIDs", intArray, null, null);
//int newTeamIDs = lg.getIndex();
newTeamIDs = lg.getIndex();
//[SH]:
il.append(InstructionFactory.createLoad(Type.INT, lgNewLen.getIndex()));
il.append((Instruction)factory.createNewArray(Type.INT, (short)1));
lg.setStart(il.append(InstructionFactory.createStore(intArray, newTeamIDs)));
// generated: int[] newTeamIDs = new int[newLen];
// start for-loop
lg = removeTeamMethod.addLocalVariable("i", Type.INT, null, null);
int loopCounter = lg.getIndex();
il.append(new ICONST(0));
lg.setStart(il.append(InstructionFactory.createStore(Type.INT, loopCounter)));
GOTO try_leave_loop = new GOTO(null);
il.append(try_leave_loop);
InstructionHandle i_lower_l = il.append(new NOP());
// loop body:
il.append(InstructionFactory.createLoad(Type.BOOLEAN, found));
IFNE already_found = new IFNE(null);
il.append(already_found);
// outer if part:
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ILOAD(loopCounter));
il.append(InstructionFactory.createArrayLoad(teamType));
il.append(new ALOAD(0)); //first parameter
IF_ACMPNE teams_not_equal = new IF_ACMPNE(null);
il.append(teams_not_equal);
// inner if part:
il.append(new ICONST(1));
il.append(InstructionFactory.createStore(Type.BOOLEAN, found));
GOTO skip_outer_else_part = new GOTO(null);
il.append(skip_outer_else_part);
// inner else part:
teams_not_equal.setTarget(il.append(new NOP()));
// [SH] sanity check:
il.append(InstructionFactory.createLoad(Type.INT, lgNewLen.getIndex()));
il.append(new ILOAD(loopCounter));
IF_ICMPLE if_len_le_i= new IF_ICMPLE(null);
il.append(if_len_le_i);
// [HS] generated: else if (!(newLen <= i)) {
il.append(new ALOAD(newTeams));
il.append(new ILOAD(loopCounter));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ILOAD(loopCounter));
il.append(InstructionFactory.createArrayLoad(teamType));
il.append(new AASTORE());
// generated: newTeams[i] = _OT$activeTeams[i];
il.append(new ALOAD(newTeamIDs));
il.append(new ILOAD(loopCounter));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
il.append(new ILOAD(loopCounter));
il.append(InstructionFactory.createArrayLoad(Type.INT));
il.append(new IASTORE());
// generated: newTeamIDs[i] = _OT$activeTeamIDs[i];
GOTO end_of_loop = new GOTO(null);
il.append(end_of_loop);
// outer else part:
already_found.setTarget(il.append(new NOP()));
il.append(new ALOAD(newTeams));
il.append(new ILOAD(loopCounter));
il.append(new ICONST(1));
il.append(new ISUB());
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
il.append(new ILOAD(loopCounter));
il.append(InstructionFactory.createArrayLoad(teamType));
il.append(new AASTORE());
// generated: newTeams[i-1] = _OT$activeTeams[i];
il.append(new ALOAD(newTeamIDs));
il.append(new ILOAD(loopCounter));
il.append(new ICONST(1));
il.append(new ISUB());
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
il.append(new ILOAD(loopCounter));
il.append(InstructionFactory.createArrayLoad(Type.INT));
il.append(new IASTORE());
// generated: newTeamIDs[i-1] = _OT$activeTeamIDs[i];
skip_outer_else_part.setTarget(il.append(new NOP()));
// [SH] connect "else if" from above:
if_len_le_i.setTarget(il.getEnd());
end_of_loop.setTarget(il.append(new IINC(loopCounter, 1)));
try_leave_loop.setTarget(il.append(InstructionFactory.createLoad(Type.INT, loopCounter)));
il.append(new ILOAD(l));
il.append(new IF_ICMPLT(i_lower_l));
// end for-loop
il.append(InstructionFactory.createLoad(Type.BOOLEAN, found));
BranchHandle notFound = il.append(new IFEQ(null));
// generated: if (found) {
il.append(InstructionFactory.createLoad(teamArray, newTeams));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC));
// generated: _OT$activeTeams = newTeams;
il.append(InstructionFactory.createLoad(intArray, newTeamIDs));
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC));
// generated: _OT$activeTeamIDs = newTeamIDs;
if (CallinBindingManager.isRole(class_name)) {
il.append(new ALOAD(0));
il.append(factory.createInvoke(class_name, "_OT$deactivateNotify", Type.VOID, new Type[] { teamType }, Constants.INVOKESTATIC));
// generated: _OT$deactivateNotify(team);
}
// No more access to array fields, release monitor:
InstructionHandle exitSequence =
il.append(InstructionFactory.createLoad(Type.OBJECT, monitor));
il.append(new MONITOREXIT());
earlyExit.setTarget(exitSequence);
notFound.setTarget(exitSequence);
il.append(InstructionFactory.createReturn(Type.VOID));
removeTeamMethod.setMaxStack();
removeTeamMethod.setMaxLocals();
removeTeamMethod.removeNOPs();
return removeTeamMethod;
}
/**
* Add infrastructure for implicit subclasses to register and be notified. This 'observer' mechanism
* is necessary, because an implicit subclass does not inherit the addition/removal
* of a team at the implicit superclass.
* @param ce The ClassEnhancer object to add methods and fields.
* @param cg The ClassGen object representing the current class.
*/
private void addImplicitSubclassNotificationInfrastructure(ClassEnhancer ce, ClassGen cg) {
ConstantPoolGen cpg = cg.getConstantPool();
factory = new InstructionFactory(cpg);
String class_name = cg.getClassName();
ObjectType linkedListType = new ObjectType("java.util.LinkedList");
int accessFlags = Constants.ACC_PROTECTED | Constants.ACC_STATIC;
FieldGen teamRegistrationObserversField = new FieldGen(accessFlags, linkedListType, "_OT$teamRegistrationObservers", cpg);
ce.addField(teamRegistrationObserversField.getField(), cg);
/***********************************************************************************************************/
InstructionList il = new InstructionList();
MethodGen observerRegistrationMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
Type.VOID,
new Type[] { classType },
new String[] { "implicitSubClass" },
"_OT$registerObserver", class_name,
il, cpg);
il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", linkedListType, Constants.GETSTATIC));
il.append(InstructionFactory.createLoad(classType, 0));
il.append(factory.createInvoke("java.util.LinkedList", "add", Type.BOOLEAN, new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL));
il.append(new POP());
il.append(new RETURN());
observerRegistrationMethod.setMaxStack(2);
observerRegistrationMethod.setMaxLocals();
ce.addMethod(observerRegistrationMethod.getMethod(), cg);
/***********************************************************************************************************/
il = new InstructionList();
MethodGen activateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
Type.VOID,
new Type[] { teamType, Type.INT },
new String[] { "team", "teamID" },
"_OT$activateNotify", class_name,
il, cpg);
createNotifyMethodImplementation(activateNotifyMethod, cpg, class_name);
ce.addMethod(activateNotifyMethod.getMethod(), cg);
/***********************************************************************************************************/
il = new InstructionList();
MethodGen deactivateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
Type.VOID,
new Type[] { teamType },
new String[] { "team" },
"_OT$deactivateNotify", class_name,
il, cpg);
createNotifyMethodImplementation(deactivateNotifyMethod, cpg, class_name);
ce.addMethod(deactivateNotifyMethod.getMethod(), cg);
}
/**
* Create implementation of methods '_OT$activateNotify' and _OT$deactivateNotify'.
* @param notifyMethod Method which has to be implemented.
* @param cpg Corresponding constant pool.
* @param class_name Name of the class for wich to implement the method.
*/
private void createNotifyMethodImplementation(MethodGen notifyMethod, ConstantPoolGen cpg, String class_name) {
boolean isActivateMethod = notifyMethod.getName().equals("_OT$activateNotify");
// int methodArgs = isActivateMethod ? 2 : 1;
int iteratorIdx = isActivateMethod ? 2 : 1;
int curClassIdx = isActivateMethod ? 3 : 2;
int anotherIdx1 = isActivateMethod ? 4 : 3;
int anotherIdx2 = isActivateMethod ? 5 : 4;
String methodToInvoke = isActivateMethod ? "_OT$addTeam" : "_OT$removeTeam";
InstructionList il = notifyMethod.getInstructionList();
il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC));
BranchInstruction ifnonnull_3 = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
il.append(ifnonnull_3);
il.append(InstructionFactory.createReturn(Type.VOID));
InstructionHandle ih_7 = il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC));
il.append(factory.createInvoke("java.util.LinkedList", "iterator", new ObjectType("java.util.Iterator"), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
il.append(InstructionFactory.createStore(Type.OBJECT,iteratorIdx));
InstructionHandle ih_14 = il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx));
il.append(factory.createInvoke("java.util.Iterator", "hasNext", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));
BranchInstruction ifeq_20 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
il.append(ifeq_20);
il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx));
il.append(factory.createInvoke("java.util.Iterator", "next", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEINTERFACE));
il.append(factory.createCheckCast(classType));
il.append(InstructionFactory.createStore(Type.OBJECT,curClassIdx));
il.append(InstructionConstants.ACONST_NULL);
il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1));
InstructionHandle ih_36 = il.append(InstructionFactory.createLoad(Type.OBJECT,curClassIdx));
il.append(new PUSH(cpg, methodToInvoke));
il.append(new PUSH(cpg,iteratorIdx));
il.append((Instruction)factory.createNewArray(classType, (short) 1));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cpg, 0));
il.append(new PUSH(cpg, OTConstants.teamName));
il.append(factory.createInvoke("java.lang.Class", "forName",
classType, new Type[] { Type.STRING },
Constants.INVOKESTATIC));
il.append(InstructionConstants.AASTORE);
if (isActivateMethod){ // add the integer argument:
il.append(InstructionConstants.DUP);
il.append(new PUSH(cpg, 1));
il.append(factory.createFieldAccess("java.lang.Integer", "TYPE", classType, Constants.GETSTATIC));
il.append(InstructionConstants.AASTORE);
}
il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"), new Type[] { Type.STRING, new ArrayType(classType, 1) }, Constants.INVOKEVIRTUAL));
InstructionHandle ih_76 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1));
BranchInstruction goto_78 = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
il.append(goto_78);
InstructionHandle ih_81 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
il.append(new PUSH(cpg, "activateNotifyMethod not found!"));
il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
InstructionHandle ih_91 = il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1));
BranchInstruction ifnull_93 = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
il.append(ifnull_93);
il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1));
il.append(InstructionConstants.ACONST_NULL);
il.append(new PUSH(cpg,iteratorIdx));
il.append((Instruction)factory.createNewArray(Type.OBJECT, (short) 1));
il.append(InstructionConstants.DUP);
il.append(new PUSH(cpg, 0));
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(InstructionConstants.AASTORE);
if (isActivateMethod) { // load the integer argument:
il.append(InstructionConstants.DUP);
il.append(new PUSH(cpg, 1));
il.append(factory.createNew("java.lang.Integer"));
il.append(InstructionConstants.DUP);
il.append(InstructionFactory.createLoad(Type.INT, 1));
il.append(factory.createInvoke("java.lang.Integer", Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[] { Type.INT }, Constants.INVOKESPECIAL));
il.append(InstructionConstants.AASTORE);
}
il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Constants.INVOKEVIRTUAL));
InstructionHandle ih_121 = il.append(InstructionConstants.POP);
InstructionHandle ih_122;
BranchInstruction goto_122 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
ih_122 = il.append(goto_122);
InstructionHandle ih_125 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
il.append(new PUSH(cpg, "Can not call activateNotifyMethod!"));
il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
BranchInstruction goto_135 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
il.append(goto_135);
InstructionHandle ih_138 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
il.append(new PUSH(cpg, "InvocationTargetException"));
il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
BranchInstruction goto_148 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
il.append(goto_148);
InstructionHandle ih_151 = il.append(InstructionFactory.createReturn(Type.VOID));
ifnonnull_3.setTarget(ih_7);
ifeq_20.setTarget(ih_151);
goto_78.setTarget(ih_91);
ifnull_93.setTarget(ih_122);
notifyMethod.addExceptionHandler(ih_36, ih_76, ih_81, new ObjectType("java.lang.NoSuchMethodException"));
notifyMethod.addExceptionHandler(ih_91, ih_121, ih_125, new ObjectType("java.lang.IllegalAccessException"));
notifyMethod.addExceptionHandler(ih_91, ih_121, ih_138, new ObjectType("java.lang.reflect.InvocationTargetException"));
notifyMethod.setMaxStack();
notifyMethod.setMaxLocals();
}
/**
* Adds initialization of the team array and the team index array to the static initializer of this class.
* If this base class is a role at the same time, then also add initialization of the observer list.
* @param cg The representation of the class.
* @param cpg The constant pool of the class.
*/
private void addStaticInitializations(ClassGen cg, ConstantPoolGen cpg) {
Method clinitMethod = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V");
/* The clinit method always exists at this moment, because it has been added
* by the interface transformer part of this transformer if necessary.
*/
MethodGen mg = newMethodGen(clinitMethod, cg.getClassName(), cpg);
InstructionList il = mg.getInstructionList();
// add static initialization for added static fields at start of the <clinit> method:
il.insert(inizializeStaticFields(cg.getClassName()));
mg.setMaxStack();
mg.setMaxLocals();
Method newClinit = mg.getMethod();
cg.replaceMethod(clinitMethod, newClinit);
il.dispose();
// Reuse instruction handles
}
/**
* @param class_name
* @return
*/
private InstructionList inizializeStaticFields(String class_name) {
// STATIC_PARTS_TODO : in base: static initialization of team fields
InstructionList il = new InstructionList();
il.append(new ICONST(0));
il.append((Instruction)factory.createNewArray(teamType, (short)1));
//this are very strange (but necessary!?) casts...
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC));
//generated: _OT$activeTeams = new Team[0];
il.append(new ICONST(0));
il.append((Instruction)factory.createNewArray(Type.INT, (short)1));
//this are very strange (but necessary!?) casts...
il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC));
//generated: _OT$activeTeamIDs = new int[0];
if (CallinBindingManager.isRole(class_name)) {
ObjectType linkedListType = new ObjectType("java.util.LinkedList");
il.append(factory.createNew(linkedListType));
il.append(new DUP());
il.append(factory.createInvoke("java.util.LinkedList",
Constants.CONSTRUCTOR_NAME,
Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(factory.createFieldAccess(class_name,
"_OT$teamRegistrationObservers",
linkedListType, Constants.PUTSTATIC ));
//generated: _OT$teamRegistrationObservers = new LinkedList();
}
return il;
}
}