mark initial contribution OTRE as of CQ 3786
diff --git a/OTRE/OTRE/.classpath b/OTRE/OTRE/.classpath
new file mode 100644
index 0000000..b98640e
--- /dev/null
+++ b/OTRE/OTRE/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/bcel4-4-1"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/OTRE/OTRE/.project b/OTRE/OTRE/.project
new file mode 100644
index 0000000..9f6b831
--- /dev/null
+++ b/OTRE/OTRE/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>OTRE</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/OTRE/OTRE/.settings/org.eclipse.jdt.core.prefs b/OTRE/OTRE/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..1aa7124
--- /dev/null
+++ b/OTRE/OTRE/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,70 @@
+#Thu Sep 18 21:57:35 CEST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/OTRE/OTRE/MANIFEST.MF b/OTRE/OTRE/MANIFEST.MF
new file mode 100644
index 0000000..c759b23
--- /dev/null
+++ b/OTRE/OTRE/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0

+Premain-Class: org.eclipse.objectteams.otre.jplis.otreAgent

+Can-Redefine-Classes: true

+Built-By: resix

+

diff --git a/OTRE/OTRE/about.html b/OTRE/OTRE/about.html
new file mode 100644
index 0000000..47048bd
--- /dev/null
+++ b/OTRE/OTRE/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>Feb 3, 2010</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/OTRE/OTRE/otre-src-jar.jardesc b/OTRE/OTRE/otre-src-jar.jardesc
new file mode 100644
index 0000000..7556776
--- /dev/null
+++ b/OTRE/OTRE/otre-src-jar.jardesc
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jardesc>
+    <jar path="org.eclipse.objectteams.runtime/lib/otre.jar"/>
+    <options buildIfNeeded="true" compress="true" descriptionLocation="/OTRE/otre-src-jar.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+    <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+    <selectedProjects/>
+    <manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+        <sealing sealJar="false">
+            <packagesToSeal/>
+            <packagesToUnSeal/>
+        </sealing>
+    </manifest>
+    <selectedElements exportClassFiles="false" exportJavaFiles="true" exportOutputFolder="true">
+        <javaElement handleIdentifier="=OTRE/src"/>
+    </selectedElements>
+</jardesc>
diff --git a/OTRE/OTRE/otre_agent.jardesc b/OTRE/OTRE/otre_agent.jardesc
new file mode 100644
index 0000000..cf1515f
--- /dev/null
+++ b/OTRE/OTRE/otre_agent.jardesc
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jardesc>
+    <jar path="org.eclipse.objectteams.otdt/lib/otre_agent.jar"/>
+    <options overwrite="false" compress="true" exportErrors="false" exportWarnings="true" saveDescription="true" descriptionLocation="/OTRE/otre_agent.jardesc" useSourceFolders="false" buildIfNeeded="true"/>
+    <manifest manifestVersion="1.0" usesManifest="true" reuseManifest="false" saveManifest="false" generateManifest="false" manifestLocation="/OTRE/MANIFEST.MF">
+        <sealing sealJar="false">
+            <packagesToSeal/>
+            <packagesToUnSeal/>
+        </sealing>
+    </manifest>
+    <selectedElements exportClassFiles="true" exportOutputFolder="false" exportJavaFiles="false">
+        <javaElement handleIdentifier="=OTRE/src&lt;org.eclipse.objectteams.otre.jplis{otreAgent.java"/>
+    </selectedElements>
+</jardesc>
diff --git a/OTRE/OTRE/otre_min.jardesc b/OTRE/OTRE/otre_min.jardesc
new file mode 100644
index 0000000..73086e6
--- /dev/null
+++ b/OTRE/OTRE/otre_min.jardesc
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jardesc>
+    <jar path="org.objectteams.otdt/lib/otre_min.jar"/>
+    <options buildIfNeeded="true" compress="true" descriptionLocation="/OTRE/otre_min.jardesc" exportErrors="false" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
+    <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
+    <selectedProjects/>
+    <manifest generateManifest="false" manifestLocation="/OTRE/MANIFEST.MF" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
+        <sealing sealJar="false">
+            <packagesToSeal/>
+            <packagesToUnSeal/>
+        </sealing>
+    </manifest>
+    <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
+        <javaElement handleIdentifier="=OTRE/src&lt;org.objectteams"/>
+    </selectedElements>
+</jardesc>
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
new file mode 100644
index 0000000..567a422
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
@@ -0,0 +1,1446 @@
+/**********************************************************************
+ * 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: BaseCallRedirection.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 de.fub.bytecode.classfile.*;
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.util.*;
+
+/**
+ * for callin-role-methods with recursive method-calls (base calls) we add a
+ * method with extendend signature.
+ * Within the extendend method recursive calls are replaced by the corresponding
+ * (chaining)base-call.<p>
+ * For example:
+ * <pre>
+ *      callin m1() { m1(); } -->
+ *      callin m1(Team _OT$teams[], int _OT$teamIDs[],
+ *                int _OT$idx, int _OT$baseMethTag){
+ *          liftToRole(b1._OT$m1$chain(Team _OT$teams[],
+ *                                     int _OT$teamIDs[],
+ *                                     int _OT$idx,
+ *                                     int _OT$baseMethTag));
+ *      }
+ * </pre>
+ *
+ * @version $Id: BaseCallRedirection.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author  Christine Hundt
+ * @author Stephan Herrmann
+ */
+public class BaseCallRedirection extends ObjectTeamsTransformation {
+
+    static class IHPair {
+		private InstructionHandle _ih1, _ih2;
+		public IHPair (InstructionHandle ih1, InstructionHandle ih2) {
+			_ih1 = ih1;
+			_ih2 = ih2;
+		}
+		public InstructionHandle fst() {return _ih1; }
+		public InstructionHandle snd() {return _ih2; }
+	}
+
+	public BaseCallRedirection(SharedState state) { this(null, state); }
+    public BaseCallRedirection(ClassLoader loader, SharedState state) {
+    	super(loader, state);
+    }
+    
+    /**
+     * @param ce
+     * @param cg
+     */
+    public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+    	factory = new InstructionFactory(cg);
+    	String class_name = cg.getClassName();
+
+    	if (state.interfaceTransformedClasses.contains(class_name)) {
+    		return; //already transformed!
+    	}
+
+        ConstantPoolGen cpg = cg.getConstantPool();
+    	checkReadClassAttributes(ce, cg, class_name, cpg);
+            
+    	if (!CallinBindingManager.isRole(class_name)) {
+    		return;
+    	}
+						
+    	if (!cg.isInterface()) {
+	    	Set<String> boundBaseMethods = CallinBindingManager.getBoundRoleMethods(class_name);    	
+	    	addBaseCallSurrogatesForReplaceBindings(ce, boundBaseMethods, cg);
+    	}
+
+    	Method[] methods = cg.getMethods();
+    	for (int i=0; i<methods.length; i++) {
+    		Method m = methods[i];
+    		String method_name  = m.getName();
+    		String method_signature = m.getSignature();
+            
+    		if (candidateForImplicitActivation(m, cg, cpg)) { // TODO: check the other preconditions, like not abstact etc. 
+    			cg.replaceMethod(m, genImplicitActivation(m, class_name, cpg, true));
+    		}
+    		
+    		if (!isCallin(m, cg))
+    			continue;
+            if (logging) printLogMessage(method_name + " in " + class_name
+                        + " IS A CALLIN-METHOD!");
+    		if (method_name.startsWith(OT_PREFIX)) {
+    			method_name = revertToOriginalName(method_name);
+    			if (logging) printLogMessage("Reverted tsuper name to " + method_name);
+    		}
+    		// code SHOULD contain at least one base call.
+            if(logging) printLogMessage("----->will add another method " + method_name
+    						+ " with enhanced signature");
+             
+//{SH: retrench signature because otherwise the binding will not be found,
+//     as a result an empty basecall surrogate will be generated leading to repetetive methods...
+//     TODO(SH) is this the proper way to retrench??
+			String enhancedPrefix = "([Lorg/objectteams/Team;[IIII[Ljava/lang/Object;";
+			if (method_signature.startsWith(enhancedPrefix)) 
+    			method_signature = "("+method_signature.substring(enhancedPrefix.length());
+// SH}    		
+    		
+    		boolean roleMethodIsBound = CallinBindingManager.roleMethodHasBinding(class_name, 
+    																	   method_name,
+																		   method_signature);
+
+    		//if (mbs.isEmpty()) {
+    		if (!roleMethodIsBound) {
+    			if (logging) printLogMessage("callin method " + method_name
+    						+ " was not bound in this class!!!");
+    		}
+    		MethodGen baseCallSurrogate = null;
+    		if (!IS_COMPILER_13X_PLUS) { // since 1.3.0 this part is legacy:
+	    		if (!roleMethodIsBound && !methodHasCallinFlags(m, cg, OVERRIDING) && !m.isStatic()) {
+	    			// method not bound in current class and doesn't inherit a base call surrogate
+	    			baseCallSurrogate = generateEmptyBaseCallSurrogate(cg, m);
+	    		}
+	    		if (baseCallSurrogate != null)
+	    			ce.addMethod(baseCallSurrogate.getMethod(), cg);
+    		}
+    		
+    	}
+    	state.interfaceTransformedClasses.add(class_name);
+    }
+
+	/**
+	 *  Generates an "empty" base call surrogate method, which just throws an 'Error'.
+	 *  This method should normaly never be called, but overwritten in a subclass. 
+	 *  It has to be generated just for the wellformedness of the class file.
+	 * @param cg
+	 * @param m
+	 * @param mbs
+	 * @param baseClassName
+	 * @return
+	 */
+	private MethodGen generateEmptyBaseCallSurrogate(ClassGen cg, Method m/*, List mbs*/) {
+		if (m.getName().startsWith(OT_PREFIX))
+			return null; // ot-internal methods don't need this?
+
+		ConstantPoolGen cpg = cg.getConstantPool();
+		String class_name = cg.getClassName();
+		MethodGen mg = new MethodGen(m, class_name, cpg);
+		
+		if (isTSuperWrapper(mg)) {
+			// tsuper wrapper do not need base call surrogates
+			return null;
+		}
+		
+		// role method already was enhanced by compiler
+		Type[] enhancedArgumentTypes = mg.getArgumentTypes();
+		if (IS_COMPILER_GREATER_123) {
+			// add super flag between enhancement and real arguments:
+			int len = enhancedArgumentTypes.length;
+			Type[] newArgumentTypes = new Type[len+1];
+			System.arraycopy(enhancedArgumentTypes, 0, newArgumentTypes, 0, EXTRA_ARGS);
+			newArgumentTypes[EXTRA_ARGS] = Type.BOOLEAN;
+			System.arraycopy(enhancedArgumentTypes, EXTRA_ARGS, newArgumentTypes, EXTRA_ARGS+1, len-EXTRA_ARGS);
+			enhancedArgumentTypes = newArgumentTypes;
+		}
+		Type   enhancedReturnType    = mg.getReturnType();
+		
+// {SH: interface method has no argument names? generate dummy names: 
+		String[] argumentNames = new String[enhancedArgumentTypes.length];
+		for (int i = 0; i < argumentNames.length; i++) {
+			argumentNames[i] = "arg"+i;
+		}
+			
+		// role method already was enhanced by compiler:
+		String[] enhancedArgumentNames = argumentNames;
+// }	
+		InstructionList il = new InstructionList();
+		//int accessFlags = m.getAccessFlags();
+		int accessFlags = Constants.ACC_PROTECTED; // no unanticipated calls possible
+
+// {SH: interface methods must be public abstract:
+		if (cg.isInterface()) 
+			accessFlags = Constants.ACC_ABSTRACT|Constants.ACC_PUBLIC;
+// }
+		
+		MethodGen baseCallSurrogate = new MethodGen(accessFlags,
+													enhancedReturnType,
+													enhancedArgumentTypes,
+													enhancedArgumentNames,
+													getBaseCallSurrogateName(m.getName(), m.isStatic(), class_name /*genRoleInterfaceName(class_name)*/), 
+													class_name,
+													il, cpg);
+// {SH: no code for interface method:
+		if (!cg.isInterface()) {
+			// orig:
+			if (logging)
+				printLogMessage("Exception has to be thrown!");
+
+			createThrowInternalError(cpg, il, new InstructionList(new PUSH(cpg, "Binding-Error: base-call impossible!")));
+
+			il.append(InstructionFactory.createNull(enhancedReturnType));
+			il.append(InstructionFactory.createReturn(enhancedReturnType));
+
+			if (debugging)
+				baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER);
+		}
+// }
+
+		il.setPositions();
+		baseCallSurrogate.removeNOPs();
+		baseCallSurrogate.setMaxStack();
+		baseCallSurrogate.setMaxLocals();
+		return baseCallSurrogate;		
+	}
+
+	/**
+	 * @param mg
+	 * @return
+	 */
+	private static boolean isTSuperWrapper(MethodGen mg) {
+		Type[] argTypes = mg.getArgumentTypes();
+		if (argTypes.length == 0) {
+			return false; // no tsuper marker interface argument existing 
+		}
+		String lastArgument = (argTypes[argTypes.length - 1]).toString();
+		return lastArgument.contains(OTDT_PREFIX);
+	}
+
+	/**
+	 * Adds base call surrogate method for all role method bindings in the current role class.
+	 * Thereby method bindings which are defined in super roles are accumulated and 
+	 * considered as well. 
+	 * @param ce				the ClassEnhancer to which the new method has to be added
+	 * @param boundRoleMethods	the bound methods of the role class
+	 * @param cg 				the ClassGen for the role class
+	 */
+	private void addBaseCallSurrogatesForReplaceBindings(ClassEnhancer ce, Set<String> boundRoleMethods, ClassGen cg)
+	{
+		Iterator<String> it = boundRoleMethods.iterator();
+		while (it.hasNext()) {
+			String nameAndSignature = it.next();
+			int dotIndex = nameAndSignature.indexOf('.');
+			String methodName = nameAndSignature.substring(0, dotIndex);
+			String methodSignature = nameAndSignature.substring(dotIndex + 1);
+			List<MethodBinding> mbs = CallinBindingManager.getBindingsForRoleMethod(cg.getClassName(), 
+																	 methodName, 
+																	 methodSignature);
+			MethodBinding anyMethodBinding = mbs.get(0);
+			if (!anyMethodBinding.isReplace()) {
+				continue; 
+			}
+			mbs.addAll(CallinBindingManager.getInheritedRoleMethodBindings(cg.getClassName(),
+																		   methodName,
+																		   methodSignature));
+			
+			if (anyMethodBinding.hasStaticRoleMethod())
+				continue; // base call surrogates for static methods are generated within the enclosing team class
+			// TODO: remove this check as soon as static replace method bindings are no longer in 'CallinMethodMappings'
+			MethodGen baseCallSurrogate = genBaseCallSurrogate(cg, mbs);
+			ce.addOrReplaceMethod(baseCallSurrogate.getMethod(), cg);
+		}
+	}
+
+	/**
+	 * Generates base call surrogate method for the role method for which the method bindings 'mbs' are.
+	 * Thereby a switch-case for each bound base method is generated.
+	 * This method is only for nonstatic role methods. Base call surrogates for static methods 
+	 * are generated within the enclosing team class
+	 * @param cg			the ClassGen for the role class	
+	 * @param mbs			the method bindings for one role method
+	 * @param baseClassName	the name of the base class
+	 */
+	MethodGen genBaseCallSurrogate(ClassGen cg, List<MethodBinding> mbs) {
+		
+		//baseClassName would not be needed here, if I could find out the root-base-class-type...
+		ConstantPoolGen cpg = cg.getConstantPool();
+		String class_name = cg.getClassName();
+
+		MethodBinding anyBindingForRoleMethod = mbs.get(0);
+		String baseClassName = anyBindingForRoleMethod.getRootBoundBase();
+		String roleMethodSignature = anyBindingForRoleMethod.getRoleMethodSignature();
+
+		Type[] enhancedArgumentTypes;
+		{
+			Type[] argTypesTail = Type.getArgumentTypes(roleMethodSignature);
+			if (IS_COMPILER_GREATER_123) {
+				// add super flag between enhancement and real arguments:
+				int len = argTypesTail.length;
+				System.arraycopy(argTypesTail, 0, argTypesTail=new Type[len+1], 1, len);
+				argTypesTail[0] = Type.BOOLEAN;
+			}
+			enhancedArgumentTypes = enhanceArgumentTypes(argTypesTail);
+		}
+		Type enhancedReturnType = generalizeReturnType(Type.getReturnType(roleMethodSignature));
+		String methodName = anyBindingForRoleMethod.getRoleMethodName();
+		InstructionList il = new InstructionList();
+		int accessFlags = Constants.ACC_PROTECTED;
+
+		MethodGen baseCallSurrogate = new MethodGen(accessFlags,
+													enhancedReturnType,
+													enhancedArgumentTypes,
+													null, // no explicit names
+													getBaseCallSurrogateName(methodName, false, 
+																			 genRoleInterfaceName(class_name)), 
+													class_name,
+													il, cpg);
+
+		ObjectType baseClass = new ObjectType(baseClassName);
+		ObjectType outerClass;
+		{
+			String outerClassName = getOuterClassName(class_name);
+			outerClass = new ObjectType(outerClassName);
+		}
+			
+		LocalVariableGen otResult = null;
+		
+		otResult = baseCallSurrogate.addLocalVariable("_OT$result",
+				enhancedReturnType, null, null);
+
+		il.insert(InstructionFactory.createStore(enhancedReturnType,
+				otResult.getIndex()));
+		il.insert(new ACONST_NULL());
+		il.setPositions(); // about to retrieve instruction handles.
+		
+		if (logging) printLogMessage("base-call switch has to be inserted!");	
+		InstructionList loading = new InstructionList();
+		loading.append(InstructionFactory.createThis());
+		int index = 1;
+		for (int i = 0; i < enhancedArgumentTypes.length; i++) {
+			loading.append(InstructionFactory.createLoad(enhancedArgumentTypes[i],index));
+			index += enhancedArgumentTypes[i].getSize();
+		}
+		
+		Type[] argumentTypes = Type.getArgumentTypes(roleMethodSignature);
+		Type returnType = Type.getReturnType(roleMethodSignature);
+		
+		if (debugging) {
+			baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER);
+		}
+		
+		boolean generateSuperAccess = false;
+		List<SuperMethodDescriptor> superAccesses = IS_COMPILER_GREATER_123 ? CallinBindingManager.getSuperAccesses(baseClassName) : null;
+		if (superAccesses != null) {
+			outer: for (SuperMethodDescriptor superMethod : superAccesses) {
+				for (MethodBinding methodBinding : mbs) {
+					if (   superMethod.methodName.equals(methodBinding.getBaseMethodName())
+						&& superMethod.signature.equals(methodBinding.getBaseMethodSignature())) 
+					{
+						generateSuperAccess = true; 
+						break outer;
+					}
+				}
+			}
+		}
+
+		BranchInstruction ifSuper = new IFEQ(null);
+		GotoInstruction skipElse  = new GOTO(null);
+		if (generateSuperAccess) {
+			// gen: if (isSuperAccess) { _OT$base._OT$m$super(args); } else ...
+			il.append(InstructionFactory.createLoad(Type.BOOLEAN, EXTRA_ARGS+1)); // last synthetic arg is super-flag
+			il.append(ifSuper);
+			il.append(genBaseCallSwitch(cpg, mbs, baseCallSurrogate,
+										 argumentTypes,
+										 outerClass, baseClass,
+										 returnType, 
+										 otResult, loading, true));
+			il.append(skipElse);
+		}
+		InstructionList 
+		basecall = genBaseCallSwitch(cpg, mbs, baseCallSurrogate,
+									 argumentTypes,
+									 outerClass, baseClass,
+									 returnType,
+									 otResult, loading, false);
+		InstructionHandle callStart = basecall.getStart(); // store handle before append eats the list
+		il.append(basecall);
+		if (generateSuperAccess) {
+			ifSuper.setTarget(callStart);
+			skipElse.setTarget(il.append(new NOP()));
+		}
+		
+		il.append(InstructionFactory.createLoad(enhancedReturnType, otResult.getIndex()));
+		il.append(InstructionFactory.createReturn(enhancedReturnType));							
+		
+		il.setPositions();
+		baseCallSurrogate.removeNOPs();
+		baseCallSurrogate.setMaxStack();
+		baseCallSurrogate.setMaxLocals();
+		return baseCallSurrogate;		
+	}
+
+/*
+    Type findBaseFieldType(JavaClass c, ConstantPoolGen cpg) {
+           Field[] fields = c.getFields();
+            for (int l=0; l<fields.length; l++) {
+                Field f = fields[l];
+                if (f.getName().equals(BASE)) {
+                    FieldGen fg = new FieldGen(f, cpg);
+                    return fg.getType();
+                }
+            }
+			JavaClass superClass = Repository.lookupClass(c.getSuperclassName());
+			// BCEL bug: super class of "Object" is "Object":
+			//System.err.println("Superclass of "+ c.getClassName()+" is " +c.getSuperclassName());
+			if (!superClass.getClassName().equals("java.lang.Object")) {
+					return findBaseFieldType(superClass, cpg);
+			}
+            return null;
+    }*/
+
+    /**
+	 * Iterate through the instructions of a callin method.
+	 * <ul>
+	 *   <li>Adjust local variable instructions due to inserted extra arguments.
+	 *   <li>Replace base-calls and calls to activate.
+	 * </ul>
+	 * @param cg
+	 * @param m
+	 * @param mbs List<MethodBinding>
+	 * @return MethodGen
+	 */
+    MethodGen replaceBaseCalls(ClassGen cg, Method m, List<MethodBinding> mbs) {
+
+    	int indexOffset = m.isStatic() ? -1 : 0; // argument indices are decremented for static methods, 
+												 // because of the missing 'this'
+        
+    	ConstantPoolGen cpg = cg.getConstantPool();
+        String class_name   = cg.getClassName();
+        String method_name  = m.getName();
+
+        MethodGen mg = new MethodGen(m, class_name, cpg);
+
+		Type[]   argumentTypes         = mg.getArgumentTypes();
+        Type     returnType            = mg.getReturnType();
+       
+        Type[] enhancedArgumentTypes = enhanceArgumentTypes(mg.getArgumentTypes());
+// {SH abstract methods may not have argument names??        
+        String[] argumentNames;
+        if (m.isAbstract()) {
+        	argumentNames = new String[argumentTypes.length];
+			int index = 0;
+        	for (int i = 0; i < argumentNames.length; i++) {
+				argumentNames[i] = "arg" + index/* i */;
+				index += argumentTypes[i].getSize();
+			}
+			
+/*			
+//			load regular arguments:
+				 int index = 1;
+				 for (int i=0; i<argTypes.length; i++) {
+					 il.append(InstructionFactory.createLoad(argTypes[i],index));
+					 index += argTypes[i].getSize();
+				 }
+//*/
+			
+        } else {
+        	argumentNames = mg.getArgumentNames();
+        }
+        String[] enhancedArgumentNames = enhanceArgumentNames(argumentNames);
+// orig:        String[] enhancedArgumentNames = enhanceArgumentNames(mg.getArgumentNames());
+// SH}       
+
+        Type enhancedMethodReturnType  = generalizeReturnType(m.getSignature());
+
+// {SH instruction list may be null for abstract method		
+// orig:   InstructionList il = mg.getInstructionList().copy();
+		InstructionList il = mg.getInstructionList();
+		if (il != null)
+			il = il.copy();
+		else
+			il = new InstructionList();
+// SH}		
+
+        MethodGen enhancedMethod = new MethodGen(m.getAccessFlags(),
+                                                 enhancedMethodReturnType,
+                                                 enhancedArgumentTypes,
+                                                 enhancedArgumentNames,
+                                                 method_name, class_name,
+                                                 il, cpg);
+		//not needed??:
+		// or not??????
+		copyLocalVariables(mg, enhancedMethod);
+		copyLineNumbers(mg, enhancedMethod);
+		
+        boolean returnValueAdded   =    (returnType               == Type.VOID)
+                                     && (enhancedMethodReturnType != Type.VOID);
+
+		// all exception handlers of this method, which have to be updated later.
+		CodeExceptionGen [] handlers = copyExceptionHandlers(mg, enhancedMethod, il);
+		// list of instruction handles (old and new) that are replaced in the sequel
+		ArrayList<IHPair> replacedInstructions = new ArrayList<IHPair>(); // of IHPair;
+		// set of instruction handles which signal TargetLostException during delete().
+		HashSet<InstructionHandle> targetLost = new HashSet<InstructionHandle>(); // of InstructionHandle
+
+        // create  LocalVariable Object _OT$result:
+        LocalVariableGen otResult = null;
+        
+        int slot = mg.getMaxLocals() + EXTRA_ARGS-indexOffset;
+        otResult = enhancedMethod.addLocalVariable("_OT$result", enhancedMethodReturnType,
+												   slot, null, null);
+        
+        // subtract EXTRA_ARGS since this offset will be added again below.
+        il.insert(InstructionFactory.createStore(enhancedMethodReturnType,
+        							    		 otResult.getIndex() - EXTRA_ARGS));
+
+        il.insert(new ACONST_NULL());
+        il.setPositions(); // about to retrieve instruction handles.
+
+        InstructionHandle[] ihs = il.getInstructionHandles();
+        //printLogMessage("every call of base." + method_name + "(...) will be replaced by "
+        //            + liftMethodName + BASE + "."+baseChainMethodName+"(...))");
+
+        int actInstruction = 0;
+        int offset = EXTRA_ARGS;
+        while (actInstruction < ihs.length) {
+			Instruction act_instruction = ihs[actInstruction].getInstruction();
+/****************************** variable index adaption: **********************************/
+   			if(act_instruction instanceof LocalVariableInstruction) {
+            // add offset to the index of every variable load or store instruction,
+			// because of the inserted EXTRA_ARGS  arguments:
+                LocalVariableInstruction localVariableInstruction = (LocalVariableInstruction) act_instruction;
+                if (localVariableInstruction.getIndex() != 0 || (enhancedMethod.isStatic())) { // 'this' stays at index 0
+                    if (localVariableInstruction instanceof StoreInstruction) {
+                        localVariableInstruction =
+							InstructionFactory.createStore(localVariableInstruction.getType(cpg),
+														   offset+localVariableInstruction.getIndex());
+                    } else if (localVariableInstruction instanceof LoadInstruction) {
+                        localVariableInstruction =
+							InstructionFactory.createLoad(localVariableInstruction.getType(cpg),
+											   			  offset+localVariableInstruction.getIndex());
+                    } else if (localVariableInstruction instanceof IINC) {
+                    	localVariableInstruction.setIndex(offset+localVariableInstruction.getIndex());
+                    	// TODO: check, if this is enough for all kinds of LocalVariableInstructions 
+                    	//               and if there are more instructions which use variable indizes!!
+                    }
+                    ihs[actInstruction].setInstruction(localVariableInstruction);
+                }
+            } else if (act_instruction instanceof RET) {
+                RET ret = (RET)act_instruction;
+                if (ret.getIndex() != 0)
+                    ihs[actInstruction].setInstruction(new RET(offset + ret.getIndex()));
+
+/*************************** "super"- & "tsuper"-call enhancement: **********************************/
+   			} else if (super_or_tsuper_instruction(act_instruction, method_name, cpg) ) {
+
+				InvokeInstruction ii = (InvokeInstruction)act_instruction;
+				InstructionHandle next = ihs[actInstruction+1];
+				InstructionList changedArea;
+				InstructionHandle[] delim = new InstructionHandle[2];
+				int stackDepth = computeArgumentStackDepth(cpg, ii);
+				InstructionList loading = pruneLoading(il, ihs, actInstruction,
+													   stackDepth, cpg,
+													   targetLost, delim, true);
+				if (loading == null) {
+					actInstruction++;
+					continue;
+				}
+				 
+				changedArea = genEnhancedSuperCall(cpg, ii, enhancedMethod, loading);
+				if (returnValueAdded) {
+                    changedArea.append(InstructionFactory.createStore(
+                            enhancedMethodReturnType, otResult.getIndex()));
+                } else {
+					InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType);
+					if (debugging && ih != null)
+						mg.addLineNumber(ih, STEP_OVER_LINENUMBER);
+				}
+				replacedInstructions.add(new IHPair(delim[0], changedArea.getStart()));
+				replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd()));
+
+				il.insert(next, changedArea);
+				actInstruction++;
+				continue;
+				
+/*************************** "activate" substitution and base-call generation: ************/
+            //} else if (act_instruction instanceof INVOKEVIRTUAL) {
+            //    INVOKEVIRTUAL iv = (INVOKEVIRTUAL)act_instruction;
+			} else if (act_instruction instanceof InvokeInstruction) {
+				InvokeInstruction iv = (InvokeInstruction)act_instruction;
+                String iv_name = iv.getName(cpg);
+
+                // FIXME(SH): is this still needed? 
+                //            - activate is commented-out,
+                //            - base call is now generated by the compiler.
+                if(!(iv_name.equals(method_name) ||
+                     iv_name.equals("activate")))
+				{
+                    actInstruction++;
+                    continue;
+                }
+                InstructionHandle next = ihs[actInstruction+1];
+                InstructionList changedArea;
+				InstructionHandle[] delim = new InstructionHandle[2];
+               /*
+                if (iv_name.equals("activate")) {
+					// blank original invokevirtual:
+					ihs[actInstruction].setInstruction(new NOP());
+					Type [] ivArgTypes = iv.getArgumentTypes(cpg);
+					int activateArgCount = ivArgTypes.length;
+					InstructionList loading = null;
+					if (activateArgCount == 1)
+						loading = pruneLoading (il, ihs, actInstruction,
+												ivArgTypes[0].getSize(), cpg,
+												targetLost, delim, false);
+					changedArea = enhanceActivateCall(factory, cpg, loading, iv);
+					if (activateArgCount == 1) {
+						replacedInstructions.add(new IHPair(delim[0],
+															changedArea.getStart()));
+						replacedInstructions.add(new IHPair(delim[1],
+															changedArea.getEnd()));
+					}
+                } else*/ { // base call:
+                    int            stackDepth = computeArgumentStackDepth(cpg, iv);
+                    boolean deleteThis = true;
+                   
+                    if(enhancedMethod.isStatic())
+                    	deleteThis = false;
+                    
+                    /*
+                    if (iv.getOpcode()==Constants.INVOKESTATIC) 
+                    	deleteThis = false; 
+                    */
+                    InstructionList   loading = pruneLoading(il, ihs, actInstruction,
+															 stackDepth, cpg,
+															 targetLost, delim, /*true*/deleteThis);
+					//System.err.println(loading);
+					if (loading == null) {
+						actInstruction++;
+						continue;
+					}
+
+					// insert call of base-call surrogate method:
+					String roleInterfaceName = genRoleInterfaceName(cg.getClassName());
+					
+					String calleeClassName = null;
+					if(m.isStatic()) {
+						calleeClassName = extractTeamName(roleInterfaceName);
+					}
+					changedArea = genBaseCallSurrogateCall(cpg, iv, enhancedMethod, loading, extractRoleName(roleInterfaceName), calleeClassName);
+
+					if (returnValueAdded) {
+						changedArea.append(InstructionFactory.createStore(enhancedMethodReturnType,
+																		 otResult.getIndex()));				
+                	} else {
+						InstructionHandle ih = adjustValue(changedArea, changedArea.getEnd(), enhancedMethodReturnType, returnType);
+						if (debugging && ih != null)
+							mg.addLineNumber(ih, STEP_OVER_LINENUMBER);
+                	}
+                    replacedInstructions.add(new IHPair(delim[0], changedArea.getStart()));
+                    replacedInstructions.add(new IHPair(delim[1], changedArea.getEnd()));
+
+				} // if (activate or base call)
+
+                il.insert(next, changedArea);
+
+
+/*************************** "return" enhancements: ************/
+			} else if (act_instruction instanceof ReturnInstruction) {
+				// replace return statement by result preparation and a new return statement
+				// construct back to front, to keep the insertion position!
+				InstructionHandle oldReturn    = ihs[actInstruction];
+				InstructionHandle replacedPos  = oldReturn;
+				il.append(oldReturn, InstructionFactory.createReturn(enhancedMethodReturnType));
+				if (returnValueAdded) {
+					// load ot_result:
+					oldReturn.setInstruction(InstructionFactory.createLoad(enhancedMethodReturnType,
+																otResult.getIndex()));
+				} else {
+					oldReturn.setInstruction(new NOP());
+					replacedPos =
+						adjustValue(il, oldReturn, returnType, enhancedMethodReturnType);
+					if (debugging && replacedPos != null)
+						mg.addLineNumber(replacedPos, STEP_OVER_LINENUMBER);
+				}
+				if (replacedPos != null)
+					replacedInstructions.add(new IHPair(oldReturn, replacedPos));
+            } // conditional over instruction types
+			actInstruction++;
+        } //end while
+
+		// tidy:
+		checkUpdate(handlers, replacedInstructions, targetLost);
+        enhancedMethod.removeNOPs();
+		il.setPositions();
+        enhancedMethod.setMaxStack();
+        enhancedMethod.setMaxLocals();
+
+        return enhancedMethod;
+    }
+
+    /**
+     * Given an invokevirtual compute the space its arguments use on the stack.
+     * @param cpg
+     * @param iv
+     * @return int stack size.
+     */
+    static int computeArgumentStackDepth(ConstantPoolGen cpg, InvokeInstruction ii) {
+        Type [] iiargs = ii.getArgumentTypes(cpg);
+        int depth=0;
+        for (int i=0; i<iiargs.length; i++)
+            depth += iiargs[i].getSize();
+        return depth;
+    }
+
+	/**
+	 *  Copy all local variables from <tt>src</tt> to <tt>dest</tt>.
+	 *  While doing so, increment their index by EXTRA_ARGS.
+	 */
+	static void copyLocalVariables(MethodGen src, MethodGen dest) {
+		Type[] argumentTypes = src.getArgumentTypes();
+		LocalVariableGen[] lvgs = src.getLocalVariables();
+		for (int l=argumentTypes.length; l<lvgs.length; l++) {
+			LocalVariableGen lvg = lvgs[l];
+			if (lvg.getIndex() > 0) {
+				dest.addLocalVariable(lvg.getName(),
+									  			   lvg.getType(),
+									  			   lvg.getIndex()+(EXTRA_ARGS+1), // +1?????
+									  			   null, null);
+				//System.err.println("adding:" +src.getClassName() +" "+src.getName()+" "+lvg.getName() +" " + lvg.getType() +" "+ (lvg.getIndex()+(EXTRA_ARGS+1)));
+			}	
+		}
+	}
+	/** Copy all line numbers from <tt>src</tt> to <tt>dest</tt>. */
+	static void copyLineNumbers(MethodGen src, MethodGen dest) {
+		InstructionList il_dest = dest.getInstructionList();
+		il_dest.setPositions();
+		LineNumberGen[] src_lng = src.getLineNumbers();
+		for (int i=0; i<src_lng.length; i++) {
+			int position = src_lng[i].getInstruction().getPosition();
+			InstructionHandle ih = il_dest.findHandle(position);
+			dest.addLineNumber(ih, src_lng[i].getSourceLine());
+		}
+	}
+   /**
+     * Prune a invokevirtual portion from a given instruction list.
+     * Note, that arguments don't include 'this', which is not pruned but blanked
+     * (need to keep as possible jump target).
+     * @param il the source list
+     * @param ihs array of handles of this list
+     * @param idx points to a invokevirtual that shall be removed
+     * @param stackDepth size of the called method's arguments on the stack.
+	 *                   This is how deep we need to cut into the stack.
+     * @param cpg
+     * @param targetLost set of lost InstructionHandles to be filled
+     * @param delim array of two handles, which should be filled with start and end of
+	 *              the pruned region.
+	 * @param blankThis should the 'this' call target be overwritten?
+     * @return InstructionList a copy of the original value loading.
+     */
+    static InstructionList pruneLoading (InstructionList il, InstructionHandle[] ihs, int idx,
+								  int stackDepth, ConstantPoolGen cpg,
+								  HashSet<InstructionHandle> targetLost, InstructionHandle[] delim,
+								  boolean blankThis)
+    {
+        InstructionList nlist = new InstructionList();
+        InstructionHandle start = ihs[idx];
+        InstructionHandle end = ihs[idx--];
+        while (stackDepth > 0) {
+            start = ihs[idx--];
+            Instruction instr = start.getInstruction();
+            stackDepth -= stackDiff(instr, cpg);
+            nlist.insert(instr);
+        }
+		if (blankThis) {
+			if (!isALoad0(ihs[idx].getInstruction()))
+				return null;
+			ihs[idx].setInstruction(new NOP()); // keep as jump target but delete 'this'
+		}
+        delim[0] = start;
+        delim[1] = end;
+        safeDelete(il, start, end, targetLost);
+		return nlist;
+    }
+
+	static boolean isALoad0(Instruction i) {
+		if (!(i instanceof ALOAD)) return false;
+		return ((ALOAD)i).getIndex() == 0;
+	}
+
+	/** Get the lenght of the longest base method signature in mbs.
+	 *  @param mbs List of {@link MethodBinding MethodBinding}
+	 */
+//	static int getMaxBaseArgLen (List mbs) {
+//		int max=0;
+//		Iterator it = mbs.iterator();
+//		while (it.hasNext()) {
+//			MethodBinding mb = (MethodBinding)it.next();
+//			String sign = mb.getBaseMethodSignature();
+//			int len = Type.getArgumentTypes(sign).length;
+//			if (len>max) max = len;
+//		}
+//		return max;
+//	}
+
+	/**
+     * Generate a dispatching switch statement which calls the proper base method.
+	 * @param cpg
+     * @param mbs list of MethodBinding that applies to this callin method
+     * @param enhancedMethod the enhanced callin method
+	 * @param roleArgumentTypes arg types of the callin method
+     * @param outerClass the Team
+     * @param baseClass the base bound to this role
+     * @param returnType the return type of the original callin method
+     * @param otResult the local variable storing the base call result
+     * @param loading an instruction list holding the original instructions for
+	 *        loading parameters
+     * @return InstructionList the complete replacement implementing the base call.
+     */
+	InstructionList genBaseCallSwitch (ConstantPoolGen cpg,
+									   List<MethodBinding> mbs, MethodGen enhancedMethod,
+									   Type[] roleArgumentTypes,
+									   ObjectType outerClass, ObjectType baseClass,
+                                       Type returnType, LocalVariableGen otResult,
+                                       InstructionList loading,
+                                       boolean isSuperAccess)
+    {
+    	
+        String  className                = enhancedMethod.getClassName();
+        Type    enhancedMethodReturnType = enhancedMethod.getReturnType();
+		boolean callinHasReturnValue     = returnType != Type.VOID;
+
+		InstructionList il = new InstructionList();
+
+		// Setup a variable which holds the result of this base call.
+		// This variabel is local to this segment of code and used only
+		// to transport this result out off the switch statement.
+		int     localResult = -1;
+		LocalVariableGen lg = null;
+		if (callinHasReturnValue) {
+			lg = enhancedMethod.addLocalVariable("_OT$tmpResult", returnType,
+												 null, null);
+			localResult = lg.getIndex();
+			il.append(InstructionFactory.createNull (returnType));
+			il.append(InstructionFactory.createStore(returnType, localResult));
+		}
+		
+				// ---- Prepare the switch: ----
+        InstructionHandle switchStart = il.append
+			(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG));
+		// generated: _OT$baseMethTag
+		
+        removeDuplicatedBaseMethodTags(mbs);
+        
+        // one break for each case clause
+        int numberOfCases = mbs.size();
+        GOTO[] breaks = new GOTO[numberOfCases];
+        for (int i=0; i<numberOfCases; i++)
+            breaks[i] = new GOTO(null);
+
+        int[]               matches = new int[numberOfCases];
+        InstructionHandle[] targets = new InstructionHandle[numberOfCases];
+		int caseCounter = 0;
+
+		Iterator<MethodBinding> it = mbs.iterator();
+		while (it.hasNext()) {
+
+			MethodBinding mb = it.next();
+
+			String wrapperName  = mb.getWrapperName();
+			int[] paramPositions = CallinBindingManager.getParamPositions(outerClass.getClassName(),
+																	wrapperName);
+            if (logging) printLogMessage("param pos(" + wrapperName + ")=" + paramPositions);
+			
+            matches[caseCounter] = CallinBindingManager.getBaseCallTag(mb.getBaseClassName(),
+            														   mb.getBaseMethodName(),
+            														   mb.getBaseMethodSignature());
+            InstructionHandle nextBranch = il.append(new NOP());
+
+			String baseMethodName            = mb.getBaseMethodName();
+			String baseMethodSignature       = mb.getBaseMethodSignature();
+			Type[] baseMethodArgumentTypes   = Type.getArgumentTypes(baseMethodSignature);
+			Type   baseMethodReturnType      = Type.getReturnType   (baseMethodSignature);
+			
+			String baseChainMethodName;
+			Type   baseChainReturnType;
+			Type[] enhancedBaseArgumentTypes;
+			if (isSuperAccess) {
+				baseChainMethodName 		 = OT_PREFIX+baseMethodName+"$super";
+				baseChainReturnType          = returnType;
+				// base arguments are un-enhanced but have a leading base instance:
+				int len = baseMethodArgumentTypes.length;
+				System.arraycopy(baseMethodArgumentTypes, 0, enhancedBaseArgumentTypes=new Type[len+1], 1, len);  
+				enhancedBaseArgumentTypes[0] = baseClass; 
+			} else {
+				baseChainMethodName          = genChainMethName(baseMethodName);
+				baseChainReturnType          = object; // ALWAYS
+				enhancedBaseArgumentTypes    = enhanceArgumentTypes(baseMethodArgumentTypes);
+			}
+			
+			// --- call target: ---
+
+			// if base class type is a role type _OT$base field has role interface type:
+			{
+				String baseClassName = baseClass.toString();
+				if (baseClassName.indexOf(OTDT_PREFIX) != -1) {
+					baseClass = new ObjectType(ObjectTeamsTransformation.genRoleInterfaceName(baseClassName));
+					if(logging) printLogMessage(baseClassName + " --> " + ObjectTeamsTransformation.genRoleInterfaceName(baseClassName));
+				}
+			}
+
+			// load '_OT$base' field:
+			InstructionHandle baseCallLine = il.append(InstructionFactory.createThis());
+			il.append(factory.createFieldAccess(className, BASE, baseClass, Constants.GETFIELD));
+			
+			if (!baseClass.getClassName().equals(mb.getBaseClassName())) {
+				// playedBy has been refined in the sub role;
+				// create a cast to the sub base class:
+				il.append(factory.createCast(baseClass, new ObjectType(mb.getBaseClassName())));
+			}
+			
+			// --- load arguments of the new method: ---
+			//     (letters refer to document parameter-passing.odg)
+			
+			// (u) generate extra arguments (indices are equal at role and base):
+			if (!isSuperAccess)
+				for (int idx = 0; idx < EXTRA_ARGS; idx++) 
+					il.append(InstructionFactory.createLoad(enhancedMethod.getArgumentTypes()[idx], 
+													        idx+1/*translating non-static*/));		
+			
+			// (v)(w)(x) split loading sequence and transfer source-level arguments
+			// (includes reverse-application of parameter mappings):
+
+			// Start at EXTRA_ARGS, because one set of enhancement has already been loaded,
+			// except when doing super access which only has one extra arg: base instance.
+			int start = isSuperAccess ? 1 : EXTRA_ARGS; 
+			il.append(translateLoads(splitLoading(cpg,
+											      loading.copy(),
+												  roleArgumentTypes), 
+									 enhancedMethod.getArgumentTypes(), 
+									 enhancedBaseArgumentTypes, 
+									 paramPositions,
+									 extractTeamName(enhancedMethod.getClassName()), 
+									 className,
+									 new BaseMethodInfo(mb.baseMethodIsCallin(), false/*static*/, mb.getTranslationFlags()),
+									 start,
+									 cpg));
+			// --- done loading ---									 
+
+			// invoke the chaining method of the base class (base-call!):
+			il.append(factory.createInvoke(mb.getBaseClassName(),
+										   baseChainMethodName,
+										   baseChainReturnType,
+										   enhancedBaseArgumentTypes,
+										   isSuperAccess 
+											   ? Constants.INVOKESTATIC
+											   : Constants.INVOKEVIRTUAL
+										   ));
+										   
+			boolean resultLiftingNecessary = ((mb.getTranslationFlags()&1)!=0);
+			
+			if (resultLiftingNecessary) { // call the static lift-method:
+				// STATIC_PARTS_OK: in role: lift method call
+//TODO: lift method args!
+				String liftMethodName = mb.getLiftMethodName();
+				Type liftMethodReturnType = Type.getReturnType(mb.getLiftMethodSignature());
+				Type[] liftMethodArgs = Type.getArgumentTypes(mb.getLiftMethodSignature());
+				
+				il.append(factory.createCast(baseChainReturnType, baseMethodReturnType));
+                il.append(InstructionFactory.createThis());
+                
+                int nestingDepth = countOccurrences(className, '$') -1;
+                il.append(factory.createGetField(className, "this$" + nestingDepth, outerClass ));
+
+                il.append(new SWAP()); // -> .., this$0, (BaseType)result
+				//il.append(new ICONST(LIFT_ARG_RES));
+				
+				il.append(factory.createInvoke(outerClass.getClassName(),
+											   liftMethodName,
+											   liftMethodReturnType,
+											   liftMethodArgs,
+											   Constants.INVOKEVIRTUAL));
+			}
+			
+			InstructionHandle afterBaseCallLine = il.append(new NOP());
+			
+			if (baseChainReturnType != Type.VOID) {
+				// adjust the return value to the type expected by the WRAPPER:
+				il.append(new DUP()); // keep for adjustment below
+				if (!resultLiftingNecessary)
+					adjustValue(il, null, baseChainReturnType, enhancedMethodReturnType);
+				il.append(InstructionFactory.createStore(enhancedMethodReturnType,
+						otResult.getIndex())); // store "globally"
+				// this store is needed to tunnel unused results through the callin.
+
+				// adjust the return value to the type expected by the ORIGINAL CALLIN:
+				adjustValue(il, null,  baseChainReturnType, returnType);
+				if (callinHasReturnValue)
+					il.append(InstructionFactory.createStore(returnType, localResult)); // store "locally"
+	 			    // this store is useful for callins which make use of the result.
+			}  
+		
+            targets[caseCounter] = nextBranch;
+            il.append(breaks[caseCounter]);
+            // generated: break;
+
+            caseCounter++;
+            
+            if (debugging) {
+            	enhancedMethod.addLineNumber(baseCallLine, STEP_INTO_LINENUMBER);
+            	enhancedMethod.addLineNumber(afterBaseCallLine, STEP_OVER_LINENUMBER);
+            }
+		}
+		// Default case: throw an exception reporting the situation:
+		// create: String msg = ("Unhandled base-call case!"+base_method_tag)
+		InstructionList messagePush = new InstructionList();
+		messagePush.append(factory.createNew(OTConstants.STRING_BUFFER_NAME));
+		messagePush.append(new DUP());
+		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[0], Constants.INVOKESPECIAL));
+		messagePush.append(new PUSH(cpg, "Unhandled base-call case: "));
+		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.STRING}, Constants.INVOKEVIRTUAL));
+		messagePush.append(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG));
+		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "append", Type.STRINGBUFFER, new Type[]{Type.INT}, Constants.INVOKEVIRTUAL));
+		messagePush.append(factory.createInvoke(OTConstants.STRING_BUFFER_NAME, "toString", Type.STRING, new Type[0], Constants.INVOKEVIRTUAL));
+		// create: throw new OTREInternalError(msg)
+		InstructionHandle defaultCase = createThrowInternalError(cpg, il, messagePush);
+		
+        InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here.
+
+		il.append(switchStart, createLookupSwitch(matches, targets, breaks,
+												  defaultCase, afterSwitch));
+
+		// retrieve locally stored result:
+		if (callinHasReturnValue) {
+			il.append(InstructionFactory.createLoad(returnType, localResult));
+			lg.setStart(il.getStart()); // restrict local variable to this segment.
+			lg.setEnd(il.getEnd());
+		}
+
+        return il;
+	}
+
+	/**
+	 * Removes duplicated method bindings with the same base call tag from the list, to avoid duplicated 
+	 * cases in the base call surrogate-switch.
+	 * @param mbs
+	 */
+	private static void removeDuplicatedBaseMethodTags(List<MethodBinding> mbs) {
+		if (mbs.size() < 2) // nothing to remove
+			return;
+		
+		MethodBinding[] mbArray = mbs.toArray(new MethodBinding[mbs.size()]);
+		
+		Comparator<MethodBinding> baseCallTagComparator = new Comparator<MethodBinding>() {
+			public int compare(MethodBinding firstMB, MethodBinding secondMB) {
+				int firstBaseTag = CallinBindingManager.getBaseCallTag(firstMB.getBaseClassName(), 
+																	   firstMB.getBaseMethodName(), 
+																	   firstMB.getBaseMethodSignature());
+				int secondBaseTag = CallinBindingManager.getBaseCallTag(secondMB.getBaseClassName(), 
+						   											    secondMB.getBaseMethodName(), 
+						   											    secondMB.getBaseMethodSignature());
+				
+				if (firstBaseTag < secondBaseTag)
+					return -1;
+				if (firstBaseTag > secondBaseTag)
+					return 1;
+				return 0;
+			}
+		};
+		Arrays.sort(mbArray, baseCallTagComparator);
+		for (int i = 0; i + 1 < mbArray.length; i++) {
+			if (baseCallTagComparator.compare(mbArray[i], mbArray[i + 1]) == 0) {
+				mbs.remove(mbArray[i + 1]);
+			}
+		}
+	}
+
+
+	/**
+	 * @param className
+	 * @return
+	 */
+	private static String extractTeamName(String roleClassName) {
+		int lastDollarIndex = roleClassName.lastIndexOf('$');
+		return roleClassName.substring(0, lastDollarIndex);
+	}
+	
+	/** 
+	 * @param className
+	 * @return
+	 */
+	private static String extractRoleName(String roleClassName) {
+		int lastDollarIndex = roleClassName.lastIndexOf('$');
+		return roleClassName.substring(lastDollarIndex+1, roleClassName.length());
+	}
+
+	/**
+	 * FIXME(SH): obsolete!
+	 * @param baseMethodReturnType
+	 * @param returnType
+	 * @return
+	 */
+//	private static boolean returnTypeCompatible(Type from, Type to) {
+//		System.out.println("test for " + from + "->" + to);
+//		if (from.equals(to))
+//			return true;
+//		if (from instanceof ObjectType && to instanceof ObjectType) {// how to handle compatible basic types??
+//			ObjectType otFrom = (ObjectType) from;
+//			ObjectType otTo = (ObjectType) to;
+//			if (otFrom.subclassOf(otTo))
+//				return true;	
+//		}
+//		return false;
+//	}
+
+	/**
+	 *	Copy all exception handlers of a method.
+	 *  @param source the method from where to copy
+	 *  @param dest the method where to copy to
+	 *  @param il instructions of `dest' which must still have the same positions
+	 *            as the instructions in `source'.
+	 *  @return an array of handler generators, which still has to be maintained,
+	 *     whenever instructions are replaced in the methods instruction list.
+	 */
+	static CodeExceptionGen[] copyExceptionHandlers(MethodGen source,
+											 MethodGen dest,
+											 InstructionList il) {
+		il.setPositions(); // needed to retrieve handles by position.
+		CodeExceptionGen[] excGens = source.getExceptionHandlers();
+		CodeExceptionGen[] newGens = new CodeExceptionGen[excGens.length];
+		if ((excGens != null) && excGens.length > 0) {
+			for (int hcount=0; hcount<excGens.length; hcount++) {
+				CodeExceptionGen excGen = excGens[hcount];
+				InstructionHandle excStart   = il.findHandle(excGen.getStartPC().getPosition());
+				InstructionHandle excEnd     = il.findHandle(excGen.getEndPC().getPosition());
+				InstructionHandle excHandler = il.findHandle(excGen.getHandlerPC().getPosition());
+				ObjectType catchType =  excGen.getCatchType();
+				newGens[hcount] =
+					dest.addExceptionHandler(excStart, excEnd, excHandler, catchType);
+			}
+		}
+		return newGens;
+	}
+
+	/**
+	 *  Update the positions of all exception handlers.
+	 *  @param handlers the handlers of this method.
+	 *  @param replaced a pair of InstructionHandles, the first is replaced by the second.
+	 */
+	static void updateHandlers (CodeExceptionGen[] handlers, IHPair replaced) {
+		InstructionHandle old = replaced.fst();
+		InstructionHandle neu = replaced.snd();
+		for (int i=0; i<handlers.length; i++) {
+            // System.out.println("handler "+handlers[i]);
+			if (handlers[i].containsTarget(old) && (old != neu)) {
+                // System.out.println("update "+old+"->"+neu);
+				handlers[i].updateTarget(old, neu);
+			}
+		}
+	}
+
+	/**
+	 * Delete a range of instructions, whithout throwing TargetLostException.
+	 * @param il the list to delete from
+	 * @param start handle to first instruction to delete.
+	 * @param end handle to last instruction to delete.
+	 * @param collect a set of InstructionHandle which are still targeted.
+	 */
+	static void safeDelete(InstructionList il,
+					InstructionHandle start, InstructionHandle end,
+					HashSet<InstructionHandle> collect)
+	{
+		try {
+			il.delete(start, end);
+		} catch(TargetLostException e) {
+			//	System.out.print("Loosing:"+e+" ");
+			InstructionHandle [] targets = e.getTargets();
+			for (int tcount = 0; tcount < targets.length; tcount++) {
+				collect.add(targets[tcount]);
+				// System.out.println(targets[tcount]+"!!");
+			}
+		}
+	}
+
+	/**
+	 *  Update all exceptions handlers with respect to all instructions that were replaced.
+	 *  Check that this covers all instruction handles in 'lost'.
+	 *  @param handles the exception handlers of this method.
+	 *  @param replacedList list of IHPairs describing what has been modified.
+	 *  @param lost set of instruction handles that were still referred to when
+	 *    they were deleted. All these handles should be updated.
+	 */
+	static void checkUpdate(CodeExceptionGen[] handlers, ArrayList<IHPair> replacedList, HashSet<InstructionHandle> lost) {
+        // System.out.println("Update "+replacedList+"/"+lost);
+		Iterator<IHPair> iter = replacedList.iterator();
+		while (iter.hasNext()) {
+			IHPair replaced = iter.next();
+			updateHandlers(handlers, replaced);
+			lost.remove(replaced.fst());
+		}
+		if (!lost.isEmpty()) {
+			System.err.println("Warning: "+lost.size()+" target(s) lost: ");
+			Iterator<InstructionHandle> it = lost.iterator();
+			while (it.hasNext())
+				System.out.println(it.next());
+		}
+	}
+
+	/**
+	 * While adding extra args to an activate call:
+	 * <ul>
+	 *   <li>Check whether an activationLevel was passed (single argument)
+	 *   <li>if so, insert the loading sequence for that expression.
+	 *   <li>also the return differs (void or int), should however be
+	 *      consistent between plain and enhanced version.
+	 *   <li>decrement "idx" so this team is the currently active in the chain.
+	 * </ul>
+	 * @param factory
+	 * @param cpg
+	 * @param loading sequence, which loads "level" argument, else null.
+	 * @param iv the invokevirtual for "activate", used to inspect the
+	 *   original signature.
+	 * @return the full sequence for loading the arguments, but not the
+	 *   call target (because that's the enclosing team and is kept
+	 *   unmodified in the original instruction list).
+	 */
+//    static InstructionList enhanceActivateCall (final InstructionFactory factory,
+//										 ConstantPoolGen cpg,
+//										 InstructionList loading,
+//										 INVOKEVIRTUAL iv) {
+//        InstructionList changedArea = new InstructionList();
+//
+//        // load arguments of the new method:
+//        int index = 1;
+//        Type[] enhancedArgumentTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg),
+//															0, false, false);
+//		Type returnType = Type.VOID;
+//		int kount = enhancedArgumentTypes.length;
+//		if (iv.getArgumentTypes(cpg).length == 1) {
+//			kount--; // "level" loaded separately via 'loading'
+//			returnType = Type.INT;
+//		}
+//
+//        for (int k=0; k<kount; k++) {
+//            changedArea.append(InstructionFactory.createLoad(enhancedArgumentTypes[k], index));
+//            index += enhancedArgumentTypes[k].getSize();
+//        }
+//		if (loading != null)
+//			changedArea.append(loading);
+//
+//        // invoke the overloaded activate method:
+//        changedArea.append(factory.createInvoke("org.objectteams.Team",
+//                                                "activate",
+//                                                returnType,
+//                                                enhancedArgumentTypes,
+//                                                Constants.INVOKEVIRTUAL));
+//
+//        // generate: idx--;
+//        changedArea.append(InstructionFactory.createLoad(Type.INT, IDX_ARG));
+//        changedArea.append(new ICONST(1));
+//        changedArea.append(new ISUB());
+//        changedArea.append(InstructionFactory.createStore(Type.INT, IDX_ARG));
+//        
+//        return changedArea;
+//    }
+
+	/**
+	 * Generates the instructions to call the enhanced version of the 'super' respectively 'tsuper'
+	 * call in a role method.
+	 * @param cpg						the constant pool
+	 * @param ii							the original invoke instruction
+	 * @param enhancedMethod	the enhanced role method
+	 * @param loading					the originally loaded arguments 
+	 * @return	the instruction list containing the method call ingredients							
+	 */
+	InstructionList genEnhancedSuperCall(ConstantPoolGen cpg, InvokeInstruction ii,
+										   MethodGen enhancedMethod, InstructionList loading)
+	{
+		Type returnType = enhancedMethod.getReturnType();
+		//Type[] argTypes = enhancedMethod.getArgumentTypes();
+		Type[] argTypes = enhanceArgumentTypes(ii.getArgumentTypes(cpg));
+		InstructionList il = new InstructionList();
+
+		il.append(InstructionFactory.createThis());
+		// load all additional arguments of the enhanced method (first EXTRA_ARGS):
+		int index = 1;
+		for (int i=0; i<EXTRA_ARGS; i++) {
+			il.append(InstructionFactory.createLoad(argTypes[i],index));
+			index += argTypes[i].getSize();
+		}
+		// load arguments of the originally call:
+		il.append(loading);
+
+		// call super.<enhancedMethod>:
+		short kind=0;
+		if (ii instanceof INVOKESPECIAL)
+			kind = Constants.INVOKESPECIAL;
+		else
+			kind = Constants.INVOKEVIRTUAL;
+
+		il.append(factory.createInvoke(ii.getClassName(cpg),
+													 	ii.getMethodName(cpg),
+												  	 	returnType,
+														argTypes,
+													 	kind));
+			return il;
+	}
+
+	/**
+	 * Generates the instructions to call the base call surrogate method.
+	 * @param cpg						the constant pool
+	 * @param iv							the original invoke instruction
+	 * @param enhancedMethod	the enhanced role method
+	 * @param loading					the originally loaded arguments 
+	 * @return	the instruction list containing the method call ingredients		
+	 */
+	InstructionList genBaseCallSurrogateCall(ConstantPoolGen cpg, InvokeInstruction/*INVOKEVIRTUAL*/ iv,
+											   MethodGen enhancedMethod, InstructionList loading, 
+											   String roleClassName, String calleeClassName) //JU: added String roleClassName and teamClassName to the method signature
+	{
+		int indexOffset = enhancedMethod.isStatic()?-1:0; // argument indexes are decremented for static methods, 
+																								// because of the missing 'this' 
+		// for static methods callee is 'null' -> substitute by current class (JU)
+		if(calleeClassName == null) {
+			calleeClassName = iv.getClassName(cpg);
+		}
+		
+		Type returnType = enhancedMethod.getReturnType();
+		//Type[] argTypes = enhancedMethod.getArgumentTypes();
+		Type[] argTypes = enhanceArgumentTypes(iv.getArgumentTypes(cpg));
+		InstructionList il = new InstructionList();
+
+		String methodName = getBaseCallSurrogateName(enhancedMethod.getName(), 
+													 enhancedMethod.isStatic(),
+													 roleClassName);
+		short invokeKind;
+				
+		if (!enhancedMethod.isStatic()) {
+			il.append(InstructionFactory.createThis());
+			invokeKind = Constants.INVOKEVIRTUAL;
+		
+		} else { // role method is static: 
+			invokeKind = Constants.INVOKESTATIC;
+		}
+			
+		// load all additional arguments of the enhanced method (first EXTRA_ARGS):
+		int index = 1;
+		for (int i = 0; i < argTypes.length; i++) {
+			if(i < EXTRA_ARGS){ // skip original arguments
+				il.append(InstructionFactory.createLoad(argTypes[i], index+indexOffset));
+			}
+			//calculate the next index
+			index += argTypes[i].getSize();
+		}
+		// load arguments of the originally call:
+		il.append(loading);
+			
+		// call _OT$<enhancedMethod>$base():
+		il.append(factory.createInvoke(calleeClassName,
+													 methodName,
+													 returnType,
+													 argTypes,
+													 invokeKind/*Constants.INVOKEVIRTUAL*/));
+		return il;
+	}
+ 
+ 		
+	/**
+	   * Checks, if a given instuction is a super or a tsuper call 
+	   * @param instr					the instruction to check
+	   * @param method_name	the name of the method from wich the 'inst' came
+	   * @param cpg					the constant pool
+	   * @return							true, if 'inst' is a super or tsuper call
+	   */
+	private static boolean super_or_tsuper_instruction(Instruction instr, String method_name, ConstantPoolGen cpg) {
+		if (isTSuperCall(instr, method_name, cpg))
+			return true;
+		if (isSuperCall(instr, method_name, cpg))
+			return true;
+		return false;
+	}   
+
+	private static boolean isTSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) {
+		if (instr instanceof INVOKEVIRTUAL) {
+			INVOKEVIRTUAL iv = (INVOKEVIRTUAL)instr;
+			String iv_name = iv.getName(cpg);
+			Type[] argTypes = iv.getArgumentTypes(cpg);
+			if (argTypes.length<1) // no tsuper marker interface parameter!
+				return false;
+			String lastArgument = (argTypes[argTypes.length-1]).toString();
+			if (iv_name.equals(method_name) && (lastArgument.indexOf(TSUPER_PREFIX)!=-1)) {
+				// if iv == <method_name>(..., TSuper__OT__<SuperTeamName>) -->
+                if(logging) printLogMessage("tsuper-call to " + iv_name + " has to be enhanced!");
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private static boolean isSuperCall(Instruction instr, String method_name, ConstantPoolGen cpg) {
+		if (instr instanceof INVOKESPECIAL) { 			
+			INVOKESPECIAL is = (INVOKESPECIAL)instr;
+			String is_name = is.getName(cpg);
+			
+			if(is_name.equals(method_name)) {
+               if(logging) printLogMessage("super-call to " + is_name + " has to be enhanced!");
+			   return true;
+			}
+		}
+		return false;
+	}
+	  
+   /**
+	* Generates the base call surrogate name for a given method name.
+	* @param	method_name the name of the role method
+	* @param	staticFlag 
+	* @param	roleClassName the name of the role method
+	* @return	the base call surrogate name
+	*/
+	private static String getBaseCallSurrogateName(String method_name, boolean staticFlag, String roleClassName) {
+		//JU: for static methods the role class name should be inserted 
+		if(staticFlag) {
+			return OT_PREFIX+roleClassName+"$"+method_name+"$base";
+		}
+		return OT_PREFIX+method_name+"$base";
+	}
+		
+   /**
+	* Reverts a method name to its original by returning the substring after the last '$'
+	* until the end.  
+	* @param	method_name method name to be adjusted
+	* @return	the original method name
+	*/
+	private static String revertToOriginalName(String method_name) {
+		int p = method_name.lastIndexOf('$');
+		return method_name.substring(p + 1);
+	}
+
+/*
+ * (non-Javadoc)
+ * 
+ * @see org.eclipse.objectteams.otre.common.ObjectTeamsTransformation#doTransformCode(de.fub.bytecode.generic.ClassGen)
+ */
+    public void doTransformCode(ClassGen cg) {
+        // nothing to do
+    }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
new file mode 100644
index 0000000..06878cb
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
@@ -0,0 +1,1861 @@
+/**********************************************************************
+ * 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: BaseMethodTransformation.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 static org.eclipse.objectteams.otre.StaticSliceBaseTransformation._OT_ACTIVE_TEAMS;
+import static org.eclipse.objectteams.otre.StaticSliceBaseTransformation._OT_ACTIVE_TEAM_IDS;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Map.Entry;
+
+import org.eclipse.objectteams.otre.util.CallinBindingManager;
+import org.eclipse.objectteams.otre.util.DebugUtil;
+import org.eclipse.objectteams.otre.util.ListValueHashMap;
+import org.eclipse.objectteams.otre.util.MethodBinding;
+import org.eclipse.objectteams.otre.util.TeamIdDispenser;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.classfile.Field;
+import de.fub.bytecode.classfile.LineNumber;
+import de.fub.bytecode.classfile.LineNumberTable;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.generic.AASTORE;
+import de.fub.bytecode.generic.ACONST_NULL;
+import de.fub.bytecode.generic.ALOAD;
+import de.fub.bytecode.generic.ANEWARRAY;
+import de.fub.bytecode.generic.ARRAYLENGTH;
+import de.fub.bytecode.generic.ATHROW;
+import de.fub.bytecode.generic.ArrayType;
+import de.fub.bytecode.generic.BasicType;
+import de.fub.bytecode.generic.BranchInstruction;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.ConstantPoolGen;
+import de.fub.bytecode.generic.DUP;
+import de.fub.bytecode.generic.DUP_X1;
+import de.fub.bytecode.generic.FieldGen;
+import de.fub.bytecode.generic.GOTO;
+import de.fub.bytecode.generic.IADD;
+import de.fub.bytecode.generic.ICONST;
+
+import de.fub.bytecode.generic.IFNE;
+import de.fub.bytecode.generic.IFNONNULL;
+import de.fub.bytecode.generic.IF_ICMPLT;
+import de.fub.bytecode.generic.IINC;
+import de.fub.bytecode.generic.INVOKESPECIAL;
+import de.fub.bytecode.generic.Instruction;
+import de.fub.bytecode.generic.InstructionConstants;
+import de.fub.bytecode.generic.InstructionFactory;
+import de.fub.bytecode.generic.InstructionHandle;
+import de.fub.bytecode.generic.InstructionList;
+import de.fub.bytecode.generic.InvokeInstruction;
+import de.fub.bytecode.generic.LDC;
+import de.fub.bytecode.generic.LocalVariableGen;
+import de.fub.bytecode.generic.MONITOREXIT;
+import de.fub.bytecode.generic.MethodGen;
+import de.fub.bytecode.generic.NOP;
+import de.fub.bytecode.generic.ObjectType;
+import de.fub.bytecode.generic.POP;
+import de.fub.bytecode.generic.PUSH;
+import de.fub.bytecode.generic.TABLESWITCH;
+import de.fub.bytecode.generic.Type;
+
+
+/**
+ * Insert dispatch code into base methods affected by callin bindings. <p>
+ * If a loaded class contains binding declarations (transmitted by attributes)
+ * these are stored for further determination of necessity for base-method-transforming.
+ * Classes for which a callin binding exists will be transformed:
+ * (base-class)methods <i>m()</i> which are changed by a callin will be copied to
+ * <tt>_OT$<i>m</i>$orig()</tt>.
+ * Hereafter the original method <i>m()</i> will be transformend depending on the
+ * callin-modifier:
+ * <ul>
+ *  <li> replace: only the (role-)callin-method is called
+ *  <li> after: first the original-method <tt>_OT$<i>m</i>$orig()</tt> is called and
+ *       then the callin-method
+ *  <li> before: first the the callin-method is called and then original-method
+ *       <tt>_OT$<i>m</i>$orig()</tt>
+ * </ul>
+ *
+ * @version $Id: BaseMethodTransformation.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author Christine Hundt
+ * @author Stephan Herrmann
+ */
+
+public class BaseMethodTransformation
+	extends ObjectTeamsTransformation
+{
+	// configurability for stepping behavior of the chaining wrapper:
+	private static boolean SHOW_ORIG_CALL 		= true;
+	private static boolean SHOW_RECURSIVE_CALL	= true;
+	private static boolean SHOW_ROLE_CALL		= true;
+	static {
+		String callinStepping = System.getProperty("ot.debug.callin.stepping");
+		if (callinStepping != null) {
+			SHOW_ORIG_CALL = SHOW_RECURSIVE_CALL = SHOW_ROLE_CALL = false;
+			StringTokenizer tokens = new StringTokenizer(callinStepping, ",");
+			while (tokens.hasMoreTokens()) {
+				String token = tokens.nextToken();
+				if ("orig".equals(token))
+					SHOW_ORIG_CALL = true;
+				else if ("recurse".equals(token))
+					SHOW_RECURSIVE_CALL = true;
+				else if ("role".equals(token))
+					SHOW_ROLE_CALL = true;
+			}
+		}
+	}
+
+	// method of o.o.Team:
+    private static final String IS_ACTIVE = "isActive";  //$NON-NLS-1$
+
+	private final static int NORESULT = -1;
+
+	// FIXME(SH): once we remove JMangler support, these maps can be reduced to their RHS because then we'll consistently have one transformer per class:
+    private HashMap /* class_name -> HashSet(method_name) */<String, HashSet<String>> transformableMethods = new HashMap<String, HashSet<String>>();
+    private HashMap /* class_name -> HashSet(method_name) */<String, HashSet<String>> overridableMethods = new HashMap<String, HashSet<String>>();
+
+	public boolean useReflection = false;
+	
+	public BaseMethodTransformation(SharedState state) {
+		this(null, state);
+	}
+
+	public BaseMethodTransformation(ClassLoader loader, SharedState state) {
+		super(loader, state);
+	}
+	/**
+	 *  The code transformer only replaces the original code with
+	 *  the initial wrapper.
+	 */
+    public void doTransformCode(ClassGen cg) {
+    	factory = new InstructionFactory(cg);
+    	ConstantPoolGen cpg        = cg.getConstantPool();
+    	String          class_name = cg.getClassName();
+			
+    	Method[] methods = cg.getMethods();
+    	for (int i=0; i<methods.length; i++) {
+    		Method m           = methods[i];
+    		//if (m.isNative())
+    		//	continue;
+    		if (m.isVolatile())
+    			continue; // don't touch bridge methods
+    		
+    		String method_name = m.getName();
+				
+    		if (CallinBindingManager.isBoundBaseClass(class_name) 
+    				&& !CallinBindingManager.hasBoundBaseParent(class_name) 
+    				&& method_name.equals(Constants.CONSTRUCTOR_NAME)) 
+    		{
+    			addToConstructor(m, getInitializedRoleSet(cg.getClassName(), false), cg, cpg);
+    			continue;
+    		}
+			                
+    		String method_signature = m.getSignature();
+
+    		if (state.interfaceTransformedClasses.contains(class_name)) {
+    			HashSet<String> transformable = transformableMethods.get(class_name);
+    			HashSet<String> overridable = overridableMethods.get(class_name);
+    			if (transformable.contains(method_name + '.' + method_signature))
+    				cg.replaceMethod(m, m = generateInitialWrapper(m, class_name, cg.getMajor(), cpg));
+    			else if (overridable.contains(method_name + '.' + method_signature))
+    				cg.replaceMethod(m, m = generateSuperCall(m, cg, cpg));
+    			
+    			Method replacement = checkReplaceWickedSuper(class_name, m, cpg);
+    			if (replacement != null)
+    				cg.replaceMethod(m, replacement);
+    		}
+    	}
+    }
+
+    /*
+     * If a base method m1 has a super-call super.m2() and if that method m2 is callin-bound
+     * we currently bypass aspect dispatch to avoid infinite recursions.
+     */
+	private Method checkReplaceWickedSuper(String className, Method m, ConstantPoolGen cpg)
+	{
+        if (m.isAbstract() || m.isNative())
+            return null;
+		MethodGen mg = new MethodGen(m, className, cpg);
+		String method_name = m.getName();
+		InstructionHandle[] ihs = mg.getInstructionList().getInstructionHandles();
+		boolean found = false;
+		for (InstructionHandle ih : ihs) {
+			if (ih.getInstruction() instanceof INVOKESPECIAL) { 			
+				Instruction actInstruction = ih.getInstruction();
+				INVOKESPECIAL is = (INVOKESPECIAL)actInstruction;
+				String is_name = is.getName(cpg);
+				if (   !is_name.equals(method_name) 							// not same method
+					&& !is_name.equals("<init>"))    							// not ctor call
+				{ 
+					String superClassName = is.getClassName(cpg);
+					if (   !superClassName.equals(className)					// not private method of same class
+						&& CallinBindingManager.isBoundBaseMethod( 				// target method is callin-affected
+													superClassName,	
+													is_name, 
+													is.getSignature(cpg)))
+					{					
+						found = true;
+	                    if(logging) printLogMessage("wicked super-call to " + is_name //$NON-NLS-1$
+	                            + " has to be redirected to the orig-version!"); //$NON-NLS-1$
+						ih.setInstruction(factory.createInvoke(superClassName, 
+															   "_OT$"+is_name+"$orig",
+															   is.getReturnType(cpg),
+															   is.getArgumentTypes(cpg),
+															   Constants.INVOKESPECIAL)); 
+					}
+				}
+			}
+		}
+		if (found) 
+			return mg.getMethod();
+		return null;
+ 	}
+
+	/**
+	 * Main entry for this transformer.
+	 */
+    public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+    	String class_name = cg.getClassName();
+    	//SourceMapGeneration sourceMapGen = new SourceMapGeneration(cg);
+
+    	ConstantPoolGen cpg = cg.getConstantPool();
+    	factory = new InstructionFactory(cg);
+    	if (CallinBindingManager.isBoundBaseClass(class_name) && !cg.isInterface())  {
+    		// TODO: where to add the role set infrastructure, if only an interface is bound? Implementing classes?
+    		if (cg.containsField(OTConstants.ROLE_SET) == null && !CallinBindingManager.hasBoundBaseParent(class_name)) {
+    			ce.addField(generateRoleSet(cpg, class_name), cg);
+    			ce.addMethod(generateAddRole(cpg, class_name), cg);
+    			ce.addMethod(generateRemoveRole(cpg, class_name), cg);
+    			ce.addImplements(OTConstants.IBOUND_BASE, cg);
+    		}
+    	}
+
+    	HashSet<String> transformedMethods = transformableMethods.get(class_name);
+    	if (transformedMethods == null) {
+    		transformedMethods = new HashSet<String>();
+    		transformableMethods.put(class_name, transformedMethods);
+    	}
+    	HashSet<String> renamedMethods = overridableMethods.get(class_name);
+    	if (renamedMethods == null) {
+    		renamedMethods = new HashSet<String>();
+    		overridableMethods.put(class_name, renamedMethods);
+    	}
+
+    	checkReadClassAttributes(ce, cg, class_name, cpg);
+		
+    	//JU: change the class modifier to 'public' if decapsulation required
+    	if(CallinBindingManager.checkBaseClassModifierChange(class_name) && !cg.isPublic()) {
+    		cg.setAccessFlags(makePublicFlags(cg.getAccessFlags()));
+    	}
+    	
+    	Collection<MethodBinding> inheritedBindings = CallinBindingManager.getInheritedCallinBindings(class_name);
+    	
+//		if (inheritedSigns!=null && !inheritedSigns.isEmpty()) {
+//			Iterator itx = inheritedSigns.iterator();
+//			while (itx.hasNext()) {
+//				System.err.print(class_name+" : ");
+//				String[] next = (String[])itx.next();
+//				System.err.println(next[0] +" " +next[1]) ;
+//			}
+//		}
+    	/*
+    	 String[] interfaceNames = cg.getInterfaceNames();
+    	 Collection interfaceInheritedSigns  = new LinkedList();
+    	 //System.err.println("searching inherited bindings for: "+class_name);
+    	  for (int i=0; i<interfaceNames.length;i++) {
+    	  		if (!interfaceNames[i].equals(class_name))
+    	  			interfaceInheritedSigns.addAll(CallinBindingManager.getInterfaceInheritedCallinBindings(interfaceNames[i]));
+          }*/
+		/*
+		 if (!interfaceInheritedSigns.isEmpty()) {
+		 	System.err.println("BMT: searching inherited bindings for: "+class_name);
+		 		for (Iterator iterator = interfaceInheritedSigns.iterator(); iterator.hasNext();) {
+		 			String[] element = (String[]) iterator.next();
+		 			System.err.println(element[0]+element[1]);
+		        }
+		 }*/
+		//inheritedSigns.addAll(interfaceInheritedSigns);
+			
+    	boolean haveDirectCallin =
+    		CallinBindingManager.isBoundBaseClass(class_name);
+		// IMPLICIT_INHERITANCE
+    	if (inheritedBindings.size() == 0 && !haveDirectCallin /*&& interfaceInheritedSigns.size()==0*/) {
+            if(logging) printLogMessage("\nCallins: nothing to do for class " + class_name); //$NON-NLS-1$
+    		return; // nothing to do
+    	}
+    	// if class is already transformed by this transformer
+    	/*
+    	 if (interfaceTransformedClasses.contains(class_name))
+    	 	continue;
+		*/
+			
+    	if(cg.isInterface()) {
+    		//CallinBindingManager.addBoundBaseInterface(class_name); // <- this is to late, implementing class may be loaded before!!
+    		return; // No transfomations neccessary for interfaces.
+    	}
+			
+        if(logging) printLogMessage("\nCallin bindings may be changing class " //$NON-NLS-1$
+    				+ class_name + ':');
+
+        // A field to optimize class-literal in initial wrapper:
+		if (cg.getMajor() < 49) {// pre 1.5?
+			if (cg.containsField(OTConstants.SELF_CLASS) == null)
+				ce.addField(new FieldGen(Constants.ACC_PROTECTED|Constants.ACC_STATIC, 
+	                           			 classType, 
+	                           			 OTConstants.SELF_CLASS,
+	                           			 cpg)
+								.getField(),
+	                        cg);
+		}
+    	
+    	Method[] methods = cg.getMethods();
+    	for (int i=0; i<methods.length; i++) {
+    		Method m           = methods[i];
+    		if (m.isVolatile()) // bridge method!
+    			continue;
+    		String method_name = m.getName();
+    		String method_signature = m.getSignature();
+    		
+    		Collection<MethodBinding> bindingsForMethod = null;
+    		// IMPLICIT_INHERITANCE
+    		if (haveDirectCallin)
+    			bindingsForMethod = CallinBindingManager .
+    			getBindingForBaseMethod(class_name, method_name, m.getSignature());
+    		
+    		//JU: added the following statement to determine overridden static base methods
+    		//Collection inheritedCallinBindings = CallinBindingManager.getInheritedCallinBindings(class_name);
+    		//CH: removed it again, because it is the same as 'inheritedSigns'!
+    		
+    		MethodGen mg = null;
+    		int firstLine = STEP_OVER_LINENUMBER;
+    		String original_signature = method_signature;
+    		/*if (bindingsForMethod != null || containsSign(inheritedSigns, m)*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) {
+    		MethodBinding match= matchingBinding(inheritedBindings, m, false);
+    		if (bindingsForMethod != null || (match!= null && !m.isStatic() && !m.isPrivate())) {
+    			
+    			mg = new MethodGen(m, class_name, cpg);
+    			Method orig_method;
+					
+    			String name_orig = genOrigMethName(method_name);
+    			if (cg.containsMethod(name_orig, m.getSignature())!=null) {
+    				continue;// method was already copied to orig-version!
+    			}
+				
+    			if (debugging)
+    				firstLine = findFirstLineNumber(m);
+    			
+    			mg.setName(name_orig);
+					
+				// TODO(SH): store this match, or keep previous?
+    			if (matchingBinding(inheritedBindings, m, true) != null) // this method was adapted in a super class 
+    				replaceSuperCalls(mg, method_name, cpg);
+					
+    			orig_method = mg.getMethod();
+    			ce.addMethod(orig_method, cg);
+                if(logging) printLogMessage("Method " + method_name + " was backuped as " //$NON-NLS-1$ //$NON-NLS-2$
+    						+ name_orig + '.');
+
+                if (match == null || method_signature.equals(match.getBaseMethodSignature()))
+                	renamedMethods.add(method_name+'.'+method_signature);
+                else // override with covariant return: at the VM-level this is a *new* method.
+                	transformedMethods.add(method_name+'.'+method_signature);
+    		}
+
+    		/*if (bindingsForMethod != null || (containsSign(inheritedSigns,m) && m.isStatic())*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) {
+    		//CH: changed 'inheritedCallinBindings' to 'inheritedSigns', because it was the same.
+    		if (bindingsForMethod != null) { 
+    			//add method '_OT$<method_name>$chain' :
+    			Method chain;
+    			mg = getConcretMethodGen(m, class_name, cpg);
+    			chain = generateChainingWrapper(mg, method_name,
+    									original_signature/*method_signature*/, class_name, cpg, cg, firstLine);
+													
+    			if (cg.containsMethod(chain.getName(), chain.getSignature()) == null)
+    				ce.addMethod(chain, cg);
+
+    			transformedMethods.add(method_name + '.' + method_signature);
+    		}
+    		if (mg == null)
+                if (logging) printLogMessage("No method binding (direct or inherited) found for " //$NON-NLS-1$
+                            + method_name);
+    	}
+    	state.interfaceTransformedClasses.add(class_name);
+    }
+    
+    private int findFirstLineNumber(Method m) {
+		LineNumberTable lnt = m.getLineNumberTable();
+		if (lnt != null && lnt.getTableLength() > 0) {
+			LineNumber[] lineNumberTable = lnt.getLineNumberTable();
+			for (int i=0; i<lineNumberTable.length; i++) {
+				int lineNumber = lineNumberTable[i].getLineNumber();
+				if (lineNumber != OTConstants.STEP_OVER_LINENUMBER)
+					return lineNumber;
+			}
+			return lineNumberTable[0].getLineNumber();
+		}
+		return STEP_OVER_LINENUMBER; // make it a valid line number
+	}
+
+	/**
+	 * "super"-calls in callin bound base methods have to be redirected to the _OT$...$orig version, if the
+	 * super-method is bound (and thus renamed to _OT$..$orig) too.
+	 *
+	 * @param orig_method	the copied method
+	 * @param method_name	the prior name of the copied method
+	 * @param cpg			the corresponding constang pool	
+	 */
+	private void replaceSuperCalls(MethodGen orig_method, String method_name, ConstantPoolGen cpg) {
+		// search for super calls:
+		InstructionList il = orig_method.getInstructionList();
+		InstructionHandle[] ihs = il.getInstructionHandles();
+		int actInstrIndex = 0;
+		while (actInstrIndex < ihs.length) {
+			if (ihs[actInstrIndex].getInstruction() instanceof INVOKESPECIAL) { 			
+				Instruction actInstruction = ihs[actInstrIndex].getInstruction();
+				INVOKESPECIAL is = (INVOKESPECIAL)actInstruction;
+				String is_name = is.getName(cpg);
+				if(is_name.equals(method_name)) {
+					String superClassName = is.getClassName(cpg);
+                    if(logging) printLogMessage("super-call to " + is_name //$NON-NLS-1$
+                            + " has to be redirected to the orig-version!"); //$NON-NLS-1$
+					// generate and set an instruction calling the orig-version of the super method:
+					InvokeInstruction superOrigCall = factory.createInvoke(superClassName, 
+																		   orig_method.getName(),
+																		   orig_method.getReturnType(),
+																		   orig_method.getArgumentTypes(),
+																		   Constants.INVOKESPECIAL);
+					ihs[actInstrIndex].setInstruction(superOrigCall); 
+				}
+			}
+			actInstrIndex++;
+		}
+		// redirect them ( change called method name to  _OT$..$orig ) if super-method has been renamed:
+		// --> 
+	}
+
+	/**
+	 *  Is method `m' contained in `baseMethodBindings'?
+	 *  @param nameSigns list of MethodBinding
+	 *  @param m
+     *  @param strict if true covariance must not be considered
+     *  @return the matching binding from baseMethodBindings or null.
+	 */
+	static MethodBinding matchingBinding (Collection<MethodBinding> baseMethodBindings, Method m, boolean strict) 
+	{
+		for (MethodBinding binding: baseMethodBindings) 
+			if (binding.matchesMethod(m.getName(), m.getSignature(), strict)) 
+				return binding;
+
+		return null;
+	}
+
+	/**
+	 *  Get a MethodGen for `m'.
+	 *  If `m' is abstract setup a new concrete method.
+	 */
+	static MethodGen getConcretMethodGen (Method m, String class_name, ConstantPoolGen cpg) {
+		MethodGen mg;
+		String signature   = m.getSignature();
+		Type[] argTypes    = Type.getArgumentTypes(signature);
+		if (m.isAbstract()) {
+			Type   returnType  = Type.getReturnType(signature);
+			InstructionList il = new InstructionList();
+			il.append(new NOP());
+			mg = new MethodGen(m.getAccessFlags()&~Constants.ACC_ABSTRACT,
+							   returnType, argTypes,
+							   null, // names are unknown
+							   m.getName(), class_name,
+							   il, cpg);
+		} else {
+            mg = wipeMethod(m, class_name, cpg);
+		}
+		if (debugging) {
+			mg.removeLocalVariables();
+			mg.removeLocalVariableTypes();
+			int slot = 0;
+			// create local variable table for "this" and arguments:
+			if (!m.isAbstract())
+				mg.addLocalVariable("this", new ObjectType(class_name),	slot++, null, null);
+			for (int i=0; i<argTypes.length; i++)
+				mg.addLocalVariable("arg"+i, argTypes[i], slot++, null, null);
+			mg.setMaxLocals();
+		}
+		return mg;
+	}
+
+    /**
+     * Generate the initial wrapper for the passed mehtod. 
+     * It binds callin dispatch to Team-unaware client code.
+     * @param m						the original method	
+     * @param class_name	the name of the appropriate class
+     * @param major 
+     * @param cpg					the ConstantPoolGen of the class
+     * @return							the generated method
+     */
+    private Method generateInitialWrapper(Method          m,
+										  String          class_name,
+										  int             major, 
+										  ConstantPoolGen cpg)
+	{
+        MethodGen mg = getConcretMethodGen(m, class_name, cpg);
+
+        String  method_name     = m.getName();
+        Type    returnType      = mg.getReturnType();
+        Type    chainReturnType = object;
+        Type[]  argTypes        = mg.getArgumentTypes();
+
+        String  name_chain      = genChainMethName(method_name);
+
+        InstructionList il      = mg.getInstructionList();
+
+        InstructionHandle startSynchronized;
+        InstructionHandle chainCall; 
+        int monitor;
+		// start generating
+		{
+		    LocalVariableGen lg; // used for several local variables
+		    
+		    // Team[] _OT$teams;
+		    int teams;
+		    lg = mg.addLocalVariable(TEAMS, teamArray, null, null);
+		    teams = lg.getIndex();
+		    
+		    // synchronized (TopMostBoundBaseClass.class) {
+		    Pair<Integer,InstructionHandle> monitorResult = addClassMonitorEnter(mg, il, CallinBindingManager.getTopmostBoundBase(class_name), major, cpg);
+		    monitor = monitorResult.first;
+		    if (debugging)
+		    	// no natural lines in this method: step-over until chain call, which has step-into: debugging => addLineNumber
+		    	mg.addLineNumber(monitorResult.second, STEP_OVER_LINENUMBER);
+
+		    // _OT$teams= new Teams[_OT$activeTeams.length];
+		    startSynchronized= // begin area protected by exception handler
+		    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
+		    il.append(InstructionConstants.ARRAYLENGTH);
+		    il.append((Instruction)factory.createNewArray(teamType, (short) 1));
+		    il.append(InstructionFactory.createStore(Type.OBJECT, teams));
+
+		    // _OT$teamIDs=new int[_OT$activeTeamIDs.length];
+		    int teamIDs;
+		    lg = mg.addLocalVariable(TEAMIDS, intArray, null, null);
+		    teamIDs = lg.getIndex();
+		    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
+		    il.append(InstructionConstants.ARRAYLENGTH);
+		    il.append((Instruction)factory.createNewArray(Type.INT, (short) 1));
+		    il.append(InstructionFactory.createStore(Type.OBJECT, teamIDs));
+		    
+		    // for (int i=0; i<_OT$activeTeams.length; ...
+		    int for_index;
+		    lg = mg.addLocalVariable("i", Type.INT, null, null); //$NON-NLS-1$
+		    for_index = lg.getIndex();
+		    il.append(new PUSH(cpg, 0));
+		    il.append(InstructionFactory.createStore(Type.INT, for_index));
+		  InstructionHandle for_start = 
+			il.append(InstructionFactory.createLoad(Type.INT, for_index));
+		    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
+		    il.append(InstructionConstants.ARRAYLENGTH);
+		  BranchInstruction if_loop_finished = 
+			          InstructionFactory.createBranchInstruction(Constants.IF_ICMPGE, null);
+		    il.append(if_loop_finished);
+    
+		    	// if (!_OT$activeTeams[i].isActive()) {
+			    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
+			    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+			    il.append(InstructionConstants.AALOAD);
+			    il.append(factory.createInvoke(OTConstants.teamName, IS_ACTIVE, Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));
+			  BranchInstruction if_team_isactive = 
+				  		  InstructionFactory.createBranchInstruction(Constants.IFNE, null);
+			    il.append(if_team_isactive);
+	
+				    // invalidate activation of current team:
+			    	// _OT$teams[i]= null;
+				    il.append(InstructionFactory.createLoad(Type.OBJECT, teams));
+				    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+				    il.append(InstructionConstants.ACONST_NULL);
+				    il.append(InstructionConstants.AASTORE);
+		
+				    // _OT$teamIDs[i]= -1;
+				    il.append(InstructionFactory.createLoad(Type.OBJECT, teamIDs));
+				    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+				    il.append(new PUSH(cpg, -1));
+				    il.append(InstructionConstants.IASTORE);
+				  BranchInstruction goto_continue = 
+					          InstructionFactory.createBranchInstruction(Constants.GOTO, null);
+				    il.append(goto_continue);
+				    
+				// } else { adopt activation of current team:
+				// _OT$teams[i]= _OT$activeTeams[i];
+			  InstructionHandle adopt_activation = 
+			    il.append(InstructionFactory.createLoad(Type.OBJECT, teams));
+			    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+			    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.GETSTATIC));
+			    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+			    il.append(InstructionConstants.AALOAD);
+			    il.append(InstructionConstants.AASTORE);
+	
+				// _OT$teamIDs[i]= _OT$activeTeamIDs[i];
+			    il.append(InstructionFactory.createLoad(Type.OBJECT, teamIDs));
+			    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+			    il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.GETSTATIC));
+			    il.append(InstructionFactory.createLoad(Type.INT, for_index));
+			    il.append(InstructionConstants.IALOAD);
+			    il.append(InstructionConstants.IASTORE);
+
+		    // closing the above for: i++ and jump back:
+		  InstructionHandle do_continue = 
+			il.append(new IINC(for_index, 1));
+		    il.append(InstructionFactory.createBranchInstruction(Constants.GOTO, for_start));
+
+		    // link jump instructions to their targets:
+		    InstructionHandle loop_finished = il.append(new NOP()); // synthetic jump target
+		    if_loop_finished.setTarget(loop_finished);
+		    if_team_isactive.setTarget(adopt_activation);
+		    goto_continue.setTarget(do_continue);
+		
+		    // No more access to array fields, release monitor:
+		    il.append(InstructionFactory.createLoad(Type.OBJECT, monitor));
+		    il.append(new MONITOREXIT());
+		    
+			// load special arguments:
+			if(!m.isStatic()) { // "this" cannot be accessed by static methods 
+				chainCall= il.append(InstructionFactory.createThis());                  // this
+			} else {
+				chainCall= il.append(new NOP());
+			}
+			
+			if (debugging)
+				mg.addLineNumber(chainCall, STEP_INTO_LINENUMBER);
+			// ih now points to end of area protected by exception handler 
+			
+			il.append(InstructionFactory.createLoad(teamArray, teams));  // _OT$teams
+			il.append(InstructionFactory.createLoad(intArray, teamIDs)); // _OT$teamIDs
+			il.append(new ICONST(0));                         // _OT$idx = 0
+			il.append(new ICONST(0));							// _OT$bindIdx = 0
+            il.append(new ICONST(-1));                        // _OT$baseMethTag is unused here
+			il.append(new ACONST_NULL());                     // _OT$unusedArgs = null
+		}
+		
+		
+        // load regular arguments:
+        int index = m.isStatic()?0:1;
+        // chaining wrapper is always public, so never user INVOKESPECIAL:
+        short invocationKind = m.isStatic()?Constants.INVOKESTATIC:Constants.INVOKEVIRTUAL;
+		
+        for (int i=0; i<argTypes.length; i++) {
+            il.append(InstructionFactory.createLoad(argTypes[i],index));
+            index += argTypes[i].getSize();
+        }
+		//
+        il.append(factory.createInvoke(class_name, name_chain,
+									   chainReturnType,
+									   enhanceArgumentTypes(argTypes),
+									   invocationKind));
+		// generated invoke: _OT$<method_name>$chain (a1,.. aN)
+
+        
+		adjustValue(il, null, chainReturnType, returnType);
+        il.append(InstructionFactory.createReturn(returnType));
+        
+        // handler for exception within synchronized:
+        LocalVariableGen ex= mg.addLocalVariable("exceptionInSynchronized", Type.THROWABLE, il.getEnd(), null); //$NON-NLS-1$
+        InstructionHandle handler=
+        il.append(InstructionFactory.createStore(Type.THROWABLE, ex.getIndex()));
+        il.append(InstructionFactory.createLoad(Type.OBJECT, monitor));
+        il.append(new MONITOREXIT());
+        il.append(InstructionFactory.createLoad(Type.THROWABLE, ex.getIndex()));
+        il.append(new ATHROW());
+        mg.addExceptionHandler(startSynchronized, chainCall, handler, Type.THROWABLE);
+        
+		// tidy:
+        mg.setMaxStack();
+        mg.setMaxLocals();
+        Method generatedMethod = mg.getMethod();
+        il.dispose();
+        return generatedMethod;
+    }
+
+	/**
+	 * Generate a version of the passed method which only calls its super method 
+	 * (which will eventually call an initial-wrapper in a directly bound class).
+	 * @param m		the original method
+	 * @param cg	the ClassGen of the appropriate class
+	 * @param cpg the ConstantPoolGen of the class
+	 * @return			the generated method
+	 */
+	Method generateSuperCall (Method          m,
+							  ClassGen        cg,
+							  ConstantPoolGen cpg)
+	{
+		short invocationKind = m.isStatic() ? Constants.INVOKESTATIC : Constants.INVOKESPECIAL;
+        MethodGen mg = getConcretMethodGen(m, cg.getClassName(), cpg);
+
+        String  method_name     = m.getName();
+        Type    returnType      = mg.getReturnType();
+        Type[]  argTypes        = mg.getArgumentTypes();
+        InstructionList il      = mg.getInstructionList();
+
+        if(logging) printLogMessage("\nReplacing with call to super: " + method_name); //$NON-NLS-1$
+		// start generating
+		if(!m.isStatic()){ //JU
+			il.append(InstructionFactory.createThis());
+		} 
+        int index = 1;
+        for (int i=0; i<argTypes.length; i++) {
+            il.append(InstructionFactory.createLoad(argTypes[i],index));
+            index += argTypes[i].getSize();
+        }
+        il.append(factory.createInvoke(cg.getSuperclassName(), method_name,
+									   returnType, argTypes,
+									   invocationKind));
+        il.append(InstructionFactory.createReturn(returnType));
+		// generated invoke: return super.<method_name> (a1,.. aN)
+
+		// tidy:
+        mg.setMaxStack();
+        mg.setMaxLocals();
+        Method generatedMethod = mg.getMethod();
+        il.dispose();
+        return generatedMethod;
+	}
+
+	
+	/**
+	 * Generate a chaining wrapper for the original method described by the passed arguments. 
+	 * This includes dispatch code and the termination condition for the recursion.
+	 * @param mg								the MethodGen of the original method
+	 * @param method_name			the name of the original method
+	 * @param method_signature	the signature of the original method
+	 * @param class_name				the name of the appropriate class
+	 * @param cpg								the ConstantPoolGen of the class
+	 * @param cg								the ClassGen of the class
+	 * @param firstLine							the first real source line of this method
+	 * @return
+	 */
+	Method generateChainingWrapper(MethodGen 		mg,
+								   String 	 		method_name,
+								   String 	 		method_signature,
+								   String 	 		class_name, 
+								   ConstantPoolGen 	cpg, 
+								   ClassGen  		cg,
+								   int 		 		firstLine)
+    {
+        Type     origReturnType        = mg.getReturnType();
+        Type[]   argumentTypes         = mg.getArgumentTypes();
+        String[] argumentNames         = mg.getArgumentNames();
+        Type[]   enhancedArgumentTypes = enhanceArgumentTypes(argumentTypes);
+        String[] enhancedArgumentNames = enhanceArgumentNames(argumentNames);
+        Type enhancedReturnType = object;  // ALWAYS!
+
+        InstructionList il = new InstructionList();
+
+        // the chaining wrapper has to be 'public' because it will be called by base calls:
+        int accessFlags = makePublicFlags(mg.getAccessFlags());
+        
+        MethodGen chainMethod = new MethodGen(accessFlags,
+                                              enhancedReturnType,
+                                              enhancedArgumentTypes,
+                                              enhancedArgumentNames,
+                                              genChainMethName(method_name),
+                                              class_name,
+                                              il, cpg);
+
+		// All chaining calls return an Object.
+		// Need to store this in a local variable to keep the stack
+		// balanced, because each section (before, replace, after)
+		// is guarded by its own exception handler, and they don't
+		// like pending objects on the stack.
+        InstructionHandle ih;
+        int result, ot_team;
+		{
+			LocalVariableGen lg =
+				chainMethod.addLocalVariable("_OT$result", enhancedReturnType, //$NON-NLS-1$
+											 null, null);
+			result = lg.getIndex();
+			ih = il.append(InstructionFactory.createNull(enhancedReturnType));
+			if (debugging)
+				chainMethod.addLineNumber(ih, STEP_OVER_LINENUMBER);
+			lg.setStart(il.append(InstructionFactory.createStore(enhancedReturnType, result)));
+			// generated: RType _OT$result = null;
+			
+			lg = chainMethod.addLocalVariable("_OT$team", teamType, null, null); //$NON-NLS-1$
+			ot_team = lg.getIndex();
+			// generated: Team _OT$team;
+		}
+		
+		int indexOffset = chainMethod.isStatic() ? -1 : 0; // argument indizes are decremented for static methods, 
+                                                           // because of the missing 'this'
+		short invocationKind = getInvocationType(mg);
+
+        il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG + indexOffset));
+        il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG + indexOffset));
+        il.append(new ARRAYLENGTH());
+        IF_ICMPLT recursionNotYetTerminated = new IF_ICMPLT(null);
+        il.append(recursionNotYetTerminated);
+        // generated: if (_OT$teams.length < _OT$idx) {
+
+        
+		// load arguments:
+        if (!chainMethod.isStatic()) {
+        	ih = il.append(InstructionFactory.createThis());
+        } else {
+        	ih = il.append(new NOP());
+        }
+        if (debugging)
+        	chainMethod.addLineNumber(ih, SHOW_ORIG_CALL ? firstLine : STEP_INTO_LINENUMBER); // show orig call at method header ("dispatching")
+
+        int index = EXTRA_ARGS + 1;
+        for (int i = 0; i < argumentTypes.length; i++) {
+            il.append(InstructionFactory.createLoad(argumentTypes[i], index + indexOffset));
+            index += argumentTypes[i].getSize();
+        }
+		//
+        il.append(factory.createInvoke(class_name, genOrigMethName(method_name),
+                                       origReturnType, argumentTypes,
+									   invocationKind));
+		// generated: this._OT$<method_name>$orig (a1,.., aN) 	for nonstatic case
+        //                     _OT$<method_name>$orig (a1,.., aN) 			for static case
+		
+        if (debugging)
+        	chainMethod.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER);
+        
+        adjustValue(il, null, origReturnType, enhancedReturnType);
+        il.append(InstructionFactory.createReturn(enhancedReturnType));
+        // generated: return _OT$result;
+
+        ih = il.append(new NOP());
+        recursionNotYetTerminated.setTarget(ih);
+        // generated: ; (end of the if part)
+
+        il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG + indexOffset));
+        il.append(InstructionFactory.createLoad(Type.INT,  IDX_ARG + indexOffset));
+        il.append(InstructionFactory.createArrayLoad(teamType));
+        il.append(InstructionFactory.createStore(teamType, ot_team));
+        // generated: _OT$team = _OT$teams[_OT$idx];
+
+        // ---------------------------------------------
+        createDispatchCode(chainMethod, il,
+						   class_name, method_name,
+						   method_signature, result, ot_team, cg, firstLine);
+        // ---------------------------------------------
+
+		ih = il.append(InstructionFactory.createLoad(enhancedReturnType, result));
+        il.append(InstructionFactory.createReturn(enhancedReturnType));
+        // generated: return _OT$result;
+        if (debugging)
+        	chainMethod.addLineNumber(ih, STEP_OVER_LINENUMBER);
+        
+		// tidy:
+		chainMethod.removeNOPs();
+		try { // [SH]: overcautious: I once saw this CCE with no clue, why it happened :(
+			chainMethod.setMaxStack();
+		} catch (ClassCastException cce) {
+			System.err.println(chainMethod);
+			cce.printStackTrace();
+		}
+        chainMethod.setMaxLocals();
+		//chainMethod.removeNOPs();
+		Method generated = chainMethod.getMethod();
+		il.dispose();
+        return generated;
+    }
+
+	private short getInvocationType(MethodGen chainMethod) {
+		if (chainMethod.isStatic())
+			return Constants.INVOKESTATIC;
+		if (chainMethod.isPrivate())
+			return Constants.INVOKESPECIAL;
+		else
+			return Constants.INVOKEVIRTUAL;
+	}
+
+	/**
+	 * @param i
+	 * @return
+	 */
+	private static int makePublicFlags(int flags) {
+		if ((flags & Constants.ACC_PUBLIC) != 0) {
+			return flags;
+		}
+		if ((flags & Constants.ACC_PRIVATE) != 0) {
+			flags &= ~Constants.ACC_PRIVATE;
+		} else if ((flags & Constants.ACC_PROTECTED) != 0) {
+			flags &= ~Constants.ACC_PROTECTED;
+		}
+		flags |= Constants.ACC_PUBLIC;
+		return flags;
+	}
+
+	/**
+	 *  Generate the dispatch code by which a chaining wrapper invokes the
+	 *  callin method(s).
+	 *  This consists of three switch blocks: before, replace, after.
+	 * @param chainMethod				the chaining wrapper method
+	 * @param il									the InstructionList of the chaining wrapper			
+	 * @param class_name				the name of the appropriate class
+	 * @param method_name			the name of the original method
+	 * @param method_signature	the signature of the original method
+	 * @param result							the index of the '_OT$result' variable
+	 * @param ot_team						the index of the variable containing the team currently processed by the chaining wrapper
+	 * @param cg								the ClassGen of the appropriate class
+	 * @param firstLine							the first real source line of this method
+	 */
+	void createDispatchCode(MethodGen chainMethod, InstructionList il,
+							String class_name, String method_name,
+							String method_signature, int result, int ot_team, ClassGen cg, int firstLine)
+    {
+
+        //    get bindings for actually modified methods and sort them by callin-modifier:
+        //      modifier -> ArrayList<MethodBinding>
+        HashMap<String, ArrayList<MethodBinding>> sortedMethodBindings = new HashMap<String, ArrayList<MethodBinding>>();
+        Collection<MethodBinding> callinsForMethod;
+        callinsForMethod = CallinBindingManager.getBindingForBaseMethod(class_name,
+        																method_name, method_signature);
+        //System.err.println(class_name +" : "+callinsForMethod);
+        List<MethodBinding> inheritedMethodBindings = CallinBindingManager.getInheritedBaseMethodBindings(class_name, method_name, method_signature);
+        //System.err.println(inheritedMethodBindings);
+        
+        //--------------------------------------------------------------------------------------------
+        //JU: initialize callinsForMethod for overridden static base methods (begin)
+//        if(chainMethod.isStatic()){
+//        	if(callinsForMethod == null) {
+//        		callinsForMethod = new LinkedList();
+//        	}
+//        	
+//        	Collection classesDefBindingsToStaticMethods = CallinBindingManager.getInheritedCallinBindingsForStaticMethods(class_name, method_name, method_signature);
+//        	Iterator classesIt = classesDefBindingsToStaticMethods.iterator();
+//        	while(classesIt.hasNext()){
+//        		String superClassName = (String) classesIt.next();
+//        		Collection callinsFromSuperClasses = CallinBindingManager.getBindingForBaseMethod(superClassName, method_name, method_signature);
+//        		callinsForMethod.addAll(callinsFromSuperClasses);
+//        	}
+//        }
+        //JU: (end)
+        //----------------------------------------------------------------------------------------------
+        if (!chainMethod.isStatic())
+        	callinsForMethod.addAll(inheritedMethodBindings);
+        
+        /*
+        String[] interfaceNames = cg.getInterfaceNames();
+		Collection interfaceInheritedMethodBindings  = new LinkedList();
+		for (int i=0; i<interfaceNames.length;i++) {
+			if (!interfaceNames[i].equals(class_name))
+				interfaceInheritedMethodBindings.addAll(
+						CallinBindingManager.getInterfaceInheritedMethodBindings(method_name,
+																														  method_signature, 
+																														  interfaceNames[i]));
+		}
+
+		if (callinsForMethod == null)
+			callinsForMethod = new LinkedList();
+		
+		callinsForMethod.addAll(interfaceInheritedMethodBindings);
+       */
+        ListValueHashMap<MethodBinding> beforeBindings = new ListValueHashMap<MethodBinding>();
+        ListValueHashMap<MethodBinding> replaceBindings = new ListValueHashMap<MethodBinding>();
+        ListValueHashMap<MethodBinding> afterBindings = new ListValueHashMap<MethodBinding>();
+        
+        Iterator<MethodBinding> it = callinsForMethod.iterator();
+        while (it.hasNext()) {
+        	MethodBinding methodBinding = it.next();
+        	//sourceMapGen.addSourceMapInfo(methodBinding);
+        	String        modifier      = methodBinding.getModifier();
+        	ArrayList<MethodBinding>     bindings      = sortedMethodBindings.get(modifier);
+        	if (bindings == null) {
+        		bindings = new ArrayList<MethodBinding>();
+        		sortedMethodBindings.put(modifier, bindings);
+        	}
+        	bindings.add(methodBinding);
+        	// ----> added for predecedence purpose:
+        	String teamName = methodBinding.getTeamClassName();
+        	if (modifier.equals("before")) {                    //$NON-NLS-1$
+        		beforeBindings.put(teamName, methodBinding);
+        	} else if (modifier.equals("replace")) {            //$NON-NLS-1$
+        		replaceBindings.put(teamName, methodBinding);
+        	} else if (modifier.equals("after")) {              //$NON-NLS-1$
+        		afterBindings.put(teamName, methodBinding);
+        	}
+        	// <---
+        }
+        
+        // if any team has multiple bindings, we need to insert additional checks to avoid duplicate
+        // invocation of before/after causes during recursion.
+        boolean useBindingIdx = false;
+        for (LinkedList<MethodBinding> perTeamMethods : replaceBindings.valueSet())
+        	if (perTeamMethods.size() > 1) {
+        		useBindingIdx = true;
+        		break;
+        	}
+
+        /****************************************************************************/
+        // before callin :
+        if (sortedMethodBindings.containsKey("before")) {          //$NON-NLS-1$
+            if(logging) printLogMessage("before bindings will be applied..."); //$NON-NLS-1$
+        	il.append(createSwitch(
+        				  beforeBindings,
+        				  chainMethod, ot_team,
+        				  NORESULT, firstLine, cg.getMajor(), useBindingIdx));
+            if(logging) printLogMessage("before bindings: "        //$NON-NLS-1$
+        					+ sortedMethodBindings.get("before")); //$NON-NLS-1$
+        }
+        /****************************************************************************/
+        // replacement callin or direct recursion :
+        if (sortedMethodBindings.containsKey("replace")) { //$NON-NLS-1$
+            if(logging) printLogMessage("recursive call and replace bindings will be applied..."); //$NON-NLS-1$
+        	il.append(createSwitch(
+        				  replaceBindings,
+        				  chainMethod, ot_team,
+        				  result, firstLine, cg.getMajor(), useBindingIdx));
+            if(logging) printLogMessage("replace bindings: " //$NON-NLS-1$
+        					+ sortedMethodBindings.get("replace")); //$NON-NLS-1$
+        } else {
+            if(logging) printLogMessage("recursive chain-method call will be done..."); //$NON-NLS-1$
+        	// recursive call:
+
+			createRecursiveCall(il, chainMethod, result, 1, 0, method_name, method_signature, firstLine);
+        }
+        /****************************************************************************/
+        // after callin :
+        if (sortedMethodBindings.containsKey("after")) { //$NON-NLS-1$
+            if(logging) printLogMessage("after bindings will be applied..."); //$NON-NLS-1$
+        	il.append(createSwitch(
+        				  afterBindings,
+        				  chainMethod, ot_team,
+        				  /*NORESULT*/result, firstLine, cg.getMajor(), useBindingIdx));
+            if(logging) printLogMessage("after bindings: " //$NON-NLS-1$
+        					+ sortedMethodBindings.get("after")); //$NON-NLS-1$
+        }
+    }
+
+	/**
+	 *  Create a switch statement which contains one case for each MethodBinding
+	 *  in a given list.
+	 *  The switch block is furthermore wrapped in a try-catch block.
+	 *  Herein all {@link org.objectteams.LiftingVetoException LiftingVetoException}
+	 *  are caught, and possibly reported (if Dot.log.lift ist set).
+	 * @param methodBindings hash map of team names to 'MethodBinding' lists
+	 * @param mg method being generated.
+	 * @param ot_team index of local variable <tt>_OT$team</tt>
+	 * @param ot_result index of local variable <tt>_OT$result</tt>
+	 */
+	private InstructionList createSwitch(ListValueHashMap<MethodBinding> methodBindings, MethodGen mg,
+										 int ot_team, int ot_result,
+										 int firstLine,
+										 int major,
+										 boolean useBindingIdx)
+	{
+        InstructionList il = new InstructionList();
+
+		boolean handlesReplacement = false;
+
+		int indexOffset = mg.isStatic()?-1:0; // argument indizes are decremented for static methods, 
+                                                                       // because of the missing 'this'
+        
+		// load value to be switched:
+        il.append(InstructionFactory.createLoad(intArray, TEAMIDS_ARG+indexOffset));
+        il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG+indexOffset));
+        InstructionHandle switchStart = il.append(InstructionFactory.createArrayLoad(Type.INT));
+		// generated: _OT$teamIDs[_OT$idx]
+
+        int numberOfCases = methodBindings.size();
+
+        // one break for each case clause
+        GOTO[] breaks = new GOTO[numberOfCases];
+        for (int i = 0; i < numberOfCases; i++)
+            breaks[i] = new GOTO(null);
+
+        int[]               matches = new int[numberOfCases];
+        InstructionHandle[] targets = new InstructionHandle[numberOfCases];
+
+        int      caseCounter     = 0;
+        
+        List<MethodBinding> methodBindingsForTeam = null;
+        MethodBinding mb = null;
+        Iterator <Entry<String, LinkedList<MethodBinding>>> teamIterator = methodBindings.entrySet().iterator();
+		while (teamIterator.hasNext()) {
+			Entry<String, LinkedList<MethodBinding>> entry = teamIterator.next();
+			String teamName = entry.getKey();
+			methodBindingsForTeam = entry.getValue();
+			//System.out.println(methodBindings.get(teamName));
+			
+			/*MethodBinding*/ mb = methodBindingsForTeam.get(0);
+			
+            matches[caseCounter] = TeamIdDispenser.getTeamId(teamName);
+            InstructionHandle nextBranch = il.append(new NOP());
+
+            // generate (_OT$teamID == teamId) branch here:
+
+			// ========== create Cases: ==========
+            if (mb.isReplace()) { // distinct treatment of replacement:
+				handlesReplacement = true;
+				createReplaceCase(mg, il,
+								  teamName, methodBindingsForTeam,
+								  ot_result, ot_team, major, firstLine);
+			} else { // before or after callin:
+				BranchInstruction ifBindingIdx = null;
+				if (useBindingIdx) {
+					// only if bindingIdx == 0
+					il.append(InstructionFactory.createLoad(Type.INT, BIND_IDX_ARG+indexOffset));
+					ifBindingIdx= new IFNE(null);
+					il.append(ifBindingIdx);
+				}
+                createBeforeAfterCase(mg, il, teamName,
+									  methodBindingsForTeam, ot_result, ot_team, major, firstLine);
+				if (useBindingIdx) {
+					ifBindingIdx.setTarget(il.append(new NOP()));
+				}
+			}
+
+			// ===================================
+
+            targets[caseCounter] = nextBranch;
+            /*InstructionHandle break_instr =*/ il.append(breaks[caseCounter]);
+			// generated: break;
+  
+            caseCounter++;
+        } // end of while
+        	
+        // generate default branch here:
+        InstructionHandle defaultBranch = il.append(new NOP());
+        if (handlesReplacement)
+			createRecursiveCall(il, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine);
+
+        InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here.
+
+		// ===== assemble the switch ====
+		il.append(switchStart,
+				  createLookupSwitch(matches, targets, breaks,
+									 defaultBranch, afterSwitch)
+				 );
+		// ==============================
+
+		// wrap everything in a try {} catch (LiftingVetoException e) {..}
+		InstructionHandle endTry = il.getEnd();
+
+		GOTO skipHdlr = null;
+		skipHdlr = new GOTO(null);
+		il.append(skipHdlr);
+		// generated: goto normal exit
+
+		InstructionHandle hdlr = il.append(new NOP());
+		il.append(DebugUtil.createReportExc(factory));
+
+		// catch: proceed with recursion if caught in a replace call
+		if (handlesReplacement)
+			createRecursiveCall(il, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine);
+
+		mg.addExceptionHandler(il.getStart(), endTry, hdlr, liftingVeto);
+
+		InstructionHandle nop = il.append(new NOP());
+		skipHdlr.setTarget(nop);
+
+        return il;
+    }
+
+	/** Create the recursice call of this chaining method.
+	 * @param il insert the call into this list.
+	 * @param mg this chaining method
+	 * @param ot_result stack index of the _OT$result variable or NORESULT.
+	 * @param idx_offset TODO
+	 * @param bindIdx_offset TODO
+	 * @param methodName TODO
+	 * @param methodSignature TODO
+	 */
+	void createRecursiveCall (InstructionList il,
+							  MethodGen mg,
+							  int ot_result, int idx_offset, int bindIdx_offset, String methodName, String methodSignature, int firstLine)
+	{
+		InstructionHandle ih = !mg.isStatic()
+				? il.append(InstructionFactory.createThis())
+				: il.append(new NOP());
+		if (debugging)
+			mg.addLineNumber(ih, SHOW_RECURSIVE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show recursive call at method header ("dispatching")
+		
+ 		Type[] argTypes = mg.getArgumentTypes();
+		Type returnType = mg.getReturnType();
+		short invocationKind = getInvocationType(mg);
+		
+		// arguments: no adjustment except idx++.
+		int index = 1;
+		int indexOffset = mg.isStatic()?-1:0; // argument indizes are decremented for static methods, 
+                                                                       // because of the missing 'this'
+		for (int i=0; i<argTypes.length; i++) {
+			il.append(InstructionFactory.createLoad(argTypes[i], index+indexOffset));
+			if (index == OTConstants.IDX_ARG && idx_offset != 0) { // _OT$idx has to be incremented (adding idx_offset)
+				il.append(new ICONST(idx_offset));
+				il.append(new IADD());
+			} else if (index == OTConstants.BIND_IDX_ARG) { // _OT$bindIdx has to be incremented (adding bindIdx_offset)
+				if (bindIdx_offset == 0) { // bindArg argument has to be set to '0'
+					il.append(new POP()); 			// remove loaded _OT$bindIdx
+					il.append(new ICONST(0)); // replace it by '0' 
+				} else {
+					il.append(new ICONST(bindIdx_offset));
+					il.append(new IADD());
+				}
+			}
+			index += argTypes[i].getSize();
+		}
+		il.append(factory.createInvoke(mg.getClassName(), mg.getName(),
+									   returnType, argTypes,
+									   invocationKind));
+
+		il.append(InstructionFactory.createStore(returnType, ot_result));
+
+		// _OT$result = _OT$<method_name>$chain(_OT$teams, _OT$teamIDs, _OT$idx+1,
+		//                                         a1, .., aN);
+		if (debugging)
+			mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER);
+	}
+
+
+	/**
+	 * Create a block for a before or after callin as a case with a surrounding switch.
+	 * @param mg TODO
+	 * @param il InstructionList being assembled.
+	 * @param connectorClassName name of a Team which has a callin to this method.
+	 * @param mbList MethodBindings describing the callins.
+	 * @param ot_result index of local variable <tt>_OT$result</tt>.
+	 * @param ot_team  index of local variable <tt>_OT$team</tt>.l
+	 * @param major
+	 * @param firstLine							the first real source line of this method
+	 */
+	void createBeforeAfterCase(MethodGen mg,
+							   InstructionList il, String connectorClassName,
+							   List<MethodBinding> mbList, int ot_result, int ot_team,
+							   int major, int firstLine)
+    {	
+
+		MethodBinding mb = mbList.get(0);
+		ConstantPoolGen cpg = mg.getConstantPool();
+		
+		mbList = CallinBindingManager.sortMethodBindings(mbList, connectorClassName);
+		
+		Iterator<MethodBinding> it = mbList.iterator();
+		while (it.hasNext()) {
+			/*MethodBinding nextMethodBinding*/mb = it.next();
+		
+			String baseMethodSignature = mb.getBaseMethodSignature();
+			Type[] baseArgTypes = Type.getArgumentTypes(baseMethodSignature);
+			Type baseReturnType = Type.getReturnType(baseMethodSignature);
+			
+			Type[] wrapperArgTypes = Type.getArgumentTypes(mb.getWrapperSignature());
+			int argsLen = wrapperArgTypes.length - 1; // don't count base arg.
+			
+			il.append(InstructionFactory.createLoad(teamType, ot_team));
+
+			int packedArgPos = 0;
+			InstructionHandle argArray = null;
+			if (useReflection) {
+				il.append(factory.createInvoke("java.lang.Object", "getClass", classType, new Type[0], Constants.INVOKEVIRTUAL));
+				il.append(new LDC(cpg.addString(mb.getWrapperName())));
+				pushTypeArray(il, wrapperArgTypes, major, cpg);
+				il.append(factory.createInvoke("java.lang.Class", "getMethod", methodType, OTConstants.getMethodSignature, Constants.INVOKEVIRTUAL));
+				
+				il.append(InstructionFactory.createLoad(teamType, ot_team));
+				// generated: 
+				//   _OT$team.getClass().getMethod(<wrapperName>, <wrapper sign>)  
+				//   _OT$team
+				argArray = il.append(new ANEWARRAY(cpg.addClass(object)));
+				
+			} else {
+				il.append(factory.createCast(teamType, new ObjectType(connectorClassName)));
+				// generated: (<TeamClass>)_OT$team
+			}
+			
+			// first argument: base object:
+			packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+			{
+				if (!mg.isStatic())
+					il.append(InstructionFactory.createThis());
+				else
+					il.append(InstructionFactory.createNull(Type.OBJECT)); // no base object
+			}
+			checkPackValue1(il, useReflection, Type.OBJECT);
+			
+			// second argument: base result (if appropriate)
+			if ( mb.isAfter() && !baseReturnType.equals(Type.VOID)) { // after callin wrapper get the base method result as second argument
+				packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+				{
+					il.append(InstructionFactory.createLoad(object, ot_result));
+					adjustValue(il, null, object, baseReturnType);
+					argsLen --; // the second (result) arg is also not part of the arg list
+				}
+				checkPackValue1(il, useReflection, baseReturnType);
+			}
+			
+			// ------- load regular args: --------
+			
+			// stack positions for load instructions (one-based for non-statics, since 0 == this)
+			int stackIndex = EXTRA_ARGS + (mg.isStatic() ? 0 : 1);
+			// where within baseArgTypes do source arguments start?
+			int firstArg = 0;
+			
+			if (mb.baseMethodIsCallin()) {
+				// skip enhancement of this callin method (lower role).
+				firstArg   += EXTRA_ARGS;
+				stackIndex += EXTRA_ARGS;
+				argsLen    += EXTRA_ARGS;
+			}
+			for (int i = firstArg; i < argsLen; i++) {
+                if(logging) printLogMessage("loading " + baseArgTypes[i].toString()); //$NON-NLS-1$
+
+                packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+                {
+					il.append(InstructionFactory.createLoad(baseArgTypes[i],stackIndex));
+                }
+				checkPackValue1(il, useReflection, baseArgTypes[i]);
+				
+				stackIndex += baseArgTypes[i].getSize();
+			}
+			
+			InstructionHandle callinCall;
+			if (useReflection) {
+				// this information was missing above:
+				il.insert(argArray, createIntegerPush(cpg, packedArgPos));
+				
+				callinCall = il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", object, new Type[]{object, objectArray}, Constants.INVOKEVIRTUAL));
+				il.append(new POP()); // before/after wrappers return void
+			} else {
+				callinCall = il.append(factory.createInvoke(connectorClassName,
+											   mb.getWrapperName(),
+											   Type.VOID, wrapperArgTypes,
+											   Constants.INVOKEVIRTUAL));
+			}
+			if (debugging) {
+				mg.addLineNumber(callinCall, SHOW_ROLE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show role call at method header ("dispatching")
+				mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER);
+			}
+		}
+    }
+
+	/* this and the next method serve as a bracket for all pushes that may or may not require
+	 * packing in an array, the array must already exist on the stack. */
+	private int checkPackValue0(InstructionList il, boolean doPack, int argCount, ConstantPoolGen cpg) {
+		if (doPack) {
+			il.append(new DUP());
+			il.append(createIntegerPush(cpg, argCount));
+			return argCount+1;
+		} else {
+			return argCount;
+		}
+	}
+	private void checkPackValue1(InstructionList il, boolean doPack, Type argType) {
+		if (doPack) {
+			if (argType instanceof BasicType)
+				il.append(createBoxing((BasicType)argType));
+			il.append(new AASTORE());
+		}
+	}
+	/* Push an array of Class representing the signature given by argTypes. */
+	private void pushTypeArray(InstructionList il, Type[] argTypes, int major, ConstantPoolGen cpg) {
+		il.append(createIntegerPush(cpg, argTypes.length));
+		il.append(new ANEWARRAY(cpg.addClass(classType)));
+		for (int i=0; i<argTypes.length; i++) {
+			Type type = argTypes[i];
+			il.append(new DUP());
+			il.append(createIntegerPush(cpg, i));
+			if (type instanceof BasicType) {
+				il.append(factory.createFieldAccess(toObjectTypeName((BasicType)type), "TYPE", classType, Constants.GETSTATIC));
+			} else if (type instanceof ObjectType) {
+				appendClassLiteral(il, ((ObjectType)type).getClassName(), major, cpg);
+			} else if (type instanceof ArrayType) { 
+				String prefix = "";
+				while (type instanceof ArrayType) {
+					prefix += '[';
+					type = ((ArrayType)type).getElementType();
+				}
+				String elemTypeName = null;
+				if (type instanceof ObjectType)
+					elemTypeName = "L"+((ObjectType)type).getClassName()+';';
+				else if (type instanceof BasicType)
+					elemTypeName = ((BasicType)type).getSignature();
+				appendClassLiteral(il, prefix+elemTypeName, major, cpg);
+			} else {
+				throw new OTREInternalError("unsupported type in signature "+type);
+			}
+			il.append(new AASTORE());
+		}
+	}
+
+	/**
+	 * Create a block for a replace callin as a case within a surrounding switch. If there are multiple bindings from the 
+	 * same team to this base method, the bindings are sorted according to the precedence list of this team.
+	 * @param mg base method being generated.
+	 * @param il instruction list being assembled.
+	 * @param connectorClassName name of a Team which has a callin to this method.
+	 * @param mbList list of 'MethodBinding's
+	 * @param ot_result index of a local variable <tt>_OT$result</tt>.
+	 * @param ot_team  index of local variable <tt>_OT$team</tt>.
+	 * @param major class file version
+	 */
+	void createReplaceCase(MethodGen mg, InstructionList il,
+						   String connectorClassName, List<MethodBinding> mbList,
+						   int ot_result, int ot_team, int major, int firstLine)
+    {
+		
+		int indexOffset = mg.isStatic() ? -1 : 0; // argument indizes are decremented for static methods, 
+												  // because of the missing 'this' 
+		boolean multipleBindings = mbList.size() > 1;
+		mbList = CallinBindingManager.sortMethodBindings(mbList, connectorClassName);
+		
+		MethodBinding mb = mbList.get(0); // default, if only one binding exists
+		
+		LocalVariableGen unused_args_lg = mg.addLocalVariable(UNUSED, objectArray, null, null);
+		int unused_args = unused_args_lg.getIndex();
+		unused_args_lg.setStart(il.append(new NOP()));
+		if (multipleBindings) {
+			InstructionList addition = new InstructionList();
+			// load value to be switched:
+			
+			InstructionHandle switchStart = addition.append(InstructionFactory.createLoad(Type.INT, BIND_IDX_ARG+indexOffset)); 
+			// loaded _OT$bindIdx
+			
+			int numberOfCases = mbList.size();
+			
+			// one break for each case clause
+			GOTO[] breaks = new GOTO[numberOfCases];
+			for (int i=0; i<numberOfCases; i++)
+				breaks[i] = new GOTO(null);
+			
+			int[] matches = new int[numberOfCases];
+			InstructionHandle[] targets = new InstructionHandle[numberOfCases];
+			
+			int      caseCounter     = 0;
+			Iterator<MethodBinding> mbIterator = mbList.iterator();
+			while (mbIterator.hasNext()) {
+				mb = mbIterator.next();
+				matches[caseCounter] = caseCounter;
+				InstructionHandle nextBranch = addition.append(new NOP());
+				// ========== create Cases: ===========
+				addition.append(createSingleReplaceCallin(mg, connectorClassName, mb, ot_result, ot_team, unused_args, multipleBindings, mg.isStatic(), major, firstLine));
+				// ==============================
+				targets[caseCounter] = nextBranch;
+				/*InstructionHandle break_instr =*/ addition.append(breaks[caseCounter]);
+				// generated: break;
+				caseCounter++;
+			}
+			// ========== create default: ===========
+			InstructionHandle defaultBranch = addition.append(new NOP());
+			createRecursiveCall(addition, mg, ot_result, 1, 0, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine);
+			// ==============================
+			
+			InstructionHandle afterSwitch = addition.append(new NOP()); // all breaks point here.
+			
+			for (int i=0; i<numberOfCases; i++)
+				breaks[i].setTarget(afterSwitch);
+			
+			addition.append(switchStart, new TABLESWITCH(matches, targets, defaultBranch));
+			// wrap everything in a try {} catch (LiftingVetoException e) {..}
+			InstructionHandle endTry = addition.getEnd();
+			
+			GOTO skipHdlr = null;
+			skipHdlr = new GOTO(null);
+			addition.append(skipHdlr);
+			// generated: goto normal exit
+			
+			InstructionHandle hdlr = addition.append(new NOP());
+			addition.append(DebugUtil.createReportExc(factory));
+			
+			// ========== create catch instructions: ===========
+			createRecursiveCall(addition, mg, ot_result, 0, 1, mb.getBaseMethodName(), mb.getBaseMethodSignature(), firstLine);
+			// =====================================
+			mg.addExceptionHandler(addition.getStart(), endTry, hdlr, liftingVeto);
+			
+			InstructionHandle nop = addition.append(new NOP());
+			skipHdlr.setTarget(nop);
+			il.append(addition);
+		} else { // only a single replace callin:
+			il.append(createSingleReplaceCallin(mg, connectorClassName, mb, ot_result, ot_team, unused_args, multipleBindings, mg.isStatic(), major, firstLine));
+		}
+		unused_args_lg.setEnd(il.getEnd());
+	}
+
+	/**
+	 * Creates a single replace callin call.
+	 *
+	 * @param mg						base method being generated.
+	 * @param connectorClassName		name of a Team which has a callin to this method.
+	 * @param mb						the 'MethodBinding' for this callin. 
+	 * @param ot_result					index of a local variable <tt>_OT$result</tt>.
+	 * @param ot_team					index of local variable <tt>_OT$team</tt>.
+	 * @param unused_args				index of local variable <tt>_OT$unused_args</tt>.
+	 * @param multipleBindings			flag indicating if there are multiple bindings in this case
+	 * @param staticBaseMethod TODO
+	 * @param major 					class file version
+	 * @param firstLine					first real source line number of this method
+	 * @return							instruction list for the callin call
+	 */
+	private InstructionList createSingleReplaceCallin(MethodGen mg, String connectorClassName, MethodBinding mb, int ot_result, int ot_team, int unused_args, boolean multipleBindings, boolean staticBaseMethod, int major, int firstLine) 
+	{
+		// Sequence of values to load is (letters refer to document parameter-passing.odg):
+		// (f) _OT$team: 	call target for invoking the callin-wrapper
+		// (g) baseObject:	this or null
+		// (h) enhancement: [Team[IIII[Object; 
+		// 					idxs are being manipulated here,
+		//					unusedArgs[] is allocated and filled with 
+		// (i)                - (int,Team) if current method is static role method.
+		// (j)                - enhancement arguments, if current method is callin method
+		// (k) regular arguments.
+		
+		// ------------------------------------------
+    	//               prepare Types:
+		// ------------------------------------------
+		Type[] chainArgTypes = mg.getArgumentTypes();
+    	Type[] baseArgTypes  = Type.getArgumentTypes(mb.getBaseMethodSignature());
+    	Type[] roleArgTypes  = Type.getArgumentTypes(mb.getRoleMethodSignature());
+    	roleArgTypes = enhanceArgumentTypes(roleArgTypes);
+    	String wrapperName = mb.getWrapperName();
+    	Type wrapperReturnType = Type.getReturnType(mb.getWrapperSignature());
+
+    	Type[] wrapperArgTypes = Type.getArgumentTypes(mb.getWrapperSignature());
+    	
+    	// calculate return type:
+        Type chainReturnType = mg.getReturnType();
+        
+        ConstantPoolGen cpg = mg.getConstantPool();
+        InstructionList il = new InstructionList();
+        // (f):
+        il.append(InstructionFactory.createLoad(teamType, ot_team));
+
+		int packedArgPos = 0;
+		InstructionHandle argArray = null;
+		if (useReflection) {
+			il.append(factory.createInvoke("java.lang.Object", "getClass", classType, new Type[0], Constants.INVOKEVIRTUAL));
+			il.append(new LDC(cpg.addString(mb.getWrapperName())));
+			pushTypeArray(il, wrapperArgTypes, major, cpg);
+			il.append(factory.createInvoke("java.lang.Class", "getMethod", methodType, OTConstants.getMethodSignature, Constants.INVOKEVIRTUAL));
+			
+			il.append(InstructionFactory.createLoad(teamType, ot_team));
+			// generated: 
+			//   _OT$team.getClass().getMethod(<wrapperName>, <wrapper sign>)  
+			//   _OT$team
+			argArray = il.append(new ANEWARRAY(cpg.addClass(object)));
+		} else {
+			il.append(factory.createCast(teamType, new ObjectType(connectorClassName)));
+			// generated: (<TeamClass>)_OT$team
+		}
+       
+        // (g):
+		packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+		{
+	        if(!staticBaseMethod)
+				il.append(InstructionFactory.createThis());
+			else
+				il.append(InstructionFactory.createNull(Type.OBJECT)); // no base object
+		}
+		checkPackValue1(il, useReflection, Type.OBJECT);
+        
+    	// ----------------------------------------
+    	// (h)   Load Extra Arguments:
+    	// ----------------------------------------
+        int staticOffset = staticBaseMethod?-1:0; // argument indizes are decremented for static methods, 
+		          								  // because of the missing 'this' 
+        // first 4 extra arguments: _OT$teams, _OT$teamIDs, _OT$idx, _OT$bindIdx
+        for (int i=0; i<4; i++) { // If this is called only once _OT$idx has to be incremented, else _OT$bindIdx has to be incremented
+        	packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+        	{
+	        	il.append(InstructionFactory.createLoad(chainArgTypes[i], i+1+staticOffset));
+	    		if (!multipleBindings && i+1+staticOffset == OTConstants.IDX_ARG+staticOffset) {// _OT$idx++:
+	    			il.append(new ICONST(1));
+	            	il.append(new IADD());
+	    		} else if (multipleBindings && i+1+staticOffset == OTConstants.BIND_IDX_ARG+staticOffset) {// _OT$bindIdx:
+	    			il.append(new ICONST(1));
+	            	il.append(new IADD());
+	    		}
+        	}
+        	checkPackValue1(il, useReflection, chainArgTypes[i]);
+        }
+		// _OT$baseMethTag:
+        int base_meth_tag = CallinBindingManager.getBaseCallTag(mb.getBaseClassName(), 
+												        		mb.getBaseMethodName(), 
+												        		mb.getBaseMethodSignature());
+//        //JU: added this if-statement (begin) ----------------------------------------------
+//        if(staticBaseMethod && !mg.getClassName().equals(mb.getBaseClassName())){
+//        	//the method binding is a dummy -> the callin wrapper is performed 
+//        	//with an invalid base method tag value -> an exception will be thrown
+//        	base_meth_tag = INVALID_BASE_METHOD_TAG;
+//        }
+//        //JU (end) --------------------------------------------------------------------------
+        
+        packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+        {
+        	il.append(createIntegerPush(cpg, base_meth_tag));
+        }
+        checkPackValue1(il, useReflection, Type.INT);
+
+        // collect regular args first, insert into il later:
+        InstructionList regularArgs = new InstructionList();
+        
+        // put "new Object[]" on stack, later containing unused arguments:
+        packedArgPos = checkPackValue0(il, useReflection, packedArgPos, cpg);
+        {
+	        il.append(createIntegerPush(cpg, baseArgTypes.length)); 
+	        		// enough space to hold ALL base arguments
+	        		// Note that the callin wrapper may add more elements to this array.
+	        il.append((Instruction)factory.createNewArray(object, (short)1));
+	        il.append(InstructionFactory.createStore(objectArray, unused_args));
+	        // generated: _OT$unusedArgs = new Object[<n_base_args>];
+	
+	    	// ----------------------------------------
+	        // handle more arguments: load regular ones, store unused arguments into the array:
+	    	// ----------------------------------------
+	        int unusedArgsIdx = 0; // index into Object[].
+	
+			int stackIdx = EXTRA_ARGS + 1 + staticOffset; // one-based, since 0 == this (unless static)
+			int regularArgsStart = EXTRA_ARGS;
+			boolean baseIsStaticCallin = mb.baseMethodIsCallin() && staticBaseMethod;
+			if (baseIsStaticCallin) { 
+				// (i) need these synthetic arguments up-front: "int dummy, Team enclosingTeam"
+				storeUnusedArg(il, unused_args, 0,  // constant
+						   	   new ICONST(0),
+						   	   Type.INT,
+						   	   cpg);
+				storeUnusedArg(il, unused_args, 1,  // constant 
+						   	   new ALOAD(regularArgsStart+1), 
+						   	   OTConstants.teamType,
+						   	   cpg);
+	
+				// consumed first two parameters into unusedArgs:
+				regularArgsStart+=2;
+				stackIdx += 2;
+				unusedArgsIdx += 2;
+			}
+	        for (int i=regularArgsStart; i<chainArgTypes.length; i++) {
+				Type argType = chainArgTypes[i];
+				Instruction loadingInstruction = InstructionFactory.createLoad(argType, stackIdx);
+				if (isRegularArg(i, mb.baseMethodIsCallin(), staticBaseMethod)) {
+					// (k) collect loading instruction, for appending after _OT$unusedArgs.
+					packedArgPos = checkPackValue0(regularArgs, useReflection, packedArgPos, cpg);
+					{
+						regularArgs.append(loadingInstruction);
+					}
+					checkPackValue0(regularArgs, useReflection, packedArgPos, cpg);
+				} else {
+					// (j) store unused arg 
+					storeUnusedArg(il, unused_args, unusedArgsIdx++, loadingInstruction, argType, cpg);
+					// generated: _OT$unusedArgs[<unusedArgsIdx>] = maybeBox(a<index>);
+				}
+				stackIdx += argType.getSize();
+	        }
+	        il.append(InstructionFactory.createLoad(objectArray, unused_args));
+        }
+        checkPackValue1(il, useReflection, objectArray);
+        
+		// (k) insert previously assembled load-sequence:
+        il.append(regularArgs);
+        
+    	// ============= INVOKEVIRTUAL (wrapper) =============
+        InstructionHandle callinCall;
+        if (useReflection) {
+    		// this information was missing above:
+			il.insert(argArray, createIntegerPush(cpg, packedArgPos));
+			
+			callinCall = il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", object, new Type[]{object, objectArray}, Constants.INVOKEVIRTUAL));
+			wrapperReturnType = Type.OBJECT;
+        } else {
+        	callinCall = il.append(factory.createInvoke(connectorClassName, wrapperName,
+    								   wrapperReturnType,
+    								   wrapperArgTypes,
+    								   Constants.INVOKEVIRTUAL));
+        }
+		if (debugging) {
+			mg.addLineNumber(callinCall, SHOW_ROLE_CALL ? firstLine : STEP_INTO_LINENUMBER); // show role call at method header ("dispatching")
+        	mg.addLineNumber(il.append(new NOP()), STEP_OVER_LINENUMBER);
+		}
+
+		adjustValue(il, null, wrapperReturnType, chainReturnType);
+		il.append(InstructionFactory.createStore(chainReturnType, ot_result));
+		
+		return il;
+	}
+
+	/**
+	 *  Store an unused value (loaded by pushInstruction) into _OT$unusedArgs 
+	 */
+	private void storeUnusedArg(InstructionList il, 
+								int 		    unused_args, 
+								int 			arrayIndex, 
+								Instruction 	pushInstruction,
+								Type        	argType,
+								ConstantPoolGen cpg) 
+	{
+		il.append(InstructionFactory.createLoad(objectArray, unused_args));
+		il.append(createIntegerPush(cpg, arrayIndex));
+		il.append(pushInstruction);
+		if (argType instanceof BasicType)
+			il.append(createBoxing((BasicType)argType));
+		il.append(InstructionFactory.createArrayStore(objectArray));
+	}
+
+	/**
+	 * Is the parameter at position idx mapped (by paramPositions or implicitly)?
+	 * Cut off head: 
+	 * 		- (int,Team) if present (static role method)
+	 * 		- enhancement (possible twice)
+	 * @param idx parameter index of enhanced signature
+	 */
+	static boolean isRegularArg (int idx, boolean baseIsCallin, boolean baseIsStatic) {
+		if (baseIsCallin && baseIsStatic) // FIXME(SH): should be baseIsRole instead of baseIsCallin!
+			idx -= 2;
+		int firstVisible = EXTRA_ARGS + (baseIsCallin?EXTRA_ARGS:0); // skip one or two enhancements
+		return idx >= firstVisible;
+	}
+
+	/**
+	 *  Given an argument of type <tt>actual</tt>, must
+	 *  we use type <tt>formal</tt> in signatures,
+	 *  because it is a supertype of <tt>actual</tt>?
+	 */
+	static Type checkWiden (Type actual, Type formal) {
+		if (!actual.equals(formal)
+			&& actual instanceof ObjectType
+			&& formal instanceof ObjectType)
+		{
+			ObjectType actualObj = (ObjectType)actual;
+			ObjectType formalObj = (ObjectType)formal;
+			if (actualObj.subclassOf(formalObj))
+				return formalObj;
+		}
+		return actual;
+	}
+
+	/**
+	 * Create an instruction list for initializing the role set field on-demand.
+	 * @param valueRequired should the role set be on the stack after this sequence?
+	 * @param cg	the ClassGen of the appropriate class
+	 */
+	private InstructionList getInitializedRoleSet(String class_name, boolean valueRequired) {;
+		InstructionList il = new InstructionList();
+
+		// try to retrieve existing set:
+		il.append(new ALOAD(0));
+		il.append(factory.createGetField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType));
+		if (valueRequired)
+			il.append(new DUP()); // a spare value to keep on the stack if successful
+		
+		// if (roleSet == null) ..
+		IFNONNULL branch = new IFNONNULL(null);
+		il.append(branch);
+
+		// conditionally create the set:
+		if (valueRequired)
+			il.append(new POP()); // remove useless "null", replace with DUP_X1 below
+		il.append(new ALOAD(0));
+		il.append(factory.createNew(OTConstants.roleSetType));
+		il.append(new DUP());
+		il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(),
+													 		Constants.CONSTRUCTOR_NAME,
+													 		Type.VOID,
+													 		Type.NO_ARGS, 
+													 		Constants.INVOKESPECIAL));
+		if (valueRequired)
+			il.append(new DUP_X1()); // push below pending "this"
+		
+		// store in the field:
+		il.append(factory.createPutField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType));
+	
+		// endif
+		branch.setTarget(il.append(new NOP()));
+		return il;
+	}
+	
+	/**
+	 * Generates the field '_OT$roleSet' which is used to store the added roles.
+	 * @param cpg			the ClassGen of the appropriate class
+	 * @param class_name	the name of the class
+	 * @return				the generated field
+	 */
+	private Field generateRoleSet(ConstantPoolGen cpg, String class_name) {
+		FieldGen fg = new FieldGen(Constants.ACC_PROTECTED, 
+                                   OTConstants.roleSetType,
+                                   OTConstants.ROLE_SET,
+                                   cpg);
+		return fg.getField();	
+	}
+	
+	/**
+	 * Generates the method 'public void _OT$addRole(Object role)' which adds the passed object 
+	 * to the role set of this base class.
+	 * @param cpg					the ClassGen of the appropriate class
+	 * @param class_name	the name of the class
+	 * @return							the generated method 
+	 */
+	private Method generateAddRole(ConstantPoolGen cpg, String class_name) {
+
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
+				 					 Type.VOID,
+				 					 new Type[] { Type.OBJECT },
+				 					 new String[] {"role"},
+				 					 OTConstants.ADD_ROLE, class_name,
+				 					 il, cpg);
+		
+		il.append(getInitializedRoleSet(class_name, /*valueRequired*/true)); 
+		
+		il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+		il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(), 
+									   "add", 
+									   Type.BOOLEAN, 
+									   new Type[] {Type.OBJECT},
+									   Constants.INVOKEVIRTUAL));
+		il.append(new POP());
+		il.append(InstructionFactory.createReturn(Type.VOID));
+		mg.removeNOPs();
+		mg.setMaxStack();
+		mg.setMaxLocals(2);
+		return mg.getMethod();
+	}
+	
+	/**
+	 * Generates the method 'public void _OT$removeRole(Object role)' which removes the passed object 
+	 * from the role set of this base class.
+	 * @param cpg			the ClassGen of the appropriate class				
+	 * @param class_name  	the name of the class
+	 * @return				the generated method 
+	 */
+	private Method generateRemoveRole(ConstantPoolGen cpg, String class_name) {
+		
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen(Constants.ACC_PUBLIC,
+						 			 Type.VOID,
+						 			 new Type[] { Type.OBJECT },
+						 			 new String[] {"role"},
+						 			 OTConstants.REMOVE_ROLE, class_name,
+						 			 il, cpg);
+		il.append(new ALOAD(0)); 			  
+		il.append(factory.createGetField(class_name, OTConstants.ROLE_SET, OTConstants.roleSetType));
+		il.append(InstructionFactory.createLoad(Type.OBJECT, 1));
+		il.append(factory.createInvoke(OTConstants.roleSetType.getClassName(), 
+									   "remove", 
+									   Type.BOOLEAN, 
+									   new Type[] {Type.OBJECT},
+									   Constants.INVOKEVIRTUAL));
+		il.append(new POP());
+		il.append(InstructionFactory.createReturn(Type.VOID));
+		mg.removeNOPs();
+		mg.setMaxStack(2);
+		mg.setMaxLocals(2);
+		return mg.getMethod();
+	}
+	
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseTagInsertion.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseTagInsertion.java
new file mode 100644
index 0000000..ebbf234
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/BaseTagInsertion.java
@@ -0,0 +1,205 @@
+/**********************************************************************
+ * 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: BaseTagInsertion.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 de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.util.*;
+
+/**
+ * This transformer inserts tag fields for all (topmost) bound base classes.
+ * Tag fields look like this:
+ * <pre>
+ *   public short <i>TeamName</i>_OT$Tag;
+ * </pre>
+ * where <i>TeamName</i> is any team which has a callin binding for this base class.
+ * It also inserts initialization of this tag into every constructor.
+ * 
+ * @version $Id: BaseTagInsertion.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author  Christine Hundt
+ * @author  Stephan Herrmann
+ */
+public class BaseTagInsertion 
+{
+    private static boolean logging   = false;
+    final   static String  tagSuffix = "_OT$Tag";
+
+	static String getTagFieldName (String teamName) {
+        return teamName.replace('.', '$') + tagSuffix;
+    }
+
+	static {
+		if (System.getProperty("ot.log") != null)
+			logging = true;
+	}
+
+	public static class SharedState extends ObjectTeamsTransformation.SharedState {
+	    // Record base tags of interfaces here (String->HashMap). 
+	    // Need to be considered in all implementing classes.
+	    // baseName -> HashMap  (teamName -> tag (Integer)):
+	    private HashMap<String, HashMap<String, Integer>> baseTagsOfInterfaces = new HashMap<String, HashMap<String, Integer>>();
+	}
+
+	SharedState state;
+	
+    public BaseTagInsertion(SharedState state) {
+		this.state = state;
+	}
+
+	/**
+     * @param ce
+     * @param cg
+     */
+    public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+       
+        String class_name = cg.getClassName();
+        ConstantPoolGen cpg = cg.getConstantPool();
+/*
+ 		if (interfaceTransformedClasses.contains(class_name))
+ 			continue; // already transformed!
+*/
+
+        HashMap<String, Integer> baseTags = getAllBaseTags(cg);
+
+        if (baseTags == null) return; // not a bound base
+
+        if (cg.isInterface())
+        	state.baseTagsOfInterfaces.put(class_name, baseTags);
+			
+        state.interfaceTransformedClasses.add(class_name);
+        if (logging)
+			printLogMessage("Found bound base: " + class_name);
+            
+        Iterator<String> teams = baseTags.keySet().iterator();
+        while (teams.hasNext()) {
+        	String teamName = teams.next();
+       	
+        	String fieldName = getTagFieldName(teamName);//team + tagSuffix;
+
+        	if (cg.containsMethod("get"+fieldName, "()S") == null)
+        	{
+        		if(logging)
+        			printLogMessage("create base tag access get" + fieldName);
+        		Integer tag = baseTags.get(teamName);
+        		MethodGen mg = genBaseTagGetter(cpg, class_name, fieldName, tag.intValue(), cg.isInterface());
+        		ce.addMethod(mg.getMethod(), cg);
+        	}
+        }
+        // addedBaseTags.addAll(baseTags);
+    }
+
+	/**
+	 * Collect base tags from this class and its super interfaces.
+	 * @param cg
+	 * @return
+	 */
+	private HashMap<String, Integer> getAllBaseTags(ClassGen cg) {
+		// accumulate here base tags from bound super interfaces and this class:
+		HashMap<String, Integer> baseTags = null;
+		
+		// TODO (SH): consider all transformed super interfaces.
+		String superIfc = getTransformedSuperIfc(cg);
+		if (superIfc != null) 
+			baseTags = state.baseTagsOfInterfaces.get(superIfc);
+		
+		String class_name = cg.getClassName();
+		HashMap<String, Integer> classBaseTags = CallinBindingManager.getBaseTags(class_name);
+		if (CallinBindingManager.isRole(class_name)) {
+				// search for base tags inherited from the implicit super (role) class:
+				HashMap<String, Integer> inheritedBaseTags = CallinBindingManager.getInheritedBaseTags(class_name);
+				classBaseTags.putAll(inheritedBaseTags);
+				// search for base tags of the implementing role class:
+				String implementingRoleName = ObjectTeamsTransformation.genImplementingRoleName(class_name);
+				HashMap<String, Integer> implementingRolebaseTags = CallinBindingManager.getBaseTags(implementingRoleName);
+				classBaseTags.putAll(implementingRolebaseTags);
+				// TODO: check, if the we also need the implicitly inherited tags of the implementing role class!
+		}
+		
+		if (baseTags == null)
+			baseTags = classBaseTags;
+		else
+			baseTags.putAll(classBaseTags);
+		
+		return baseTags;
+	}
+
+    /**
+     * Search the interfaces implemented by the class `cg' for an interface
+     * that is a bound base. 
+     * TODO (SH): should return all such interfaces!
+	 * @param cg
+	 * @return
+	 */
+	private String getTransformedSuperIfc(ClassGen cg) {
+		String[] ifcs = cg.getInterfaceNames();
+		for (int i=0; i<ifcs.length; i++){
+			if (state.interfaceTransformedClasses.contains(ifcs[i]))
+				return ifcs[i];
+		}
+		return null;
+	}
+
+	/**
+	 * Generate a getter method for the base tag field.
+	 * @param cpg
+	 * @param class_name this (base-) class shall carry the new method
+	 * @param fieldName name of the tag field.
+	 * @param abstractFlg should the method be generated as abstract (ie., without a body)?
+	 * @return
+	 */
+	static MethodGen genBaseTagGetter(
+			ConstantPoolGen cpg, String class_name, 
+			String fieldName, int tagValue, boolean abstractFlg) 
+	{
+		int accessFlags = Constants.ACC_PUBLIC;
+		if (abstractFlg)
+			accessFlags |= Constants.ACC_ABSTRACT;
+			
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen(
+				accessFlags, 
+				Type.SHORT, Type.NO_ARGS, new String[]{}, 
+				"get"+fieldName, class_name, 
+				il, cpg);
+		if (!abstractFlg) {
+			// gen: "return <constant tagValue>"
+			il.append(new PUSH(cpg, tagValue));
+			il.append(InstructionFactory.createReturn(Type.INT));
+		}
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg;
+	}
+	
+    /**
+     *  Insert tag initializations into each constructor.
+     */	
+	public void doTransformCode(ClassGen cg) {
+    	// FIXME(SH): do not declare as CodeTransformer.
+    }
+  
+    /**
+     * @param message
+     */
+    private static void printLogMessage(String message) {
+    	System.out.println(message);
+    }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java
new file mode 100644
index 0000000..aa80c98
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ClassEnhancer.java
@@ -0,0 +1,79 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2005-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: ClassEnhancer.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 de.fub.bytecode.classfile.Field;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.ConstantPoolGen;
+
+
+
+/**
+ * This interface is used to abstract from the BCEL external transformations.
+ *  
+ * @author Christine Hundt
+ * @author Juergen Widiker
+ * @author Stephan Herrmann
+ */
+public interface ClassEnhancer {
+
+	/**
+	 * Adds the interface 'interfaceName' to the implements clause of class 'cg'.
+	 */
+	public void addImplements(String interfaceName, ClassGen cg);
+	
+	/**
+	 * Adds the method 'm' to the class represented by 'cg'.
+	 * @param m		the method to be added
+	 * @param cg	the ClassGen of the appropriate class
+	 */
+	void addMethod(Method m, ClassGen cg);
+
+	/**
+	 * Adds method 'm' to the class 'cg' or, if a method with the
+	 * same name and signature already exists, replace that method.
+	 * @param method
+	 * @param cg
+	 */
+	void addOrReplaceMethod(Method method, ClassGen cg);
+	
+	/**
+	 * Adds the field 'f' to the class represented by 'cg'.
+	 * @param f
+	 * @param cg
+	 */
+	void addField(Field f, ClassGen cg);
+
+	/**
+	 * Loads the class named 'className'.
+	 * @param className	the name of the class to be loaded
+	 * @param client the transformer on behalf of which we are called, can be used to call checkReadClassAttributes.
+	 */
+	void loadClass(String className, ObjectTeamsTransformation client);
+	
+	/**
+	 * Decapsulation of the method 'm'. This means that the access modifier of this method is set to 'public'.
+	 * @param m							the name of the method to be decapsulated				
+	 * @param className			the name of the belonging class
+	 * @param packageName  the name of the belonging package
+	 * @param cpg						the ConstantPoolGen of the class	
+	 */
+	void decapsulateMethod(Method m, ClassGen cg, String packageName, ConstantPoolGen cpg);
+
+
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java
new file mode 100644
index 0000000..9f74123
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/Decapsulation.java
@@ -0,0 +1,427 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2003, 2009 Technical University Berlin, 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: Decapsulation.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.objectteams.otre.util.CallinBindingManager;
+import org.eclipse.objectteams.otre.util.FieldDescriptor;
+import org.eclipse.objectteams.otre.util.SuperMethodDescriptor;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.ConstantPoolGen;
+import de.fub.bytecode.generic.InstructionFactory;
+import de.fub.bytecode.generic.InstructionList;
+import de.fub.bytecode.generic.MethodGen;
+import de.fub.bytecode.generic.ObjectType;
+import de.fub.bytecode.generic.Type;
+
+/**
+ *  For each base method that is bound by callout and has
+ *  insufficient visibility, the visibility is set to public.
+ *  If the corresponding JMangler-patch is installed, check
+ *  whether the affected base class resides in a sealed package.
+ *  In that case dissallow decapsulation by throwing an IllegalAccessError.
+ *  
+ *  @version $Id: Decapsulation.java 23408 2010-02-03 18:07:35Z stephan $
+ *  @author Stephan Herrmann
+ */
+public class Decapsulation 
+	extends ObjectTeamsTransformation
+	implements Constants 
+{
+	
+//	HashSet modifiedPackages = new HashSet();
+
+	public static class SharedState extends ObjectTeamsTransformation.SharedState {
+		private HashMap /* class_name -> HashSet(callout accessed fields) */<String, HashSet<String>> generatedFieldCalloutAccessors
+			= new HashMap<String, HashSet<String>>();
+		private HashMap /* class_name -> HashSet(super-accessed methods (sign))*/<String, HashSet<String>> generatedSuperAccessors
+    		= new HashMap<String, HashSet<String>>();
+	}
+	@Override
+	SharedState state() {
+		return (SharedState)this.state;
+	}
+   
+    public Decapsulation(SharedState state) {
+    	this(null, state);
+    }
+    public Decapsulation(ClassLoader loader, SharedState state) {
+    	super(loader, state);
+    	// FIXME(SH): can we ever release this transformer and its state?
+    	synchronized(ObjectTeamsTransformation.reentrentTransformations) {
+    		ObjectTeamsTransformation.reentrentTransformations.add(this);
+    	}
+    }
+
+	/**
+	 * Main entry for this transformer.
+	 */
+//	@SuppressWarnings("unchecked")
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {		
+		String          class_name = cg.getClassName();
+		ConstantPoolGen cpg        = cg.getConstantPool();
+		
+		// if class is already transformed by this transformer
+		if (state.interfaceTransformedClasses.contains(class_name))
+			return;
+
+		checkReadClassAttributes(ce, cg, class_name, cpg);
+            
+        // next step starts to transform, so record this class now.
+		state.interfaceTransformedClasses.add(class_name);
+
+		generateFieldAccessForCallout(ce, cg, class_name, cpg);
+		
+		generateSuperAccessors(ce, cg, class_name, cpg);
+
+		HashSet<String> calloutBindings = CallinBindingManager.getCalloutBindings(class_name);
+
+		if (calloutBindings == null) {
+            if(logging) printLogMessage("\nClass " + class_name 
+					+ " requires no callout adjustment.");
+			return; 
+		}
+			
+        if(logging) printLogMessage("\nCallout bindings might be changing class " 
+					+ class_name + ":");
+
+		HashSet<String> oldStyleBinding = new HashSet<String>();
+		
+		// try new style decapsulation first (since 1.2.8):
+		for (String calloutBinding : calloutBindings) {
+			DecapsulationDescriptor desc = new DecapsulationDescriptor();
+			if (!desc.decode(calloutBinding, cg))
+				oldStyleBinding.add(calloutBinding); // old style attribute
+			else if (!desc.existsAlready) 
+				ce.addMethod(desc.generate(class_name, cpg), cg);
+		}
+		
+		if (oldStyleBinding.isEmpty()) return;
+		
+		// --> follows: old style decapsulation for remaining bindings:
+		int pos = class_name.lastIndexOf('.');
+		String package_name = "NO_PACKAGE";
+		if (pos != -1)
+			package_name = class_name.substring(0,pos);
+			
+		Method[] methods = cg.getMethods();
+		for (int i = 0; i < methods.length; i++) {
+			Method m           = methods[i];
+			String method_name = m.getName();
+			
+			boolean requiresAdjustment = CallinBindingManager.
+			requiresCalloutAdjustment(oldStyleBinding, 
+										method_name,
+										m.getSignature());
+				
+			if (requiresAdjustment) {
+				ce.decapsulateMethod(m, cg, package_name, cpg);
+			}
+		}
+	}
+	class DecapsulationDescriptor {
+		short invokeKind;
+		String targetClass;
+		String methodName;
+		String methodSign;
+		Type returnType; 
+		Type[] args;
+		String accessorName;
+		
+		boolean existsAlready;
+		
+		/**
+		 * new style encoding is
+		 * targetClassName ('!' | '?') methodName '.' methodSign 
+		 */
+		boolean decode(String encodedBinding, ClassGen cg) {
+			int sepPos = encodedBinding.indexOf('!');
+			if (sepPos != -1) { // static method:
+				invokeKind = INVOKESTATIC;
+			} else {
+				sepPos = encodedBinding.indexOf('?');
+				if (sepPos != -1) {
+					invokeKind = INVOKEVIRTUAL;
+				} else {
+					return false; // old style
+				}
+			}
+			targetClass = encodedBinding.substring(0, sepPos);
+			int sigPos = encodedBinding.indexOf('(', sepPos);
+			methodName = encodedBinding.substring(sepPos+1, sigPos);
+			methodSign = encodedBinding.substring(sigPos);
+			
+			returnType = Type.getReturnType(methodSign); 
+			args = Type.getArgumentTypes(methodSign);
+
+			accessorName = "_OT$decaps$"+methodName;
+			existsAlready = cg.containsMethod(accessorName, methodSign) != null;
+			if (invokeKind == INVOKEVIRTUAL) {
+				Method existing = cg.containsMethod(methodName, methodSign);
+				if (existing != null && existing.isPrivate())
+					invokeKind = INVOKESPECIAL; // accessing private
+			}
+			
+			return true;
+		}
+		Method generate(String currentClass, ConstantPoolGen cpg) {
+			InstructionList il = new InstructionList();
+			int instanceOffset = 0;
+			short flags = Constants.ACC_PUBLIC;
+			if (invokeKind != INVOKESTATIC) {
+				instanceOffset=1;
+				il.append(InstructionFactory.createThis());
+			} else {
+				flags |= Constants.ACC_STATIC;
+			}
+			int pos= 0;
+			for (int i = 0; i < args.length; i++) {
+				il.append(InstructionFactory.createLoad(args[i], pos+instanceOffset));
+				pos += args[i].getSize();
+			}
+			il.append(new InstructionFactory(cpg).createInvoke(targetClass, methodName, returnType, args, invokeKind));
+			il.append(InstructionFactory.createReturn(returnType));
+			MethodGen newMethod = new MethodGen(flags, returnType, args, /*argNames*/null, accessorName, currentClass, il, cpg);
+			newMethod.setMaxLocals();
+			newMethod.setMaxStack();
+			return newMethod.getMethod();
+		}
+	}
+
+	/**
+	 * Generates getter and setter methods for all fields of the class 'class_name' which are accessed via callout. 
+	 * Informations are received via attributs (CallinBindingManager). 
+	 * @param cg					the ClassGen of the appropriate class
+	 * @param class_name		the name of the class
+	 * @param cpg					the ConstantPoolGen of the class
+	 * @param es					the ExtensionSet to add the new access methods
+	 */
+	private void generateFieldAccessForCallout(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
+		InstructionFactory factory = null;
+		
+		HashSet<String> addedAccessMethods = state().generatedFieldCalloutAccessors.get(class_name);
+
+		List<FieldDescriptor> getter = CallinBindingManager.getCalloutGetFields(class_name);
+		if (getter != null) {
+	    	factory = new InstructionFactory(cg);
+			Iterator<FieldDescriptor> it = getter.iterator();
+			while (it.hasNext()) {
+				FieldDescriptor fd = it.next();
+				String key = "get_" + fd.getFieldName() + fd.getFieldSignature();
+				if (logging)
+					printLogMessage("Generating getter method "+key);
+				if (addedAccessMethods == null)
+					addedAccessMethods = new HashSet<String>();
+				if (addedAccessMethods.contains(key))
+					continue; // this getter has already been created
+				ce.addMethod(generateGetter(cpg, class_name, fd, factory), cg);
+				addedAccessMethods.add(key);
+				state().generatedFieldCalloutAccessors.put(class_name, addedAccessMethods);
+			}
+		}
+
+		List<FieldDescriptor> setter = CallinBindingManager.getCalloutSetFields(class_name);
+		if (setter != null) {
+			if (factory == null)
+		    	factory = new InstructionFactory(cg);
+			Iterator<FieldDescriptor> it = setter.iterator();
+			while (it.hasNext()) {
+				FieldDescriptor fd = it.next();
+				String key = "set_"+fd.getFieldName()+fd.getFieldSignature();
+				if (logging)
+					printLogMessage("Generating setter method "+key);
+				if (addedAccessMethods == null)
+					addedAccessMethods = new HashSet<String>();
+				if (addedAccessMethods.contains(key))
+					continue; // this setter has already been created
+				ce.addMethod(generateSetter(cpg, class_name, fd, factory), cg);
+				addedAccessMethods.add(key);
+				state().generatedFieldCalloutAccessors.put(class_name, addedAccessMethods);
+			}
+		}
+	}
+
+
+	/**
+	 * Generates a getter method for the field described by 'fd' in the class 'class_name'. 
+	 * @param cpg					the ConstantPoolGen of the class
+	 * @param class_name		the name of the class
+	 * @param fd						the FieldDescriptor describing the affected field
+	 * @param factory				an InstructionFactory for this class
+	 * @return							the generated getter method
+	 */
+	private Method generateGetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory) {
+		String fieldName = fd.getFieldName();
+		Type fieldType =  Type.getType(fd.getFieldSignature());
+		Type baseType = new ObjectType(class_name);
+		
+		InstructionList il = new InstructionList();
+		String[] argumentNames;
+		Type[]   argumentTypes;
+		if (fd.isStaticField()) {
+			argumentNames = new String[0];
+			argumentTypes = new Type[0];
+		} else {
+			argumentNames = new String[] {"base_obj"};
+			argumentTypes = new Type[]   {baseType};
+		}
+		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
+	 			  												  fieldType,
+																  argumentTypes,
+																  argumentNames,
+																  OT_PREFIX+"get$"+fieldName,
+																  class_name,
+																  il, cpg);
+		if (!fd.isStaticField())
+			il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods
+		short fieldKind = fd.isStaticField()?Constants.GETSTATIC:Constants.GETFIELD;
+		il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind));
+		il.append(InstructionFactory.createReturn(fieldType));
+
+		mg.removeNOPs();
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg.getMethod();
+	}
+	
+
+	/**
+	 * Generates a setter method for the field described by 'fd' in the class 'class_name'. 
+	 * @param cpg					the ConstantPoolGen of the class
+	 * @param class_name		the name of the class
+	 * @param fd						the FieldDescriptor describing the affected field
+	 * @param factory				an InstructionFactory for this class
+	 * @return							the generated getter method
+	 */
+	private Method generateSetter(ConstantPoolGen cpg, String class_name, FieldDescriptor fd, InstructionFactory factory ) {
+		String fieldName = fd.getFieldName();
+		Type fieldType =  Type.getType(fd.getFieldSignature());
+		Type baseType = new ObjectType(class_name);
+
+		Type[]   argumentTypes;
+		String[] argumentNames;
+		if (fd.isStaticField()) {
+			argumentTypes = new Type[]   { fieldType};
+			argumentNames = new String[] {"new_value"};			
+		} else {
+			argumentTypes = new Type[]   {baseType,   fieldType};
+			argumentNames = new String[] {"base_obj", "new_value"};
+		}
+		
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
+	 			  												  Type.VOID,
+																  argumentTypes,
+																  argumentNames,
+																  OT_PREFIX+"set$"+fieldName,
+																  class_name,
+																  il, cpg);
+
+		int argumentPosition; // position for the argument holding the new field value.
+		if (!fd.isStaticField()) {
+			il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is at slot 0 in static methods
+			argumentPosition = 1;
+		} else {
+			argumentPosition = 0;
+		}
+		il.append(InstructionFactory.createLoad(fieldType, argumentPosition));
+		short fieldKind = fd.isStaticField()?Constants.PUTSTATIC:Constants.PUTFIELD;
+		il.append(factory.createFieldAccess(class_name, fieldName, fieldType, fieldKind));
+		il.append(InstructionFactory.createReturn(Type.VOID));
+
+		mg.removeNOPs();
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg.getMethod();
+	}
+	
+	private void generateSuperAccessors(ClassEnhancer ce, ClassGen cg, String class_name, ConstantPoolGen cpg) {
+		InstructionFactory factory = null;
+		
+		HashSet<String> addedAccessMethods = state().generatedSuperAccessors.get(class_name);
+
+		List<SuperMethodDescriptor> methods = CallinBindingManager.getSuperAccesses(class_name);
+		if (methods != null) {
+	    	factory = new InstructionFactory(cg);
+	    	for (SuperMethodDescriptor superMethod : methods) {
+				String key = superMethod.methodName+'.'+superMethod.signature;
+				if (logging)
+					printLogMessage("Generating super access method "+key);
+				if (addedAccessMethods == null)
+					addedAccessMethods = new HashSet<String>();
+				if (addedAccessMethods.contains(key))
+					continue; // this accessor has already been created
+				ce.addMethod(generateSuperAccessor(cpg, class_name, superMethod, factory), cg);
+				addedAccessMethods.add(key);
+				state().generatedSuperAccessors.put(class_name, addedAccessMethods);
+			}
+		}
+	}
+	
+	private Method generateSuperAccessor(ConstantPoolGen cpg, String className, SuperMethodDescriptor superMethod, InstructionFactory factory) 
+	{ 
+		int endPos = superMethod.signature.indexOf(')');
+		String segment = superMethod.signature.substring(1, endPos);
+		String[] typeNames = (segment.length() > 0) ? segment.split(",") : new String[0];
+		Type[] argTypes = new Type[typeNames.length];
+		for (int i = 0; i < argTypes.length; i++) 
+			argTypes[i] = Type.getType(typeNames[i]);
+		
+		int index = superMethod.signature.lastIndexOf(')') + 1;
+		Type returnType = Type.getType(superMethod.signature.substring(index));
+		
+		Type baseType = new ObjectType(className);
+		Type[] wrapperTypes = new Type[argTypes.length+1];
+		System.arraycopy(argTypes, 0, wrapperTypes, 1, argTypes.length);
+		wrapperTypes[0] = baseType;
+		String[] argNames = new String[wrapperTypes.length];
+		for (int i = 0; i < argNames.length; i++) {
+			argNames[i] = "arg"+i;
+		}
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen((Constants.ACC_PUBLIC|Constants.ACC_STATIC),
+									 returnType,
+									 wrapperTypes,
+									 argNames,
+									 OT_PREFIX+superMethod.methodName+"$super",
+									 className,
+									 il, cpg);
+		il.append(InstructionFactory.createLoad(baseType, 0)); // first argument is base instance
+		for (int i = 0; i < argTypes.length; i++) 
+			il.append(InstructionFactory.createLoad(argTypes[i], i+1));
+		
+		// if super method is also callin bound directly invoke the orig-version 
+		// (to avoid that BaseMethodTransformation.checkReplaceWickedSuper() has to rewrite this code again): 
+		String methodName = (CallinBindingManager.isBoundBaseMethod(superMethod.superClass, superMethod.methodName, superMethod.signature))
+								? genOrigMethName(superMethod.methodName)
+								: superMethod.methodName;
+		
+		il.append(factory.createInvoke(superMethod.superClass, methodName, returnType, argTypes, INVOKESPECIAL));
+		il.append(InstructionFactory.createReturn(returnType));
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg.getMethod();
+	}
+	
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
new file mode 100644
index 0000000..48e949d
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
@@ -0,0 +1,162 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2009 Stephan Herrmann
+ *  
+ * 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: LiftingParticipantTransformation.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+
+import org.objectteams.Team;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.generic.ALOAD;
+import de.fub.bytecode.generic.BranchInstruction;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.ConstantPoolGen;
+import de.fub.bytecode.generic.DUP;
+import de.fub.bytecode.generic.GOTO;
+import de.fub.bytecode.generic.IFNULL;
+import de.fub.bytecode.generic.INVOKESPECIAL;
+import de.fub.bytecode.generic.InstructionFactory;
+import de.fub.bytecode.generic.InstructionHandle;
+import de.fub.bytecode.generic.InstructionList;
+import de.fub.bytecode.generic.LDC;
+import de.fub.bytecode.generic.MethodGen;
+import de.fub.bytecode.generic.NEW;
+import de.fub.bytecode.generic.NOP;
+import de.fub.bytecode.generic.ObjectType;
+import de.fub.bytecode.generic.POP;
+import de.fub.bytecode.generic.Type;
+
+/**
+ * If the property ot.lifting.participant is set transform all lift methods and insert 
+ * static calls to createRole(Team,Object,String)Object; to the registered lifting participant
+ * before creating a new role. If createRole returns non-null then that value is taken
+ * as the new role, otherwise lifting proceeds as normal, i.e., normally creates a new role.
+ *  
+ * @author stephan
+ * @since 1.3.1
+ */
+public class LiftingParticipantTransformation extends ObjectTeamsTransformation {
+	
+
+	private static String PARTICIPANT_NAME = System.getProperty("ot.lifting.participant");
+	private static boolean checked = false;
+	
+	final private static String LIFT_PREFIX = "_OT$liftTo"; 
+
+	private static final String WRONG_ROLE_EXCEPTION = "org.objectteams.WrongRoleException";
+	private static final String LIFTING_FAILED_EXCEPTION = "org.objectteams.LiftingFailedException";
+	private static final String LIFTING_VETO_EXCEPTION = "org.objectteams.LiftingVetoException";
+	
+	private static final ObjectType iLiftingParticipant = new ObjectType("org.objectteams.ILiftingParticipant"); 
+
+	private static final String CREATE_ROLE_METHOD = "createRole";
+	private static final String LIFTING_PARTICIPANT_FIELD = "_OT$liftingParticipant";
+	
+	public LiftingParticipantTransformation(SharedState state) { this(null, state); }
+
+	public LiftingParticipantTransformation(ClassLoader loader, SharedState state) { super(loader, state); }
+
+	public void doTransformCode(ClassGen cg) 
+	{
+		if (PARTICIPANT_NAME == null) return;
+	
+		if (!classNeedsTeamExtensions(cg)) return;
+		
+		synchronized (LiftingParticipantTransformation.class) {
+			if (!checked) {
+				try {
+					// install a shared instance into class Team:
+					Class<?> participantClass = loader.loadClass(PARTICIPANT_NAME);
+					Team.class.getField(LIFTING_PARTICIPANT_FIELD).set(null, participantClass.newInstance());
+				} catch (Exception e) {
+					new IllegalArgumentException("Lifting participant "+PARTICIPANT_NAME+" is invalid.", e).printStackTrace();
+					PARTICIPANT_NAME = null;
+				}
+				checked = true;
+			}
+		}
+		
+    	factory = new InstructionFactory(cg);
+    	ConstantPoolGen cpg        = cg.getConstantPool();
+    	String          class_name = cg.getClassName();
+    	
+    	// FIXME(SH): evaluate inclusion/exclusion filter per className
+			
+    	Method[] methods = cg.getMethods();
+    	for (int i=0; i<methods.length; i++) {
+    		Method m           = methods[i];
+    		if (!m.getName().startsWith(LIFT_PREFIX))
+    			continue;
+    		
+			cg.replaceMethod(m, m = weaveLiftingParticipant(m, class_name, cpg));
+    	}
+	}
+
+	private Method weaveLiftingParticipant(Method m, String className, ConstantPoolGen cpg) {
+		MethodGen mg = new MethodGen(m, className, cpg);
+		InstructionList il = mg.getInstructionList();
+		InstructionHandle[] ihs = il.getInstructionHandles();
+		for (int i=0; i<ihs.length; i++) {
+			InstructionHandle ih = ihs[i];
+			if (ih.getInstruction() instanceof NEW) 
+			{
+				NEW newInstr = (NEW) ih.getInstruction();
+				Type newType = newInstr.getType(cpg);
+				String newTypeName = newType.toString();
+				
+				// don't transform creation of these exceptions:
+				if (newTypeName.equals(LIFTING_FAILED_EXCEPTION)) continue;
+				if (newTypeName.equals(LIFTING_VETO_EXCEPTION)) continue;
+				if (newTypeName.equals(WRONG_ROLE_EXCEPTION)) continue;
+				
+				ih.setInstruction(new NOP()); // keep this handle for the enclosing switch
+				
+				InstructionList inset = new InstructionList();
+				// fetch instance of lifting participant from Team._OT$liftingParticipant
+				inset.append(factory.createFieldAccess(teamClassType.getClassName(),  
+													   LIFTING_PARTICIPANT_FIELD, 
+													   iLiftingParticipant, 
+													   Constants.GETSTATIC));
+				inset.append(new ALOAD(0)); 						// load the team
+				inset.append(new ALOAD(1));							// load the base
+				inset.append(new LDC(cpg.addString(newTypeName)));	// load the role class name
+				inset.append(factory.createInvoke(iLiftingParticipant.getClassName(),	// receiver type 
+												  CREATE_ROLE_METHOD, 					// method
+												  object, 								// return type
+												  new Type[] {teamType, object, string},// arg types
+												  Constants.INVOKEINTERFACE));
+				inset.append(new DUP());	// keep value after null-check
+				BranchInstruction isNull = new IFNULL(null);
+				inset.append(isNull);
+				inset.append(factory.createCast(object, newType));
+				// let goto skip: 0: new R, 1: dup, 2: aload_0, 3: aload_1, (4: cast if needed), 4: o. 5: invokespecial<init>
+				int invokeOffset = 4;
+				if (!(ihs[i+invokeOffset].getInstruction() instanceof INVOKESPECIAL))
+					invokeOffset++;
+				inset.append(new GOTO(ihs[i+invokeOffset+1])); // one past above sequence
+				
+				// continue here if null, i.e., perform the original new-instruction
+				InstructionHandle goOn = inset.append(new POP()); // discard dup'ed value from above
+				isNull.setTarget(goOn);
+				inset.append(newInstr); // re-insert deleted first instruction
+				
+				il.append(ih, inset);
+			}
+		}
+		return mg.getMethod();
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/LowerableTransformation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/LowerableTransformation.java
new file mode 100644
index 0000000..1db8d9f
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/LowerableTransformation.java
@@ -0,0 +1,72 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2009 Stephan Herrmann
+ *  
+ * 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: LowerableTransformation.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.MethodGen;
+import de.fub.bytecode.generic.Type;
+
+/**
+ * This transformer helps legacy class files pre 1.3.2 to cope with changes re ILowerable.lower().
+ * 
+ * @author stephan
+ * @since 1.3.2
+ */
+public class LowerableTransformation extends ObjectTeamsTransformation {
+	
+	// static because checking is performed without instance context (from scanClassOTAttribrutes)
+	// using ClassGen rather than names should, however, avoid conflicts between different class loaders etc.
+	static Set<ClassGen> transformationRequests = new HashSet<ClassGen>();
+	
+	public LowerableTransformation(SharedState state) { this(null, state); }
+
+	public LowerableTransformation(ClassLoader loader, SharedState state) {
+		super(loader, state);
+	}
+	
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+		synchronized (transformationRequests) {
+			if (!transformationRequests.remove(cg))
+				return;
+		}
+		// yes, a change was requested, add method "public abstract Object lower();"
+		MethodGen lower = new MethodGen(Constants.ACC_PUBLIC|Constants.ACC_ABSTRACT, object, new Type[0], new String[0], "lower", cg.getClassName(), null, cg.getConstantPool());
+		ce.addMethod(lower.getMethod(), cg);
+	}
+
+	/** After reading the compiler version of a class file, check if this class is affected by the change. */
+	public static void checkRequiresAdaptation(int major, int minor, int revision, ClassGen cg) {
+		// only 1.3.1 and below:
+		if (major > 1) return;
+		if (major == 1 && minor > 3) return;
+		if (major == 1 && minor == 3 && revision > 1) return;
+		// only interfaces ...
+		if (!cg.isInterface()) return;
+		// ... implementing ILowerabel:
+		for (String superInterface : cg.getInterfaceNames()) {
+			if ("org.objectteams.Team$ILowerable".equals(superInterface))
+				synchronized(transformationRequests) {
+					transformationRequests.add(cg);
+					return;
+				}
+		}
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java
new file mode 100644
index 0000000..d207abd
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTConstants.java
@@ -0,0 +1,178 @@
+/**********************************************************************
+ * 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: OTConstants.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 de.fub.bytecode.generic.*;
+
+
+/**
+ * Constants for the Object Teams Runtime Environment
+ * @author Christine Hundt
+ * @author Stephan Herrmann
+ */
+public interface OTConstants {
+	// ------------------------------------------
+	// ---------- Types: ------------------------
+	// ------------------------------------------
+	/**                            Type <tt>java.lang.Object</tt> */
+    ObjectType object        = new ObjectType("java.lang.Object");
+	/**                            Type <tt>java.lang.Object</tt> */
+    ObjectType string        = new ObjectType("java.lang.String");
+    /**                            Type <tt>java.lang.Class</tt> */
+    ObjectType classType = new ObjectType("java.lang.Class");
+    /** 						   Signature of java.lang.Class#getMethod(String, Class...) */
+    public static final Type[] getMethodSignature = new Type[]{string, new ArrayType(classType, 1)};
+    /**                            Type <tt>java.lang.reflect.Method</tt> */
+    ObjectType methodType = new ObjectType("java.lang.reflect.Method");
+    /**                            Type <tt>org.objectteams.Team</tt> */
+    String     teamName          = "org.objectteams.ITeam";
+    ObjectType teamType          = new ObjectType(teamName);
+    String     teamClassName     = "org.objectteams.Team";
+    ObjectType teamClassType     = new ObjectType(teamClassName);
+	/**                            Type <tt>org.objectteams.LiftingVetoException</tt> */
+    ObjectType liftingVeto   = new ObjectType("org.objectteams.LiftingVetoException");
+    /**                            Type <tt>org.eclipse.objectteams.otre.OTREInternalError</tt> */	
+    ObjectType internalError = new ObjectType("org.eclipse.objectteams.otre.OTREInternalError");
+	/**                            Type <tt>org.eclipse.objectteams.otre.OTREInternalError</tt> */	
+	ObjectType notProvidedError = new ObjectType("org.objectteams.ResultNotProvidedError");
+	/**                            Type <tt>org.eclipse.objectteams.otre.UnsupportedFeatureException</tt> */	
+	ObjectType unsupportedFeature = new ObjectType("org.objectteams.UnsupportedFeatureException");
+	
+	ObjectType threadType  = new ObjectType("java.lang.Thread");
+	
+	/**                          Type <tt>org.objectteams.Team[]</tt> */
+    ArrayType  teamArray   = new ArrayType(teamType, 1);
+	/**                          Type <tt>int[]</tt> */
+    ArrayType  intArray    = new ArrayType(Type.INT, 1);
+	/**                          Type <tt>java.lang.Object[]</tt> */
+    ArrayType  objectArray = new ArrayType(object, 1);
+
+	ObjectType roleSetType = new ObjectType("java.util.HashSet");
+	
+	ObjectType nullPointerException = new ObjectType("java.lang.NullPointerException");
+
+	String STRING_BUFFER_NAME    = "java.lang.StringBuffer";
+	
+	// ============ VERSION: ==============
+	public static final int    OT_VERSION_MAJOR = 0;
+    public static final int    OT_VERSION_MINOR = 8;
+    public static final int    OT_REVISION = 18;
+    
+    // required compiler revision in the 0.9 stream:
+    public static final int    OT09_REVISION = 26;
+
+    // required compiler revision in the 1.0 stream:
+    public static final int    OT10_REVISION = 0;
+    
+    // required compiler revision in the 1.1 stream:
+    public static final int    OT11_REVISION = 0;
+
+    // required compiler revision in the 1.2 stream:
+    public static final int    OT12_REVISION = 0;
+
+    // required compiler revision in the 1.3 stream:
+    public static final int    OT13_REVISION = 0;
+
+    // required compiler revision in the 1.4 stream:
+    public static final int    OT14_REVISION = 1;
+
+    // ------------------------------------------
+	// ---------- Flags and Modifiers: ----------
+	// ------------------------------------------
+	/** Bytecode encoding of modifier <tt>team</tt> */
+    final static int TEAM  = 0x8000;
+
+	// 'CallinFlags':
+	final static int OVERRIDING =1; // this role method is inherited from the super role
+	final static int WRAPPER =2; // this is a role method wrapper (in a team)
+
+	// ------------------------------------------
+	// ---------- Names: ------------------------
+	// ------------------------------------------
+	/**                              General prefix to mark all generated names. */
+    final static String OT_PREFIX = "_OT$";
+	/**                              Name of the base reference of roles. */
+    final static String BASE      = "_OT$base";
+	/**                              Name of the getBase method of roles (ifc and class). */
+    final static String GET_BASE  = "_OT$getBase";
+	/**							  Prefix for otdt. */
+	final static String OTDT_PREFIX = "__OT__";
+	/**							  Tsuper marker interface prefix. */
+	final static String TSUPER_PREFIX = "TSuper__OT__";
+	/** field for storing the class object in JVM < 5 */
+	final static String SELF_CLASS = "_OT$self_class$";
+
+	// -----------------------------------------
+	// ---------- Signature enhancement --------
+	// -----------------------------------------
+	
+	/**                              Name of synthetic parameter. */
+	final static String TEAMS     = "_OT$teams";
+	/**                              Name of synthetic parameter. */
+	final static String TEAMIDS   = "_OT$teamIDs";
+	/**                              Name of synthetic parameter. */
+	final static String IDX       = "_OT$idx";
+	/**                              Name of synthetic parameter. */
+	final static String BIND_IDX       = "_OT$bindIdx";
+	/**                              Name of synthetic parameter. */
+	final static String UNUSED    = "_OT$unusedArgs";
+	/**                              Name of synthetic parameter. */
+    final static String BASE_METH_TAG = "_OT$baseMethTag";
+
+	/**                            Number of extra arguments in enhanced signatures. */
+	static final int EXTRA_ARGS  = 6;
+	/**                            Position of generated argument. */
+	static final int TEAMS_ARG   = 1;
+	/**                            Position of generated argument. */
+	static final int TEAMIDS_ARG = 2;
+	/**                            Position of generated argument. */
+	static final int IDX_ARG     = 3;
+	/**                            Position of generated argument. */
+	static final int BIND_IDX_ARG = 4;
+	/**                            Position of generated argument. */
+    static final int BASE_METH_ARG = 5; // ## really const? also UNUSED?
+	/**                            Position of generated argument. */
+	static final int UNUSED_ARG  = 6;
+
+	// ---------- Features to prevent/aid garbage collection: ----------
+	String ROLE_SET              = OT_PREFIX + "roleSet";    // field  HashSet _OT$roleSet;
+	String ADD_ROLE              = OT_PREFIX + "addRole";    // method void _OT$addRole(Object)
+	String REMOVE_ROLE           = OT_PREFIX + "removeRole"; // method void _OT$removeRole(Object)
+
+	String IBOUND_BASE           = "org.objectteams.IBoundBase"; // interface comprising the above methods.
+	
+	
+	// -----------------------------------------
+	// ---------- Other constants --------
+	// -----------------------------------------
+	/**							Marker for comment lines in the team config file. */    
+	static final String COMMENT_MARKER = "#";
+	/**							Constant for invalid base method tags (a method can not be relocated from a base call). */    
+	static final int INVALID_BASE_METHOD_TAG = -2;
+	
+	// --------------------------------------------------------------
+	// ---------- Separator for static replace binding keys ---------
+	// --------------------------------------------------------------
+	 static final String STATIC_REPLACE_BINDING_SEPARATOR = ".."; 
+	 
+	 // ------------------------------------------------------------------------------------
+	 // ---------- Linenumbers with more information.  ----------------------
+	 // ---------- (semantic linenumber) For debugging purpose.  ------
+	 // ------------------------------------------------------------------------------------
+	 static final int STEP_OVER_LINENUMBER = Short.MAX_VALUE *2;
+	 static final int STEP_INTO_LINENUMBER = STEP_OVER_LINENUMBER - 1;
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java
new file mode 100644
index 0000000..04110e2
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/OTREInternalError.java
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2003-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$
+ *
+ * Please visit http://www.objectteams.org for updates and contact.
+ *
+ * Contributors:
+ * Berlin Institute of Technology - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+/**
+ * @author stephan 
+ */
+public class OTREInternalError extends Error {
+
+    /**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private static final String _bugmsg = 
+        "An error occurred in the Object Teams runtime environment.\n"+
+        "We would appreciate if you send a bug report to bugs@ObjectTeams.org.\n"+
+        "Please include your program (if possible) and the following diagnostic\n"+
+        "in your report. -- Thank you. The OT/J developers\n";
+    /**
+     * 
+     */
+    public OTREInternalError() {
+        super(_bugmsg);
+    }
+
+    /**
+     * @param message
+     */
+    public OTREInternalError(String message) {
+        super(_bugmsg+message);
+    }
+
+    /**
+     * @param cause
+     */
+    public OTREInternalError(Throwable cause) {
+        super(_bugmsg+cause.toString());
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public OTREInternalError(String message, Throwable cause) {
+        super(_bugmsg+message+cause.toString());
+    }
+
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
new file mode 100644
index 0000000..7158659
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
@@ -0,0 +1,2259 @@
+/**********************************************************************
+ * 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: ObjectTeamsTransformation.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 java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.objectteams.otre.util.AnnotationHelper;
+import org.eclipse.objectteams.otre.util.AttributeReadingGuard;
+import org.eclipse.objectteams.otre.util.CallinBindingManager;
+import org.eclipse.objectteams.otre.util.RoleBaseBinding;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.Repository;
+import de.fub.bytecode.classfile.Attribute;
+import de.fub.bytecode.classfile.Constant;
+import de.fub.bytecode.classfile.ConstantUtf8;
+import de.fub.bytecode.classfile.InnerClass;
+import de.fub.bytecode.classfile.InnerClasses;
+import de.fub.bytecode.classfile.JavaClass;
+import de.fub.bytecode.classfile.LineNumberTable;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.classfile.Unknown;
+import de.fub.bytecode.generic.*;
+
+/**
+ * Superclass for all transformations in this package.
+ * This class and its subclasses depends on neither JMangler nor JPLIS.
+ * 
+ * Contains common fields and methods.
+ *
+ * @author  Christine Hundt
+ * @author  Stephan Herrmann
+ */
+public abstract class ObjectTeamsTransformation
+	implements OTConstants
+{
+	
+	// ------------------------------------------
+	// ---------- Flags: ------------------------
+	// ------------------------------------------
+
+	/** Check whether <tt>flags</tt> denote a generated callin wrapper. */
+    static boolean isCallinWrapper(Method m, ClassGen cg) {
+		return methodHasCallinFlags(m, cg, WRAPPER);
+	}
+
+	/** Check whether <tt>flags</tt> denote a callin method from the source code. */
+    static boolean isCallin(Method m, ClassGen cg) {
+    	return (methodHasCallinFlags(m, cg, 0) && !isCallinWrapper(m, cg));
+    }
+
+
+	// ------------------------------------------
+	// ---------- Names: ------------------------
+	// ------------------------------------------
+
+	/** Generate the name for a backup of a method. */
+    static String genOrigMethName(String methName) {
+        return "_OT$" + methName + "$orig";
+    }
+
+	/** Generate the name for a chaining wrapper. */
+    static String genChainMethName(String methName) {
+        return "_OT$" + methName + "$chain";
+    }
+
+    static ArrayList<ObjectTeamsTransformation> reentrentTransformations = new ArrayList<ObjectTeamsTransformation>();
+    
+    /** Common factory for all tranformers.
+	 *	To be initialized once we get a class for transformation. */
+	InstructionFactory factory;
+
+    /** State shared among all instances that work for the same class loader. */
+    public static class SharedState {
+    	/** ArrayList of classes whose interfaces have already been transformed by this transformer/classloader combo. */
+    	ArrayList<String> interfaceTransformedClasses = new ArrayList<String>();
+    }
+    /** Reference to the shared state of transformers. */
+    final SharedState state;
+
+    SharedState state() {
+    	return state;
+    }
+    
+    /** Which class loader are we working for? */
+    protected ClassLoader loader;
+    
+	public ObjectTeamsTransformation(SharedState state) { this(null, state); }
+
+	public ObjectTeamsTransformation(ClassLoader loader, SharedState state) {
+		this.loader = loader;
+		this.state = state;
+	}
+
+	// ------------------------------------------
+	// ---------- Logging: ----------------------
+	// ------------------------------------------
+	/** Initialized from property <tt>ot.log</tt>. */
+    static boolean logging = false;
+
+    static {
+        if(System.getProperty("ot.log") != null)
+            logging = true;
+    }
+
+	/** Print <tt>message</tt> only if <tt>logging</tt> is true. */
+    public static void printLogMessage(String message) {
+        System.out.println(message);
+    }
+	
+	//	------------------------------------------
+	// ---------- use the following file as config file for additional active teams: --------
+	// ------------------------------------------
+	 /** Initialized from property <tt>ot.teamconfig</tt>. */
+	 
+	 static String TEAM_CONFIG_FILE = null;
+
+	 static {
+		TEAM_CONFIG_FILE = System.getProperty("ot.teamconfig");
+	 }
+	 
+	 //	------------------------------------------
+	 // ---------- Compatibility with different compiler versions: --------
+	 // ------------------------------------------
+	 
+	 // compiler 1.2.4 introduces isSuperAccess flag for basecall surrogate:
+	 protected static boolean IS_COMPILER_GREATER_123 = false;
+	 
+	 protected static boolean IS_COMPILER_13X_PLUS = false;
+	 
+	 protected static boolean IS_COMPILER_14X_PLUS = false;
+
+	 // ------------------------------------------
+	 // ---------- This flag must currently be true for OT/Equinox: ----------------------
+	 // ------------------------------------------
+	 /** Initialized from property <tt>ot.equinox</tt>. */
+	 public static boolean WORKAROUND_REPOSITORY = false;
+	 
+	 static {
+	 	if(System.getProperty("ot.equinox") != null)
+	 		WORKAROUND_REPOSITORY = true;
+	 }
+	 
+	 // ------------------------------------------
+	 // ---------- Debugging: ----------------------
+	 // ------------------------------------------
+	 /** Initialized from property <tt>ot.debug</tt>. */
+	 static boolean debugging = false;
+	 
+	 static {
+	 	if(System.getProperty("ot.debug") != null)
+	 		debugging = true;
+	 }
+	 
+	// -------------------------------------------------------
+	// ---------- Modes for implicit team activateion --------
+	// -------------------------------------------------------
+	enum ImplicitActivationMode { NEVER, ANNOTATED, ALWAYS }
+	static ImplicitActivationMode implicitActivationMode = ImplicitActivationMode.ANNOTATED;
+	static {
+		String prop = System.getProperty("ot.implicit.team.activation");
+		for (ImplicitActivationMode mode : ImplicitActivationMode.values()) {
+			if (mode.name().equals(prop)) {
+				implicitActivationMode = mode;
+				break;
+			}
+		}
+	}
+
+	// -----------------------------------------
+	// ---------- Signature enhancement --------
+	// -----------------------------------------
+
+	/**
+	 *  Prepend hidden arguments to the signature.
+	 *  This methods only treats argument names.
+	 * @see #enhanceArgumentTypes
+	 *  The arguments are:
+	 *  <dl>
+	 *  <dt><tt>Team[] _OT$teams</tt></dt>
+	 *      <dd>array of active Teams affecting the current base method.
+	 *  <dt><tt>int[] _OT$teamIDs</tt></dt>
+	 *      <dd>array of IDs of the above Teams.
+	 *  <dt><tt>int _OT$idx</tt></dt>
+	 *      <dd>index into above arrays: the Team currently being processed.
+	 *  <dt><tt>Object[] _OT$unusedArgs</tt></dt>
+	 *      <dd>array of arguments which are unused by the current role method.
+	 *  </dl>
+	 *  @param argumentNames array of original argument names.
+	 *  @return augmented array of argument names.
+	 */
+    static String[] enhanceArgumentNames(String[] argumentNames) {
+		return enhanceArgumentNames(argumentNames, 0);
+	}
+
+	/**
+	 *  Prepend hidden arguments to the signature.
+	 *  This methods only treats argument names.
+	 * @see #enhanceArgumentTypes
+	 *  The arguments are:
+	 *  <dl>
+	 *  <dt><tt>Team[] _OT$teams</tt></dt>
+	 *      <dd>array of active Teams affecting the current base method.
+	 *  <dt><tt>int[] _OT$teamIDs</tt></dt>
+	 *      <dd>array of IDs of the above Teams.
+	 *  <dt><tt>int _OT$idx</tt></dt>
+	 *      <dd>index into above arrays: the Team currently being processed.
+	 *  <dt><tt>Object[] _OT$unusedArgs</tt></dt>
+	 *      <dd>array of arguments which are unused by the current role method.
+	 *  </dl>
+	 *  @param argumentNames array of original argument names.
+	 *  @param idx position where new arguments should be inserted into
+	 *             <tt>originalArgumentTypes</tt>.
+	 *  @return augmented array of argument names.
+	 */
+    static String[] enhanceArgumentNames(String[] argumentNames, int idx) {
+  
+    	String[] enhancedArgumentNames =
+			new String[argumentNames.length + EXTRA_ARGS];
+
+        for (int j=0; j<idx; j++)
+            enhancedArgumentNames[j] = argumentNames[j];
+
+        enhancedArgumentNames [idx + TEAMS_ARG     - 1] = TEAMS;
+        enhancedArgumentNames [idx + TEAMIDS_ARG   - 1] = TEAMIDS;
+        enhancedArgumentNames [idx + IDX_ARG       - 1] = IDX;
+        enhancedArgumentNames [idx + BIND_IDX_ARG  - 1] = BIND_IDX;
+        enhancedArgumentNames [idx + BASE_METH_ARG - 1] = BASE_METH_TAG;
+        enhancedArgumentNames [idx + UNUSED_ARG    - 1] = UNUSED;
+
+        for (int j = idx; j < argumentNames.length; j++)
+            enhancedArgumentNames[j + EXTRA_ARGS] = argumentNames[j];
+       
+        return enhancedArgumentNames;
+    }
+
+	/**
+	 * @see #enhanceArgumentTypes(Type[])
+	 * @param signature String from which to extract the argument types.
+	 * @return
+	 */
+	static Type[] enhanceArgumentTypes(String signature) {
+		Type[] types = Type.getArgumentTypes(signature);
+		return enhanceArgumentTypes(types);
+	}
+
+	/**
+	 *  Prepend hidden arguments to the signature.
+	 *  This methods only treats argument types.
+	 *  @see #enhanceArgumentNames
+	 *
+	 *  @param originalArgumentTypes array of original argument types.
+	 *  @return augmented array of argument names.
+	 */
+    static Type[] enhanceArgumentTypes(Type[] originalArgumentTypes) {
+		return enhanceArgumentTypes(originalArgumentTypes, 0, true);
+	}
+
+	/**
+	 *  Prepend hidden arguments to the signature.
+	 *  This methods only treats argument types.
+	 *  @see #enhanceArgumentNames
+	 *
+	 *  @param originalArgumentTypes array of original argument types.
+	 *  @param idx position where new arguments should be inserted into
+	 *             <tt>originalArgumentTypes</tt>.
+	 *  @param createUnused should the <tt>unusedArgs</tt> argument be created?
+	 *  @return augmented array of argument types.
+	 */
+    static Type[] enhanceArgumentTypes(Type[]  originalArgumentTypes,
+								int     idx,
+								boolean createUnused)
+	{
+    // creates enhanced argument type array:
+    // ..(a1,.., aN) -> ..(Team[], int[], int, Object[], a1, .., aN)
+		int offset = createUnused ? EXTRA_ARGS : EXTRA_ARGS-1;
+
+        Type[] enhancedArgumentTypes =
+			new Type[originalArgumentTypes.length+offset];
+
+        for (int j=0; j<idx; j++)
+            enhancedArgumentTypes[j] = originalArgumentTypes[j];
+
+        enhancedArgumentTypes     [idx+TEAMS_ARG     - 1] = teamArray;
+        enhancedArgumentTypes     [idx+TEAMIDS_ARG   - 1] = intArray;
+        enhancedArgumentTypes     [idx+IDX_ARG       - 1] = Type.INT;
+        enhancedArgumentTypes     [idx+BIND_IDX_ARG	 - 1] = Type.INT;
+        enhancedArgumentTypes     [idx+BASE_METH_ARG - 1] = Type.INT;
+		if (createUnused) {
+			enhancedArgumentTypes [idx+UNUSED_ARG    - 1] = objectArray;
+		}
+
+        for (int j = idx; j < originalArgumentTypes.length; j++)
+            enhancedArgumentTypes[j + EXTRA_ARGS] = originalArgumentTypes[j];
+
+        return enhancedArgumentTypes;
+    }
+
+    /**
+	 * Remove the arguments previously added by
+	 * {@link #enhanceArgumentTypes enhanceArgumentTypes}.
+	 * 
+	 * @param enhancedArgumentTypes
+	 * @param staticFlag
+	 * @return
+	 */
+    // FIXME(SH): obsolete
+    public static Type[] _retrenchArgumentTypes(Type[] enhancedArgumentTypes, boolean staticFlag) {
+    // create retrenched argument type array:
+    // ..(Team[], int[], int, Object[], a1, .., aN) -> ..(a1,.., aN)
+
+        int offset = staticFlag? -1 : 0;
+    	
+        Type[] retrenchedArgumentTypes =
+			new Type[enhancedArgumentTypes.length - EXTRA_ARGS + offset];
+
+        for (int j = EXTRA_ARGS; j < enhancedArgumentTypes.length + offset; j++)
+            retrenchedArgumentTypes[j - EXTRA_ARGS] = enhancedArgumentTypes[j];
+
+        return retrenchedArgumentTypes;
+    }
+
+	// ---------------------------------------------------
+	// ---------- further type and value conversions -----
+	// ---------------------------------------------------
+
+	/**
+	 *  @see #generalizeReturnType(Type)
+	 *  @param signature String from which to extract the return type.
+	 */
+	static Type generalizeReturnType (String signature) {
+		Type type = Type.getReturnType(signature);
+		return generalizeReturnType(type);
+	}
+
+	/**
+	 * Given a return type, determine a reference type to which this type can be
+	 * converted. "Object" if type is VOID.
+	 * 
+	 * @param type
+	 * @return
+	 */
+	static Type generalizeReturnType (Type type) {
+		if (type instanceof ReferenceType) return type;
+		return object;
+	}
+
+	/**
+	 * Get the generalized return type from <tt>sign1</tt>, unless
+	 * <tt>sing2</tt> has void return type. In the latter case return
+	 * <tt>Object</tt>.
+	 * 
+	 * @see #generalizeReturnType(Type)
+	 * @param sign1
+	 * @param sign2
+	 * @return
+	 */
+	static Type generalizeReturnType (String sign1, String sign2) {
+		Type type = Type.getReturnType(sign2);
+		if (type == Type.VOID) return object;
+		return generalizeReturnType(sign1);
+	}
+
+	/**
+	 * Assuming a value of type <tt>oldType</tt> on the stack, convert it to a
+	 * value of type <tt>newType</tt>. Changes instruction list <tt>il</tt>
+	 * after position <tt>ih</tt> or at its end if <tt>ih</tt> is null.
+	 * 
+	 * @param il
+	 * @param ih
+	 * @param oldType
+	 * @param newType
+	 * @return the first inserted instruction or null if no adjustment needed
+	 */
+    InstructionHandle adjustValue (InstructionList il, InstructionHandle ih,
+								   Type oldType, Type newType) {
+		if (ih == null)
+			ih = il.getEnd();
+        if (oldType.equals(newType))
+			return null;
+
+        if (newType == Type.VOID)
+            return il.append(ih, new POP());
+        else if (oldType == Type.VOID)
+            return il.append(ih, InstructionFactory.ACONST_NULL);
+        else if (oldType instanceof BasicType)
+            return il.append(ih, createBoxing((BasicType)oldType));
+        else if (newType instanceof BasicType)
+            return il.append(ih, createUnboxing((BasicType)newType));
+        else
+            return il.append(ih, factory.createCast(oldType, newType));
+    }
+
+	// ------------------------------------------
+	// ---------- (Un-)Boxing: ------------------
+	// ------------------------------------------
+
+	/**
+	 * Get the name of the class suitable for boxing <tt>basicType</tt>.
+	 * 
+	 * @param basicType
+	 * @return
+	 */
+    static String toObjectTypeName(BasicType basicType) {
+        String result = "";
+        switch (basicType.getType()) {
+            case Constants.T_BOOLEAN : result = "java.lang.Boolean";   break;
+            case Constants.T_INT :     result = "java.lang.Integer";   break;
+            case Constants.T_FLOAT :   result = "java.lang.Float";     break;
+            case Constants.T_DOUBLE :  result = "java.lang.Double";    break;
+            case Constants.T_SHORT :   result = "java.lang.Short";     break;
+            case Constants.T_BYTE :    result = "java.lang.Byte";      break;
+            case Constants.T_CHAR :    result = "java.lang.Character"; break;
+            case Constants.T_LONG :    result = "java.lang.Long";      break;
+            default: throw new Error("OTRE failure: Basic Type not supported!!"+basicType);
+        }
+        return result;
+    }
+
+	/**
+	 * Create the instructions needed for boxing a basic type value. The value
+	 * is expected on the stack an will be replaced by the boxed value.
+	 * 
+	 * @param basicType	type of the value on the stack.
+	 * @return an InstructionList containing the conversion instructions.
+	 */
+    InstructionList createBoxing(BasicType basicType) {
+        InstructionList il   = new InstructionList();
+		String boxedTypeName = toObjectTypeName(basicType);
+		                                              // .., result
+        il.append(factory.createNew(boxedTypeName));  // .., result, box,
+
+        if (basicType.equals(Type.DOUBLE) || basicType.equals(Type.LONG)) {
+        // 'double' and 'long' are category 2 computational type:
+            il.append(new DUP_X2());                  // .., box, result, box
+            il.append(new DUP_X2());                  // .., box, box, result, box
+        } else {
+            il.append(new DUP_X1());                  // .., box, result, box
+            il.append(new DUP_X1());                  // .., box, box, result, box
+        }
+        il.append(new POP());                         // .., box, box, result
+        il.append(factory.createInvoke(boxedTypeName,
+                                       Constants.CONSTRUCTOR_NAME,
+                                       Type.VOID,
+                                       new Type[] { basicType },
+                                       Constants.INVOKESPECIAL));
+        return il;
+    }
+
+	/**
+	 * Create the instructions needed for unboxing a basic type value. The value
+	 * is expected on the stack an will be replaced by the unboxed value.
+	 * 
+	 * @param basicType	expected type after unboxing.
+	 * @return an InstructionList containing the conversion instructions.
+	 */
+    InstructionList createUnboxing(BasicType basicType) {
+        InstructionList il   = new InstructionList();
+		String boxedTypeName = toObjectTypeName(basicType);
+        il.append(factory.createCast(object,
+									 new ObjectType(boxedTypeName)));
+        il.append(factory.createInvoke(boxedTypeName,
+									   basicType.toString() + "Value",
+									   basicType,
+									   Type.NO_ARGS,
+									   Constants.INVOKEVIRTUAL));
+        return il;
+    }
+
+    /** Push an integer constant using the most appropriate/compact instruction. */
+    Instruction createIntegerPush(ConstantPoolGen cpg, int val) {
+    	if (val <= 5)
+    		return new ICONST(val);
+    	if (val <= Byte.MAX_VALUE)
+    		return new BIPUSH((byte)val);
+    	if (val <= Short.MAX_VALUE)
+    		return new SIPUSH((short)val);
+    	return new LDC(cpg.addInteger(val));
+    }
+    
+    /** 
+     * Create a throwing instruction for an OTREInternalError.
+     * 
+     * @param cpg
+     * @param il		  instruction list to generate into
+     * @param messagePush push sequence producing the exception message.
+     * @return 			  handle to the first generated instruction
+     */
+	InstructionHandle createThrowInternalError(ConstantPoolGen cpg, InstructionList il, InstructionList messagePush) {
+		InstructionHandle start = il.append(factory.createNew(OTConstants.internalError));
+		il.append(new DUP());
+		il.append(messagePush);
+		il.append(factory.createInvoke(OTConstants.internalError.getClassName(),
+				Constants.CONSTRUCTOR_NAME,
+				Type.VOID,
+				new Type[] { Type.STRING }, 
+				Constants.INVOKESPECIAL));
+		il.append(new ATHROW());
+		return start;
+	}
+
+	/**
+	 * Create a lookswitch from its constituents. Since JVM 1.4 this requires
+	 * sorting of matches.
+	 * 
+	 * @param matches
+	 * @param targets
+	 * @param breaks an array of breaks (GOTOs) whose target will
+	 *               be updated to point to <tt>afterSwitch</tt>
+	 * @param defaultBranch
+	 * @param afterSwitch
+	 * @return the generated instruction.
+	 */
+	static BranchInstruction createLookupSwitch (int[] matches,
+										  InstructionHandle[] targets,
+										  GOTO[]              breaks,
+										  InstructionHandle   defaultBranch,
+										  InstructionHandle   afterSwitch) {
+
+		int numberOfCases = matches.length;
+        for (int i = 0; i < numberOfCases; i++)
+            breaks[i].setTarget(afterSwitch);
+
+        HashMap<Integer, InstructionHandle> match_target_mapping = new HashMap<Integer, InstructionHandle>();
+        for (int i = 0; i < numberOfCases; i++)
+            match_target_mapping.put(Integer.valueOf(matches[i]), targets[i]);
+
+        Arrays.sort(matches);
+        for (int i = 0; i < numberOfCases; i++)
+            targets[i] = match_target_mapping.get(Integer.valueOf(matches[i]));
+
+        BranchInstruction inst = new LOOKUPSWITCH(matches, targets, defaultBranch);
+		return inst;
+	}
+
+	
+    /**
+	 * Read all byte code attributes for a given class. Side-Effect: depending
+	 * on the Referenced-Team attribute, additional classes may be scheduled for
+	 * loading.
+	 * 
+	 * @param ce
+	 * @param cg
+	 * @param class_name
+	 * @param cpg
+	 */
+    public void checkReadClassAttributes(ClassEnhancer ce,
+								         ClassGen cg,
+								  		 String class_name,
+								  		 ConstantPoolGen cpg)
+    {
+    	AttributeReadingGuard guard = AttributeReadingGuard.getInstanceForLoader(this.loader);
+    	boolean addTeamInitializations = false;
+    	List<String> classesToLoad;
+    	synchronized (guard) {
+    		if (!guard.iAmTheFirst(class_name))
+    			return;
+			if (AttributeReadingGuard.isFirstLoadedClass())
+				addTeamInitializations = true;
+			// scan for attributes here, because this transformer is applied first:
+			Attribute[] attrsClass = cg.getAttributes();
+			classesToLoad = scanClassOTAttributes(attrsClass, class_name, cpg, cg);
+			
+			guard.workDone(class_name);
+		}
+    	if (addTeamInitializations)
+    		addTeamInitializations(cg, ce);
+    	
+		Iterator<String> it = classesToLoad.iterator();
+		while (it.hasNext()) {
+			String next = it.next();
+            if(logging) printLogMessage("Loading of class " + next + " will be forced now!");
+			ce.loadClass(next, this);
+		}
+			
+		// scan for parameter bindings:
+		Method[] possibleRoleMethods = cg.getMethods();
+		for (int i=0; i<possibleRoleMethods.length; i++) {
+			Method meth = possibleRoleMethods[i];
+			Attribute[] attrsMethod = meth.getAttributes();
+			scanMethodOTAttributes(attrsMethod, class_name, meth.getName(), cpg);
+		}
+        if(logging) printLogMessage(this.getClass().getName()
+						+ " picked up the attributes for class " + class_name );
+    }
+        
+    // --- helpers for adding line numbers at the front of a method  ---
+    // unfortunately BCEL does not sort line numbers, but the debugger expects them sorted.
+    class Pair<F,S> {
+    	F first;
+    	S second;
+    	Pair(F f, S s) {
+    		this.first = f;
+    		this.second = s;
+    	}
+    }
+    @SuppressWarnings("unchecked") // can't declare array of generics
+	Pair<InstructionHandle, Integer>[] saveLineNumbers(MethodGen method, ConstantPoolGen cpg) {
+    	LineNumberTable lnt = method.getLineNumberTable(cpg);
+    	InstructionHandle[] ihs = method.getInstructionList().getInstructionHandles();
+    	Pair<InstructionHandle, Integer>[] oldLines = new Pair[lnt.getTableLength()];
+    	{
+			int cur = -1;
+			int n = 0;
+			for (int i=0; i<ihs.length; i++) {
+				int next = lnt.getSourceLine(ihs[i].getPosition());
+				if (next > cur)  // reached a new source line
+					oldLines[n++] = new Pair<InstructionHandle, Integer>(ihs[i], new Integer(next));
+				cur = next;
+			}
+    	}
+    	return oldLines;    	
+    }
+    /** Append the saved line numbers to the end of the method's line number table. */
+	void restoreLineNumbers(MethodGen method, Pair<InstructionHandle, Integer>[] oldLines) {
+		for (int i=0; i<oldLines.length; i++) {
+			if (oldLines[i] == null)
+				continue;
+			InstructionHandle ih = oldLines[i].first;
+			int line = oldLines[i].second.intValue();
+			method.addLineNumber(ih, line);
+		}
+	}
+
+    /**
+	 * Adds team initialization for all teams in the config file.
+	 * 
+	 * @param cg
+	 * @param ce
+	 */
+    private void addTeamInitializations(ClassGen cg, ClassEnhancer ce) {
+    	String main_class_name = cg.getClassName();
+    	ConstantPoolGen cpg = cg.getConstantPool();
+    	InstructionFactory factory = new InstructionFactory(cpg);
+    	Method main = cg.containsMethod("main", "([Ljava/lang/String;)V");
+    	if (main == null) {
+    		// JPLIS launching may intercept system classes before the custom main.
+    		// reset the guard in order to retry with subsequent classes.
+    		AttributeReadingGuard.reset();
+    		return; // no main method in the first loaded class...
+    	}
+    	
+    	MethodGen mainMethod = new MethodGen(main, main_class_name, cpg);
+    	InstructionList il = mainMethod.getInstructionList();
+    	
+    	int startLine = -1;
+    	Pair<InstructionHandle,Integer>[] oldLines = null;
+    	if (debugging) {
+    		LineNumberTable lnt = mainMethod.getLineNumberTable(cpg);
+    		if (lnt != null) {
+    			startLine = lnt.getSourceLine(0);
+    			oldLines = saveLineNumbers(mainMethod, cpg);
+    		}
+    	}
+    	
+    	if (TEAM_CONFIG_FILE != null) {
+    		
+    		InstructionList teamInitializations = new InstructionList();
+    		List<String> teamsToInitialize = getTeamsFromConfigFile();
+    		Iterator<String> teamIt = teamsToInitialize.iterator();
+    		while (teamIt.hasNext()) {
+    			String nextTeam = teamIt.next();
+    			JavaClass teamClass = Repository.lookupClass(nextTeam);
+    			if (teamClass == null) {
+    				System.err.println("Config error: Team class '"+nextTeam+ "' in config file '"+ TEAM_CONFIG_FILE+"' can not be found!");
+    				System.err.println("Main class = "+main_class_name+
+    									", class loader = "+(this.loader!=null?this.loader.getClass().getName():"null")+
+    									", transformer = "+this.getClass().getName());
+    				continue;
+    			}
+    			ClassGen teamClassGen = new ClassGen(teamClass);
+    			if (teamClassGen.containsMethod(Constants.CONSTRUCTOR_NAME, "()V") == null) {
+    				System.err.println("Activation failed: Team class '"+nextTeam+ "' has no default constuctor!");
+    				continue;
+    			}
+    			ce.loadClass(nextTeam, this);
+    			if (logging)
+					printLogMessage("Adding initialization of team " + nextTeam
+							+ " to main method of class " + main_class_name);
+    			teamInitializations.append(factory.createNew(nextTeam));
+    			teamInitializations.append(new DUP());
+    			teamInitializations.append(factory.createInvoke(nextTeam,
+    					Constants.CONSTRUCTOR_NAME,
+						Type.VOID,
+						Type.NO_ARGS,
+						Constants.INVOKESPECIAL));
+    			teamInitializations.append(factory.createGetStatic(OTConstants.teamClassName,
+						"ALL_THREADS",
+						 OTConstants.threadType));
+    			teamInitializations.append(factory.createInvoke(nextTeam,
+    					"activate",
+						Type.VOID,
+						new Type[] {OTConstants.threadType},
+						Constants.INVOKEVIRTUAL));
+    		}
+    		il.insert(teamInitializations);
+    	}
+    	// register main thread with TeamThreadManager:
+        InstructionHandle cursor;
+        cursor = il.insert(new ICONST(1)); // isMain=true
+        cursor = il.append(cursor, new ACONST_NULL()); // parent=null
+        cursor = il.append(cursor, factory.createInvoke("org.objectteams.TeamThreadManager", 
+						                "newThreadStarted",
+										 Type.BOOLEAN,
+										 new Type[]{Type.BOOLEAN, OTConstants.threadType},
+										 Constants.INVOKESTATIC));
+        cursor = il.append(cursor, new POP()); // don't use boolean return
+
+    	il.setPositions(); 
+    	if (debugging && startLine > 0) {
+    		mainMethod.removeLineNumbers(); 					  // fresh start, to ensure correct order
+    		mainMethod.addLineNumber(il.getStart(), startLine-1); // new number to the front
+    		restoreLineNumbers(mainMethod, oldLines);		      // append old numbers
+    	}
+    	mainMethod.setInstructionList(il);
+    	mainMethod.setMaxStack();
+    	mainMethod.setMaxLocals();
+    	
+    	cg.replaceMethod(main, mainMethod.getMethod());
+    }
+
+	/**
+	 * @return a list of teams in the team initialization config file
+	 */
+	private static List<String> getTeamsFromConfigFile() {
+		List<String> result = new LinkedList<String>();
+		try {
+			FileInputStream fstream = new FileInputStream(TEAM_CONFIG_FILE);
+			BufferedReader in = new BufferedReader(new InputStreamReader(fstream));
+ 			while (in.ready()) {
+				String nextLine = in.readLine();
+				String nextTeam = nextLine.trim();
+				if (nextTeam.startsWith(COMMENT_MARKER))
+					continue; // this is a comment line
+				if (!nextTeam.equals("")) {
+					result.add(nextTeam.trim());
+				}
+			}
+			in.close();
+		} catch (Exception e) {
+			System.err.println("File input error: config file '" + TEAM_CONFIG_FILE + "' can not be found!");
+		}
+		return result;
+	}
+
+	 // -------------------------------------------------------------------------------------------------
+	 // -------- store and return adapted bases for OT/Equinox --------------
+	 // this data is collected by scanClassOTAttributes and must be collected by the caller
+	 // before processing the next class.
+	 // -------------------------------------------------------------------------------------------------
+	 public HashSet<String> adaptedBases = new HashSet<String>();
+
+	 /** Internal API for {@link org.eclipse.objectteams.otre.jplis.ObjectTeamsTransformer} */
+	 public Collection<String> fetchAdaptedBases() {
+		 HashSet<String> result;
+		 result = new HashSet<String>(adaptedBases);
+		 adaptedBases.clear();
+		 return result;
+	 }
+
+	 // ------------------------------------------------------------------------------------------------- 
+     /**
+ 	  * Container for base method properties
+	  */
+	 public static class BaseMethodInfo {
+		 private String baseClassName;
+		private String baseMethodName;
+		private String baseMethodSignature;
+		boolean isCallin;
+		private boolean isRoleMethod;
+		boolean isStatic;
+		private int[] parameterPositions;
+		int translationFlags;
+
+		BaseMethodInfo(String base_class_name, String base_method_name,
+					   String base_method_signature, boolean isCallin,
+					   boolean isRoleMethod, boolean isStatic,
+					   int[] parameter_positions, int translationFlags) 
+		{
+			this.baseClassName = base_class_name;
+			this.baseMethodName = base_method_name;
+			this.baseMethodSignature = base_method_signature;
+			this.isCallin = isCallin;
+			this.isRoleMethod = isRoleMethod;
+			this.isStatic = isStatic;
+			this.parameterPositions = parameter_positions;
+			this.translationFlags = translationFlags;
+		}
+		/** Minimal version to pass some info into #translateLoads(): */
+		BaseMethodInfo(boolean isCallin, boolean isStatic, int translationFlags) 
+		{
+			this.isCallin = isCallin;
+			this.isStatic = isStatic;
+			this.translationFlags = translationFlags;
+		}
+
+		public boolean isStaticRoleMethod() {
+			return this.isRoleMethod && this.isStatic;
+		}
+
+		String getBaseClassName() {
+			return baseClassName;
+		}
+
+		String getBaseMethodName() {
+			return baseMethodName;
+		}
+
+		String getBaseMethodSignature() {
+			return baseMethodSignature;
+		}
+
+		int[] getParameterPositions() {
+			return parameterPositions;
+		}
+	}
+	
+	/**
+	 * Scan the Attributes found in the class class_name for binding attributes
+     * and registers them in the CallinBindingManager.
+	 * 
+	 * @param attributes    the Attributes to be examined
+	 * @param class_name    the name of the class where the Attributes were found
+     * @param cpg           the classes ConstantPoolGen
+	 * @return              an ArrayList containing the names of classes which have
+	*                       to be loaded immediately
+    */
+    ArrayList<String> scanClassOTAttributes(Attribute[] attributes,
+								 String          class_name,
+								 ConstantPoolGen cpg,
+								 ClassGen cg)
+	{
+        if(logging) printLogMessage("Inspecting " + class_name);
+        ArrayList<String> classesToLoad = new ArrayList<String>();
+        String base_class_name = null;
+        for (int k=0; k<attributes.length; k++) {
+            Attribute actAttr = attributes[k];
+            Unknown attr = isOTAttribute(actAttr);
+	
+            if (attr != null) { //this is a callin attribute
+                String attrName = attr.getName();
+                if(logging) printLogMessage("CallinBindingAttribute: " + attrName);
+                byte[] indizes = attr.getBytes();
+                int count = combineTwoBytes(indizes, 0);
+                int numberOfEntries=0;
+				String [] names;
+				if (attrName.equals("OTClassFlags")) {
+					int classFlags = combineTwoBytes(indizes, 0);
+					String flagsString = "";
+					if ((classFlags & 1) != 0) {
+						flagsString = "team ";
+						// TODO: use this instead of team modifier
+					}
+					if ((classFlags & 2) != 0) {
+						flagsString += "role";
+						CallinBindingManager.addRole(class_name);
+					}
+                    if (logging) {
+						printLogMessage("OTClassFlags:");
+						printLogMessage("\t" + flagsString);
+					}
+				} else if (attrName.equals("CallinRoleBaseBindings")) {
+                    numberOfEntries = 2;
+                    int i = 2;
+                    int n = 2 * count * numberOfEntries; // n = count << 2; 
+                    names = new String[numberOfEntries];
+                    while (i <= n) {
+						i = scanStrings(names, indizes, i, cpg);
+						String role_name = names[0];
+						String base_name = names[1];
+                        if(logging) printLogMessage("**** Binding: " + role_name 
+                                                    + " playedBy " + base_name);
+
+                        //set binding:
+                        CallinBindingManager.addRoleBaseBinding(role_name, base_name, class_name);
+                        CallinBindingManager.addTeamBaseRelation(class_name, base_name);
+                        
+                		// [OT/Equinox] store adapted bases:
+               			adaptedBases.add(base_name);
+
+                        // super roles have to be loaded first for binding inheritance purpose:
+                        // not necessary anymore?
+                        //classesToLoad.addAll(getSuperRoles(role_name, attributes, cpg));
+                        // roles themselve have to be loaded too:
+                        classesToLoad.add(role_name);
+                    }
+				} else if (attrName.equals("BoundClassesHierarchy")) {
+                    numberOfEntries = 2;
+                    int i = 2;
+                    int n = 2 * count * numberOfEntries; // n = count << 2; 
+                    names = new String[numberOfEntries];
+                    while (i <= n) {
+						i = scanStrings(names, indizes, i, cpg);
+						String sub_name = names[0];
+						String super_name = names[1];
+						
+						CallinBindingManager.addBoundSuperclassLink(sub_name, super_name);
+                        if(logging)printLogMessage("**** super-class link: "+sub_name
+										+" -> "+super_name);
+                    }
+                } else if (attrName.equals("CallinMethodMappings")) {
+                    //numberOfEntries = 6;
+                    int i = 2;
+                    for (int n=0; n<count;n++) {
+                    	// JSR-045 support:
+                    	names = new String[1];
+                    	i = scanStrings(names, indizes, i, cpg);
+                    	String binding_file_name = names[0];
+                    	int binding_line_number = combineTwoBytes(indizes, i);
+                    	i += 2;
+                    	int binding_line_offset = combineTwoBytes(indizes, i);
+                    	i += 2;
+                    	boolean is_static_role_method = false;
+                    	boolean covariant_base_return= false;
+                    	// regular stuff:
+                    	numberOfEntries = 3;
+						names = new String[numberOfEntries];
+						i = scanStrings(names, indizes, i, cpg);
+						String wrapper_name = null;
+						String wrapper_signature = null;
+						// first 3 names:
+						int index = 0;
+						
+						String binding_label         = names[index++];
+						String role_method_name      = names[index++];
+						String role_method_signature = names[index++];
+						
+						{	// a flag:
+							int flags = combineTwoBytes(indizes, i);
+							is_static_role_method = (flags & 1) != 0;
+							// flag value 4 is "inherited"
+							covariant_base_return = (flags & 8) != 0;
+							i+=2;
+						}
+						// 3 more names
+						numberOfEntries = 3;
+						names = new String[numberOfEntries];
+						i = scanStrings(names, indizes, i, cpg);
+						index = 0;
+						//if (NEW_COMPILER_VERSION)
+						// static_role_method = see attribute
+							
+						String lift_method_name				= names[index++];
+						String lift_method_signature		= names[index++];
+						String binding_modifier				= names[index++];
+
+                        int base_len = combineTwoBytes(indizes, i);
+                        i += 2;
+
+                        names = new String[4];
+                        for (int n_base = 0; n_base < base_len; n_base++) {
+                            i = scanStrings(names, indizes, i, cpg);
+                            String base_method_name         = names[0];
+						    String base_method_signature	= names[1];
+							wrapper_name               		= names[2];
+							wrapper_signature          		= names[3];
+
+							byte baseFlags = indizes[i++];
+							boolean baseIsCallin = (baseFlags & 1) != 0;
+							boolean baseIsStatic = (baseFlags & 2) != 0;
+	                        int translationFlags = (combineTwoBytes(indizes, i)<<16) + combineTwoBytes(indizes, i+2);
+	                        i += 4;
+
+                            if(logging) {
+                                printLogMessage("**** Binding: " + binding_label + ":"
+                                        + role_method_name + role_method_signature
+                                        + " <- " + binding_modifier + " "
+                                        + base_method_name + base_method_signature);
+                                printLogMessage("**** Wrapper: " + wrapper_name
+                                        + wrapper_signature);
+                            }
+                            //set binding:
+                            CallinBindingManager.addMethodBinding(class_name,
+                            									  base_class_name, // previously read from PlayedBy attribute
+                            								  	  binding_file_name,
+															  	  binding_line_number,
+															  	  binding_line_offset,
+															  	  binding_label,
+															  	  role_method_name,
+															  	  role_method_signature,
+															  	  is_static_role_method,
+															  	  wrapper_name,
+															  	  wrapper_signature,
+															  	  binding_modifier,
+															  	  base_method_name,
+															  	  base_method_signature,
+															  	  baseIsStatic,
+															  	  baseIsCallin,
+															  	  covariant_base_return,
+															  	  translationFlags,
+															  	  lift_method_name, 
+															  	  lift_method_signature); 
+
+                        }
+                    }
+                } else if (attrName.equals("OTSpecialAccess")) {
+                	numberOfEntries = 3;
+                	int i = 2;
+                	for (int j = 0; j < count; j++) {
+                		short kind = indizes[i++];
+                		switch (kind) {
+                		case 1: // DecapsulatedMethodAccess
+                			names = new String[numberOfEntries];
+                			i = scanStrings(names, indizes, i, cpg);
+                			if(logging) printLogMessage("**** Callout: " + names[0] + "." 
+								     + names[1]+ " " + names[2]);
+                			CallinBindingManager.addCalloutBinding(names[0], names[1], names[2]);
+                			break;
+                		case 2: // CalloutFieldAccess
+                			short flags = indizes[i++];
+                			String accessMode = (flags & 1) == 1 ? "set" : "get";
+                			boolean isStaticField = (flags & 2) != 0;
+                			names = new String[numberOfEntries];
+                			i = scanStrings(names, indizes, i, cpg);
+                			if (logging)
+                				printLogMessage("**** Callout bound field: " + accessMode+(isStaticField?" static ":" ")
+                							    + names[2]+ " " + names[1]);
+                			CallinBindingManager.addCalloutBoundFileds(names[0], names[1], names[2], accessMode, isStaticField);
+
+                			synchronized(reentrentTransformations) {
+	                			for (ObjectTeamsTransformation transformation : reentrentTransformations) 
+	            					transformation.state.interfaceTransformedClasses.remove(names[0]);
+                			}
+                			
+                			break;
+                		case 3: // SuperMethodAccess
+                			numberOfEntries = 4; 
+                			names = new String[numberOfEntries];
+                			i = scanStrings(names, indizes, i, cpg);
+                			if(logging) printLogMessage("**** SuperAccess: " + names[0] + "." 
+								     + names[2]+ names[3]+" superclass "+names[1]);
+                			CallinBindingManager.addSuperAccess(names[0], names[1], names[2], names[3]);
+                			break;
+                		}
+                	}                	
+                	// adapted baseclasses (w/ or w/o decapsulation):
+                	count = combineTwoBytes(indizes, i);
+                	i += 2;
+                	names = new String[1];
+                	for (int j=0; j<count; j++) {
+	                	i = scanStrings(names, indizes, i, cpg);
+	                	byte flag = indizes[i++];
+	                	if (flag == 1) {
+							CallinBindingManager.addBaseClassForModifierChange(names[0]);
+						} else {
+							CallinBindingManager.addExtraReferencedBase(class_name, names[0]);
+	                		// [OT/Equinox]: store adapted bases:
+                			adaptedBases.add(names[0]);
+						}
+                	}
+				} else if (attrName.equals("ReferencedTeams")) {
+                    numberOfEntries = 1;
+                    int i = 2;
+                    int n = 2 * count * numberOfEntries; // n = count << 1;
+                    names = new String[numberOfEntries];
+                    while (i <= n) {
+						i = scanStrings(names, indizes, i, cpg);
+						String referenced_team = names[0];
+                        if(logging) printLogMessage("**** found ReferencedTeams: " + referenced_team);
+                        classesToLoad.add(referenced_team);
+
+                    }
+                } else if (attrName.equals("BaseClassTags")) {
+                    numberOfEntries = 2;
+                    String baseClass = "";
+		            int tag = 0;
+		            HashMap<String, Integer> tagMap = new HashMap<String, Integer>();
+
+                    int i = 2;
+                    int n = 2 * count * numberOfEntries; //count << 2; 
+                    while (i <= n) {
+						for (int j = 0; j < numberOfEntries; j++) {
+							int nextIndex = combineTwoBytes(indizes, i);
+							if (j == 0) {
+								ConstantUtf8 cons = (ConstantUtf8) cpg
+										.getConstant(nextIndex);
+								baseClass = cons.getBytes();
+							} else if (j == 1) {
+								tag = nextIndex;
+							}
+							i += 2;
+						}
+			            tagMap.put(baseClass, Integer.valueOf(tag));
+                        if(logging) printLogMessage("**** found Base tag: " + class_name + "."
+                                + baseClass + "->" + tag);
+                    }
+		            CallinBindingManager.addBaseTags(class_name, tagMap);
+				} else if (attrName.equals("PlayedBy")) {
+					names = new String[1];
+					scanStrings(names, indizes, 0, cpg);
+					base_class_name = names[0];
+					int langle = base_class_name.indexOf('<');
+					if (langle > -1) // it's an anchored type p.T$R<@C.o.f>, cut off everything after and including '<'.
+						base_class_name = base_class_name.substring(0, langle-1);
+                    if(logging) printLogMessage("**** found PlayedBy:  " + base_class_name);
+                    // base_class_name is stored for later use, when method bindings are found.
+					CallinBindingManager.addSuperRoleLink(cg.getClassName(), cg.getSuperclassName());
+					// this information is NOT NEEDED at moment!		
+				} else if (attrName.equals("OTCompilerVersion")) {
+					int encodedVersion = combineTwoBytes(indizes, 0);
+					int major = encodedVersion >>> 9;
+					int minor = (encodedVersion >>> 5) & 0xF;
+					int revision = encodedVersion & 0x1F;
+                    if(logging) printLogMessage("**** class file was produced by compiler version "
+                            + major + "." + minor + "." + revision + " ****");
+                    IS_COMPILER_GREATER_123 = false; // reset, may be updated below
+                    LowerableTransformation.checkRequiresAdaptation(major, minor, revision, cg);
+					// 1.4 stream:
+					if (major == 1 && minor == 4) {
+						if (revision < OT14_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+						IS_COMPILER_GREATER_123 = true;
+						IS_COMPILER_13X_PLUS = true;
+						IS_COMPILER_14X_PLUS = true;
+					// 1.3 stream:
+					} else if (major == 1 && minor == 3) {
+						if (revision < OT13_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+						IS_COMPILER_GREATER_123 = true;
+						IS_COMPILER_13X_PLUS = true;
+					// 1.2 stream:
+					} else if (major == 1 && minor == 2) {
+						if (revision < OT12_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+						if (revision > 3)
+							IS_COMPILER_GREATER_123 = true;
+						// 1.1 stream:
+					} else if (major == 1 && minor == 1) {
+						if (revision < OT11_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+						// 1.0 stream:
+					} else if (major == 1 && minor == 0) {
+						if (revision < OT10_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+					// 0.9 stream:
+					} else if (major == 0 && minor == 9) {
+						if (revision < OT09_REVISION) {
+							if (class_name.startsWith(OTConstants.teamClassName))
+								continue; // no specific byte codes in ooTeam and its inner classes.
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+						}
+					// 0.8 stream (OBSOLETE!)
+					} else {
+						if (major != OT_VERSION_MAJOR)
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported major version " + major);
+						if (minor != OT_VERSION_MINOR)
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported minor version " + minor);
+						if (revision < OT_REVISION)
+							throw new InternalError("OTRE: Class " + class_name + " has unsupported revision " + revision);
+					}
+				} else if (attrName.equals("CallinPrecedence")) {
+                    List<String> precedenceList = new LinkedList<String>(); 
+                    numberOfEntries = 1;
+                    int i = 2;
+                    int n = 2 * count * numberOfEntries; // n = count << 1;
+                    names = new String[numberOfEntries];
+                    while (i <= n) {
+                        i = scanStrings(names, indizes, i, cpg);
+                        String binding_label = names[0];
+                        precedenceList.add(binding_label);
+                    }
+                    if(logging) printLogMessage("**** found precedence list for " + class_name + ": "
+                            + precedenceList + " ****");
+                    CallinBindingManager.addPrecedenceList(precedenceList, class_name);
+                }
+            }
+        }
+        return classesToLoad;
+    }
+    
+	/**
+	 * Read some strings from a byte array.
+	 * @param entries Result array to be provided by caller.
+	 * @param indizes buffer of read bytes to be provided by caller,
+	 *                consists if indizes into the constant pool
+	 * @param i       current index into indizes
+	 * @param cpg     the pool.
+	 * @result        updated value of <tt>i</tt>.
+	 */
+	public static int scanStrings(String[] entries,
+					byte[]          indizes,
+					int             i,
+					ConstantPoolGen cpg)
+	{
+		for (int j = 0; j < entries.length; j++) {
+			int nextIndex = combineTwoBytes(indizes, i);
+			ConstantUtf8 cons      = (ConstantUtf8)cpg.getConstant(nextIndex);
+			String       content   = cons.getBytes();
+			entries[j] = content;
+			i += 2;
+		}
+		return i;
+	}
+
+    /**
+    *  Scan the Attributes found in the method <tt>method_name</tt> for binding attributes
+    *  and registers them in the {@link CallinBindingManager CallinBindingManager}.
+    *
+    *  @param attributes    the Attributes to be examined
+    *  @param class_name    the name of the class where the Attributes were found
+    *  @param method_name   the name of the method where the Attributes were found
+    *  @param cpg
+    */
+    static void scanMethodOTAttributes(Attribute[] attributes,
+								String          class_name,
+								String          method_name,
+								ConstantPoolGen cpg)
+	{
+        for (int k = 0; k < attributes.length; k++) {
+            Attribute actAttr = attributes[k];
+            Unknown attr = isOTAttribute(actAttr);
+            if (attr != null) { //this is an OT attribute
+                String attrName = attr.getName();
+                if(logging) printLogMessage("CallinBindingAttribute(" + method_name + ") :"
+                        + attrName);
+                if (attrName.equals("CallinParamMappings")) {
+					byte[] indizes = attr.getBytes();
+					int [] positions = null;
+					if (indizes == null) throw new RuntimeException("Unexpected null attr");
+					int count = combineTwoBytes(indizes, 0);
+					positions = new int[count];
+					int p = 2;
+					for (int i = 0; i < count; i++, p += 2) {
+						positions[i] = combineTwoBytes(indizes, p);
+						// System.out.println(" "+i+"<-"+positions[i]);
+					}
+					CallinBindingManager.addParameterBinding(class_name,
+															 method_name,
+															 positions);
+					// Here it is correct to use the (wrapper) method name without a signature, 
+					// because for overloaded methods there are separate wrappers with unique (mangled) names. 
+				}
+            }
+        }
+    }
+
+
+	/**
+    *  Determines, if the given Attribute is a callin-attribute.
+    *
+    *  @param attr      the Attriute to be checked
+    *  @return          the Attribute casted to Unknown, for later use, if true
+    *                   null, if it is not a callin-attribute
+    */
+    static Unknown isOTAttribute(Attribute attr) {
+        if (attr instanceof Unknown) {
+            Unknown unknown = (Unknown)attr;
+            String attrName = unknown.getName();
+            if (attrName.equals("CallinRoleBaseBindings") 	||
+                attrName.equals("BoundClassesHierarchy")    ||
+                attrName.equals("CallinMethodMappings")   	||
+                attrName.equals("CallinParamMappings")     	||
+                attrName.equals("CallinFlags")             	||
+				attrName.equals("OTSpecialAccess")     		||
+                attrName.equals("WrappedRoleSignature")   	||
+				attrName.equals("WrappedBaseSignature") 	||
+                attrName.equals("ReferencedTeams")        	||
+                attrName.equals("BaseClassTags")		  	||
+                attrName.equals("PlayedBy") 			  	||
+                attrName.equals("Modifiers")				||
+                attrName.equals("OTCompilerVersion") 		||
+                attrName.equals("OTClassFlags")				||
+                attrName.equals("OTJoinPoints")				||
+				attrName.equals("CallinPrecedence")			||
+				attrName.equals("StaticReplaceBindings"))
+            {
+                return unknown;
+            }
+        }
+        return null;
+    }
+
+    /**
+    *  Combines two int's representing the higher and the lower part
+	*  of a two byte number.
+    *
+    *  @param first     the first (higer?) byte
+    *  @param second    the second (lower?) byte
+    *  @return          the combined number
+    */
+    public static int combineTwoBytes(byte [] indizes, int start) {
+		int first = indizes[start];
+		int second = indizes[start + 1];
+		int twoBytes = 0;
+
+		twoBytes = twoBytes | (first & 0xff);
+		twoBytes = twoBytes << 8;
+		twoBytes = twoBytes | (second & 0xff);
+		return twoBytes;
+    }
+    
+	/**
+	 *  Returns a list of names of all super classes of class 'role_name' which are inner
+	 *  classes of the enclosing team, what are all super roles of the 
+	 *  role 'role_name'.
+	 *
+	 *  @param role_name     the name of the role class
+	 *  @param attributes    the attributes of the enclosing team class
+	 *  @param cpg	the constant pool of the enclosing team class
+	 *  @return          the list of super role names
+	 */
+	/*
+	private List getSuperRoles(String role_name, Attribute[] attributes, ConstantPoolGen cpg) {
+		LinkedList superRoleNames = new LinkedList();
+		JavaClass[] super_classes = Repository.getSuperClasses(role_name);
+		 if (super_classes.length < 2) {// extends only Object, or none?
+		 	return superRoleNames;
+		 }
+		LinkedList innerClassNames = new LinkedList();
+		for (int i=0; i<attributes.length; i++) {
+			Attribute actAttr = attributes[i];
+			if (actAttr instanceof InnerClasses) {
+				InnerClass[] inners = ((InnerClasses)actAttr).getInnerClasses();
+				for (int j=0; j<inners.length; j++) {
+					int name_index = inners[j].getInnerNameIndex();
+					Constant name_c = cpg.getConstant(name_index);
+					String name = ((ConstantUtf8)name_c).getBytes();
+					int outer_class_index = inners[j].getOuterClassIndex();	
+					Constant outer_c = cpg.getConstant(outer_class_index);
+					String outerName = ((ConstantClass)outer_c).getBytes(cpg.getConstantPool());
+					outerName = outerName.replace('/', '.');
+					innerClassNames.add(outerName + "$" +name);
+				}
+			}
+		}
+		for (int i=0; i<super_classes.length; i++) {
+			String superClassName = super_classes[i].getClassName();
+			if (innerClassNames.contains(superClassName)) {
+				superRoleNames.addFirst(superClassName);
+			}
+		}
+		return superRoleNames;	
+	}*/
+    
+    /**
+     * Remove all contents of a method as preparation for adding a new implementation
+	 *
+     * @param m 			The original method
+     * @param class_name 	The class containing the method
+     * @param cpg 			The class' constant pool
+     * @return An empty method generator with the same declaration as m 
+     *     	   and no implementation.
+     */
+    protected static MethodGen wipeMethod(Method m, String class_name, ConstantPoolGen cpg) {
+        MethodGen mg;
+        mg = new MethodGen(m, class_name, cpg);
+        mg.getInstructionList().dispose(); //throw away the old implementation
+        mg.removeLineNumbers();
+        mg.removeLocalVariables();
+        mg.removeLocalVariableTypes();
+        mg.removeExceptionHandlers();
+        mg.removeAttributes();
+        return mg;
+    }
+    
+	/**
+	 * Add instructions of InstructionList il after the super constructor call of this constuctor.
+	 *
+	 * @param m 		the constructor method
+	 * @param addedCode	the InstructionList containing the instructions to be added
+	 * @param cg		the ClassGen
+	 * @param cpg		the constant pool
+	 */
+	static void addToConstructor(Method m, InstructionList addedCode, ClassGen cg, ConstantPoolGen cpg) {
+		String class_name = cg.getClassName();
+		MethodGen mg = new MethodGen(m, class_name, cpg);
+		InstructionList il = mg.getInstructionList().copy();
+		InstructionHandle[] ihs = il.getInstructionHandles();
+
+		MethodGen newConstructor = new MethodGen(mg.getAccessFlags(),
+												 mg.getReturnType(),
+												 mg.getArgumentTypes(),
+												 mg.getArgumentNames(),
+												 mg.getName(),
+												 class_name,
+												 il,
+												 cpg );
+
+//[SH:] 				
+		updateCopiedMethod(mg, il, ihs, newConstructor);
+//[:HS]
+
+		int stackDepth = 0;
+		int actInstrIndex = 0;
+		
+		boolean pauseStackCounting = false;
+		InstructionHandle gotoTarget = null;
+		
+		// skip everything up to and including super() or this() call
+		while (!((ihs[actInstrIndex].getInstruction() instanceof INVOKESPECIAL)
+					&& (stackDepth - (ihs[actInstrIndex].getInstruction().consumeStack(cpg))) == 0)) {
+
+			Instruction actInstruction = ihs[actInstrIndex].getInstruction();
+
+			if (gotoTarget != null && actInstruction.equals(gotoTarget.getInstruction())) {
+				pauseStackCounting = false;
+				gotoTarget = null;
+			}
+			
+			if (actInstruction instanceof GotoInstruction) {
+				GotoInstruction gotoInsruction = (GotoInstruction)actInstruction;
+				gotoTarget = gotoInsruction.getTarget();
+				pauseStackCounting = true;
+			}
+			if (!pauseStackCounting) {
+				stackDepth -= actInstruction.consumeStack(cpg);
+				stackDepth += actInstruction.produceStack(cpg);
+			}
+
+			actInstrIndex++;
+		}
+		
+		InstructionHandle ih = ihs[actInstrIndex];
+		INVOKESPECIAL invoke = (INVOKESPECIAL)ih.getInstruction();
+		String specialName = invoke.getName(cpg);
+		if (!specialName.equals(Constants.CONSTRUCTOR_NAME)) {
+			System.err.println("###ALERT: " + specialName);
+			return;
+		}
+
+		if (logging) printLogMessage("Adding code to " + class_name + "." + m.getName());
+		
+		// calculate the length of the added code BEFORE it is inserted into the instruction list:
+//[SH:] extracted for adding further manipulation of addedCode:
+		int addedCodeLength = padCodeToAdd(addedCode);
+//[:HS]
+		
+		InstructionHandle startOfAddedCode = il.append(ih, addedCode);
+
+		il.setPositions();
+
+		newConstructor.setInstructionList(il);
+		newConstructor.setMaxStack();
+		newConstructor.setMaxLocals();
+//[SH:] if an unused local variable was copied in updateCopiedMethod() 
+//      we have to adjust max_locals,
+//      because unused locals are not found by setMaxLocals().
+		newConstructor.setMaxLocals(Math.max(newConstructor.getMaxLocals(), mg.getMaxLocals()));
+//[:HS]
+		
+		copyAndAdjustLineNumbers(mg, newConstructor, addedCodeLength, startOfAddedCode);
+		
+		cg.replaceMethod(m, newConstructor.getMethod());
+	}
+
+	/** 
+	 * Pads a given instruction list to multiples of 4 returning the padded length.
+	 * Note that clients of this function must not call removeNOPs()!
+	 * 
+	 * Rationale: 
+	 * switch instructions pad the lists of jmp targets to start at an offset % 4 == 0. 
+	 * In order to ensure that this padding will not change when inserting new bytes
+	 * the added bytes have to be a multiple of 4.
+	 */
+	static int padCodeToAdd(InstructionList addedCode) {
+//[orig:]
+		int addedCodeLength = 0;
+		Instruction[] instr = addedCode.getInstructions();
+		for (int i = 0; i < instr.length; i++) {
+			addedCodeLength += instr[i].getLength();
+		}
+//[:giro]
+		while (addedCodeLength % 4 > 0) {
+			addedCode.append(new NOP());
+			addedCodeLength++;
+		}
+		return addedCodeLength;
+	}
+
+//[SH:] helper methods for more complete method copying:
+	
+	/** After a method (incl. its instruction list) has been copied,
+	 *  we need to manually copy some more properties:
+	 *  + local variables
+	 *  + declared exceptions
+	 *  + exception handlers.
+	 */
+	static void updateCopiedMethod(MethodGen methodOrig, 
+								   InstructionList ilCopy, 
+								   InstructionHandle[] ihsCopy, 
+								   MethodGen methodCopy) 
+	{
+		// local variables:
+		LocalVariableGen[] oldLocals = methodOrig.getLocalVariables();
+		int argLen = methodOrig.getArgumentTypes().length;
+		if (!methodOrig.isStatic())
+			argLen++; // this
+		if (oldLocals.length > argLen) {
+			InstructionList oldIL = methodOrig.getInstructionList();
+			int maxLocals = methodOrig.getMaxLocals();
+			for (int i = argLen; i<oldLocals.length; i++) {
+				LocalVariableGen var = oldLocals[i];
+				LocalVariableGen newVar =
+					methodCopy.addLocalVariable(var.getName(), var.getType(), 
+												mapIH(var.getStart(), oldIL, ihsCopy), 
+												mapIH(var.getEnd(),   oldIL, ihsCopy));
+				newVar.setIndex(var.getIndex());
+				// reset, addLocalVariable might have changed this.
+				methodCopy.setMaxLocals(maxLocals); 
+			}
+		}
+		// declared exceptions:
+		BaseCallRedirection.copyExceptionHandlers(methodOrig, methodCopy, ilCopy);
+		// exception handlers:
+		for(String excName : methodOrig.getExceptions())
+			methodCopy.addException(excName);
+	}
+	
+	static InstructionHandle mapIH(InstructionHandle alienIH, InstructionList oldIL, InstructionHandle[] newIHs) 
+	{
+		int position = alienIH.getPosition();
+		int[] newPositions = oldIL.getInstructionPositions();
+		for (int i=0; i<newPositions.length; i++) {
+			if (newPositions[i] == position)
+				return newIHs[i];
+		}
+		return null;
+	}
+//[:HS]
+	
+	/**
+	 * Copy all line numbers from <tt>src</tt> to <tt>dest</tt>.
+	 * For bytecode instructions after the added code area an offset has to be added to the 
+	 * bytecode positions of the line numbers. 
+	 * If in debug modus (flag 'debugging') add 'STEP_OVER_LINENUMBER' for the added code. 
+	 * 
+	 * @param src				The source method.
+	 * @param dest				The destination method.
+	 * @param offset			The offest to be added (the length of the added code list).
+	 * @param startOfAddedCode	InstructionHandle to the beginning of the added code. 
+	 */
+	static void copyAndAdjustLineNumbers(MethodGen src, MethodGen dest, int offset, InstructionHandle startOfAddedCode) {
+		InstructionList il_dest = dest.getInstructionList();
+		LineNumberGen[] src_lng = src.getLineNumbers();
+		boolean addedCodeHasLineNumber = false;
+
+		for (int i = 0; i < src_lng.length; i++) {
+			int position = src_lng[i].getInstruction().getPosition();
+			if (position == startOfAddedCode.getPosition()) { // add the line number for added code here:
+				dest.addLineNumber(startOfAddedCode, STEP_OVER_LINENUMBER);
+				addedCodeHasLineNumber = true;
+				continue;
+			}
+			if (position >= startOfAddedCode.getPosition())  // move line numbers, because of inserted code (add offset)
+				position += offset;
+			InstructionHandle ih = il_dest.findHandle(position);
+			if (ih == null) {
+				System.err.println("Handle not found!");
+			} else {
+				dest.addLineNumber(ih, src_lng[i].getSourceLine());
+			}
+		}
+		if (!addedCodeHasLineNumber) { // no custom code after added code: add line number now:
+			dest.addLineNumber(startOfAddedCode, STEP_OVER_LINENUMBER);
+		}
+	}
+	
+	/**
+	* Test if a method has the given 'callin_flag'. 
+	*
+	* @param m				the method to search
+	* @param cg				the ClassGen
+	* @param callin_flags 	the flags to check for; 0 means any callin flags
+	* @return true, if the method has the callin flag
+	*/
+	public  static boolean methodHasCallinFlags(Method m, ClassGen cg, int callin_flags) {
+		boolean found = false;
+		Attribute[] attributes = m.getAttributes();
+		for (int i = 0; i < attributes.length; i++) {
+			Attribute actAttr = attributes[i];
+			if (!(actAttr instanceof Unknown)) 
+				continue; 
+			Unknown attr = (Unknown)actAttr;
+			if (!(attr.getName().equals("CallinFlags")))
+				continue;
+			if (callin_flags == 0)
+				return true;
+			byte [] bytes = attr.getBytes();
+			int flags = combineTwoBytes(bytes, 0);
+			if ((flags & callin_flags) != 0) {
+                if(logging) printLogMessage("Found CallinFlag " + callin_flags + " for "
+                        + cg.getClassName() + "." + m.getName() + ".");
+				found = true;
+			}
+		}
+		return found;
+	}
+
+	/**
+	 * A team needs to get added the team specific part, if it is a non-abstract team and
+	 * not the class org.objectteams.Team itself.
+	 * 
+	 * @param cg 	the class to be tested
+	 * @return true if this is a team which has to be extended
+	 */
+	protected static boolean classNeedsTeamExtensions(ClassGen cg) {
+		return !(( (cg.getAccessFlags() & OTConstants.TEAM) == 0)
+				|| (cg.getClassName().equals(OTConstants.teamClassName))
+				|| ((cg.getAccessFlags() & Constants.ACC_ABSTRACT) != 0));
+	}
+
+	/**
+	 * Generates the name of the implementing role for the given role interface name.
+	 * (Inserts the '__OT__' marker.)
+	 *
+	 * @param roleName the role interface name
+	 * @return the implementing role class name
+	 */
+	protected static String genImplementingRoleName(String roleName) {
+		int lastDollar = roleName.lastIndexOf('$');
+		StringBuilder sb = new StringBuilder(roleName);
+		sb.insert(lastDollar + 1, OTDT_PREFIX);
+		return sb.toString();
+	}
+
+	/**
+	 * Generates the name of the role interface the given role class is implementing. 
+	 *(Removes the '__OT__' marker.) 
+	 *
+	 * @param roleName the role class name
+	 * @return the implemented role interface
+	 */
+	public static String genRoleInterfaceName(String roleName) {
+	      int lastDollar = roleName.lastIndexOf('$');
+	      StringBuilder sb = new StringBuilder(roleName);
+	      sb.delete(lastDollar + 1, lastDollar + 1 + OTDT_PREFIX.length());
+	      return sb.toString();
+	}
+		
+	protected static boolean isReflectiveOTMethod(String methodName, String methodSignature) {
+		if ((methodName.equals("hasRole") && methodSignature.equals("(Ljava/lang/Object;)Z"))
+				|| (methodName.equals("hasRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)Z"))
+				|| (methodName.equals("getRole") && methodSignature.equals("(Ljava/lang/Object;)Ljava/lang/Object;"))
+				|| (methodName.equals("getRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;"))
+				|| (methodName.equals("getAllRoles") && methodSignature.equals("()[Ljava/lang/Object;"))
+				|| (methodName.equals("getAllRoles") && methodSignature.equals("(Ljava/lang/Class;)[Ljava/lang/Object;"))
+				|| (methodName.equals("unregisterRole") && methodSignature.equals("(Ljava/lang/Object;)V"))
+				|| (methodName.equals("unregisterRole") && methodSignature.equals("(Ljava/lang/Object;Ljava/lang/Class;)V"))
+		   )
+			return true;
+		return false;
+	}
+	
+	/**
+	 * Calculates the name of the outer class.
+	 *
+	 * @param className	the full name of the inner class
+	 * @return the name of the outer class
+	 */
+	public static String getOuterClassName(String className) {
+		int    dollarIndex       = className.lastIndexOf('$');
+		if (dollarIndex == -1) // no outer class exists!
+			return null;
+		String outerClassName    = className.substring(0, dollarIndex);
+		return outerClassName;
+	}
+	
+	/**
+	 * @param m
+	 * @param cg 
+	 * @return
+	 */
+	static boolean candidateForImplicitActivation(Method m, ClassGen cg, ConstantPoolGen cpg) {
+		if (!IS_COMPILER_14X_PLUS)
+			implicitActivationMode = ImplicitActivationMode.ALWAYS;
+		switch (implicitActivationMode) {
+		case NEVER:	
+			return false;
+		case ANNOTATED :
+			if (   AnnotationHelper.containsImplicitActivationAttribute(m.getAttributes(), cpg)
+				|| AnnotationHelper.containsImplicitActivationAttribute(cg.getAttributes(), cpg))
+				return canImplicitlyActivate(m);
+			return false;
+		case ALWAYS:
+			if (!canImplicitlyActivate(m))
+				return false;
+			
+			Attribute[] attributes = m.getAttributes();
+			for(Attribute a : attributes) {
+				if (a instanceof Unknown) {
+					Unknown attr = (Unknown) a;
+					String attrName = attr.getName();
+					if ("RoleClassMethodModifiers".equals(attrName)) {
+						byte[] bytes = attr.getBytes();
+						int flags = combineTwoBytes(bytes, 0);
+						if (flags == 0 ||/* flags == 2 || */flags == 4) {
+							// 0: default, 2: private, 4: protected
+							return false;
+						}
+					}
+				}
+			}
+			if (!m.isPublic()) 
+				return false; // m originally wasn't public
+			
+			String className = cg.getClassName();
+			return !(CallinBindingManager.isRole(className) && cg.isProtected());
+		default:
+			return false; // cannot happen switch is exhaustive.
+		}
+    }
+
+	private static boolean canImplicitlyActivate(Method m) {
+		String methodName = m.getName();
+		String methodSignature = m.getSignature();
+		boolean isCandidate =
+			(!m.isAbstract()) &&
+			(!m.isStatic()) &&
+			(!methodName.startsWith(OT_PREFIX)) &&
+			(!methodName.equals(Constants.CONSTRUCTOR_NAME)) &&
+			(!(methodName.equals("activate") && methodSignature.equals("()V"))) &&
+			(!(methodName.equals("deactivate") && methodSignature.equals("()V"))) &&
+			(!isReflectiveOTMethod(m.getName(), methodSignature));
+		return isCandidate;
+	}
+
+	/**
+	 * @param s
+	 * @param c
+	 * @return
+	 */
+	static int countOccurrences(String s, char c) {
+		int count = 0;
+        int idx = s.indexOf(c);
+        while (idx != -1) {
+            idx = s.indexOf(c, idx + 1);
+            count++;
+        }
+        return count;
+    }
+
+	/**
+	 * This method performs the changes for implicit Team activation.
+	 * @param m					a method for which implicit activation will be enabled.
+	 * @param className			the class name for 'm'.
+	 * @param cpg				the constant pool of the class 'className'.
+	 * @param activateOuter 	true, if the surrounding team has to be activated
+	 * @return 
+	 */
+	Method genImplicitActivation(Method m, String className, ConstantPoolGen cpg, boolean activateOuter) {
+		String targetName = className;
+		int nestingDepth = 0;
+		ObjectType outerClass = null;
+		if (activateOuter) {
+			outerClass = new ObjectType(getOuterClassName(className));
+			nestingDepth = countOccurrences(className, '$') - 1;
+			targetName = outerClass.getClassName();
+		}
+		MethodGen mg = new MethodGen(m, className, cpg);
+		InstructionList il = mg.getInstructionList();
+		InstructionList prefix = new InstructionList();
+		InstructionHandle try_start = il.getStart();
+		// ---> new implicit activation
+		prefix.append(InstructionFactory.createThis());
+		if (activateOuter) {// this is for a role method: activate the outer team
+			// FIXME(SH): check replacing this$n with _OT$getTeam()
+			prefix.append(factory.createGetField(className, "this$" + nestingDepth, outerClass));
+		}
+         prefix.append(factory.createInvoke(targetName, "_OT$implicitlyActivate",
+				Type.VOID, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		// <-- new implicit activation
+        if (debugging)
+         	mg.addLineNumber(prefix.getStart() , STEP_OVER_LINENUMBER); 
+		il.insert(prefix);
+
+		InstructionList postfix = new InstructionList();
+		// ---> new implicit deactivation
+		postfix.append(InstructionFactory.createThis());
+		if (activateOuter) {// this is for a role method: deactivate the outer team
+			postfix.append(factory.createGetField(className, "this$"+nestingDepth, outerClass));
+		}
+		postfix.append(factory.createInvoke(targetName,
+				"_OT$implicitlyDeactivate", Type.VOID, Type.NO_ARGS,
+				Constants.INVOKEVIRTUAL));
+		// <-- new implicit deactivation
+
+		FindPattern findPattern = new FindPattern(il);
+		String pat = "`ReturnInstruction'";
+		InstructionHandle ih = findPattern.search(pat);
+		while (ih != null) {
+			// insert deactivate-call before return instruction in ih:
+			InstructionList postfixCopy = postfix.copy();
+			if (debugging)
+				mg.addLineNumber(postfixCopy.getStart(), STEP_OVER_LINENUMBER);
+			InstructionHandle inserted = il.insert(ih, postfixCopy); // instruction lists can not be reused
+			il.redirectBranches(ih, inserted); // SH: retarget all jumps that targeted at the return instruction
+			if (ih.getNext() == null)
+				break; // end of instruction list reached
+			ih = findPattern.search(pat, ih.getNext());
+		}
+
+		/**
+		 * **** add an exception handler which calls deactivate before throwing
+		 * the exception (finaly-simulation): ***
+		 */
+		ObjectType throwable = new ObjectType("java.lang.Throwable");
+		LocalVariableGen exception = mg.addLocalVariable(
+				"_OT$thrown_exception", throwable, null, null);
+		InstructionHandle try_end = il.getEnd();
+		InstructionList postfix_ex = postfix.copy();
+		if (debugging)
+			mg.addLineNumber(postfix_ex.getStart(), STEP_OVER_LINENUMBER);
+		postfix_ex.insert(InstructionFactory.createStore(throwable, exception
+				.getIndex()));
+		postfix_ex.append(InstructionFactory.createLoad(throwable, exception
+				.getIndex()));
+		postfix_ex.append(new ATHROW());
+		InstructionHandle deactivation_handler = il.append(il.getEnd(),
+				postfix_ex);
+		mg.addExceptionHandler(try_start, try_end, deactivation_handler,
+				throwable);
+		/** ******************************************************************** */
+
+		mg.setInstructionList(il);
+		mg.setMaxLocals();
+		mg.setMaxStack();
+		
+		if (!debugging)
+			return mg.getMethod();
+		
+		/* sorting the line numbers per start pc: */
+		Method newMethod = mg.getMethod();
+		MethodGen newMethodGen = new MethodGen(newMethod, className, cpg);
+		
+		LineNumberGen[] lineNumbers = newMethodGen.getLineNumbers();
+		
+		newMethodGen.removeLineNumbers();
+		
+		Arrays.sort(lineNumbers, new Comparator<LineNumberGen>() {
+		public int compare(LineNumberGen ln1, LineNumberGen ln2) {
+			int firstLineNumberPC = ln1.getLineNumber().getStartPC();
+			int secondLineNumberPC = ln2.getLineNumber().getStartPC();
+			
+			if (firstLineNumberPC < secondLineNumberPC)
+				return -1;
+			if (firstLineNumberPC > secondLineNumberPC)
+				return 1;
+			return 0;
+		}
+	}); 
+
+		for (int i = 0; i<lineNumbers.length; i++) {
+			newMethodGen.addLineNumber(lineNumbers[i].getInstruction(), lineNumbers[i].getSourceLine());
+		}		
+
+		return newMethodGen.getMethod();
+	}
+	
+	/**
+	 *  How many bytes does an instruction produce on the stack?
+	 */
+	static protected int stackDiff(Instruction instr, ConstantPoolGen cpg) {
+		return instr.produceStack(cpg) - instr.consumeStack(cpg);
+	}
+
+	/**
+	 *  Split an instruction list that loads method arguments into
+	 *  one list for each argument.
+	 *  @param cpg
+	 *  @param src the original loading sequence (will be destroyed by this method).
+	 *  @param argumentTypes source-level argument types of the callin method.
+	 *  @return array of load sequences, same order as before but split into individual arguments.
+	 */
+	protected InstructionList[] splitLoading(ConstantPoolGen cpg, InstructionList src, Type[] argumentTypes) {
+		int len = argumentTypes.length;
+		InstructionList[] res = new InstructionList[len];
+		// starting right _before_ an invoke instruction we loop backwards 
+		// to find those values on the stack that would be passed to the method.
+		for (int idx = len-1; idx>=0; idx--) {
+			// new sub-list:
+			res[idx] = new InstructionList();
+			// how many bytes to expect on the stack:
+			int expectedArgSize = argumentTypes[idx].getSize();
+			// loop until we have a sequence that produces the expected number of bytes:
+			while (expectedArgSize > 0) {
+				InstructionHandle loadH = src.getEnd();
+				Instruction       load  = loadH.getInstruction();
+				expectedArgSize -= stackDiff(load, cpg);
+				try {
+					// transfer instruction from src to res[roleIdx]:
+					res[idx].insert(load);
+					src.delete(loadH);
+				} catch (TargetLostException e) {
+					throw new OTREInternalError(e);
+				}
+			}
+		}
+		return res;
+	}
+
+	/**
+	 *  Translate the parameter loading of a base call to the correct sequence
+	 *  expected by the base chaining wrapper.
+	 *  Treats tunneled arguments but not current enhancement args.
+	 *  Tasks performed:
+	 *  <ul>
+	 *     <li>pick load sequences from <tt>splitLoad</tt>
+	 *     <li>extract unused args from Object[]
+	 *     <li>insert casting or lowering if needed.
+	 *  </ul>
+	 *  More documentation is found in document parameter-passing.odg.
+	 *  
+	 * @param splitLoad one list of load instructions for each argument, ordered as found in the bytecode.
+	 * @param enhancedRoleArgumentTypes enhanced role arguments
+	 * @param enhancedBaseArgumentTypes arguments of the base chaining wrapper.
+	 * @param parameterPosition encoded parameter mappings.
+	 * @param teamName The name of the team containing the role class.
+	 * @param enclosingRoleName enclosing role class or null for static replace/base-call.
+	 * @param baseIsCallin is the base method a callin method?
+	 * @param baseIsStaticRoleMethod is the base method a static role method?
+	 * @param one byte for each parameter, signalling if lowering is required
+	 * @return a complete loading sequence for all source-level and tunneled arguments
+	 */
+	protected InstructionList translateLoads(InstructionList[] splitLoad, 
+											 Type[]  		   enhancedRoleArgumentTypes, 
+											 Type[]  		   enhancedBaseArgumentTypes, 
+											 int[]   		   parameterPositions,
+											 String  		   teamName, 
+											 String  		   enclosingRoleName,
+											 BaseMethodInfo    baseMethod,
+											 int    		   start,
+											 ConstantPoolGen   cpg) 
+	{
+		boolean isStatic               = baseMethod.isStatic;
+		boolean baseIsStaticRoleMethod = baseMethod.isStaticRoleMethod();
+		boolean baseIsCallin 	       = baseMethod.isCallin;
+		int     translationFlags	   = baseMethod.translationFlags;
+		
+		InstructionList il = new InstructionList();		
+
+		// index into "Object[] _OT$unusedArgs" (points to first arg that has not yet been consumed):
+		int nextUnusedArg = 0; 
+		// index into enhancedBaseArgumentTypes:
+		int baseIdx;
+		// source-level version of baseIdx, i.e., ignoring any enhanced arguments:
+		int baseSrcIdx;
+		// index into roleArgumentTypes:
+		int roleIdx;
+		// source-level version of roleIdx, i.e., ignoring any enhanced arguments:
+		int roleSrcIdx;		
+
+		// ==  Note: letters (u-x) below refer to document parameter-passing.odg. ==
+		// Skip enhancements that are already loaded (given in start).
+		for (baseIdx = start; baseIdx < enhancedBaseArgumentTypes.length; baseIdx++) {
+			baseSrcIdx = baseIdx-start;      // (u) skip first enhancement (already loaded)
+			if (baseIsStaticRoleMethod) 
+				baseSrcIdx -= 2;			 // (v) not mapped but extracted from unusedArgs
+			if (baseIsCallin)
+				baseSrcIdx -= EXTRA_ARGS;    // (w) not mapped but extracted from unusedArgs
+
+			// value-dispatching: where to find this parameters? 
+			if (baseSrcIdx < 0) {
+				// (v) or (w)
+				roleSrcIdx = -1;
+			} else {
+				// (x) merge arguments from unused and real:
+				int numAvailableRoleArgs = enhancedRoleArgumentTypes.length-EXTRA_ARGS;
+				if (!isStatic && IS_COMPILER_GREATER_123)
+					numAvailableRoleArgs--; // don't count isSuperAccess
+				roleSrcIdx = getMappedRolePosition(baseSrcIdx, parameterPositions, numAvailableRoleArgs);
+			}
+			
+			// got all information, fetch it now:
+			Type baseArgumentType = enhancedBaseArgumentTypes[baseIdx];
+			if (roleSrcIdx == -1) {
+				// not mapped, retrieve from _OT$unusedArgs:
+				retrieveFromUnusedArg(il, nextUnusedArg++, baseArgumentType, cpg);
+			} else {
+				// mapped, fetch from splitLoad:
+				roleIdx = roleSrcIdx+EXTRA_ARGS; // role always has an additional set of enhancements 
+				if (IS_COMPILER_GREATER_123 && !isStatic) roleIdx++; // (+ isSuperAccess)
+				Type roleArgumentType = enhancedRoleArgumentTypes[roleIdx];
+				il.append(splitLoad[roleSrcIdx]);
+				if (!roleArgumentType.equals(baseArgumentType)) {
+					convertParamToBase(il, teamName, enclosingRoleName, roleArgumentType, baseArgumentType, 
+										(translationFlags & (2<<baseSrcIdx)) != 0);
+				}
+			}
+		}
+		if (il.isEmpty())
+			il.append(new NOP()); // ensure caller receives at least one instruction handle (for line number)
+		return il;
+	}
+	
+	/* Is the base arg identified by 'baseIdx' mapped to a role parameter?
+	 * If so: which role position is it mapped to?
+	 * If not: return -1
+	 */
+	private int getMappedRolePosition(int     baseSrcIdx, 
+									  int[]   parameterPositions, 
+									  int     numAvailableRoleArgs) 
+	{
+		if (parameterPositions == null) {
+			if (baseSrcIdx < numAvailableRoleArgs) // as many as available ...
+				return baseSrcIdx;        		   // in original order.
+		} else {
+			// search parameter mapping:
+			for (int i = 0; i < parameterPositions.length; i++) {
+				if (parameterPositions[i] == baseSrcIdx+1) // positions are one-based (base side)
+					return i;
+			}
+		}
+		return -1;
+	}
+
+	/* Retrieve an unused (tunneled) argument from position 'unusedIdx' of the _OT$unusedArgs array. */
+	private void retrieveFromUnusedArg(InstructionList il, 
+							   int             unusedIdx, 
+							   Type            baseArgumentType,
+							   ConstantPoolGen cpg) 
+	{
+		il.append(InstructionFactory.createLoad(objectArray, /*this*/1 + (UNUSED_ARG-1))); // 'UNUSED_ARG' is one-based
+		il.append(createIntegerPush(cpg, unusedIdx));
+		il.append(InstructionFactory.createArrayLoad(objectArray));
+		if (baseArgumentType instanceof BasicType)
+			il.append(createUnboxing((BasicType) baseArgumentType));
+		else  // ObjectTypes just have to be re-casted
+			il.append(factory.createCast(object, baseArgumentType));
+	}
+
+	/* May perform any of these conversions: casting, lowering, array-lowering.
+	 * Conversion is generated into 'il'. 
+	 */
+	private void convertParamToBase(InstructionList il, 
+									String          teamName, 
+									String 			enclosingRoleName, 
+									Type 			roleArgumentType, 
+									Type 			baseArgumentType,
+									boolean         loweringFlag) 
+	{
+		if (roleArgumentType instanceof ObjectType
+		    && baseArgumentType instanceof ObjectType) 
+		{
+			if (loweringFlag) {
+				lowerObject(il, teamName, roleArgumentType, baseArgumentType);
+			} else {
+				if(logging) printLogMessage("Try to cast " + roleArgumentType +
+						" to " + baseArgumentType);
+				il.append(factory.createCast(roleArgumentType,
+						baseArgumentType));
+			}
+		} else 
+		if (   roleArgumentType instanceof BasicType
+			&& baseArgumentType instanceof ObjectType) 
+		{
+			il.append(createBoxing((BasicType)roleArgumentType));
+		} else 
+		if (   roleArgumentType instanceof ObjectType
+			&& baseArgumentType instanceof BasicType) 
+		{
+			il.append(createUnboxing((BasicType)baseArgumentType));
+		} else
+		if (   roleArgumentType instanceof ArrayType
+		    && baseArgumentType instanceof ArrayType)
+		{
+			lowerArray(il, teamName, enclosingRoleName, roleArgumentType, baseArgumentType);
+		} else {
+			throw new OTREInternalError("OTRE internal error:"+
+							   "No way to make types conform\n"+
+							   "role type "+roleArgumentType+
+							   " -> "+baseArgumentType);
+		}
+	}
+
+	/* Lower one object from roleArgumentType to baseArgumentType. */
+	private void lowerObject(InstructionList il, 
+							 String 		 teamName, 
+							 Type 			 roleArgumentType, 
+							 Type 			 baseArgumentType) 
+	{
+		String roleIfcName = ((ObjectType)roleArgumentType).getClassName();
+		// use interface implementing role type for base-field access! 
+		String roleClassName = ObjectTeamsTransformation.genImplementingRoleName(roleIfcName);
+		
+		int dollarIdx = roleClassName.lastIndexOf('$');
+		if (dollarIdx == -1) {
+			throw new OTREInternalError("OTRE internal error:" +
+										"No way to make types conform\n" +
+										"role type " + roleArgumentType +
+										" -> " + baseArgumentType);
+		}
+		boolean isNested = dollarIdx != roleClassName.indexOf('$'); // is last == first?
+		String strengthenedRoleName = teamName + roleClassName.substring(dollarIdx);
+		
+		// baseArgumentType may be imprecise due to cast in param mapping, 
+		// try a RBB instead to find the exact base type
+		RoleBaseBinding rbb = CallinBindingManager.getRoleBaseBinding(strengthenedRoleName);
+		if (rbb != null) 
+			baseArgumentType = new ObjectType(rbb.getBaseClassName());
+
+		if (isNested) {
+			// cannot use field access here, because role strengthening would require resolved information
+			// so use the _OT$getBase() method instead:
+			short kind = (roleIfcName.lastIndexOf('$') == roleIfcName.lastIndexOf("$__OT__")) // last segment is roleclass?
+							? Constants.INVOKEVIRTUAL
+							: Constants.INVOKEINTERFACE;
+			il.append(factory.createInvoke(roleIfcName, GET_BASE, baseArgumentType, new Type[0], kind));
+		} else {
+			// access field via the role class:
+			il.append(factory.createCast(roleArgumentType, new ObjectType(strengthenedRoleName)));
+			
+			// optimized version directly accessing the field:
+			il.append(factory.createGetField(strengthenedRoleName,
+											 BASE,
+											 baseArgumentType));
+		}
+	}
+
+	/* Lower from roleArgumentType[] to baseArgumentType[]. */
+	private void lowerArray(InstructionList il, String teamName, String enclosingRoleName, Type roleArgumentType, Type baseArgumentType) {
+		ArrayType array = (ArrayType)roleArgumentType;
+		String roleName =((ObjectType)array.getElementType()).getClassName();
+		int dollarIdx = roleName.lastIndexOf('$');
+		String pureRoleName = roleName.substring(dollarIdx + 1);
+		String transformMethodName = getArrayLoweringMethodName(pureRoleName, array.getDimensions());
+		if (enclosingRoleName != null) {
+			// fetch team from enclosing role:
+			il.append(InstructionFactory.createThis());
+			// FIXME(SH): is this$0 always correct (nesting!)??
+			il.append(factory.createGetField(enclosingRoleName, "this$0", new ObjectType(teamName)));
+		} else {
+			// "this" is the team:
+			il.append(InstructionFactory.createThis());
+		}
+		il.append(new SWAP()); // 'push' team instance below the role array
+		il.append(factory.createInvoke(teamName, 
+									   transformMethodName, 
+									   baseArgumentType, 
+									   new Type[]{roleArgumentType}, 
+									   Constants.INVOKEVIRTUAL));
+	}
+	
+	private String getArrayLoweringMethodName(String roleName, int dimensions) {
+		return "_OT$transformArray" + roleName + "_OT$" + dimensions;
+	}
+
+	public List<String> getInnerClassNames(ClassGen cg, ConstantPoolGen cpg) {
+		Attribute[] attributes = cg.getAttributes();		
+		LinkedList<String> innerClassNames = new LinkedList<String>();
+		for (int i = 0; i < attributes.length; i++) {
+			Attribute actAttr = attributes[i];
+			if (actAttr instanceof InnerClasses) {
+				InnerClass[] inners = ((InnerClasses)actAttr).getInnerClasses();
+				for (int j=0; j<inners.length; j++) {
+					int name_index = inners[j].getInnerNameIndex();
+					Constant name_c = cpg.getConstant(name_index);
+					String name = ((ConstantUtf8)name_c).getBytes();
+					innerClassNames.add(name);
+				}
+			}
+		}
+		return innerClassNames;
+	}
+
+	/**
+	 * Create a monitor enter using a class literal
+	 * @param mg 		 target method to which a local variable is added which holds the monitor object
+	 * @param il		 instruction list to append to
+	 * @param class_name name of the class literal to use as monitor
+	 * @param major		 major class file version, used to determine how to translate class literals
+	 * @param cpg		 constant pool gen
+	 * @return the slot index of the monitor local variable and the handle of the first generated instruction.
+	 */
+	protected Pair<Integer,InstructionHandle> addClassMonitorEnter(MethodGen 		mg, 
+																   InstructionList 	il,
+																   String			class_name, 
+																   int 				major, 
+																   ConstantPoolGen 	cpg)
+	{
+		int monitor;
+		InstructionHandle ih= 
+			appendClassLiteral(il, class_name, major, cpg);
+		il.append(new DUP()); // for store and monitorenter
+		LocalVariableGen lg2= 
+			mg.addLocalVariable("monitor", Type.OBJECT, il.getStart(), null); //$NON-NLS-1$
+		monitor= lg2.getIndex();
+		il.append(InstructionFactory.createStore(Type.OBJECT, monitor)); // for use by monitorexit
+		il.append(new MONITORENTER());
+		return new Pair<Integer, InstructionHandle>(monitor, ih);
+	}
+	
+	/** 
+	 * Append an instruction sequence for loading the class literal for `class_name'.
+	 * @param il	instruction list to append to
+	 * @param class_name class name of the class literal
+	 * @param major java version as stored in the byte code.
+	 * @param cpg   for generating bytes
+	 * @return the handle of the first instruction of the sequence.
+	 */
+	protected InstructionHandle appendClassLiteral(InstructionList il, 
+												   String          class_name, 
+												   int             major,
+												   ConstantPoolGen cpg) 
+	{
+		if (major >= 49) // java 5
+			return il.append(new LDC(cpg.addClass(new ObjectType(class_name))));
+		// pre java 5, do it the hard way:
+		// if (_OT$self_class$ != null)
+	  InstructionHandle start= 
+		il.append(factory.createFieldAccess(class_name, OTConstants.SELF_CLASS, classType, Constants.GETSTATIC));
+	    il.append(new DUP()); // keep a copy as a potential result
+	  BranchInstruction checkLoaded=
+		          InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
+	    il.append(checkLoaded);
+	    il.append(new POP()); // discard null from above
+	    // _OT$self_class$= Class.forName(<class_name>); // never fails, it is THIS class
+		il.append(new LDC(cpg.addString(class_name)));
+	  	il.append(factory.createInvoke("java.lang.Class", 
+	  								   "forName", 
+	  								   classType,
+	  								   new Type[]{new ObjectType("java.lang.String")},
+	  								   Constants.INVOKESTATIC));
+	  	il.append(new DUP()); // keep a copy as the result
+	  	il.append(factory.createFieldAccess(class_name, OTConstants.SELF_CLASS, classType, Constants.PUTSTATIC));
+	
+	  	checkLoaded.setTarget(il.append(new NOP()));
+	  	return start;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
new file mode 100644
index 0000000..3525912
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
@@ -0,0 +1,757 @@
+/**********************************************************************
+ * 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 de.fub.bytecode.classfile.*;
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+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(SharedState state) { this(null, state); }
+	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 = new MethodGen(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;
+    }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
new file mode 100644
index 0000000..104374d
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
@@ -0,0 +1,175 @@
+/**********************************************************************
+ * 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: SubBoundBaseMethodRedefinition.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 de.fub.bytecode.classfile.*;
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.util.*;
+
+/**
+ * Redefines inherited (and not redefined) base methods in subclasses with a
+ * call to the super method if they are bound for the subclass only. This is
+ * done in order to provide a place for the BaseMethodTransformer to weave in
+ * the callin code.
+ * 
+ * @version $Id: SubBoundBaseMethodRedefinition.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author  Christine Hundt
+ * @author  Stephan Herrmann
+ */
+
+public class SubBoundBaseMethodRedefinition 
+	extends ObjectTeamsTransformation {
+
+	public SubBoundBaseMethodRedefinition(SharedState state) { this(null, state); }
+	public SubBoundBaseMethodRedefinition(ClassLoader loader, SharedState state) { super(loader, state); }
+
+	/**
+	 * Main entry for this transformer.
+	 */
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+		String class_name = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+
+		factory = new InstructionFactory(cg);
+
+		checkReadClassAttributes(ce, cg, class_name, cpg);
+
+		// if class is already transformed by this transformer
+		if (state.interfaceTransformedClasses.contains(class_name)) {
+			return;
+		}
+
+		List<MethodBinding> mbsForClass = CallinBindingManager
+				.getMethodBindingsForBaseClass(class_name);
+		if (mbsForClass.isEmpty()) {
+			return; // no bindings for this base class
+		}
+
+		List<MethodBinding> inheritedBoundMethods = getInheritedBoundMethods(mbsForClass, cg);
+		
+		addSubBoundMethodRedefinitions(inheritedBoundMethods, ce, cg);
+		state.interfaceTransformedClasses.add(class_name);
+	}
+
+	/**
+	 * Adds redefinitions with calls to the super method to all methods
+	 * contained in the 'inheritedBoundMethods' list.
+	 * 
+	 * @param inheritedBoundMethods
+	 *            The list of method bindings for inherited methods.
+	 * @param ce
+	 *            ClassEnhancer with the extension set of this class.
+	 * @param cg
+	 *            The ClassGen object for the transformed class.
+	 */
+	private void addSubBoundMethodRedefinitions(List<MethodBinding> inheritedBoundMethods,
+			ClassEnhancer ce, ClassGen cg) {
+		List<String> alreadyAddedRedefinitions = new LinkedList<String>();
+
+		Iterator<MethodBinding> it = inheritedBoundMethods.iterator();
+		while (it.hasNext()) {
+			MethodBinding mb = it.next();
+			String baseMethodKey = mb.getBaseMethodName() + "."
+					+ mb.getBaseMethodSignature();
+
+			if (alreadyAddedRedefinitions.contains(baseMethodKey)) {
+				continue;
+			}
+			Method m = genMethodRedefinition(mb, cg);
+			
+			ce.addMethod(m, cg);
+            if(logging) printLogMessage("Added " + baseMethodKey + " to " + cg.getClassName());
+			alreadyAddedRedefinitions.add(baseMethodKey);
+		}
+	}
+
+	/**
+	 * Generates a (redefining) method, which just calls its super version.
+	 * 
+	 * @param mb
+	 *            A method binding containing the method to be redefined.
+	 * @param cg
+	 *            The ClassGen object for the transformed class.
+	 * @return The generated method.
+	 */
+	private Method genMethodRedefinition(MethodBinding mb, ClassGen cg) {
+		boolean staticMethod = mb.hasStaticBaseMethod();
+		short invocationKind = staticMethod ? Constants.INVOKESTATIC : Constants.INVOKESPECIAL;
+		
+		String methodName = mb.getBaseMethodName();
+		String methodSignature = mb.getBaseMethodSignature();
+		String className = mb.getBaseClassName();
+		Type returnType = Type.getReturnType(methodSignature);
+		Type[] argTypes = Type.getArgumentTypes(methodSignature);
+		InstructionList il = new InstructionList();
+
+		int accFlags = Constants.ACC_PUBLIC;
+		if (staticMethod) {
+			accFlags = accFlags | Constants.ACC_STATIC;
+		}
+		MethodGen redefinition = new MethodGen(accFlags, returnType, argTypes, 
+											   null, methodName, className, il, 
+											   cg.getConstantPool());
+
+		if(!staticMethod){
+			il.append(InstructionFactory.createThis());
+		}
+		// load all arguments:
+		int index = 1;
+		for (int i = 0; i < argTypes.length; i++) {
+			il.append(InstructionFactory.createLoad(argTypes[i], index));
+			index += argTypes[i].getSize();
+		}
+		il.append(factory.createInvoke(cg.getSuperclassName(), methodName,
+				returnType, argTypes, invocationKind));
+		il.append(InstructionFactory.createReturn(returnType));
+
+		redefinition.removeNOPs();
+		il.setPositions();
+		redefinition.setMaxStack();
+		redefinition.setMaxLocals();
+		return redefinition.getMethod();
+	}
+
+	/**
+	 * Selects all method bindings from the 'mbsForClass' list which methods are
+	 * inherited only (not defined in the class itself).
+	 * 
+	 * @param mbsForClass
+	 *            The method bindings of the transformed class.
+	 * @param cg
+	 *            The ClassGen object for the transformed class.
+	 * @return A sublist of 'mbsForClass' containing all bindings for methods
+	 *         which are inherited only.
+	 * 
+	 */
+	private static List<MethodBinding> getInheritedBoundMethods(List<MethodBinding> mbsForClass, ClassGen cg) {
+		List<MethodBinding> inheritedBoundMethod = new LinkedList<MethodBinding>();
+		Iterator<MethodBinding> it = mbsForClass.iterator();
+		while (it.hasNext()) {
+			MethodBinding mb = it.next();
+			if ((cg.containsMethod(mb.getBaseMethodName(), mb
+					.getBaseMethodSignature())) == null)
+				inheritedBoundMethod.add(mb);
+		}
+		return inheritedBoundMethod;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
new file mode 100644
index 0000000..faa7cd1
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
@@ -0,0 +1,1011 @@
+/**********************************************************************
+ * 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: TeamInterfaceImplementation.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 de.fub.bytecode.classfile.*;
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.util.*;
+
+/**
+ * Adds the general Team infrastructure to team classes.
+ * 
+ * Fields: public (static) final_OT$ID <- static if 'ot.no_static' ist set
+ * Methods: public int activate(int level) public int deactivate(int level)
+ * public int _OT$getID() Static initialization (adds clinit method, if not yet
+ * presented) OR to every constructor: <- if 'ot.no_static' is set _OT$ID =
+ * TeamIdDispenser.getTeamId(class_name)
+ * 
+ * Enables implicit team activation for normal (user defined) public team-level
+ * methods. A call to 'activate' is woven at the beginning of the method. A call
+ * to 'deactivate' is woven before every return and at every thrown exception.
+ * 
+ * @version $Id: TeamInterfaceImplementation.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author Christine Hundt
+ * @author Stephan Herrmann
+ */
+public class TeamInterfaceImplementation 
+	extends ObjectTeamsTransformation {
+
+	private boolean isJPLIS;
+
+
+	public TeamInterfaceImplementation(boolean isJPLIS, SharedState state) {
+		this(isJPLIS, null, state);
+	}
+
+	public TeamInterfaceImplementation(boolean isJPLIS, ClassLoader loader, SharedState state) {
+		super(loader, state);
+		this.isJPLIS = isJPLIS;
+	}
+
+	/**
+	 * @param cg
+	 */
+	public void doTransformCode(ClassGen cg) {
+		factory = new InstructionFactory(cg);
+
+		if (!classNeedsTeamExtensions(cg)) {
+			return;
+		}
+
+        ConstantPoolGen cpg = cg.getConstantPool();
+        String class_name = cg.getClassName();
+		genImplicitActivation(cg, cpg);
+		
+		InstructionList implicitSuperRoleRegistrations = genImplicitSuperRegistration(cg, cpg);
+		if (!implicitSuperRoleRegistrations.isEmpty()) {
+			// add implicitSuperRoleRegistrations to the static initializer:
+			Method clinitMethod = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V");
+			addToMethodStart(implicitSuperRoleRegistrations, clinitMethod, cg, cpg);
+		}
+
+		if (CallinBindingManager.getBasesPerTeam(class_name) == null) {
+			return; // this team does not adapt any base class
+		}
+
+		/**
+		 * ******************* add initialization of the field '_OT$ID' to the static initializer : ******
+		 */
+		int nextTeamId = TeamIdDispenser.getTeamId(class_name);
+		
+		/*
+		 * The clinit method always exists at this moment, because it has
+		 * been added by the interface transformer part of this transformer
+		 * if necessary.
+		 */
+		addStaticInitializations(nextTeamId, cg, cpg);
+	}
+
+	/**
+	 * Add initialization of "_OT$ID" with 'nextTeamID' to the static
+	 * initializer of this team class.
+	 * 
+	 * @param nextTeamId
+	 *            the id which will be associated with the currently transformed
+	 *            team
+	 * @param cg
+	 *            the ClassGen for the given team class
+	 * @param cpg
+	 *            the constant pool ot the team
+	 */
+	private void addStaticInitializations(int nextTeamId, ClassGen cg,
+			ConstantPoolGen cpg) {
+		Method clinitMethod = cg.containsMethod(
+				Constants.STATIC_INITIALIZER_NAME, "()V");
+		MethodGen mg = new MethodGen(clinitMethod, cg.getClassName(), cpg);
+		InstructionList il = mg.getInstructionList();
+
+		InstructionList addedInitialization = new InstructionList();
+		addedInitialization.append(createIntegerPush(cpg, nextTeamId));
+		addedInitialization.append(factory.createFieldAccess(cg.getClassName(),
+				"_OT$ID", Type.INT, Constants.PUTSTATIC));
+		// generated: _OT$ID = <id dispensed by TeamIdDispenser>;
+		
+		// add static initialization for added static field at the beginning of
+		// the <clinit> method:
+		il.insert(addedInitialization);
+		mg.setMaxStack();
+		mg.setMaxLocals();
+
+		Method newClinit = mg.getMethod();
+		cg.replaceMethod(clinitMethod, newClinit);
+
+		il.dispose(); // Reuse instruction handles
+	}
+	
+	/**
+	 * For all roles in the current team which have tsuper versions: 
+	 * Generate instruction list containig calls to registration methods 
+	 * the implicit super roles. 
+	 *
+	 * @param cg	The ClassGen of the current team.
+	 * @param cpg	The constant pool of the current team.
+	 * @return		The instruction list containing the registration calls.
+	 */
+	private InstructionList genImplicitSuperRegistration(ClassGen cg, ConstantPoolGen cpg) {
+		InstructionList il = new InstructionList();
+		List<String> inheritedRoleNames = getInheritedRoleNames(cg, cpg);
+			if (inheritedRoleNames.isEmpty())
+				return il; // nothing to do
+			Iterator<String> iter = inheritedRoleNames.iterator();
+			while (iter.hasNext()) {
+				String roleName = iter.next();
+				String unqualifiedRoleName = roleName.substring(roleName.lastIndexOf('$') + 1);
+				if (CallinBindingManager.isBoundBaseAndRoleClass(roleName)) {
+					String potientialImplicitSuperRoleName = cg.getSuperclassName() + '$' + unqualifiedRoleName;
+					
+ 					if (!CallinBindingManager.isBoundBaseAndRoleClass(potientialImplicitSuperRoleName)) {
+						// Only bound base classes have the infrastructure for notifying 
+						// implicit subclasses about team activation!
+						continue;
+					}
+ 					il.append(new PUSH(cpg, roleName));
+					il.append(factory.createInvoke("java.lang.Class", "forName", 
+												   classType, new Type[] { Type.STRING },
+												   Constants.INVOKESTATIC));
+					il.append(factory.createInvoke(potientialImplicitSuperRoleName, "_OT$registerObserver", 
+												   Type.VOID, new Type [] { classType },
+												   Constants.INVOKESTATIC));
+				}
+			}
+		return il;
+	}
+
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+		String class_name = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+
+		checkReadClassAttributes(ce, cg, class_name, cpg);
+
+		if (state.interfaceTransformedClasses.contains(class_name)) {
+			return; // class has already been transformed by this transformer
+		}
+
+		if (!classNeedsTeamExtensions(cg)) {
+			return;
+		}
+		
+		factory = new InstructionFactory(cg);
+		
+		/**
+		 * ********** empty implementation of the static class initialization method '<clinit>' ***
+		 * NOTE: this is unnecessary in some cases, but checking is too complicated
+		 */
+		addStaticInitializer(cg, cpg, class_name, ce);
+
+		List<String> handledBases = CallinBindingManager.getBasesPerTeam(class_name);
+		// TeamInterfaceImplementer only registers teams at bases, wich are part
+		// of a 'CallinRoleBaseBinding'-attribute of the team.
+		if (handledBases == null) {
+			return; // this team does not adapt any base class
+		}
+		
+		if(logging) printLogMessage("Adding the general Team infrastructure to "
+				+ class_name);
+
+		/**
+		 * ******************* addition of the field '_OT$ID'
+		 * **********************************
+		 */
+
+		int accessFlags = Constants.ACC_PUBLIC | Constants.ACC_FINAL | Constants.ACC_STATIC;
+
+		FieldGen IDField = new FieldGen(accessFlags, Type.INT, "_OT$ID", cpg);
+		ce.addField(IDField.getField(), cg);
+		// generated global variable: public final static int _OT$ID;
+
+		factory = new InstructionFactory(cpg);
+		InstructionList il;
+
+		/**
+		 * ******************* implementation of method '_OT$getID'
+		 * ************************
+		 */
+
+		il = new InstructionList();
+		MethodGen getIDMethod = new MethodGen(Constants.ACC_PUBLIC, Type.INT,
+				Type.NO_ARGS, new String[] {}, "_OT$getID", class_name, il, cpg);
+
+		il.append(factory.createFieldAccess(class_name, "_OT$ID", Type.INT,
+				Constants.GETSTATIC));
+		il.append(InstructionFactory.createReturn(Type.INT));
+
+		getIDMethod.setMaxStack();
+		getIDMethod.setMaxLocals();
+
+		ce.addMethod(getIDMethod.getMethod(), cg);
+
+		/**
+		 * ***************** implementation of team (un)registration methods
+		 * **********************
+		 */
+
+		ce.addMethod(generateTeamRegistrationMethod(cpg, class_name,
+				handledBases), cg);
+
+		ce.addMethod(generateTeamUnregistrationMethod(cpg, class_name,
+				handledBases), cg);
+
+		/**
+		 * ***************** implementation of base call surrogtes for static methods
+		 * **********************
+		 */
+		Method [] base_call_surrogates = generateStaticBaseCallSurrogates(class_name, cpg, cg);
+		for(int i=0; i<base_call_surrogates.length;i++) {
+			// perhaps the compiler already generated an empty surrogate for an unbound super-role?
+			// (see X.1.5-otjld-callin-from-static-base-method-12a)
+			ce.addOrReplaceMethod(base_call_surrogates[i], cg);
+		}
+		
+		/** *************************************************************************** */
+
+		il.dispose();
+		state.interfaceTransformedClasses.add(class_name);
+	}
+	
+	/**
+	 * Add the given instruction list to the start of the givern method.
+	 * @param additionalInstructions
+	 * @param method
+	 * @param cg
+	 * @param cpg
+	 */
+	private void addToMethodStart(InstructionList additionalInstructions, Method method, ClassGen cg, ConstantPoolGen cpg) {
+		MethodGen mg = new MethodGen(method, cg.getClassName(), cpg);
+		InstructionList il = mg.getInstructionList();
+		il.insert(additionalInstructions);
+		mg.setMaxStack();
+		mg.setMaxLocals();
+
+		Method newMethod = mg.getMethod();
+		cg.replaceMethod(method, newMethod);
+		il.dispose(); // Reuse instruction handles	
+	}
+
+	/**
+	 * Generate the static initializer method 'clinit'.
+	 * @param cpg			The constant pool
+	 * @param class_name	The name of the class
+	 * @param cg			The ClassGen for the class
+	 * @return				The static initialier for this class
+	 */
+	void addStaticInitializer(ClassGen cg, ConstantPoolGen cpg, String class_name, ClassEnhancer ce) {
+		/*
+		 * 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 existingClinit = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V");
+		if (existingClinit == null &&  !TeamIdDispenser.clinitAdded(class_name, loader)) {
+			// otherwise the clinit-Method already exists and only has to be extended
+			// by the code transformation of this transformer
+			InstructionList il = new InstructionList();
+			MethodGen clinitMethodGen = 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));
+
+			clinitMethodGen.setMaxStack();
+			clinitMethodGen.setMaxLocals();
+			Method clinitMethod = clinitMethodGen.getMethod();
+			ce.addMethod(clinitMethod, cg);
+		}
+	}
+
+	/**
+	 * Generates the ' _OT$registerAtBases()' method. This method registers the
+	 * team at every adapted base class by calling the respective 'addTeam'
+	 * method.
+	 * 
+	 * @param cpg
+	 *            The ConstantPoolGen of the team class.
+	 * @param class_name
+	 *            The name of the team class.
+	 * @param handledBases
+	 *            The list of teams adapted by (roles of) this team.
+	 * @return The generated 'activate' method.
+	 */
+	Method generateTeamRegistrationMethod(ConstantPoolGen cpg,
+			String class_name, List<String> handledBases)
+	{
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
+				Type.NO_ARGS, null, "_OT$registerAtBases", class_name, il, cpg);
+
+		Iterator<String> it = handledBases.iterator();
+		while (it.hasNext()) {
+			String actBase = it.next();
+			//if (CallinBindingManager.hasBoundBaseParent(actBase))
+			//	continue; // team was already added to a super base class
+			//	problem: bound base parent could be bound to another team class!!!
+			
+			//String boundBase = CallinBindingManager.getBoundBaseParent(actBase);
+			//if (boundBase != null && handledBases.contains(boundBase))
+			//	continue;
+			if (CallinBindingManager.teamAdaptsSuperBase(class_name, actBase)) 
+				continue;
+			
+			InstructionHandle startTry = il.append(new ALOAD(0));
+			
+			il.append(factory.createFieldAccess(class_name, "_OT$ID", Type.INT,
+					Constants.GETSTATIC));
+			il.append(factory.createInvoke(actBase, "_OT$addTeam", Type.VOID,
+					new Type[] { teamType, Type.INT }, Constants.INVOKESTATIC));
+			// generated: <actBase>._OT$addTeam(this, _OT$ID);
+			
+			addNoSuchMethodErrorHandling(startTry, il.getEnd(), getErrorMessage(class_name, actBase, "Activation"), il, mg, cpg);
+		}
+		il.append(new RETURN());
+
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg.getMethod();
+	}
+
+	/**
+	 * Direct inverse of generateTeamRegistrationMethod(..). Generates the '
+	 * _OT$unregisterFromBases' method. This method deregisters the team at
+	 * every adapted base class by calling the respective 'removeTeam' method.
+	 * 
+	 * @param cpg
+	 *            The ConstantPoolGen of the team class.
+	 * @param class_name
+	 *            The name of the team class.
+	 * @param handledBases
+	 *            The list of teams adapted by (roles of) this team.
+	 * @return The generated 'deactivate' method.
+	 */
+	Method generateTeamUnregistrationMethod(ConstantPoolGen cpg,
+			String class_name, List<String> handledBases) {
+
+		InstructionList il = new InstructionList();
+		MethodGen mg = new MethodGen(Constants.ACC_PUBLIC, Type.VOID,
+				Type.NO_ARGS, null, "_OT$unregisterFromBases", class_name, il,
+				cpg);
+
+		Iterator<String> it = handledBases.iterator();
+		while (it.hasNext()) {
+			String actBase = it.next();
+			//if (CallinBindingManager.hasBoundBaseParent(actBase))
+			//	continue; // team was only added to a super base class
+			// problem: bound base parent could be bound to another team class!!!
+			
+			// String boundBase = CallinBindingManager.getBoundBaseParent(actBase);
+			//if (boundBase != null && handledBases.contains(boundBase))
+			//	continue;
+			if (CallinBindingManager.teamAdaptsSuperBase(class_name, actBase)) 
+				continue;
+			
+			InstructionHandle startTry = il.append(new ALOAD(0));
+
+			il.append(factory.createInvoke(actBase, "_OT$removeTeam",
+					Type.VOID, new Type[] { teamType }, Constants.INVOKESTATIC));
+			// generated: <actBase>._OT$removeTeam(this, _OT$ID);
+			
+			addNoSuchMethodErrorHandling(startTry, il.getEnd(), getErrorMessage(class_name, actBase, "Deactivation"), il, mg, cpg);
+		}
+		il.append(new RETURN());
+
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		return mg.getMethod();
+	}
+
+	private String getErrorMessage(String teamName, String baseName, String action) {
+		String errorMessage = action+" of team '" + teamName + "' failed! Callins of this team have NOT been WOVEN into base class '" + baseName + "'!\n" 
+		  + "This is probably caused by a loading order problem.";
+		if (!isJPLIS)
+			errorMessage += "\nIf "+baseName+" is loaded from the bootstrap classpath launching the program in JPLIS mode may perhaps avoid this problem.";
+		return errorMessage;
+	}
+	
+	/**
+	 * Adds an exception handler to the given method which catches 'java.lang.NoSuchMethodError's 
+	 * caused by missing team registration methods in base classes. Causes the throwing of an 
+	 * 'org.objectteams.UnsupportedFeatureException'.
+	 * 
+	 * @param startTry		handle to the start of the try block
+	 * @param endTry		handle to the end of the try block
+	 * @param errorMessage	the error message to be printed when throwing the exception
+	 * @param il			instruction list of the method
+	 * @param mg			MethodGen of the method
+	 * @param cpg			corresponding ConstantPoolGen
+	 */
+	private void addNoSuchMethodErrorHandling(InstructionHandle startTry, InstructionHandle endTry, 
+											  String errorMessage, InstructionList il, MethodGen mg, 
+											  ConstantPoolGen cpg) {
+		GOTO skipHdlr = null;
+		skipHdlr = new GOTO(null);
+		il.append(skipHdlr);
+		// generated: goto normal exit
+		
+		// throw away the expection reference:
+		InstructionHandle hdlr = il.append(new POP()); 
+		
+		il.append(factory.createNew(OTConstants.unsupportedFeature));
+		il.append(new DUP());
+		il.append(new PUSH(cpg, errorMessage));
+		il.append(factory.createInvoke(OTConstants.unsupportedFeature.getClassName(),
+													 Constants.CONSTRUCTOR_NAME,
+													 Type.VOID,
+													 new Type[] { Type.STRING }, 
+													 Constants.INVOKESPECIAL));
+		il.append(new ATHROW());
+		
+		InstructionHandle nop = il.append(new NOP());
+		skipHdlr.setTarget(nop);
+		mg.addExceptionHandler(startTry, endTry, hdlr, new ObjectType("java.lang.NoSuchMethodError"));
+	}
+
+	/**
+	 * Generate implicit Team activation for each "normal" public method.
+	 * 
+	 * @param cg
+	 *            class for which methods are to be augmented.
+	 * @param cpg
+	 *            the constant pool of the class 'cg'.
+	 */
+	void genImplicitActivation(ClassGen cg, ConstantPoolGen cpg) {
+		Method[] methods = cg.getMethods();
+		for (int i = 0; i < methods.length; i++) {
+			Method m = methods[i];
+			if (candidateForImplicitActivation(m, cg, cpg)) {
+                if(logging) printLogMessage("Adding implicit activation to " + m.getName());
+				cg.replaceMethod(m, genImplicitActivation(m, cg.getClassName(), cpg, false)); 
+			}
+		}
+	}
+	
+	/**
+	 * Scans the team attribute StaticReplaceBinding and generates an array of base call surrogates
+	 * 
+	 * @param class_name
+	 * @param cpg
+	 * @param cg
+	 * @return
+	 */
+	private Method [] generateStaticBaseCallSurrogates(String class_name, ConstantPoolGen cpg, ClassGen cg){
+		
+		Set<String> roleMethodKeys = new HashSet<String>();
+		
+		//------------------------------------------------------------------------------------------
+		// scan static replace bindings attributes
+		//------------------------------------------------------------------------------------------
+		Attribute [] attributes = cg.getAttributes();
+		for(int k=0; k<attributes.length; k++){
+			
+			Unknown attr = isOTAttribute(attributes[k]);
+			if(attr == null) continue;
+		
+			if(attr.getName().equals("StaticReplaceBindings")) {
+				
+				byte[] indizes = attr.getBytes();
+				int count = combineTwoBytes(indizes, 0);
+	            int numberOfEntries=0;
+				String [] names;
+				numberOfEntries = 5;
+				int i = 2;
+				
+				for (int n=0; n<count;n++) {
+					names = new String[numberOfEntries];
+					i = scanStrings(names, indizes, i, cpg);
+					int index = 0;
+					String role_name             = names[index++];
+					String role_method_name      = names[index++];
+					String role_method_signature = names[index++];
+					String lift_method_name      = names[index++];
+					String lift_method_signature = names[index++];
+										
+					String roleMethodKey = genRoleMethodKey(class_name, role_name, role_method_name, role_method_signature, lift_method_name, lift_method_signature);
+					roleMethodKeys.add(roleMethodKey);
+						
+					int base_len = combineTwoBytes(indizes, i);
+					BaseMethodInfo baseMethod;
+					i += 2;
+					names = new String[3];
+					for (int n_base = 0; n_base < base_len; n_base++) {
+						int [] positions = null;
+						
+						i = scanStrings(names, indizes, i, cpg);
+						
+						int flags = indizes[i++];
+						boolean baseIsCallin     = (flags & 1) != 0;
+						boolean baseIsRoleMethod = (flags & 2) != 0;
+						boolean baseIsStatic     = (flags & 4) != 0;
+						//parameter positions scanning
+						int pos_len = combineTwoBytes(indizes, i);
+                        i+=2;
+                        
+                        if(pos_len > 0) {
+                        	positions = new int[pos_len];
+                        }
+                        
+                        for(int pos = 0; pos < pos_len; pos++){
+                        	positions[pos] = combineTwoBytes(indizes,i);
+                        	i += 2;
+                        }
+                        int translationFlags = (combineTwoBytes(indizes, i)<<16) + combineTwoBytes(indizes, i+2);
+                        i+=4;
+						baseMethod = new BaseMethodInfo(names[0], names[1], names[2], 
+														baseIsCallin, baseIsRoleMethod, baseIsStatic, 
+														positions, translationFlags);
+						
+						CallinBindingManager.assignBaseCallTag(names[0],names[1],names[2]);
+						CallinBindingManager.addStaticReplaceBindingForRoleMethod(roleMethodKey, baseMethod);
+					}					
+				}
+				break; 
+			}
+		}
+		
+		//------------------------------------------------------------------------------------------
+		// generate base call surrogates
+		//------------------------------------------------------------------------------------------
+		Iterator<String> roleMethodIter = roleMethodKeys.iterator();
+		int count = roleMethodKeys.size();
+		Method [] generatedSurrogates = new Method[count];
+		
+		int j = 0;
+		
+		while(roleMethodIter.hasNext()) {
+			String roleMethodKey = roleMethodIter.next();
+			LinkedList<BaseMethodInfo> baseMethods = CallinBindingManager.getStaticReplaceBindingsForRoleMethod(roleMethodKey);
+			
+			//split the key into team class name, role class name, role method name and role method signature
+			int firstPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR);
+			int secondPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, firstPointIndex+1);
+			int thirdPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, secondPointIndex+1);
+			int fourthPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, thirdPointIndex+1);
+			int fifthPointIndex = roleMethodKey.indexOf(STATIC_REPLACE_BINDING_SEPARATOR, fourthPointIndex+1);
+			
+			String role_name = roleMethodKey.substring(firstPointIndex+2, secondPointIndex);
+			String role_method_name = roleMethodKey.substring(secondPointIndex+2, thirdPointIndex);
+			String role_method_signature = roleMethodKey.substring(thirdPointIndex+2, fourthPointIndex);
+			String lift_method_name = null;
+			String lift_method_signature = null;
+			// SH: without this check we get 
+			//        StringIndexOutOfBoundsException: String index out of range: -1
+			//     I hope this patch is correct..
+			if (  fourthPointIndex + 2 <= fifthPointIndex
+				&& fifthPointIndex + 2 < roleMethodKey.length()) 
+			{
+				lift_method_name = roleMethodKey.substring(fourthPointIndex+2, fifthPointIndex);
+				lift_method_signature = roleMethodKey.substring(fifthPointIndex+2, roleMethodKey.length());
+			}
+			
+			generatedSurrogates[j] = genBaseCallSurrogate(cg, role_name, role_method_name, 
+														  role_method_signature, 
+														  lift_method_name, lift_method_signature, baseMethods);
+			j++;
+		}
+		
+		return generatedSurrogates;
+	}
+	
+	/**
+	 * Generates a base call surrogate for a given static role method
+	 * @param cg
+	 * @param role_name		
+	 * @param role_method_name
+	 * @param role_method_signature
+	 * @param lift_method_name
+	 * @param lift_method_signature
+	 * @param base_methods
+	 * @return
+	 */
+	private Method genBaseCallSurrogate(ClassGen cg,
+										String role_name, 
+										String role_method_name,
+										String role_method_signature,
+										String lift_method_name,
+										String lift_method_signature, 
+										LinkedList<BaseMethodInfo> base_methods)
+	{	
+		ConstantPoolGen cpg = cg.getConstantPool();
+		String class_name = cg.getClassName();
+
+		if (base_methods.isEmpty()) { 
+			return null;
+		}
+		Type[] enhancedArgumentTypes = enhanceArgumentTypes(Type.getArgumentTypes(role_method_signature));
+		Type enhancedReturnType  = generalizeReturnType(Type.getReturnType(role_method_signature));
+		String[] enhancedArgumentNames = null;
+		InstructionList il = new InstructionList();
+		int accessFlags = Constants.ACC_PROTECTED;
+		
+		MethodGen baseCallSurrogate = new MethodGen(accessFlags,
+																enhancedReturnType,
+																enhancedArgumentTypes,
+																enhancedArgumentNames,
+																getBaseCallSurrogateName(role_name, role_method_name), 
+																class_name,
+																il, cpg);
+			
+		
+		LocalVariableGen otResult = null;
+		
+		/*
+		 int slot = enhancedArgumentTypes.length+1;
+		 otResult = baseCallSurrogate.addLocalVariable("_OT$result",
+		 enhancedReturnType,
+		 slot, null, null);
+		 */
+		otResult = baseCallSurrogate.addLocalVariable("_OT$result",
+				enhancedReturnType, null, null);
+		
+		il.insert(InstructionFactory.createStore(enhancedReturnType,
+				otResult.getIndex()));
+		il.insert(new ACONST_NULL());
+		il.setPositions(); // about to retrieve instruction handles.
+		
+		if(logging) printLogMessage("base-call switch has to be inserted!");
+		InstructionList loading = new InstructionList();
+		loading.append(InstructionFactory.createThis());
+		int index = 1;
+		for (int i = 0; i < enhancedArgumentTypes.length; i++) {
+			loading.append(InstructionFactory.createLoad(enhancedArgumentTypes[i],index));
+			index += enhancedArgumentTypes[i].getSize();
+		}
+		
+		Type[] argumentTypes = Type.getArgumentTypes(role_method_signature);
+		Type returnType = Type.getReturnType(role_method_signature);
+		
+		if (debugging) {
+			baseCallSurrogate.addLineNumber(il.getStart(), STEP_OVER_LINENUMBER);
+		}
+		
+		il.append(genBaseCallSwitch(cpg, base_methods, baseCallSurrogate,
+				argumentTypes,
+				returnType,
+				lift_method_name,
+				lift_method_signature,
+				otResult, loading, cg.getClassName()));
+		
+		il.append(InstructionFactory.createLoad(enhancedReturnType, otResult.getIndex()));
+		il.append(InstructionFactory.createReturn(enhancedReturnType));							
+		
+		il.setPositions();
+		baseCallSurrogate.removeNOPs();
+		baseCallSurrogate.setMaxStack();
+		baseCallSurrogate.setMaxLocals();
+		return baseCallSurrogate.getMethod();
+	}
+	
+	private static String getBaseCallSurrogateName(String class_name, String method_name){
+		// base call surrogate for static callin methods:
+		// name contains role class name and role method name, 
+		// because its generated into the team.
+		return OT_PREFIX + class_name + "$" + method_name + "$base";		
+	}
+	
+	/** 
+     * Generate a dispatching switch statement which calls the proper base method.
+	 * @param cpg
+	 * @param base_methods list of BaseMethodInfo that applies to this callin method
+	 * @param enhancedMethod the enhanced callin method
+	 * @param argumentTypes arg types of the callin method
+	 * @param returnType the return type of the original callin method
+	 * @param liftMethodSignature
+	 * @param otResult the local variable storing the base call result
+	 * @param loading an instruction list holding the original instructions for
+	 *        loading parameters
+	 * @param teamName
+	 * @param lift_method_name
+	 * @return InstructionList the complete replacement implementing the base call.
+     */
+	InstructionList genBaseCallSwitch (ConstantPoolGen cpg,
+									   LinkedList<BaseMethodInfo> base_methods, MethodGen enhancedMethod,
+									   Type[] argumentTypes,
+                                       Type returnType, String liftMethodName, String liftMethodSignature,
+                                       LocalVariableGen otResult, InstructionList loading, String teamName)
+    {
+    	
+		short invocationKind = Constants.INVOKESTATIC;
+		
+        String  className                = enhancedMethod.getClassName();
+        Type    enhancedMethodReturnType = enhancedMethod.getReturnType();
+		boolean callinHasReturnValue = returnType != Type.VOID;
+
+		InstructionList il = new InstructionList();
+
+		// Setup a variable which holds the result of this base call.
+		// This variabel is local to this segment of code and used only
+		// to transport this result out off the switch statement.
+		int     localResult = -1;
+		LocalVariableGen lg = null;
+		if (callinHasReturnValue) {
+			lg = enhancedMethod.addLocalVariable("_OT$tmpResult", returnType,
+												 null, null);
+			localResult = lg.getIndex();
+			il.append(InstructionFactory.createNull (returnType));
+			il.append(InstructionFactory.createStore(returnType, localResult));
+		}
+		
+				// ---- Prepare the switch: ----
+        InstructionHandle switchStart = il.append
+			(InstructionFactory.createLoad(Type.INT, BASE_METH_ARG));
+		// generated: _OT$baseMethTag
+        
+        //base_methods may contain duplicates!
+        //baseMethodTags is used to determine the number of cases without duplicates
+        HashSet<Integer> baseMethodTags = new HashSet<Integer>();
+        Iterator<BaseMethodInfo> iter = base_methods.iterator();
+        while(iter.hasNext()) {
+        	BaseMethodInfo baseMethod = iter.next();
+        	//baseMethodTags.add(CallinBindingManager.getBaseCallTag( baseMethod.getBaseClassName(),
+        	//														baseMethod.getBaseMethodName(),
+        	//														baseMethod.getBaseMethodSignature()));
+        	int baseMethodTag = CallinBindingManager.getBaseCallTag(baseMethod.getBaseClassName(),
+        															baseMethod.getBaseMethodName(),
+																	baseMethod.getBaseMethodSignature());
+        	baseMethodTags.add(Integer.valueOf(baseMethodTag));
+        }       
+        
+        // one break for each case clause
+        int numberOfCases = baseMethodTags.size();
+        
+        GOTO[] breaks = new GOTO[numberOfCases];
+        for (int i=0; i<numberOfCases; i++)
+            breaks[i] = new GOTO(null);
+        
+        int[]               matches = new int[numberOfCases];
+        InstructionHandle[] targets = new InstructionHandle[numberOfCases];
+		int caseCounter = 0;
+
+		//now baseMethodTags is used to store the handled tags
+		baseMethodTags.clear();
+		
+		//JU:
+		Type[] enhancedMethodArguments = enhancedMethod.getArgumentTypes();
+		Type[] enhancedArgumentsForBaseCall = new Type[enhancedMethodArguments.length - 1];
+		System.arraycopy(enhancedMethodArguments, 0,
+                enhancedArgumentsForBaseCall, 0,
+                enhancedArgumentsForBaseCall.length);
+		
+		Iterator<BaseMethodInfo> it = base_methods.iterator();
+		while (it.hasNext()) {
+			
+			BaseMethodInfo baseMethod = it.next();
+			String baseClassName = baseMethod.getBaseClassName();
+			String baseMethodName = baseMethod.getBaseMethodName();
+			String baseMethodSignature = baseMethod.getBaseMethodSignature();
+			int base_method_tag = CallinBindingManager.getBaseCallTag(baseClassName, baseMethodName, baseMethodSignature);
+			
+			//if the current baseMethod is a dulpicate:
+			// workaround for jdk 1.4:
+			Integer bmt = Integer.valueOf(base_method_tag);
+			//if(baseMethodTags.contains(base_method_tag)){
+			if (baseMethodTags.contains(bmt)) {
+				continue;
+			}
+			
+			//baseMethodTags.add(base_method_tag);
+			baseMethodTags.add(bmt);
+		
+			int [] parameterPositions = baseMethod.getParameterPositions();
+			int len = Type.getArgumentTypes(baseMethodSignature).length;
+
+			// if the base method is a callin method as well, further enhance the signature:
+			if (baseMethod.isCallin) 
+				len += EXTRA_ARGS;			
+
+
+			matches[caseCounter] = CallinBindingManager.getBaseCallTag(baseClassName, baseMethodName, baseMethodSignature);
+            InstructionHandle nextBranch = il.append(new NOP());
+
+			Type[] baseMethodArgumentTypes   = Type.getArgumentTypes(baseMethodSignature);
+			Type   baseMethodReturnType      = Type.getReturnType   (baseMethodSignature);
+			String baseChainMethodName       = genChainMethName(baseMethodName);
+			Type   baseChainReturnType       = object; // ALWAYS
+			Type[] enhancedBaseArgumentTypes = enhanceArgumentTypes(baseMethodArgumentTypes);
+			
+			boolean resultLiftingNecessary   = false;
+
+            // TODO (SH): if both types are ObjectType we should probably use subclassOf() ??
+            // (don't lift if simple polymorphism suffices!)
+            //TODO: if the base method return type is a subtype of the role method return type no lifting has to take place!! is this allowed??
+			//if (!returnTypeCompatible(baseMethodReturnType, returnType) && callinHasReturnValue)
+			if (/*!baseMethodReturnType.equals(object) &&*/ 
+				   !baseMethodReturnType.equals(returnType) 
+				&& !(baseMethodReturnType instanceof BasicType) // requires boxing not lifting
+				&& !(returnType instanceof BasicType)			// requires unboxing not lifting
+				&& callinHasReturnValue)
+			{
+				resultLiftingNecessary = true;
+			}
+
+			// --- load arguments of the new method: ---
+			//     (letters refer to document parameter-passing.odg)
+		
+			// (u) generate extra arguments (indices are equal at role and base):
+			for (int idx = 0; idx < EXTRA_ARGS; idx++) 
+				il.append(InstructionFactory.createLoad(enhancedMethodArguments[idx], 
+														idx+1)); // first arg is "this" (enclosing team)			
+			
+			// (v)(w)(x) split loading sequence and transfer source-level arguments
+			// (includes reverse-application of parameter mappings):
+			InstructionHandle baseCallLine = il.append(translateLoads(splitLoading(cpg,
+																				   loading.copy(),
+																				   argumentTypes), 
+																	  enhancedMethodArguments, 
+																	  enhancedBaseArgumentTypes, 
+																	  parameterPositions, 
+																	  teamName, 
+																	  null,
+																	  baseMethod,
+																	  EXTRA_ARGS/*start*/,
+																	  cpg));
+			// --- done loading ---			
+
+			// invoke the chaining method of the base class (base-call!):
+			il.append(factory.createInvoke(baseClassName, 
+										   baseChainMethodName,
+										   baseChainReturnType,
+										   enhancedBaseArgumentTypes,
+										   invocationKind));
+
+			// FIXME(SH): if this assert holds, remove computing of resultLiftingNecessary above.
+			assert resultLiftingNecessary == ((baseMethod.translationFlags & 1) != 0);
+			
+			if (resultLiftingNecessary) { // call the lift-method: 
+				Type[] liftMethodArgs = Type.getArgumentTypes(liftMethodSignature);
+				Type liftMethodReturnType = Type.getReturnType(liftMethodSignature);
+
+				// cast result of base call:
+				il.append(factory.createCast(baseChainReturnType, baseMethodReturnType));
+
+				// load the team instance at which to call the lift method:
+				il.append(InstructionFactory.createThis());
+				il.append(factory.createCast(object, new ObjectType(teamName)));
+				
+				// put them in correct order:
+                il.append(new SWAP()); // -> .., this$0, (BaseType)result
+				
+				il.append(factory.createInvoke(teamName,
+											   liftMethodName,
+											   liftMethodReturnType,
+											   liftMethodArgs,
+											   Constants.INVOKEVIRTUAL));
+			}
+
+			// adjust the return value to the type expected by the WRAPPER:
+			il.append(new DUP()); // keep for adjustment below
+			if (!resultLiftingNecessary)
+				adjustValue(il, null, baseChainReturnType, enhancedMethodReturnType);
+			il.append(InstructionFactory.createStore(enhancedMethodReturnType,
+					otResult.getIndex())); // store "globally"
+			// this store is needed to tunnel unused results through the callin.
+			
+			InstructionHandle afterBaseCallLine = il.append(new NOP());
+			
+			// adjust the return value to the type expected by the ORIGINAL CALLIN:
+			adjustValue(il, null,  baseChainReturnType, returnType);
+			if (callinHasReturnValue) {
+				il.append(InstructionFactory.createStore(returnType, localResult)); // store "locally"
+			}	
+ 			    // this store is useful for callins which make use of the result.
+
+            targets[caseCounter] = nextBranch;
+            il.append(breaks[caseCounter]);
+            // generated: break;
+
+            caseCounter++;
+            
+            if (debugging) {
+            	enhancedMethod.addLineNumber(baseCallLine, STEP_INTO_LINENUMBER);
+            	enhancedMethod.addLineNumber(afterBaseCallLine, STEP_OVER_LINENUMBER);
+            }
+		}
+        
+        //JU: added the follwing part (begin) -----------------------------------------------------	
+        InstructionHandle defaultBranch = il.append(new NOP());
+        
+        if (logging)
+			printLogMessage("Exeption has to be thrown! Base-Call is impossible.");
+		
+		il.append(factory.createNew(OTConstants.unsupportedFeature));
+		il.append(new DUP());
+		// ## FIXME: fix otld$
+		il.append(new PUSH(cpg, "Binding-Error: base-call from " + className + "." + enhancedMethod.getName()
+								+ "impossible! This problem is documented in OTLD $XY."));
+		il.append(factory.createInvoke(OTConstants.unsupportedFeature.getClassName(),
+													 Constants.CONSTRUCTOR_NAME,
+													 Type.VOID,
+													 new Type[] { Type.STRING }, 
+													 Constants.INVOKESPECIAL));
+		il.append(new ATHROW());
+		//JU: (end) --------------------------------------------------------------------------------
+		
+		InstructionHandle afterSwitch = il.append(new NOP()); // all breaks point here.
+
+		il.append(switchStart, createLookupSwitch(matches, targets, breaks,
+												  defaultBranch, afterSwitch));
+
+		// retrieve locally stored result:
+		if (callinHasReturnValue) {
+			il.append(InstructionFactory.createLoad(returnType, localResult));
+			lg.setStart(il.getStart()); // restrict local variable to this segment.
+			lg.setEnd(il.getEnd());
+		}
+        return il;
+	}
+	
+	/**
+	 * Generates a key for the given role method parameters
+	 * 
+	 * @param teamClassName
+	 * @param roleClassName
+	 * @param roleMethodName
+	 * @param roleMethodSignature
+	 * @param liftMethodSignature
+	 * @return
+	 */
+	private static String genRoleMethodKey(String teamClassName,
+			String roleClassName, String roleMethodName,
+			String roleMethodSignature, String liftMethodName,
+			String liftMethodSignature)
+	{
+		StringBuilder roleMethodKey = new StringBuilder(64);
+		roleMethodKey.append(teamClassName);
+		roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR);
+		roleMethodKey.append(roleClassName);
+		roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR);
+		roleMethodKey.append(roleMethodName);
+		roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR);
+		roleMethodKey.append(roleMethodSignature);
+		roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR);
+		roleMethodKey.append(liftMethodName);
+		roleMethodKey.append(STATIC_REPLACE_BINDING_SEPARATOR);
+		roleMethodKey.append(liftMethodSignature);
+		return roleMethodKey.toString();
+	}
+	
+	/**
+	  * Read the InheritedRoles attribute and return the list of inherited roles.
+	  * @param cg	The ClassGen of the inspected class.
+	  * @param cpg	The constant pool of the instpected class.
+	  * @return		A list of inherited role names.
+	  */
+	 private List<String> getInheritedRoleNames(ClassGen cg, ConstantPoolGen cpg) {
+		 Attribute[] attributes = cg.getAttributes();		
+		 LinkedList<String> inheritedRoleNames = new LinkedList<String>();
+		 for (int i = 0; i < attributes.length; i++) {
+			 Attribute actAttr = attributes[i];
+			 if (actAttr instanceof Unknown) {
+				 Unknown attr = (Unknown)actAttr;
+				 byte[] indizes = attr.getBytes();
+				 int count = combineTwoBytes(indizes, 0);
+				 if (attr.getName().equals("InheritedRoles")) {
+					 int j = 2;
+					 while (j<=2*count) {
+						 String[] names = new String[1];
+						 j = scanStrings(names, indizes, j, cpg);
+						 String inherited_role = names[0];
+						 inheritedRoleNames.add(inherited_role);
+					 }
+				 }
+			 }
+		 }
+		 return inheritedRoleNames;
+	 }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java
new file mode 100644
index 0000000..7ac2e1e
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/ThreadActivation.java
@@ -0,0 +1,190 @@
+/**********************************************************************
+ * 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: ThreadActivation.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 java.util.HashSet;
+
+import de.fub.bytecode.classfile.*;
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.*;
+
+
+/**
+ * This transformer inserts a notification call to the TeamThreadManager at the 
+ * beginning of every run()-Method in Subtypes of java.lang.Thread or java.lang.Runnable. 
+ * Thre TeamThreadManager then ensures the thread activation of the current thread 
+ * for every global active team instance.
+ * 
+ * @author  Christine Hundt
+ * @author  Stephan Herrmann
+ */
+public class ThreadActivation 
+{
+	// name of a generated field that stores the thread which created a given runnable:
+	private static final String CREATION_THREAD = "_OT$creationThread";
+	HashSet<String> transformableClasses = new HashSet<String>();
+	
+	private boolean shouldTransform(ClassGen cg) {
+		Method runMethode = cg.containsMethod("run", "()V");
+		if (runMethode == null || runMethode.isAbstract()) {
+			// this class contains no concrete run() method
+			return false;
+		}
+		String class_name = cg.getClassName();
+		// check if this class is a subtype of Thread or Runnable:
+		try {
+			return Repository.implementationOf(class_name, "java.lang.Runnable") || Repository.instanceOf(class_name, "java.lang.Thread");
+		} catch (NullPointerException npe) {
+			if (ObjectTeamsTransformation.WORKAROUND_REPOSITORY) {
+				return false;
+			}
+			else
+				throw npe; // rethrow
+		}
+	}
+	public void doTransformInterface(ClassEnhancer enhancer, ClassGen cg) {
+		if (!shouldTransform(cg))
+			return;
+		
+		// if class is already transformed by this transformer
+		if (this.transformableClasses.contains(cg.getClassName()))
+			return;
+		
+		this.transformableClasses.add(cg.getClassName());
+		FieldGen field = new FieldGen(Constants.ACC_PRIVATE, OTConstants.threadType, CREATION_THREAD, cg.getConstantPool());
+		enhancer.addField(field.getField(), cg);
+	}
+	/**
+     *  
+     */	
+	public void doTransformCode(ClassGen cg) {
+		if (!this.transformableClasses.contains(cg.getClassName()))
+			return;
+		
+		this.transformableClasses.remove(cg.getClassName());
+
+		InstructionFactory factory = new InstructionFactory(cg);
+
+		for (Method method : cg.getMethods()) {
+			MethodGen mg = isRootCtor(method, cg);
+			if (mg != null)
+				enhanceConstructor(cg, factory, method, mg);
+		}
+		
+		enhanceRunMethod(cg, factory);
+    }
+	private void enhanceRunMethod(ClassGen cg, InstructionFactory factory) {
+		String class_name = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+
+		Method runMethode = cg.containsMethod("run", "()V"); // existence checked in transformInterface
+
+		MethodGen mg = new MethodGen(runMethode, class_name, cpg);
+		InstructionList il = mg.getInstructionList();
+		InstructionHandle try_start = il.getStart();
+		
+		/** *** Insert a call to TeamThreadManager.newThreadStarted() at the beginning of the run() method: ****** */	
+		InstructionList threadActivation = new InstructionList();
+		threadActivation.append(new ICONST(0)); // isMain = false
+		threadActivation.append(InstructionConstants.ALOAD_0); // parent=this._OT$creationThread;
+		threadActivation.append(factory.createFieldAccess(class_name, CREATION_THREAD, OTConstants.threadType, Constants.GETFIELD));
+		threadActivation.append(factory.createInvoke("org.objectteams.TeamThreadManager", 
+				                                             "newThreadStarted",
+															 Type.BOOLEAN,
+															 new Type[]{Type.BOOLEAN, OTConstants.threadType},
+															 Constants.INVOKESTATIC));
+		LocalVariableGen flag = mg.addLocalVariable("_OT$isThreadStart", Type.BOOLEAN, il.getStart(), il.getEnd());
+		threadActivation.append(new ISTORE(flag.getIndex()));
+		il.insert(threadActivation);
+		
+		/** *** Insert a call to TeamThreadManager.threadEnded() before every return of the run() method: ******** */	
+		InstructionList threadDeactivation = new InstructionList();
+		threadDeactivation.append(new ILOAD(flag.getIndex()));
+		BranchInstruction ifIsThreadStarted = new IFEQ(null);
+		threadDeactivation.append(ifIsThreadStarted);
+		threadDeactivation.append(factory.createInvoke("org.objectteams.TeamThreadManager", 
+                "threadEnded",
+				 Type.VOID,
+				 Type.NO_ARGS,
+				 Constants.INVOKESTATIC));
+		ifIsThreadStarted.setTarget(threadDeactivation.append(new NOP()));
+
+		FindPattern findPattern = new FindPattern(il);
+		String pat = "`ReturnInstruction'";
+		InstructionHandle ih = findPattern.search(pat);
+		while (ih != null) {
+			// insert deactivate-call before return instruction in ih:
+			InstructionList deactivationCopy = threadDeactivation.copy();
+			InstructionHandle inserted = il.insert(ih, deactivationCopy); // instruction lists can not be reused
+			il.redirectBranches(ih, inserted);// SH: retarget all jumps that targeted at the return instruction
+			if (ih.getNext() == null)
+				break; // end of instruction list reached
+			ih = findPattern.search(pat, ih.getNext());
+		}
+
+		/** **** Add an exception handler which calls TeamThreadManager.threadEnded() *****
+		 * ***** before throwing the exception (finaly-simulation): 											        */
+		ObjectType throwable = new ObjectType("java.lang.Throwable");
+		LocalVariableGen exception = mg.addLocalVariable(
+				"_OT$thrown_exception", throwable, null, null);
+		InstructionHandle try_end = il.getEnd();
+		InstructionList deactivation_ex = threadDeactivation.copy();
+		deactivation_ex.insert(InstructionFactory.createStore(throwable, exception.getIndex()));
+		deactivation_ex.append(InstructionFactory.createLoad(throwable, exception.getIndex()));
+		deactivation_ex.append(new ATHROW());
+		InstructionHandle deactivation_handler = il.append(il.getEnd(), deactivation_ex);
+		mg.addExceptionHandler(try_start, try_end, deactivation_handler, throwable);
+		/** ******************************************************************** */		
+		
+		mg.setMaxStack();
+        mg.setMaxLocals();
+        Method generatedMethod = mg.getMethod();
+        cg.replaceMethod(runMethode, generatedMethod);
+        threadActivation.dispose();
+        il.dispose();
+	}
+	// is method a constructor that does not invoke another this()-ctor?
+	private MethodGen isRootCtor(Method method, ClassGen cg) {
+		if (!method.getName().equals("<init>"))
+			return null;
+		String className = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+		MethodGen mg = new MethodGen(method, className, cpg);
+		InstructionList il = mg.getInstructionList();
+		InstructionHandle ih = il.getStart();
+		while (ih != null && ih.getInstruction().getOpcode() != Constants.INVOKESPECIAL) {
+			ih = ih.getNext();
+		}
+		if (ih == null)
+			return null;
+		if (((InvokeInstruction)ih.getInstruction()).getClassName(cpg).equals(className))
+			return null; // this-call
+		return mg;
+	}
+	// add statements to store the thread that created this runnable
+	private void enhanceConstructor(ClassGen cg, InstructionFactory factory, Method initMethod, MethodGen mg) {
+		String class_name = cg.getClassName();
+		InstructionList il = mg.getInstructionList();
+		il.insert(il.getEnd(), InstructionConstants.ALOAD_0);
+		il.insert(il.getEnd(), factory.createInvoke("java.lang.Thread", "currentThread", OTConstants.threadType, new Type[0], Constants.INVOKESTATIC));
+		il.insert(il.getEnd(), factory.createFieldAccess(class_name, CREATION_THREAD, OTConstants.threadType, Constants.PUTFIELD));
+		mg.setMaxStack();
+	    mg.setMaxLocals();
+	    cg.replaceMethod(initMethod, mg.getMethod());
+	    il.dispose();
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
new file mode 100644
index 0000000..e390663
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
@@ -0,0 +1,143 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2005-2008 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: JPLISEnhancer.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.jplis;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.objectteams.otre.ClassEnhancer;
+import org.eclipse.objectteams.otre.OTREInternalError;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+
+import de.fub.bytecode.Constants;
+import de.fub.bytecode.classfile.ClassParser;
+import de.fub.bytecode.classfile.Field;
+import de.fub.bytecode.classfile.Method;
+import de.fub.bytecode.classfile.Utility;
+import de.fub.bytecode.generic.ClassGen;
+import de.fub.bytecode.generic.ConstantPoolGen;
+import de.fub.bytecode.generic.MethodGen;
+
+
+/**
+* This class implements the ClassEnhancer interface with the JPLIS (Java5) specific behavior.
+*  
+* @author Christine Hundt
+* @author Juergen Widiker
+* @author Stephan Herrmann
+*/
+
+public class JPLISEnhancer implements ClassEnhancer {
+
+	private ClassLoader loader;
+	
+	public JPLISEnhancer(ClassGen cg, ClassLoader loader) {
+		this.loader = loader;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.ClassEnhancer#addImplements(java.lang.String, de.fub.bytecode.generic.ClassGen)
+	 */
+	public void addImplements(String interfaceName, ClassGen cg) {
+		cg.addInterface(interfaceName);		
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addMethod(de.fub.bytecode.classfile.Method, de.fub.bytecode.generic.ClassGen)
+	 */
+	public void addMethod(Method m, ClassGen cg) {
+		if (cg.containsMethod(m.getName(), m.getSignature()) != null)
+			new OTREInternalError("Warning: repetive adding of method "
+					           + m.getName() + m.getSignature() 
+							   + " to class " + cg.getClassName())
+						.printStackTrace();
+		cg.addMethod(m);
+	}
+
+	public void addOrReplaceMethod(Method method, ClassGen cg) {
+		Method existingMethod = cg.containsMethod(method.getName(), method.getSignature());
+		if (existingMethod == null)
+			addMethod(method, cg);
+		else
+			cg.replaceMethod(existingMethod, method);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addField(de.fub.bytecode.classfile.Field, de.fub.bytecode.generic.ClassGen)
+	 */
+	public void addField(Field f, ClassGen cg) {
+		if (cg.containsField(f.getName()) != null)
+			new OTREInternalError("Warning: repetitive adding of field "
+					           + f.getName() + f.getSignature() 
+							   + " to class " + cg.getClassName())
+						.printStackTrace();
+		cg.addField(f);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#loadClass(java.lang.String)
+	 */
+	public void loadClass(String className, ObjectTeamsTransformation client) {
+		// SH: no forced class loading within OT/Equinox
+		if(System.getProperty("ot.equinox") != null)
+			return;
+		try {
+			String binaryName = className.replace('.', '/');
+			InputStream is = loader.getResourceAsStream(binaryName+".class");
+			if (is != null) {
+				ClassGen cg = new ClassGen(new ClassParser(is, className).parse());
+				client.checkReadClassAttributes(this, cg, className, cg.getConstantPool());
+			}
+		} catch (IOException ex) {
+			ex.printStackTrace();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#decapsulateMethod(de.fub.bytecode.classfile.Method, java.lang.String, de.fub.bytecode.generic.ConstantPoolGen)
+	 */
+	public void decapsulateMethod(Method m, ClassGen cg, String packageName, ConstantPoolGen cpg) {
+		String className = cg.getClassName();
+		int flags = m.getAccessFlags();
+		MethodGen mg = new MethodGen(m, className, cpg);
+
+		if ((flags & Constants.ACC_PUBLIC) == 0) {
+			int newFlags = flags;
+			newFlags &= ~(Constants.ACC_PROTECTED|Constants.ACC_PRIVATE); // clear old visibility
+			newFlags |= Constants.ACC_PUBLIC;                             // set new visibility
+			mg.setAccessFlags(newFlags);
+            if(System.getProperty("ot.log") != null)
+                ObjectTeamsTransformation.printLogMessage("Adjusting from "
+										+ Utility.accessToString(flags)
+										+ " to public:\n\t"
+										+ className
+                        				+ "." + m);
+			if (!packageName.equals("NO_PACKAGE")) 
+				checkSeal(packageName, className);
+		}
+		cg.replaceMethod(m, mg.getMethod());
+	}
+	
+	private static void checkSeal(String package_name, String class_name) {
+		Package pckg = Package.getPackage(package_name);
+		if ( (pckg != null) && pckg.isSealed()) 
+			throw new IllegalAccessError(
+					"OT/J callout binding:\n"
+					+"Trying to break sealed "+pckg);
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
new file mode 100644
index 0000000..df7488b
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
@@ -0,0 +1,287 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2005-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: ObjectTeamsTransformer.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.jplis;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.objectteams.otre.BaseCallRedirection;
+import org.eclipse.objectteams.otre.BaseMethodTransformation;
+import org.eclipse.objectteams.otre.BaseTagInsertion;
+import org.eclipse.objectteams.otre.Decapsulation;
+import org.eclipse.objectteams.otre.LiftingParticipantTransformation;
+import org.eclipse.objectteams.otre.LowerableTransformation;
+import org.eclipse.objectteams.otre.OTConstants;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.eclipse.objectteams.otre.StaticSliceBaseTransformation;
+import org.eclipse.objectteams.otre.SubBoundBaseMethodRedefinition;
+import org.eclipse.objectteams.otre.TeamInterfaceImplementation;
+import org.eclipse.objectteams.otre.ThreadActivation;
+import org.eclipse.objectteams.otre.util.AttributeReadingGuard;
+import org.eclipse.objectteams.otre.util.CallinBindingManager;
+
+import de.fub.bytecode.Repository;
+import de.fub.bytecode.classfile.ClassParser;
+import de.fub.bytecode.classfile.JavaClass;
+import de.fub.bytecode.generic.ClassGen;
+
+
+/**
+ * Main entry into the OTRE when using JPLIS
+ * 
+ * @author Christine Hundt
+ * @author Stephan Herrmann
+ */
+public class ObjectTeamsTransformer implements ClassFileTransformer {
+	
+	// force loading all transformer classes to reduce risk of deadlock in class loading.
+	static Class<?>[] transformerClasses = new Class<?>[] {	
+		BaseCallRedirection.class, 
+		BaseMethodTransformation.class,
+		BaseTagInsertion.class,
+		Decapsulation.class,
+		LiftingParticipantTransformation.class,
+		LowerableTransformation.class,
+		StaticSliceBaseTransformation.class,
+		SubBoundBaseMethodRedefinition.class,
+		TeamInterfaceImplementation.class,
+		ThreadActivation.class
+	};
+	
+	/**
+	 * One instance of this class is used per class loader to ensure disjoint scopes.
+	 */
+	static class StateGroup {
+		ObjectTeamsTransformation.SharedState bcrState = new ObjectTeamsTransformation.SharedState();
+		ObjectTeamsTransformation.SharedState bmtState = new ObjectTeamsTransformation.SharedState();
+		BaseTagInsertion.SharedState 		  btiState = new BaseTagInsertion.SharedState();
+		Decapsulation.SharedState 			  decState = new Decapsulation.SharedState();
+		ObjectTeamsTransformation.SharedState lptState = new ObjectTeamsTransformation.SharedState();
+		ObjectTeamsTransformation.SharedState lowState = new ObjectTeamsTransformation.SharedState();
+		ObjectTeamsTransformation.SharedState ssbtState = new ObjectTeamsTransformation.SharedState();
+		ObjectTeamsTransformation.SharedState sbbmrState = new ObjectTeamsTransformation.SharedState();
+		ObjectTeamsTransformation.SharedState tiiState = new ObjectTeamsTransformation.SharedState();
+	}
+	static Map<ClassLoader, StateGroup> states = new HashMap<ClassLoader, StateGroup>();
+
+	static boolean warmedUp = false;
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.instrument.ClassFileTransformer#transform(java.lang.ClassLoader,
+	 *      java.lang.String, java.lang.Class, java.security.ProtectionDomain,
+	 *      byte[])
+	 */
+	public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+			ProtectionDomain protectionDomain, byte[] classfileBuffer)
+			throws IllegalClassFormatException
+	{
+		if (warmedUp)
+			return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+		synchronized (loader) {
+			try {
+				return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+			} finally {
+				warmedUp = true;
+			}		
+		}
+	}
+	public byte[] internalTransform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+			ProtectionDomain protectionDomain, byte[] classfileBuffer)
+			throws IllegalClassFormatException
+	{
+		if (className.startsWith("org/objectteams/transformer")
+				|| className.startsWith("org/cs3/jmangler")
+				|| className.startsWith("de/fub/bytecode"))
+		{
+			// skip OTRE, BCEL and JMangler classes
+			return null;
+		}
+//		if (!(className.startsWith("java") || className.startsWith("sun")))
+			// System.err.println("ObjectTeamsTransformer transforming: " + className);
+		if (classBeingRedefined != null) {
+			System.out.println("Redefinition!");
+			return null;
+		}
+		
+		// state sharing among transformers:
+		StateGroup states = ObjectTeamsTransformer.states.get(loader);
+		if (states == null)
+			ObjectTeamsTransformer.states.put(loader, states = new StateGroup());
+		//
+		// One fresh instance of each transformer for a given class:
+		//
+		BaseCallRedirection baseCallRedirection 
+			= new BaseCallRedirection(				loader,	states.bcrState);
+		BaseMethodTransformation baseMethodTransformation 
+			= new BaseMethodTransformation(			loader,	states.bmtState);
+		BaseTagInsertion baseTagInsertion 
+			= new BaseTagInsertion(							states.btiState);
+		Decapsulation decapsulation 
+			= new Decapsulation(					loader,	states.decState);
+		LiftingParticipantTransformation liftingParticipantTransformation 
+			= new LiftingParticipantTransformation(	loader, states.lptState);
+		LowerableTransformation lowerableTransformation 
+			= new LowerableTransformation(			loader, states.lowState);
+		StaticSliceBaseTransformation staticSliceBaseTransformation
+			= new StaticSliceBaseTransformation(	loader, states.ssbtState);
+		SubBoundBaseMethodRedefinition subBoundBaseMethodRedefinition 
+			= new SubBoundBaseMethodRedefinition(	loader,	states.sbbmrState);
+		TeamInterfaceImplementation teamInterfaceImplementation 
+			= new TeamInterfaceImplementation(true, loader, states.tiiState);
+		ThreadActivation threadActivation 
+			= new ThreadActivation();
+				
+		// tell Repository about the class loader for improved lookupClass()
+		ClassLoader prevLoader= Repository.classLoaders.get();
+		Repository.classLoaders.set(loader);
+		
+		InputStream is  = new ByteArrayInputStream(classfileBuffer);
+		try {
+			JavaClass java_class = new ClassParser(is, className).parse();
+			//Repository.addClass(java_class);
+			ClassGen cg = new ClassGen(java_class);
+			
+			JPLISEnhancer jpe = new JPLISEnhancer(cg, loader);
+			
+			Collection<String> adaptedBases; // [OT/Equinox]
+			// [OT/Equinox] remember the first transformation which holds adaptedBases
+			adaptedBases= setFirstTransformation(subBoundBaseMethodRedefinition);
+			// [OT/Equinox] if class has previously been transformed fetch the list of
+			// adapted bases from the CallinBindingManager instead of reading it now.
+			if (   (cg.getAccessFlags() & OTConstants.TEAM) != 0
+				&& !AttributeReadingGuard.getInstanceForLoader(loader).iAmTheFirst(cg.getClassName())) 
+			{
+				List<String> basesOfTeam = CallinBindingManager.getBasesPerTeam(cg.getClassName());
+				if (basesOfTeam != null)
+					adaptedBases.addAll(basesOfTeam);				
+			}
+			subBoundBaseMethodRedefinition.doTransformInterface(jpe, cg);
+			baseCallRedirection.doTransformInterface(jpe, cg);
+			decapsulation.doTransformInterface(jpe, cg);
+		try {
+			baseMethodTransformation.useReflection = (loader == null); // bootstrap classes cannot be called directly
+			baseMethodTransformation.doTransformInterface(jpe, cg);
+		} catch (Throwable t) {
+			System.err.println("Error transforming class: "+cg.getClassName());
+			t.printStackTrace();
+		}
+			baseTagInsertion.doTransformInterface(jpe, cg);
+			lowerableTransformation.doTransformInterface(jpe, cg);
+			staticSliceBaseTransformation.doTransformInterface(jpe, cg);
+			teamInterfaceImplementation.doTransformInterface(jpe, cg);
+			
+//			subBoundBaseMethodRedefinition.doTransformInterface(jpe, cg);
+//			baseCallRedirection.doTransformInterface(jpe, cg);
+//			decapsulation.doTransformInterface(jpe, cg);
+//			baseMethodTransformation.doTransformInterface(jpe, cg);
+//			baseTagInsertion.doTransformInterface(jpe, cg);
+//			staticSliceBaseTransformation.doTransformInterface(jpe, cg);
+//			teamInterfaceImplementation.doTransformInterface(jpe, cg);
+			threadActivation.doTransformInterface(jpe, cg);
+
+			
+//			baseCallRedirection.doTransformCode(cg); // empty method
+			baseMethodTransformation.doTransformCode(cg);
+			baseTagInsertion.doTransformCode(cg);
+			liftingParticipantTransformation.doTransformCode(cg);
+			staticSliceBaseTransformation.doTransformCode(cg);
+			teamInterfaceImplementation.doTransformCode(cg);
+			threadActivation.doTransformCode(cg);
+			
+			JavaClass new_java_class = cg.getJavaClass(); 
+			if (dumping) {
+				new_java_class.dump("jplis_dump/" + className + ".class");
+			}
+			return new_java_class.getBytes();
+		} catch (IOException e) {
+			System.err.println("ClassFileTransformer could not parse class file buffer to JavaClass");
+			e.printStackTrace();
+		} finally {
+			// uninstall class loader:
+			Repository.classLoaders.set(prevLoader);
+		}
+		return null;
+	}
+	
+	/**
+	 * External API (for OT/Equinox):
+	 * Destructively fetch the set of adapted base classes 
+	 * recorded since the last call to this method.
+	 * 
+	 * @return
+	 */
+	public Collection<String> fetchAdaptedBases() {
+		if (this.firstTransformation == null)
+			return null;
+		Collection<String>result= this.firstTransformation.fetchAdaptedBases();
+		this.firstTransformation= null;
+		return result;
+	}
+	
+	/**
+	 * External API (for OT/Equinox):
+	 * Read the OT-Attributes of a class without loading the class.
+	 * @throws IOException 
+	 * @throws ClassFormatError 
+	 */
+	public void readOTAttributes(InputStream file, String fileName, ClassLoader loader) 
+			throws ClassFormatError, IOException 
+	{
+		ClassParser   cp  = new ClassParser(file, fileName);
+		ClassGen      cg  = new ClassGen(cp.parse());
+		JPLISEnhancer jpe = new JPLISEnhancer(cg, /*loader (unused)*/null);
+		ClassLoader prevLoader= Repository.classLoaders.get();
+		Repository.classLoaders.set(loader);
+		try {
+			setFirstTransformation(new ObjectTeamsTransformation(loader, null) {});
+			firstTransformation.checkReadClassAttributes(jpe, cg, cg.getClassName(), cg.getConstantPool());
+		} finally {
+			Repository.classLoaders.set(prevLoader);
+		}
+	}
+	
+	// helper structure for above:
+	/* The first transformation performed holds the list of adapted bases. */
+	private ObjectTeamsTransformation firstTransformation;
+
+	/* @return the collection of adapted bases currently in use. */
+	private Collection<String> setFirstTransformation(ObjectTeamsTransformation t) {
+		if (this.firstTransformation != null)
+			t.adaptedBases= this.firstTransformation.adaptedBases; // collect into existing
+		this.firstTransformation= t;
+		return t.adaptedBases;
+	}
+
+	//	 ------------------------------------------
+	// ---------- Class file dumping: ----------------------
+	// ------------------------------------------
+	/** Initialized from property <tt>ot.dump</tt>. */
+    static boolean dumping = false;
+    static {
+        if(System.getProperty("ot.dump")!=null)
+            dumping = true;
+    }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java
new file mode 100644
index 0000000..ee6077f
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/jplis/otreAgent.java
@@ -0,0 +1,48 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2005-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: otreAgent.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.jplis;
+
+import java.lang.instrument.Instrumentation;
+
+/**
+*
+* @version $Id: otreAgent.java 23408 2010-02-03 18:07:35Z stephan $
+* @author Christine Hundt
+*/
+public class otreAgent {
+
+	private static Instrumentation instCopy;
+//	private static String optionsCopy;
+	
+	private static ObjectTeamsTransformer otTransformer;
+
+	public static void premain(String options, Instrumentation inst) {
+		instCopy = inst;
+//		optionsCopy = options;
+		
+		// add all necessary transformers:
+		otTransformer = new ObjectTeamsTransformer();
+		instCopy.addTransformer(otTransformer);
+		
+		/* All future class definitions will be seen by the transformer, 
+		 except definitions of classes upon which any registered transformer is dependent. */
+	}
+	
+	public static Instrumentation getInstrumentation() {
+		return instCopy;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java
new file mode 100644
index 0000000..9f01412
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java
@@ -0,0 +1,102 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2009 Stephan Herrmann
+ * 
+ * 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$
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 			Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre.util;
+
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.objectteams.ImplicitTeamActivation;
+
+import de.fub.bytecode.classfile.Attribute;
+import de.fub.bytecode.classfile.Unknown;
+import de.fub.bytecode.generic.ConstantPoolGen;
+
+/** 
+ * Helper class for parsing / skipping runtime visible annotations.
+ * 
+ * @author stephan
+ * @since 1.4.0
+ */
+public class AnnotationHelper {
+
+	/**
+	 * Does any of the given attributes contain an {@link ImplicitTeamActivation} annotation?
+	 * @param attrs attributes to inspect
+	 * @param cpg   constant pool for string lookup
+	 * @return true if an {@link ImplicitTeamActivation} annotation was found.
+	 */
+	public static boolean containsImplicitActivationAttribute(Attribute[] attrs, ConstantPoolGen cpg) {
+		if (attrs != null) {
+			for (Attribute attr : attrs) {
+				if (attr instanceof Unknown && ((Unknown)attr).getName().equals("RuntimeVisibleAnnotations")) {
+					Unknown unknown = (Unknown) attr;
+					byte[] bytes = unknown.getBytes();
+					int len = ObjectTeamsTransformation.combineTwoBytes(bytes, 0);
+					int i = 2;
+					String[] names = new String[1];
+					for (int n=0; n<len; n++) {
+						i = ObjectTeamsTransformation.scanStrings(names, bytes, i, cpg);
+						if ("Lorg/objectteams/ImplicitTeamActivation;".equals(names[0]))
+							return true;
+						i = skipNameValuePairs(bytes, i, names[0], cpg);
+					}
+				}						
+			}
+		}
+		return false;
+	}
+
+	private static int  skipNameValuePairs(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) {
+		int numPairs = ObjectTeamsTransformation.combineTwoBytes(bytes, i);
+		i+=2;
+		for (int p=0; p<numPairs; p++)
+			i = skipElementValue(bytes, i+2 /*skip name*/, typeName, cpg);
+		return i;
+	}
+
+	private static int skipElementValue(byte[] bytes, int i, String typeName, ConstantPoolGen cpg) {
+		short tag = bytes[i++];
+		switch (tag) {
+		case 'B': // byte
+		case 'C': // char
+		case 'D': // double
+		case 'F': // float
+		case 'I': // int
+		case 'J': // long
+		case 'S': // short
+		case 'Z': // boolean
+		case 's': // String
+		case 'c': // Class
+			i+=2; break;
+		case 'e': // Enum constant
+			i+=4; break;
+		case '@': // Annotation
+			String[] typeName2 = new String[1];
+			i = ObjectTeamsTransformation.scanStrings(typeName2, bytes, i, cpg); // nested annotation type			
+			i = skipNameValuePairs(bytes, i, typeName2[0], cpg);
+			break;
+		case '[': // Array
+			int numArrayVals = ObjectTeamsTransformation.combineTwoBytes(bytes, i);
+			i+=2;
+			for (int j = 0; j < numArrayVals; j++)
+				i = skipElementValue(bytes, i, typeName, cpg);
+			break;
+		default:
+			throw new RuntimeException("Unexpected element value kind in annotation: " + typeName);
+		}
+		return i;
+	}
+
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
new file mode 100644
index 0000000..4d72e02
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
@@ -0,0 +1,80 @@
+/**********************************************************************
+ * 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: AttributeReadingGuard.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.util;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Christine Hundt
+ * @author Stephan Herrmann
+ */
+public class AttributeReadingGuard {
+	
+	private static Map<ClassLoader, AttributeReadingGuard> instances = new HashMap<ClassLoader, AttributeReadingGuard>();
+    private static AttributeReadingGuard defaultInstance = new AttributeReadingGuard();
+    
+    private ArrayList<String> servedClasses = new ArrayList<String>();
+    
+    // this one flag is really global (concerns the one main class of the application):
+    private static boolean firstLoaded = true;
+
+    /**
+     * @param className
+     * @return
+     */
+    public boolean iAmTheFirst(String className) {
+        return !this.servedClasses.contains(className);    
+    }
+    
+    /**
+     * Processing the given class is done.
+     * @param className
+     */
+    public void workDone(String className) {
+    	this.servedClasses.add(className);    
+    }
+    
+    /**
+     * @return whether this class is the first being loaded => possibly the main class.
+     */
+    public static synchronized boolean isFirstLoadedClass() {
+    	if (!firstLoaded)
+    		return false;
+    	firstLoaded = false;
+    	return true;
+    }
+
+    /** First loaded class has no main => it was a false alarm. */
+	public static void reset() {
+		firstLoaded = true;
+	}
+
+	/**
+	 * Since actual data are stored in an instance, static methods need to retrieve the appropriate
+     * instance regarding the given class loader.
+	 */
+	public static AttributeReadingGuard getInstanceForLoader(ClassLoader loader) {
+		if (loader == null)
+			return defaultInstance;
+		
+		AttributeReadingGuard instance = instances.get(loader);
+		if (instance == null)
+			instances.put(loader, instance = new AttributeReadingGuard());
+		return instance;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java
new file mode 100644
index 0000000..1746be5
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundClass.java
@@ -0,0 +1,80 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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$
+ *
+ * Please visit http://www.objectteams.org for updates and contact.
+ *
+ * Contributors:
+ * Berlin Institute of Technology - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre.util;
+
+import java.util.HashSet;
+
+import de.fub.bytecode.generic.ObjectType;
+
+/**
+ * @version $Id: BoundClass.java,v 1.8 2006-12-19 21:31:30 stephan Exp $ 
+ * @author Christine Hundt
+ */
+public class BoundClass {
+	private String name;
+	
+	private BoundClass _super;
+	//private BoundClass _tsuper;
+	private HashSet<String> adaptingTeams = new HashSet<String>(); 
+
+	public BoundClass(String className, String teamName) {
+		name = className;
+		this.adaptingTeams.add(teamName);
+		_super = null;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public boolean isAdaptedByTeam(String teamName) {
+		return this.adaptingTeams.contains(teamName);
+	}
+	
+	public void addAdaptingTeam(String teamName) {
+		this.adaptingTeams.add(teamName);
+	}
+
+	public void setSuper(BoundClass superClass) {
+		_super = superClass;
+	}
+	
+	public BoundClass getSuper() {
+		return _super;
+	}
+	
+	public boolean isSubClassOf(String anotherClass) {
+		BoundClass superClass = _super;
+		while (superClass!=null) {
+			if (superClass.getName().equals(anotherClass)) {
+				return true;
+			}
+			superClass = superClass.getSuper();
+		}
+		return false;
+	}
+
+	public void updateSuper(BoundClass newSuperBaseClass, ObjectType newSuperBaseType) {
+		// FIXME(SH): implement ;-)		
+		// test if newSuperBaseType is above or below _super.
+		// also check if tsupers (i.e., more than one super) must be treated as well.
+	}
+	
+//	public String toString() {
+//		return name;
+//	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java
new file mode 100644
index 0000000..4a4a8fb
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/BoundMethod.java
@@ -0,0 +1,48 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: BoundMethod.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.util;
+
+/**
+ * @author Christine Hundt
+ * @version $Id: BoundMethod.java 23408 2010-02-03 18:07:35Z stephan $
+ */
+public class BoundMethod {
+	private String name;
+	private String signature;
+	private boolean isCallin;
+	
+//	private MethodBinding binding;
+	
+	public BoundMethod(String methodName, String methodSignature, boolean isCallin, MethodBinding methodBinding) {
+		name = methodName;
+		signature = methodSignature;
+		this.isCallin = isCallin;
+//		binding = methodBinding;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public String getSignature() {
+		return signature;
+	}
+	
+	public boolean getIsCallin() {
+		return this.isCallin;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java
new file mode 100644
index 0000000..ba2330a
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java
@@ -0,0 +1,1429 @@
+/**********************************************************************
+ * 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: CallinBindingManager.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.util;
+
+//import de.fub.bytecode.generic.Type; // just for javadoc.
+import de.fub.bytecode.Repository;
+import de.fub.bytecode.classfile.JavaClass;
+import de.fub.bytecode.generic.ObjectType;
+
+import org.eclipse.objectteams.otre.OTREInternalError;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation.BaseMethodInfo;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * @version $Id: CallinBindingManager.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author Christine Hundt
+ */
+@SuppressWarnings("nls")
+public class CallinBindingManager {
+	// map of bindings for role classes: roleClassName -> RoleBaseBinding
+	private static HashMap<String, RoleBaseBinding> roleBindings = new HashMap<String, RoleBaseBinding>(); 
+	
+	// map of bindings for base classes: baseClassName -> List[RoleBaseBinding]
+	private static ListValueHashMap<RoleBaseBinding> baseBindings = new ListValueHashMap<RoleBaseBinding>();
+	
+	// maps a team to its handled bases: teamClassName -> List[BaseClassName]
+	private static ListValueHashMap<String> basesPerTeam = new ListValueHashMap<String>();
+	
+	//	maps a team to its contained roles: teamClassName -> List[RoleClassName]
+	private static ListValueHashMap<String> rolesPerTeam = new ListValueHashMap<String>();
+	
+	// store sets of bases indexed by a team name, 
+	// where the team adapts (decapsulates) the given bases without a direct playedBy relation
+	private static HashMap<String, HashSet<String>> extraReferencedBases = new HashMap<String, HashSet<String>>();
+
+	/**
+	 * Add super-link of the BoundRole object for the RoleBaseBinding of 'className' to 'superClassName'.
+	 * @param className				the name of the class for which to add the super-link
+	 * @param superClassName	the name of the super class to be linked
+	 */
+	public static void addSuperRoleLink(String className, String superClassName) {
+		if (!roleBindings.containsKey(superClassName))
+			return; // no super role class stored!
+		RoleBaseBinding rbbSuper = roleBindings.get(superClassName);
+		RoleBaseBinding rbb = roleBindings.get(className);
+		// establish link from the role to its super role class:
+		rbb.getRoleClass().setSuper(rbbSuper.getRoleClass());
+	}
+	
+	/**
+	 * @param baseClassName
+     */
+	private static void addSuperBaseLink(String teamClassName, String baseClassName, RoleBaseBinding rbb) 
+	{
+		BoundClass baseClass = rbb.getBaseClass();
+		ObjectType baseClassType = new ObjectType(baseClassName);
+		if (!checkLookup(baseClassType.getClassName())) // TODO: workaround for classes loaded from special locations
+			return;
+		// clone the set for re-entrance:
+		Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator();
+		while (it.hasNext()) {
+			Entry<String, LinkedList<RoleBaseBinding>> entry = it.next();
+			String currentBaseClassName = entry.getKey();
+			if (currentBaseClassName.equals(baseClassName)) continue;
+			ObjectType currentType = new ObjectType(currentBaseClassName);
+			if (!checkLookup(currentType.getClassName())) // TODO: workaround for classes loaded from special locations
+				continue;
+			// BoundClass objects are unique per base object, so just take the first binding: 
+			BoundClass currentBaseClass = entry.getValue().getFirst().getBaseClass();
+			if(baseClassType.subclassOf(currentType)) {
+				BoundClass rbbSuper = baseClass.getSuper();
+				if (rbbSuper != null)  {
+					if (rbbSuper.getName().equals(currentBaseClassName))
+						continue; // no need for action: already set.
+					baseClass.updateSuper(currentBaseClass, currentType);
+				}
+				baseClass.setSuper(currentBaseClass);
+			}
+			else if (currentType.subclassOf(baseClassType)) {
+				BoundClass currentSuper = currentBaseClass.getSuper();
+				// if sub base classes may be registered before super base class, 
+				// this case has to be considered too:
+				if (currentSuper != null) {
+					if (currentSuper.getName().equals(baseClassName))
+						continue; // no need for action: already set.
+					currentBaseClass.updateSuper(baseClass, baseClassType);
+				}
+				currentBaseClass.setSuper(baseClass);
+			}
+		}
+	}
+
+    /**
+     * Declare role playedBy base.
+	 *
+     * @param roleClassName		the name of the played role class
+     * @param baseClassName		the name of the playing base class
+     */
+    public static void addRoleBaseBinding(String roleClassName, String baseClassName, String teamClassName) {
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		if (rbb == null) {
+			rbb = new RoleBaseBinding(roleClassName, baseClassName, teamClassName);
+			roleBindings.put(roleClassName, rbb);
+		}
+		addSuperBaseLink(teamClassName, baseClassName, rbb);
+		synchronized (baseBindings) {
+			baseBindings.put(baseClassName, rbb);
+		}
+		addTeamRoleRelation(teamClassName, roleClassName);
+  	}
+
+    /**
+     * @param teamClassName
+     * @param baseClassName
+     */
+    public static void addTeamBaseRelation(String teamClassName, String baseClassName) {
+    	JavaClass baseClass = Repository.lookupClass(baseClassName);
+    	if (checkLookup(baseClassName) && baseClass.isInterface()) { // TODO: workaround for classes loaded from special locations
+    		// TODO (SH): need to register with all implementing classes!
+            if (logging) {
+                ObjectTeamsTransformation.printLogMessage("*** Skipping base " + baseClassName + ": is an interface");
+    			ObjectTeamsTransformation.printLogMessage("Classses implementing the interface " + baseClassName + " have to be transformed!");
+    		}
+    		addBoundBaseInterface(baseClassName);
+    	} else {
+    		List<String> bases = basesPerTeam.get(teamClassName);
+    		if (bases==null || !bases.contains(baseClassName))
+    			basesPerTeam.put(teamClassName, baseClassName);
+    	}
+    }
+    
+    /**
+     * @param teamClassName
+     * @return
+     */
+    public static List<String> getBasesPerTeam(String teamClassName) {
+        // (PH): return empty list instead of null when team has no bases?
+    	return basesPerTeam.get(teamClassName);
+    }
+    
+    /**
+     * @param teamClassName
+     * @param roleClassName
+     */
+    public static void addTeamRoleRelation(String teamClassName, String roleClassName) {
+        	List<String> roles = rolesPerTeam.get(teamClassName);
+    		if (roles == null || !roles.contains(roleClassName))
+    			rolesPerTeam.put(teamClassName, roleClassName);
+    }
+    
+    /**
+     * @param teamClassName
+     * @return
+     */
+    public static List<String> getRolePerTeam(String teamClassName) {
+    	return rolesPerTeam.get(teamClassName);
+    }
+
+    private static LinkedList<String> allRoles = new LinkedList<String>();
+    
+    /**
+     * @param roleName
+     */
+    public static void addRole(String roleName) {
+    	allRoles.add(roleName);
+    }
+    
+    /**
+     * @param roleName
+     * @return
+     */
+    public static boolean isRole(String roleName) {
+    	return allRoles.contains(roleName);
+    }
+    
+    public static void addExtraReferencedBase(String teamName, String baseName) {
+    	HashSet<String> bases = extraReferencedBases.get(teamName);
+    	if (bases == null) {
+    		bases = new HashSet<String>();
+    		extraReferencedBases.put(teamName, bases);
+    	}
+    	bases.add(baseName);
+    }
+    
+    /**
+     * Get all bases adapted by a team without a direct playedBy relation.
+     * @param teamName
+     * @return non-null Set (may be empty).
+     */
+    public static Set<String> getExtraReferencedBases(String teamName) {
+    	Set<String> bases = extraReferencedBases.get(teamName);
+    	if (bases != null)
+    		return bases;
+    	return new HashSet<String>();
+    }
+    
+	/**
+     * Declare binding of a pair of methods.
+	 * @param roleClassName
+	 * @param bindingFileName TODO
+	 * @param bindingLineNumber TODO
+	 * @param bindingLineOffset TODO
+	 * @param roleMethodName
+	 * @param roleMethodSignature signature ready for interpretation by
+     *                      {@link Type de.fub.bytecode.generic.Type}
+	 * @param isStaticRoleMethod TODO
+	 * @param modifier "before", "after" or "replace"
+	 * @param baseMethodName
+	 * @param baseMethodSignature
+	 * @param isStaticBaseMethod is the base method static?
+	 * @param baseIsCallin is the base method a callin method?
+	 * @param translationFlags one bit for the result and for each argument indicating whether lifting/lowering is needed
+	 * @param liftMethodName
+	 * @param liftMethodSignature
+     */
+    public static void addMethodBinding(
+	        String roleClassName, String baseClassName, 
+	        String bindingFileName, int bindingLineNumber, int bindingLineOffset,
+            String bindingLabel, String roleMethodName, String roleMethodSignature, boolean isStaticRoleMethod, 
+			String wrapperName, String wrapperSignature, String modifier, 
+			String baseMethodName, String baseMethodSignature, 
+			boolean isStaticBaseMethod,	boolean baseIsCallin, boolean covariantBaseReturn, 
+			int translationFlags, String liftMethodName, String liftMethodSignature)
+	{
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		if (rbb == null) {
+			// no binding found, create it now:
+			if (baseClassName == null)
+				throw new OTREInternalError("PlayedBy attribute must be read before method bindings.");
+			int lastDollar = roleClassName.lastIndexOf('$');
+			String teamClassName = roleClassName.substring(0, lastDollar);
+			rbb = new RoleBaseBinding(roleClassName, baseClassName, teamClassName);
+			roleBindings.put(roleClassName, rbb);
+		}
+		//System.err.println(rbb.getRoleClass().getName()+"<-*->"+rbb.getBaseClass().getName());
+		rbb.addMethodBinding(bindingFileName, bindingLineNumber, bindingLineOffset, 
+											 bindingLabel, roleMethodName, roleMethodSignature, isStaticRoleMethod,
+			                                 wrapperName, wrapperSignature, modifier,
+			                                 baseMethodName, baseMethodSignature, 
+			                                 isStaticBaseMethod, baseIsCallin, covariantBaseReturn,
+			                                 translationFlags,
+			                                 liftMethodName, liftMethodSignature);
+  	
+		if (modifier.equals("replace"))
+			assignBaseCallTag(rbb.getBaseClassName(), baseMethodName, baseMethodSignature);
+	}
+
+    /**
+     * Get all callin bindings for a given base method.
+     * @param className the base class
+     * @param methodName the base method
+     * @return Collection of <pre>MethodBinding</pre>
+     */
+    public static Collection<MethodBinding> getBindingForBaseMethod(String baseClassName, String baseMethodName, String baseMethodSignature)
+	{
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		LinkedList<MethodBinding> resultList = new LinkedList<MethodBinding>();
+		if (rbbList != null) {
+			Iterator<RoleBaseBinding> it = rbbList.iterator();
+			while (it.hasNext()) {
+				RoleBaseBinding rbb = it.next();
+				List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature);
+				if (mbs != null)
+					addFiltered(resultList, mbs, baseMethodName, baseMethodSignature);
+			}
+		}
+		// IMPLICIT_INHERITANCE
+		addFiltered(resultList, 
+					getImplicitlyInheritedBaseMethodBindings(baseClassName, baseMethodName, baseMethodSignature),
+					baseMethodName,
+					baseMethodSignature);
+		if (resultList.isEmpty())
+			return null;
+		return resultList;
+    }
+    /** variant of the above, optimized for computing only a boolean result instead of a complete list. */
+    public static boolean isBoundBaseMethod(String baseClassName, String baseMethodName, String baseMethodSignature)
+	{
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null) {
+			for (RoleBaseBinding rbb : rbbList) {
+				List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature);
+				if (mbs != null)
+					for (MethodBinding mb : mbs)
+						if (mb.matchesMethod(baseMethodName, baseMethodSignature, /* strict */ true))
+								return true;
+			}
+		}
+		// IMPLICIT_INHERITANCE
+		for (MethodBinding mb : getImplicitlyInheritedBaseMethodBindings(baseClassName, baseMethodName, baseMethodSignature))
+			if (mb.matchesMethod(baseMethodName, baseMethodSignature, /* strict */ true))
+					return true;
+		return false;
+    }
+    // add bindings from candidates to resultList, perhaps checking
+    // full signatures (i.e., if not covariantBaseReturn).
+    private static void addFiltered(Collection<MethodBinding> resultList, 
+    								Collection<MethodBinding> candidates,
+    								String name,
+    							    String fullSignature) 
+    {
+   		for (MethodBinding methodBinding : candidates) 
+			if (methodBinding.matchesMethod(name, fullSignature, /*strict*/false)) 
+				resultList.add(methodBinding);			
+    }
+    
+    /**
+     * Gets all implicitly inherited method bindings for the given base method.
+     * Note: the result can only contain elements for base classes which are
+     * roles at the same time! 
+     * @param baseClassName			the name of the base class
+     * @param baseMethodName		the name of the base mehtod
+     * @param baseMethodSignature	the descriptor or the base method signature
+     * @return a Collection with all implicitly inherited method bindings
+     */
+    private static Collection<MethodBinding> getImplicitlyInheritedBaseMethodBindings(String baseClassName, String baseMethodName, String baseMethodSignature) { 
+    	List<MethodBinding> resultList = new LinkedList<MethodBinding>();
+    	
+    	if (!isRole(baseClassName))
+    		return resultList; // only roles can have implicit super types
+		
+		Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator();
+
+		while (it.hasNext()) {
+			Entry<String, LinkedList<RoleBaseBinding>> entry = it.next();
+			String have = entry.getKey();
+			// look for true superClass (not same):
+			if (have.equals(baseClassName)) 
+				continue;
+			if (isImplicitSubtype(baseClassName, have)) {
+				// now we have an implicit superClass:
+				if (logging)
+                    ObjectTeamsTransformation.printLogMessage(baseClassName
+                            + " implicitly inherits callin bindings from " + have);
+                // collect the signatures of all bound base methods:
+   				List<RoleBaseBinding> rbbList = entry.getValue();
+				if (rbbList != null) {
+					Iterator<RoleBaseBinding> rbb_it = rbbList.iterator();
+					while (rbb_it.hasNext()) {
+						RoleBaseBinding rbb = rbb_it.next();
+						List<MethodBinding> mbs = rbb.getBaseMethodBindings(baseMethodName, baseMethodSignature);
+						if (mbs != null)
+							resultList.addAll(mbs);
+					}
+				}
+			}
+		}
+		//if (!resultList.isEmpty())
+		//	System.err.println(resultList);
+		return resultList;
+    }
+
+	/**
+	 * Get all callin bindings that a given base class may inherit from its superclass.
+	 * @param className
+	 * @result list of MethodBinding
+	 */
+	public static Collection<MethodBinding> getInheritedCallinBindings (String className) {
+/*
+		List classBindings = baseBindings.get(className);
+	if (classBindings!=null) {
+		// any RoleBaseBinding contains the corresponding BoundClass object for the super base:
+		RoleBaseBinding anyRBB = (RoleBaseBinding)classBindings.get(0);
+		// problem: if a sub base class is not explicitly bound to a role class no corresponding 
+		//                BoundClass object exists. How can we access the super bindings via the 
+		//                super-link??
+		BoundClass bc = anyRBB.getBaseClass();
+		//System.out.println("-----------");
+		while (bc.getSuper()!=null) {
+			System.out.println(bc.getName());
+			bc = bc.getSuper();
+	}
+		//System.out.println("-----------");
+		}
+*/		
+
+		List<MethodBinding> result = new LinkedList<MethodBinding>();
+		ObjectType current = new ObjectType(className);
+		if (!checkLookup(current.getClassName())) // TODO: workaround for classes loaded from special locations
+			return result; 
+		// clone for re-entrance:
+		Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it= getBaseBindingsCloneIterator();
+		while (it.hasNext()) {
+			Entry<String, LinkedList<RoleBaseBinding>> entry = it.next();
+			String have = entry.getKey();
+			// look for true superClass (not same):
+			if (have.equals(className)) continue;
+			ObjectType haveType = new ObjectType(have);
+			//System.err.println(current + " : "+haveType);
+			//System.err.println(de.fub.bytecode.Repository.lookupClass(have));
+			if (!checkLookup(haveType.getClassName())) // TODO: workaround for classes loaded from special locations
+					continue;
+			if (current.subclassOf(haveType)) {
+				// now we have a true superClass:
+				if (logging)
+                    ObjectTeamsTransformation.printLogMessage(className
+                            + " inherits callin bindings from " + have);
+                // collect the signatures of all bound base methods:
+   				List<RoleBaseBinding> rbbList = entry.getValue();
+				if (rbbList != null) {
+					Iterator<RoleBaseBinding> rbb_it = rbbList.iterator();
+					while (rbb_it.hasNext()) {
+						RoleBaseBinding rbb = rbb_it.next();
+						result.addAll(rbb.getBaseMethodBindings());
+					}
+				}
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * Get all super classes defining callin bindings that a given static base
+	 * method may inherit.
+	 * 
+	 * @author juerwid
+	 * @param className
+	 * @param methodName
+	 * @param methodSignaturte
+	 * @result list of <String[] {class_name}>
+	 */
+	public static Collection<String> getInheritedCallinBindingsForStaticMethods(
+			String className, String methodName, String methodSignature)
+	{
+		List<String> result = new LinkedList<String>();
+		ObjectType current = new ObjectType(className);
+		if (!checkLookup(current.getClassName())) // TODO: workaround for classes loaded from special locations
+			return result; 
+		// clone for re-entrance:
+		Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = getBaseBindingsCloneIterator();
+		boolean getNextClass = false;
+		while (it.hasNext()) {
+			Entry<String,LinkedList<RoleBaseBinding>> entry = it.next();			
+			String have = entry.getKey();
+			// look for true superClass (not same):
+			if (have.equals(className)) continue;
+			ObjectType haveType = new ObjectType(have);
+			if (!checkLookup(haveType.getClassName())) // TODO: workaround for classes loaded from special locations
+					continue;
+			if (current.subclassOf(haveType)) {
+				// now we have a true superClass:
+				if (logging)
+					ObjectTeamsTransformation.printLogMessage(className
+							+ " inherits callin bindings from " + have);
+                // collect the signatures of all bound base methods:
+   				LinkedList<RoleBaseBinding> rbbList = entry.getValue();
+				if (rbbList != null) {
+					Iterator<RoleBaseBinding> rbb_it = rbbList.iterator();
+					while (rbb_it.hasNext() && !getNextClass) {
+						RoleBaseBinding rbb = rbb_it.next();
+						List<String[]> methods = rbb.getBaseSignatures();
+						Iterator<String[]> methodsIter = methods.iterator();
+						while(methodsIter.hasNext() && !getNextClass){
+							String[] aMethod = methodsIter.next();
+							if(methodName.equals(aMethod[0]) && methodSignature.equals(aMethod[1])){
+								result.add(have);
+								getNextClass = true;
+							}
+						}
+					}
+					if(getNextClass){
+						getNextClass = false;
+						continue;
+					}
+				}
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * Checks if 'subType' is an implicit subtype of 'superType'.
+	 * To be true the role name parts have to be equal and the 
+	 * team name parts have to be in a 'real' subtype relationship.
+	 *
+	 * @param subType	the name of the potential subtype.
+	 * @param superType	the name of the potential supertype.
+	 * @return	true, if subType implicitly inherits from superType.
+	 */
+	private static boolean isImplicitSubtype(String subType, String superType) {
+		//System.err.println(subType +" -?-> " + superType);
+		int dollarIdxSub = subType.lastIndexOf('$');
+		int dollarIdxSuper = superType.lastIndexOf('$');
+		if (dollarIdxSub==-1 || dollarIdxSuper==-1)
+			return false; // no roles
+		String pureSubType = subType.substring(dollarIdxSub+1, subType.length());
+		String pureSuperType = superType.substring(dollarIdxSuper+1, superType.length());
+		if (!pureSubType.equals(pureSuperType))
+			return false;// no identical role names
+		
+		String subTeamName = subType.substring(0, dollarIdxSub);
+		String superTeamName = superType.substring(0,dollarIdxSuper);
+
+		if (!(checkLookup(subTeamName) && checkLookup(superTeamName)))
+				return false; // Repository can not lookup types
+		ObjectType subTeamType = new ObjectType(subTeamName);
+		ObjectType superTeamType = new ObjectType(superTeamName);
+		if (subTeamType.subclassOf(superTeamType)) {
+            if (logging)
+                ObjectTeamsTransformation.printLogMessage(subType
+                        + " implicitly inherits method bindings from " + superType);
+			//System.err.println(subType + " implicitly inherits method bindings from " + superType);
+			return true;
+		}
+		return false; // no inheritance relation between teams
+	}
+	
+	/**
+	 * Check to avoid NullPointerExceptions caused by the Repository when classes can not be looked up (because they loaded by
+	 * classloaders with special a classpath)
+	 *
+	 * @param current	The name of the class to look up in the Repository.
+	 * @return False, if the class can not be found, true else.
+	 */
+	private static boolean checkLookup(String className) {
+		if (Repository.lookupClass(className) == null) {
+			if (OTEQUINOX_WARN)
+				System.err.println("Warning: Repository could not lookup class " + className + "!");
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Get all inherited method bindings for a given base method, which are 
+	 * bindings declared for a super base class.
+	 *
+	 * the actual base class has additional bindings for this method!  
+	 * @param baseClassName			the name of the role class
+	 * @param baseMethodName		the name of the role method
+	 * @param baseMethodSignature	the signature of the role method
+	 * @result a List containing all inherited bindings for the role method
+	 */
+	public static List<MethodBinding> getInheritedBaseMethodBindings(String baseClassName, String baseMethodName, String baseMethodSignature) {
+
+		List<MethodBinding> inheritedMethodBindings = new LinkedList<MethodBinding>();
+		if (!isBoundBaseClass(baseClassName)) {
+			return inheritedMethodBindings;
+		}
+		LinkedList<RoleBaseBinding> baseBindingsForBase = baseBindings.get(baseClassName);
+		if (baseBindingsForBase == null) 
+			return inheritedMethodBindings;
+		
+		Iterator<RoleBaseBinding> it = baseBindingsForBase.iterator();
+		while (it.hasNext()) {
+			RoleBaseBinding rbb = it.next(); 
+			BoundClass bc = rbb.getBaseClass();
+			while (bc.getSuper() != null) {
+				bc = bc.getSuper();
+				String superRoleName = bc.getName();
+				Collection<MethodBinding> superRoleMethodBindings = CallinBindingManager.getBindingForBaseMethod(
+																				   		 superRoleName, 
+																						 baseMethodName, 
+																						 baseMethodSignature);
+				if (superRoleMethodBindings!=null)
+					inheritedMethodBindings.addAll(superRoleMethodBindings);
+			}
+		}
+		return inheritedMethodBindings;
+	}
+
+	/**
+	 * Get all inherited method bindings for a given role method, which are
+	 * bindings declared in a super role class. The actual role class has
+	 * additional bindings for this method!
+	 * 
+	 * @param roleClassName			the name of the role class
+	 * @param roleMethodName		the name of the role method
+	 * @param roleMethodSignature	the signature of the role method
+	 * @result a List containing all inherited bindings for the role method
+	 */
+	public static List<MethodBinding> getInheritedRoleMethodBindings(String roleClassName, String roleMethodName, String roleMethodSignature) {
+		List<MethodBinding> inheritedMethodBindings = new LinkedList<MethodBinding>();
+		if (!isBoundRoleClass(roleClassName)) {
+			return inheritedMethodBindings;
+		}
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		BoundClass bc = rbb.getRoleClass();
+		while (bc.getSuper() != null) {
+			bc = bc.getSuper();
+			String superRoleName = bc.getName();
+			List<MethodBinding> superRoleMethodBindings = CallinBindingManager.getBindingsForRoleMethod(
+																		superRoleName, 
+																		roleMethodName, 
+																		roleMethodSignature);
+			inheritedMethodBindings.addAll(superRoleMethodBindings);
+		}
+		return inheritedMethodBindings;
+	}
+
+	/**
+	 * All bindings for a given role method concerning its base class.
+	 * 
+	 * @return List of MethodBinding
+	 */
+	public static List<MethodBinding> getBindingsForRoleMethod(String roleClassName,
+			String roleMethodName, String roleMethodSignature)
+	{
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		if (rbb==null) {
+			return new LinkedList<MethodBinding>();
+		}
+		List<MethodBinding> roleMethodBindings = rbb.getRoleMethodBindings(roleMethodName, roleMethodSignature);
+		if (roleMethodBindings == null) {
+			return new LinkedList<MethodBinding>();
+		}
+		return roleMethodBindings;
+	}
+
+	/**
+	 * @param className
+	 * @return
+	 */
+	public static boolean isBoundBaseClass(String className) {
+		// and has at least one method binding?
+		boolean result = baseBindings.containsKey(className);
+		if (result || !isRole(className)) {
+			return result;
+		}
+		else {// bound implicit super class?
+			Iterator<String> it = getBaseBindingsKeyIterator();
+			while (it.hasNext()) {
+				String have = it.next();
+				// look for true superClass (not same):
+				if (have.equals(className)) 
+					continue;
+				if (isImplicitSubtype(className, have))
+					return true;
+			}
+			return result;
+		}
+	}
+	
+	/**
+	 * @param className
+	 * @return
+	 */
+	public static boolean isBoundBaseAndRoleClass(String className) {
+		// and has at least one method binding?
+		if (baseBindings.containsKey(className)) 
+			return true;
+		// bound implicit super class?
+		Iterator<String> it = getBaseBindingsKeyIterator();
+		while (it.hasNext()) {
+			String have = it.next();
+			// look for true superClass (not same):
+			if (have.equals(className)) 
+				continue;
+			if (isImplicitSubtype(className, have))
+				return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+	public static boolean hasBoundBaseParent(String baseClassName) {
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null) {
+			Iterator<RoleBaseBinding> it = rbbList.iterator();
+			while (it.hasNext()) {
+				RoleBaseBinding rbb = it.next();
+				if (rbb.getBaseClass().getSuper()!=null)
+					return true;
+			}
+		}
+		// IMPLICIT_INHERITANCE
+		//if (isUnboundSubBase(baseClassName))
+		//	return true;
+		return false;
+	}
+	
+	
+	/**
+	 * Returns the name of the topmost bound base class.
+	 * 
+	 * @param baseClassName
+	 * @return
+	 */
+	public static String getTopmostBoundBase(String baseClassName) {
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null) {
+			// assumption: EVERY BoundClass object has been connected to its bound super classes.
+			RoleBaseBinding anyRBB = rbbList.get(0);
+			BoundClass bc = anyRBB.getBaseClass();
+			while (bc.getSuper() != null) {
+	            bc = bc.getSuper();
+	        }
+			return bc.getName();
+		}
+		return baseClassName;
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+	public static String getBoundBaseParent(String baseClassName) {
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null) {
+			Iterator<RoleBaseBinding> it = rbbList.iterator();
+			while (it.hasNext()) {
+				RoleBaseBinding rbb = it.next();
+				BoundClass bc = rbb.getBaseClass().getSuper();
+				if (bc!=null)
+					return bc.getName();
+			}
+		}
+		// IMPLICIT_INHERITANCE
+		//if (isUnboundSubBase(baseClassName))
+		//	return true;
+		return null;
+	}
+	
+	/**
+	 * @param teamClassName
+	 * @param baseClassName
+	 * @return
+	 */
+	public static boolean teamAdaptsSuperBase(String teamClassName, String baseClassName) {
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null && !rbbList.isEmpty()) {
+			RoleBaseBinding rbb = rbbList.getFirst(); // all entries refer to the same base class.
+			BoundClass bc = rbb.getBaseClass().getSuper();
+			while (bc!=null) {
+				if (bc.isAdaptedByTeam(teamClassName))
+					return true;
+				bc = bc.getSuper();
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+//	private static boolean isUnboundSubBase(String baseClassName) {
+//		ObjectType current = new ObjectType(baseClassName);
+//		if (!checkLookup(current.getClassName())) // TODO: workaround for classes loaded from special locations
+//			return false; 
+//		Iterator /* String */ it = baseBindings.keySet().iterator();
+//		while (it.hasNext()) {
+//			String have = (String)it.next();
+//			// look for true superClass (not same):
+//			if (have.equals(baseClassName)) continue;
+//			ObjectType haveType = new ObjectType(have);
+//			//System.err.println(current + " : "+haveType);
+//			//System.err.println(de.fub.bytecode.Repository.lookupClass(have));
+//			if (!checkLookup(haveType.getClassName())) // TODO: workaround for classes loaded from special locations
+//					continue;
+//			if (current.subclassOf(haveType)) {
+//				return true;
+//			}
+//		}
+//		return false;
+//	}
+
+	/**
+	 * @param className
+	 * @return
+	 */
+	public static boolean isBoundRoleClass(String className) {
+		return roleBindings.containsKey(className);
+	}
+
+	/**
+	 * @param className
+	 * @return
+	 */
+	public static RoleBaseBinding getRoleBaseBinding(String roleClassName) {
+		return roleBindings.get(roleClassName);
+	}
+	
+	/**
+	 * @param roleClassName
+	 * @return
+	 */
+	public static List<MethodBinding> getMethodBindingsForRoleClass(String roleClassName)
+	{
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		return rbb.getRoleMethodBindings();
+	}
+	
+	/**
+	 * @param roleClassName
+	 * @return
+	 */
+	public static Set<String> getBoundRoleMethods(String roleClassName) {
+		Set<String> roleMethodKeySet = new HashSet<String>();
+		if (roleBindings.get(roleClassName) != null) {
+			RoleBaseBinding rbb = roleBindings.get(roleClassName);
+			roleMethodKeySet = rbb.getRoleMethodSignatures();
+		}
+		return roleMethodKeySet;
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+	public static List<MethodBinding> getMethodBindingsForBaseClass(String baseClassName) 
+	{
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		LinkedList<MethodBinding> resultList = new LinkedList<MethodBinding>();
+		if (rbbList != null) {
+			Iterator<RoleBaseBinding> it = rbbList.iterator();
+			while (it.hasNext()) {
+				RoleBaseBinding rbb = it.next();
+				resultList.addAll(rbb.getRoleMethodBindings());
+			}
+		 }
+		 return resultList;
+	}
+	
+    // --------------------------------------------------
+    //     discriminate base methods by tag per callin
+    //  --------------------------------------------------
+    // baseClass.baseMeth.baseMethodSignature -> tag
+    private static HashMap<String, Integer> baseCallTags = new HashMap<String, Integer>();
+    // -- follow access methods for baseCallTags:
+	
+    /**
+     * @param baseClass
+     * @param baseMeth
+     * @param baseMethodSignature
+     */
+    public static void assignBaseCallTag (String baseClass, String baseMeth, 
+    														   String baseMethodSignature) 
+    {
+		// every base method bound by a replace callin gets an unique tag:	
+		String key = baseClass+"."+baseMeth+"."+baseMethodSignature;
+		int tag = baseCallTags.size();
+		if (!baseCallTags.containsKey(key))
+			baseCallTags.put(key, Integer.valueOf(tag));
+	}
+
+    public static int getBaseCallTag (String base_class_name, 
+    								  String base_method_name, 
+    								  String base_method_signature) {
+        String key = base_class_name + "." + base_method_name
+		+ "." + base_method_signature;
+		return baseCallTags.get(key).intValue();
+    }
+
+    // ----------------------------------------------
+    //      Map argument positions:
+    // ----------------------------------------------
+    // teamName -> callinWrapperName -> int[]
+	private static HashMap<String, HashMap<String, int[]>> paramMappings = new HashMap<String, HashMap<String, int[]>>();
+    // -- follow access methods for paramMappings:
+
+	/**
+	 * @param teamName
+	 * @param methodWrapper
+	 * @param positions
+	 */
+	public static void addParameterBinding (String teamName,
+											String methodWrapper,
+											int[] positions) {
+		HashMap<String, int[]> teamMap = paramMappings.get(teamName);
+		if (teamMap == null) {
+			teamMap = new HashMap<String, int[]>();
+			paramMappings.put(teamName, teamMap);
+		}
+		teamMap.put(methodWrapper, positions);
+	}
+
+	public static boolean hasParamMappings (String teamName, String methodWrapper)
+	{
+		HashMap<String,int[]> teamMap = paramMappings.get(teamName);
+		if (teamMap == null) return false;
+		return teamMap.containsKey(methodWrapper);
+	}
+
+	/** Get parameter positions for the given team or any super team. */
+	public static int[] getParamPositions (String teamName, String methodWrapper)
+	{
+		int[] positions = getExactParamPositions(teamName, methodWrapper);
+		if (positions != null)
+			return positions;
+		// inherit parameter mappings from super teams: -- >> 
+		Iterator<String> superTeams = getSuperTeamsWithParamMappigs(teamName).iterator();
+		while (superTeams.hasNext()) {
+			positions = getExactParamPositions(superTeams.next(), methodWrapper);
+			if (positions != null) // found (the!) parameter mapping
+				return positions;
+		}
+		return null;
+	}
+	/** Get parameter positions for exactly the given team (no super teams). */
+	private static int[] getExactParamPositions(String teamName, String methodWrapper) {
+		HashMap<String,int[]>teamMap = paramMappings.get(teamName);
+		if (teamMap == null)
+			return null;
+		return teamMap.get(methodWrapper);
+	}
+	
+	private static List<String> getSuperTeamsWithParamMappigs(String teamName) {
+		LinkedList<String> result = new LinkedList<String>();
+		if (!checkLookup(teamName)) // TODO: workaround for classes loaded from special locations
+			return result;
+		for (JavaClass superTeam : Repository.getSuperClasses(teamName))
+			if (paramMappings.get(superTeam.getClassName()) != null)
+				result.add(superTeam.getClassName());
+		return result;
+	}
+	
+
+    // -----------------------------------------------
+    //   tags for teams per base class:
+    // -----------------------------------------------
+    // baseName -> HashMap  (teamName -> tag (Integer))
+    private static HashMap<String, HashMap<String, Integer>> baseTags = new HashMap<String, HashMap<String, Integer>>();
+
+    /**
+     * @param teamName
+     * @param baseToTag
+     */
+    public static void addBaseTags (String teamName, HashMap<String, Integer> baseToTag) {
+	    Iterator<Entry<String, Integer>> iter = baseToTag.entrySet().iterator();
+	    while (iter.hasNext()) {
+	    	Entry<String,Integer> entry = iter.next();
+	        String baseName = entry.getKey();
+	        Integer tag = entry.getValue();
+	        HashMap<String, Integer> thisBaseTags = baseTags.get(baseName);
+	        if (thisBaseTags == null) {
+    		    thisBaseTags = new HashMap<String, Integer>();
+    		    baseTags.put(baseName, thisBaseTags);
+	        }
+	        thisBaseTags.put(teamName, tag);
+	    }
+    }
+
+    /**
+     *  Get all tags of teams which have callins for a given base class.
+     * @param baseClassName base class name.
+     * @return HashMap: team name -> tag (Integer)
+     */
+    public static HashMap<String, Integer> getBaseTags (String baseClassName) {
+    	HashMap<String, Integer> baseClassTags = baseTags.get(baseClassName);
+    	if (baseClassTags == null)
+    		return new HashMap<String, Integer>();
+    	return baseTags.get(baseClassName); 
+    }
+    
+    /**
+     * Get all tags of teams which have callins for implicit super types
+     * of the given base class. 
+     * Note: this is only possible if the base class is a role at the same time! 
+     * @param baseClassName	base class name.
+     * @return HashMap: team name -> tag (Integer)
+     */
+    public static HashMap<String, Integer> getInheritedBaseTags(String baseClassName) {
+    	HashMap<String, Integer> result = new HashMap<String, Integer>();
+    	// clone for re-entrance:
+    	Iterator<String> it = getBaseBindingsKeyIterator();
+		while (it.hasNext()) {
+			String have = it.next();
+			// look for true superClass (not same):
+			if (have.equals(baseClassName)) 
+				continue;
+			if (isImplicitSubtype(baseClassName, have))
+				result.putAll(getBaseTags(have));
+		}
+		return result;
+    }
+
+	// -----------------------------------------------
+	//   callout bindings that require adjustment:
+	// -----------------------------------------------
+	// baseClass -> HashSet (method_name+signature)
+	private static HashMap<String, HashSet<String>> calloutBindings = new HashMap<String, HashSet<String>>();
+
+	/**
+	 * @param clazz
+	 * @param meth
+	 * @param sign
+	 */
+	public static void addCalloutBinding(String clazz, String meth, String sign) {
+		HashSet<String> bindings = calloutBindings.get(clazz);
+		if (bindings == null) {
+			bindings = new HashSet<String>();
+			calloutBindings.put(clazz, bindings);
+		}
+		bindings.add(meth + sign);
+	}
+
+	/**
+	 * @param clazz
+	 * @return
+	 */
+	public static HashSet<String> getCalloutBindings (String clazz) {
+		return calloutBindings.get(clazz);
+	}
+	
+	/**
+	 * @param bindings
+	 * @param method_name
+	 * @param signature
+	 * @return
+	 */
+	public static boolean requiresCalloutAdjustment(HashSet<String> bindings,
+											 		String method_name,
+											 		String signature)
+	{
+		return bindings.contains(method_name+signature);
+	}
+	
+	//	 -----------------------------------------------
+	//   callouts to base class fields are stored here for furher reading and get/set method generation:
+	// -----------------------------------------------
+	private static ListValueHashMap<FieldDescriptor> calloutSetFields = new ListValueHashMap<FieldDescriptor>();
+	private static ListValueHashMap<FieldDescriptor> calloutGetFields = new ListValueHashMap<FieldDescriptor>();
+
+ 
+	/**
+	 * @param roleClassName
+	 * @param fieldName
+	 * @param fieldSignature
+	 * @param accessMode
+	 * @param isStaticField
+	 */
+	public static void addCalloutBoundFileds(String baseClassName, String fieldName, 
+			String fieldSignature, String accessMode, boolean isStaticField) 
+	{
+		FieldDescriptor fd = new FieldDescriptor(fieldName, fieldSignature, isStaticField);
+
+		if (accessMode.equals("get")) {
+			calloutGetFields.put(baseClassName, fd);
+		} else if (accessMode.equals("set")) {
+			calloutSetFields.put(baseClassName, fd);
+		} else {
+			throw new OTREInternalError("CalloutFieldAccess attribute contains wrong access mode: "+accessMode);
+		}
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+	public static List<FieldDescriptor> getCalloutGetFields(String baseClassName) {
+		return calloutGetFields.get(baseClassName);
+	}
+	
+	/**
+	 * @param baseClassName
+	 * @return
+	 */
+	public static List<FieldDescriptor> getCalloutSetFields(String baseClassName) {
+		return calloutSetFields.get(baseClassName);
+	}
+
+	// -----------------------------------------------
+	// base calls to super methods via special accessor
+	// -----------------------------------------------
+	private static ListValueHashMap<SuperMethodDescriptor> superMethods = new ListValueHashMap<SuperMethodDescriptor>();
+
+	public static void addSuperAccess(String baseClassName, String superClassName, String methodName, String signature) {
+		SuperMethodDescriptor superMethod = new SuperMethodDescriptor(methodName, baseClassName, superClassName, signature);
+		superMethods.put(baseClassName, superMethod);
+	}
+	public static List<SuperMethodDescriptor> getSuperAccesses(String class_name) {
+		return superMethods.get(class_name);
+	}
+
+	//	 -----------------------------------------------
+	//   bound interfaces have to be registered, for implementing classes to inherit callin bindings:
+	// -----------------------------------------------
+	private static List<String> boundBaseInterfaces = new LinkedList<String>();
+
+	/**
+	 * @param baseInterfaceName	The name of the bound base interface.
+	 */
+	public static void addBoundBaseInterface(String baseInterfaceName) {
+		if (!boundBaseInterfaces.contains(baseInterfaceName))
+			boundBaseInterfaces.add(baseInterfaceName);
+	}
+
+	/**
+	 * @param interfaceName
+	 * @return
+	 */
+	public static Collection<String[]> getInterfaceInheritedCallinBindings(String interfaceName) {
+		List<String[]> result = new LinkedList<String[]>();
+		//System.err.println(interfaceName);
+		//System.err.println(boundBaseInterfaces);
+		if (boundBaseInterfaces.contains(interfaceName)) {
+            if (logging)
+                ObjectTeamsTransformation.printLogMessage(interfaceName
+                        + " bequests callin bindings to implementing class");
+              // collect the signatures of all bound base methods:
+ 				LinkedList<RoleBaseBinding> rbbList = baseBindings.get(interfaceName);
+				if (rbbList != null) {
+					Iterator<RoleBaseBinding> rbb_it = rbbList.iterator();
+					while (rbb_it.hasNext()) {
+						RoleBaseBinding rbb = rbb_it.next();
+						result.addAll(rbb.getBaseSignatures());
+
+						// System.err.println("inheriting binding: "+rbb);
+				}
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @param methodName
+	 * @param methodSignature
+	 * @param interfaceName
+	 * @return
+	 */
+	public static Collection<MethodBinding> getInterfaceInheritedMethodBindings(
+			String methodName, String methodSignature, String interfaceName) {
+		List<MethodBinding> result = new LinkedList<MethodBinding>();
+		if (boundBaseInterfaces.contains(interfaceName)) {
+			LinkedList<RoleBaseBinding> rbbList = baseBindings.get(interfaceName);
+			if (rbbList != null) {
+				Iterator<RoleBaseBinding> rbb_it = rbbList.iterator();
+				while (rbb_it.hasNext()) {
+					RoleBaseBinding rbb = rbb_it.next();
+					List<MethodBinding> mbs = rbb.getBaseMethodBindings(methodName, methodSignature);
+					if (mbs != null)
+						result.addAll(mbs);
+				}
+			}
+		}
+		return result;
+	}
+	
+	/**
+	 * @param interfaceNames
+	 * @return
+	 */
+	public static boolean containsBoundBaseInterface(String[] interfaceNames) {
+		for (int i = 0; i < interfaceNames.length; i++) {
+			if (boundBaseInterfaces.contains(interfaceNames[i]))
+				return true;
+		}
+		return false;
+	}
+	
+	//	 -----------------------------------------------
+	//   precedence can be set for a list of method bindings:
+	// -----------------------------------------------
+	
+	private static ListValueHashMap<List<String>> precedencePerTeam = new ListValueHashMap<List<String>>();
+	
+	/**
+	 * Add a precedence list for the given team.
+	 * @param precedenceList	the list of binding labels defining their precedence
+	 * @param teamName 		the name of the team for which the precedence list was defined
+	 */
+	public static void addPrecedenceList(List<String> precedenceList, String teamName) {
+		precedencePerTeam.put(teamName, precedenceList);
+	}
+	
+	/**
+	 * Sorts the method binding list according to the given precedence for the team
+	 * @param mbList			the list of 'MethodBinding's to be sorted
+	 * @param teamName	the name of the corresponding team
+	 * @return	the sorted 'MethodBindig' list
+	 */
+	public static List<MethodBinding> sortMethodBindings(List<MethodBinding> mbList, String teamName) {
+		if (mbList.size() < 2)
+			return mbList; // nothing to sort
+		String outermostTeamName;
+		int dollarIdx = teamName.indexOf('$');
+		if (dollarIdx > 0)
+			outermostTeamName = teamName.substring(0, dollarIdx);
+		else outermostTeamName = teamName;
+		
+		List<List<String>> precedenceList = precedencePerTeam.get(outermostTeamName);
+		if (precedenceList==null) {
+			// mbList has to be reduced by removing overridden bindings:
+			return removeOverridden(mbList);
+		}
+		
+		LinkedList<MethodBinding> sortedMethodBindings = new LinkedList<MethodBinding>();
+		Iterator<List<String>> predIt = precedenceList.iterator();
+		
+		while (predIt.hasNext()) {
+			List<String> plainList = predIt.next();
+			Iterator<String> plainIt = plainList.iterator();
+			
+			while (plainIt.hasNext()) {
+				boolean foundOne = false;
+				String label = plainIt.next();
+				Iterator<MethodBinding> mbIter = mbList.iterator();
+				List<MethodBinding> alreadySorted = new LinkedList<MethodBinding>();
+				
+				while (mbIter.hasNext()) {
+					MethodBinding mb = mbIter.next();
+					
+					if (mb.getQualifiedBindingLabel().equals(label)) { // mb exactly fits binding label:
+						alreadySorted.add(mb);
+						if (!foundOne) {
+							sortedMethodBindings.add(mb);
+							foundOne = true;
+						} else checkInheritance(sortedMethodBindings.getLast(), mb); 
+					
+					} else if (mb.inheritsBindingLabel(label, teamName)) { // mb inherits  binding label:
+						alreadySorted.add(mb);
+						if (!foundOne) {
+							sortedMethodBindings.add(mb);
+							foundOne = true;
+						} else {// maybe it is a subtype of the already added?
+							MethodBinding lastAdded = sortedMethodBindings.getLast();
+							if (mb.overridesMethodBinding(lastAdded)) {
+								sortedMethodBindings.set(sortedMethodBindings.size()-1, mb);
+								foundOne = true;
+							} else checkInheritance(sortedMethodBindings.getLast(), mb);
+						}
+					}
+				}
+				if (foundOne) {
+					Iterator<MethodBinding> sortedIter = alreadySorted.iterator();
+					while (sortedIter.hasNext()) {
+						MethodBinding mb = sortedIter.next();
+						mbList.remove(mb);
+					}
+				}
+			}
+		}
+//		if (mbList.size() > 0) {
+//			System.err.println("ERROR: Unsortable method bindings: " + mbList +"!");
+//			 // assumption: all remaining method bindings are overridden! TODO: check assumption!
+//		}
+		return sortedMethodBindings;
+	}
+
+	/**
+	 * Removes overridden method bindings from the given list. Assumes that 
+	 * all bindings in the list are in a sub/super type relationship.
+	 * @param mbList		the method binding list
+	 * @return		the most specific method binding overriding all others
+	 */
+	private static List<MethodBinding> removeOverridden(List<MethodBinding> mbList) {
+		MethodBinding mostSpecificMB = mbList.get(0);
+		Iterator<MethodBinding> mbIter = mbList.iterator();
+		while (mbIter.hasNext()) {
+			MethodBinding mb = mbIter.next();
+			if (mb.overridesMethodBinding(mostSpecificMB)) {
+				mostSpecificMB = mb;
+			} else checkInheritance(mostSpecificMB, mb);
+		}
+		List<MethodBinding> resultList = new LinkedList<MethodBinding>();
+		resultList.add(mostSpecificMB);
+		return resultList;
+	}
+		
+	/**
+	 * Checks if 'subMB' 'inherits' from 'superMB'. Used to check if assumptions 
+	 * about the precedence lists are fulfilled.
+	 *
+	 * @param subMB		the overriding method binding
+	 * @param superMB	the overridden method binding
+	 */
+	private static void checkInheritance(MethodBinding subMB, MethodBinding superMB) {
+		if (! (subMB.equals(superMB) || subMB.overridesMethodBinding(superMB))) {
+			//System.err.println("sub: " + subMB + "\n super: " + superMB);
+			throw new OTREInternalError("Wrong assumption! Broken precedence list possible.");
+		}
+	}
+    
+    // ------------------------------------------
+    // ---------- Logging: ----------------------
+    // ------------------------------------------
+    /** Initialized from property <tt>ot.log</tt>. */
+    static boolean logging = false;
+    /** Initialized from property <tt>otequinox.debug</tt> */
+    static boolean OTEQUINOX_WARN = false;
+    static {
+        if(System.getProperty("ot.log") != null)
+            logging = true;
+        String warnlevel = System.getProperty("otequinox.debug");
+        if (warnlevel != null) {
+        	warnlevel = warnlevel.toUpperCase();
+        	if (warnlevel.startsWith("INFO") || warnlevel.equals("OK"))
+        		OTEQUINOX_WARN = true;
+        }
+    }
+    
+	//	 -----------------------------------------------
+	//   static replace callin bindings have to be stored in the team, special treatment:
+	// -----------------------------------------------
+    	
+	// maps an implemented role method to its base methods: roleMethod -> List[baseMethod] // added by JU
+	private static ListValueHashMap<BaseMethodInfo> staticReplaceBindings = new ListValueHashMap<BaseMethodInfo>();
+	
+	/**
+	 * Adds a base method to its implemented role method (static replace bindings).
+	 * 
+	 * @param roleMethodKey a string structured according team_class_ name.role_class_name.role_method_name.role_method_signature
+	 * @param baseMethodInfo an Object contained base class name, base method name and base method signature
+	 */
+	public static void addStaticReplaceBindingForRoleMethod(String roleMethodKey, BaseMethodInfo baseMethodInfo) {
+		staticReplaceBindings.put(roleMethodKey, baseMethodInfo);
+	}
+	
+	/**
+	 * Returns static method bindings for the given role method
+	 * @param roleMethodKey
+	 * @return
+	 */
+	public static LinkedList<BaseMethodInfo> getStaticReplaceBindingsForRoleMethod(String roleMethodKey) {
+		return staticReplaceBindings.get(roleMethodKey);
+	}
+
+	/**
+	 * @param roleClassName
+	 * @param roleMethodName
+	 * @param roleMethodSignature
+	 * @return
+	 */
+	public static boolean roleMethodHasBinding(String roleClassName, String roleMethodName, String roleMethodSignature) {
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		if (rbb == null) {
+			return false;
+		}
+		return rbb.hasRoleMethodBinding(roleMethodName, roleMethodSignature);
+	}
+	
+	// -----------------------------------------------
+	//  access modifiers of some base classes have to be changed to 'public' (decapsulation)
+	//  the names of these classes are stored in baseClassesForModifierChange 
+	// -----------------------------------------------
+	private static LinkedList<String> baseClassesForModifierChange = new LinkedList<String>();
+	
+	/**
+	 * Adds the given class name to the list of class names intended for decapsulation 
+	 * @param className
+	 */
+	public static void addBaseClassForModifierChange(String className){
+		baseClassesForModifierChange.add(className);
+	}
+	
+	/**
+	 * Checks whether a class name is contained in the list of classes intended for decapsulation
+	 * @param className
+	 * @return
+	 */
+	public static boolean checkBaseClassModifierChange(String className) {
+		Iterator<String> iter = baseClassesForModifierChange.iterator();
+		while(iter.hasNext()) {
+			if(className.equals(iter.next())){
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public static void addBoundSuperclassLink(String sub_name, String super_name) {
+		synchronized (baseBindings) {
+			bases:
+			for (RoleBaseBinding subBinding : baseBindings.getFlattenValues()) {
+				if (subBinding.getBaseClassName().equals(sub_name)) {
+					for (RoleBaseBinding superBinding : baseBindings.getFlattenValues()) {
+						if (subBinding == superBinding) continue;
+						if (superBinding.getBaseClassName().equals(super_name)) {
+							subBinding.getBaseClass().setSuper(superBinding.getBaseClass());
+							break bases;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/** Either retrieve an existing BoundClass for `className' are create a new one. 
+     *  If an existing one is used it is updated for the new adapting team.
+     */
+	public static BoundClass getBoundBaseClass(String className, String teamClassName) {
+		for (RoleBaseBinding subBinding : baseBindings.getFlattenValues()) {
+			if (subBinding.getBaseClassName().equals(className)) { 
+				BoundClass baseClass = subBinding.getBaseClass();
+				baseClass.addAdaptingTeam(teamClassName);
+				return baseClass;
+			}
+		}
+		return new BoundClass(className, teamClassName);
+	}
+
+	// ==== HELPERS FOR RE-ENTRANCE SAFETY: ====
+
+	private static Iterator<String> getBaseBindingsKeyIterator() {
+		synchronized (baseBindings) {
+			ArrayList<String> list = new ArrayList<String>();
+	    	list.addAll(baseBindings.keySet());
+	    	Iterator<String> it = list.iterator();
+			return it;
+		}
+	}
+
+	private static Iterator<Entry<String, LinkedList<RoleBaseBinding>>> getBaseBindingsCloneIterator() {
+		synchronized (baseBindings) {
+			ArrayList<Entry<String, LinkedList<RoleBaseBinding>>> list = new ArrayList<Entry<String,LinkedList<RoleBaseBinding>>>();
+			list.addAll(baseBindings.entrySet());
+			Iterator<Entry<String, LinkedList<RoleBaseBinding>>> it = list.iterator();
+			return it;
+		}
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java
new file mode 100644
index 0000000..7282185
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/DebugUtil.java
@@ -0,0 +1,155 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2003-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: DebugUtil.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.util;
+
+import de.fub.bytecode.generic.*;
+import de.fub.bytecode.Constants;
+import java.util.Enumeration;
+
+import org.eclipse.objectteams.otre.OTConstants;
+
+/**
+ * @author Stephan Herrmann
+ */
+@SuppressWarnings("nls")
+public class DebugUtil {
+
+	// -----------------------------------------
+	// -------- Development utilities  ---------
+	// -----------------------------------------
+
+    /**
+    *  Creates an the instructions necessary to "System.out.println" 
+	*  the given string.
+    *
+    *  @param cpg     the constant pool of the class where this instructions 
+	*                 will be inserted
+    *  @param string  the String to be printed
+    *  @return        an InstructionList containing the necessary instructions
+    */
+	public static InstructionList createPrintln(ConstantPoolGen cpg, 
+												InstructionFactory factory,
+												String string) 
+	{
+        InstructionList il  = new InstructionList();
+        ObjectType p_stream = new ObjectType("java.io.PrintStream");
+
+        il.append(factory.createFieldAccess("java.lang.System", "out", 
+											p_stream,
+											Constants.GETSTATIC));
+        il.append(new PUSH(cpg, string + "\n"));
+        il.append(factory.createInvoke("java.io.PrintStream", "print", 
+									   Type.VOID, 
+									   new Type[] { Type.STRING }, 
+									   Constants.INVOKEVIRTUAL));
+        return il;
+    }
+
+	/**
+	 * Create a <tt>System.out.println</tt> call for an <tt>Object</tt>
+	 * argument. The argument is assumed to be on the stack and will not
+	 * be consumed.
+	 */
+    public static InstructionList createPrintlnObj(InstructionFactory factory) {
+        InstructionList il  = new InstructionList();
+        ObjectType p_stream = new ObjectType("java.io.PrintStream");
+
+		il.append(new DUP());
+        il.append(factory.createFieldAccess("java.lang.System", "out", 
+											p_stream,
+											Constants.GETSTATIC));
+		il.append(new SWAP());
+        il.append(factory.createInvoke("java.io.PrintStream", "print", 
+									   Type.VOID, 
+									   new Type[] { OTConstants.object }, 
+									   Constants.INVOKEVIRTUAL));
+        return il;
+    }
+
+	/**
+	 * Create a <tt>System.out.println</tt> call for an <tt>Exception</tt>
+	 * argument. The argument is assumed to be on the stack and _will_
+	 * be consumed. This effect is however only performed, if 
+	 * the property ot.log.lift is set.
+	 */
+    public static InstructionList createReportExc(InstructionFactory factory) {
+        InstructionList il  = new InstructionList();
+		if (System.getProperty("ot.log.lift") == null) {
+			il.append(new POP());
+		} else {
+			ObjectType p_stream = new ObjectType("java.io.PrintStream");
+			
+			il.append(factory.createFieldAccess("java.lang.System", "out", 
+												p_stream,
+												Constants.GETSTATIC));
+			il.append(new SWAP());
+			il.append(factory.createInvoke("java.io.PrintStream", "println", 
+										   Type.VOID, 
+										   new Type[] { OTConstants.object }, 
+										   Constants.INVOKEVIRTUAL));
+		}
+        return il;
+    }
+
+	/**
+	 * Create a <tt>System.out.println</tt> call for an <tt>int</tt>
+	 * argument. The argument is assumed to be on the stack and will not
+	 * be consumed.
+	 */
+    public static InstructionList createPrintlnInt(InstructionFactory factory) {
+        InstructionList il  = new InstructionList();
+        ObjectType p_stream = new ObjectType("java.io.PrintStream");
+
+		il.append(new DUP());
+        il.append(factory.createFieldAccess("java.lang.System", "out", 
+											p_stream,
+											Constants.GETSTATIC));
+		il.append(new SWAP());
+        il.append(factory.createInvoke("java.io.PrintStream", "print", 
+									   Type.VOID, 
+									   new Type[] { Type.INT }, 
+									   Constants.INVOKEVIRTUAL));
+        return il;
+    }
+    
+    public static InstructionList createPrintlnBool(ConstantPoolGen cp) {
+    	InstructionList il= new InstructionList();
+    	int             out     = cp.addFieldref("java.lang.System", "out",
+    											 "Ljava/io/PrintStream;");
+    	int             println = cp.addMethodref("java.io.PrintStream", "println",
+    											  "(Z)V");
+    	il.append(new DUP());
+    	il.append(new GETSTATIC(out));
+    	il.append(new SWAP());
+    	il.append(new INVOKEVIRTUAL(println));
+    	return il;
+    }
+
+    @SuppressWarnings("unchecked")
+	public static void printIL (InstructionList il, ConstantPoolGen cpg) {
+        int off = 0;
+        Enumeration en =  il.elements();
+        while(en.hasMoreElements()) {
+            Instruction i = ((InstructionHandle)en.nextElement()).getInstruction();
+            off += i.produceStack(cpg);
+            off -= i.consumeStack(cpg);
+            System.out.print(off);
+            System.out.println("  = "+i);
+        }
+    }
+
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java
new file mode 100644
index 0000000..30a3dd0
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java
@@ -0,0 +1,53 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: FieldDescriptor.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.util;
+
+/**
+ * @author resix
+ */
+public class FieldDescriptor {
+	private String fieldName;
+	private String fieldSignature;
+	private boolean isStaticField;
+
+	public FieldDescriptor(String name, String signature, boolean is_static) {
+		fieldName = name;
+		fieldSignature = signature;
+		isStaticField = is_static;
+	}
+	
+	/**
+	 * @return Returns the fieldName.
+	 */
+	public String getFieldName() {
+		return fieldName;
+	}
+	
+	/**
+	 * @return Returns the fieldSignature.
+	 */
+	public String getFieldSignature() {
+		return fieldSignature;
+	}
+	
+	/**
+	 * @return Returns the isStaticField.
+	 */
+	public boolean isStaticField() {
+		return isStaticField;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java
new file mode 100644
index 0000000..665ee5f
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java
@@ -0,0 +1,103 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: ListValueHashMap.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.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * @author resix
+ */
+public class ListValueHashMap<ValueType> {
+	private HashMap<String, LinkedList<ValueType>> hashMap = new HashMap<String, LinkedList<ValueType>>();
+	//redundant structure for faster access:
+	private LinkedList<ValueType> flattenValues = new  LinkedList<ValueType>();
+
+	/**
+	 * @param key
+	 * @param value
+	 */
+	public void put(String key, ValueType value) {
+		LinkedList<ValueType> list;
+		if (!hashMap.containsKey(key)) {
+			list = new LinkedList<ValueType>();
+		} else {
+			list = hashMap.get(key);
+		}
+		list.add(value);
+		hashMap.put(key, list);
+		flattenValues.add(value);
+	}
+
+	/**
+	 * @return
+	 */
+	public List<ValueType> getFlattenValues() {
+		return flattenValues;
+	}
+	
+	/**
+	 * @param key
+	 * @return
+	 */
+	public LinkedList<ValueType> get(String key) {
+		if (!hashMap.containsKey(key))  {
+			return null;
+		}
+		return hashMap.get(key);
+	}
+	
+	public boolean containsKey(Object o) {
+		return hashMap.containsKey(o);	
+	}
+
+	public Set<String> keySet() {
+		return hashMap.keySet();
+	}
+
+	public Set<Entry<String, LinkedList<ValueType>>>  entrySet() {
+		return hashMap.entrySet();
+	}
+	
+	public int size() {
+		return hashMap.size();
+	}
+	
+	public String toString() {
+		StringBuilder result = new StringBuilder(32);
+		Iterator it = hashMap.entrySet().iterator();
+		while (it.hasNext()) {
+			Entry entry = (Entry) it.next();
+			result.append(entry.getKey());
+            result.append(": ");
+            result.append(entry.getValue().toString());
+            result.append("\n");
+		}
+		if (result.length() == 0)
+			return super.toString();
+		return result.toString();
+	}
+
+	public Collection<LinkedList<ValueType>> valueSet() {
+		return hashMap.values();
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java
new file mode 100644
index 0000000..ecc5436
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/MethodBinding.java
@@ -0,0 +1,395 @@
+/**********************************************************************
+ * 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: MethodBinding.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.util;
+
+import org.eclipse.objectteams.otre.OTConstants;
+
+/**
+ * @version $Id: MethodBinding.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author Christine Hundt
+ */
+public class MethodBinding {
+
+	private String bindingFileName;
+	private int bindingLineNumber;
+	private int bindingLineOffset;
+	
+	private String bindingLabel;
+	
+	private BoundMethod baseMethod;
+	private BoundMethod roleMethod;
+
+	private boolean isStaticBaseMethod;
+	private boolean isStaticRoleMethod;
+	private boolean covariantBaseReturn;
+	
+	private int translationFlags;
+	
+   	private String wrapperName;
+	private String wrapperSignature;
+
+   	private String modifier;
+   	private String liftMethodName;
+   	private String liftMethodSignature;
+    
+    private String roleClassName;
+    
+    // back reference for the class binding containing this method binding.
+    private RoleBaseBinding classBinding;
+
+    /**
+     * 
+     */
+    public MethodBinding() {}
+
+    /**
+     * @param bindingFileName
+     * @param bindingLineNumber
+     * @param bindingLineOffest
+     * @param bindingLabel
+     * @param roleMethodName
+     * @param roleMethodSignature
+     * @param isStaticRoleMethod
+     * @param wrapperName
+     * @param wrapperSignature
+     * @param modifier
+     * @param baseMethodName
+     * @param baseMethodSignature
+     * @param isStaticBaseMethod
+     * @param baseIsCallin
+     * @param liftMethodName
+     * @param liftMethodSignature
+     * @param classBinding
+     */
+    public MethodBinding(
+            String bindingFileName, int bindingLineNumber, int bindingLineOffest,
+			String bindingLabel, String roleMethodName, String roleMethodSignature, boolean isStaticRoleMethod, 
+			String wrapperName, String wrapperSignature, String modifier, 
+			String baseMethodName, String baseMethodSignature, 
+			boolean isStaticBaseMethod,	boolean baseIsCallin, boolean covariantBaseReturn, 
+			int translationFlags, 
+			String liftMethodName, String liftMethodSignature, RoleBaseBinding classBinding) 
+	{
+    	this.bindingFileName = bindingFileName;
+    	this.bindingLineNumber = bindingLineNumber;
+    	this.bindingLineOffset = bindingLineOffest;
+    	
+    	this.bindingLabel = bindingLabel;
+		roleMethod = new BoundMethod(roleMethodName, roleMethodSignature, false, this);
+		baseMethod = new BoundMethod(baseMethodName, baseMethodSignature, baseIsCallin, this);
+		// BoundMethod object for one method is not unique!
+		// but if it would be unique the 'binding' link would not be unique
+		this.isStaticRoleMethod  = isStaticRoleMethod;
+		this.isStaticBaseMethod  = isStaticBaseMethod;
+		this.covariantBaseReturn = covariantBaseReturn;
+		this.translationFlags    = translationFlags;
+        this.wrapperName         = wrapperName;
+        this.wrapperSignature    = wrapperSignature;
+        this.modifier            = modifier;
+        this.liftMethodName      = liftMethodName;
+        this.liftMethodSignature = liftMethodSignature;
+        this.classBinding        = classBinding;
+        this.roleClassName       = classBinding.getRoleClassName();
+    }
+
+    /**
+     * @return
+     */
+    public String getRoleClassName() {
+		return roleClassName;
+    }
+
+    /**
+     * @return
+     */
+    public String getBindingFileName() {
+		return bindingFileName;
+	}
+	
+	/**
+	 * @return
+	 */
+	public int getBindingLineNumber() {
+		return bindingLineNumber;
+	}
+	
+	/**
+	 * @return
+	 */
+	public int getBindingLineOffset() {
+		return bindingLineOffset;
+	}
+    
+    /**
+     * @return
+     */
+    public String getBindingLabel() {
+    	return bindingLabel;
+    }
+    
+    /**
+     * @return
+     */
+    public String getQualifiedBindingLabel() {
+    	String result = roleClassName;
+    	// remove the outermost team (use the '$' to distinguish pack1.Team1$Role from Team1$__OT__Team2$Role):
+    	result = result.substring(result.indexOf('$') + 1);
+    	// replace "$" by "." in the role class name:
+    	result = result.replace('$', '.');
+    	// remove  "__OT__" prefixes in role class names:
+    	result = result.replace(OTConstants.OTDT_PREFIX, ""); //$NON-NLS-1$
+    	// add the binding label and return:    	
+    	return result + '.' + bindingLabel;
+    }
+    
+    /**
+     * @return
+     */
+    public String getRoleMethodName() {
+		return roleMethod.getName();
+    }
+    
+    /**
+     * @return
+     */
+    public String getRoleMethodSignature() {
+		return roleMethod.getSignature();
+    }
+	
+	/**
+	 * @return
+	 */
+	public String getWrapperName() {
+		return wrapperName;
+	}
+	
+	/**
+	 * @return
+	 */
+	public String getWrapperSignature() {
+		return wrapperSignature;
+	}
+
+    /**
+     * @return
+     */
+    public String getBaseClassName() {
+		return classBinding.getBaseClassName();
+    }
+
+    /**
+     * @return
+     */
+    public String getBaseMethodName() {
+		return baseMethod.getName();
+    }
+
+    /**
+     * @return
+     */
+    public String getBaseMethodSignature() {
+		return baseMethod.getSignature();
+    }
+
+    /**
+     * @return
+     */    
+    public boolean baseMethodIsCallin() {
+    	return baseMethod.getIsCallin();
+    }
+ 
+    /**
+     * @return
+     */    
+    public String getModifier() {
+        return modifier;
+    }
+	
+    /**
+     * @return
+     */
+    public boolean isReplace() {
+		return modifier.equals("replace");
+	}
+	
+	/**
+	 * @return
+	 */
+	public boolean isAfter() {
+		return modifier.equals("after");
+	}
+	
+	/**
+	 * @return
+	 */
+	public boolean isBefore() {
+		return modifier.equals("before");
+	}
+	
+	/**
+	 * @return Returns the liftMethodName.
+	 */
+	public String getLiftMethodName() {
+		return liftMethodName;
+	}
+	
+	/**
+	 * @return Returns the liftMethodSignature.
+	 */
+	public String getLiftMethodSignature() {
+		return liftMethodSignature;
+	}
+	
+	/**
+	 * @return Returns the corresponding class binding.
+	 */
+	public RoleBaseBinding getClassBinding() {
+		return classBinding;
+	}
+	
+	/**
+	 * Returns the most super bound base class of the base class belonging to
+	 * this MethodBinding. Note: only consider base classes bound by roles of
+	 * the corresponding team!
+	 * 
+	 * @return the most super bound base class
+	 */
+	public String getRootBoundBase() {
+		BoundClass bc = classBinding.getRoleClass();
+		while (bc.getSuper() != null && CallinBindingManager.isBoundRoleClass(bc.getSuper().getName()) ) {
+            bc = bc.getSuper();
+        }
+		RoleBaseBinding rbb = CallinBindingManager.getRoleBaseBinding(bc.getName());
+		return rbb.getBaseClassName();
+	}
+	
+	/**
+	 * Returns the name of the team surrounding the role class of this binding.
+	 * 
+	 * @return the name of the corresponding team
+	 */
+	public String getTeamClassName() {
+		int dollarIndex = roleClassName.lastIndexOf('$');
+		// return everything before the last '$', because for nested teams there are more than one:
+        return roleClassName.substring(0, dollarIndex);
+	}
+	
+	/**
+	 * @param anotherMB
+	 * @return
+	 */
+	public boolean overridesMethodBinding(MethodBinding anotherMB) {
+		if (anotherMB == null)
+			return false;
+		if (!bindingLabel.equals(anotherMB.getBindingLabel()))
+			return false;
+		return classBinding.getRoleClass().isSubClassOf(anotherMB.getClassBinding().getRoleClassName());
+	}
+	
+	/**
+	 * @param bindingLabel
+	 * @param teamName
+	 * @return
+	 */
+	public boolean inheritsBindingLabel(String bindingLabel, String teamName) {
+		String prefix = teamName + "$__OT__";
+		int dotIndex = bindingLabel.lastIndexOf('.');
+		String classOfLabel = prefix + bindingLabel.substring(0, dotIndex);
+		if (!bindingLabel.substring(dotIndex + 1).equals(this.bindingLabel))
+			return false;
+		
+		if (classBinding.getRoleClass().isSubClassOf(classOfLabel))
+			return true;
+		return false;
+	}
+
+    /**
+     * @param mb
+     * @return
+     */
+    public boolean equals(MethodBinding mb) {
+        return roleMethod.getName().equals(mb.getRoleMethodName())
+			&& roleMethod.getSignature().equals(mb.getRoleMethodSignature())
+			&& classBinding.getBaseClassName().equals(mb.getBaseClassName())
+			&& baseMethod.getName().equals(mb.getBaseMethodName())
+			&& baseMethod.getSignature().equals(mb.getBaseMethodSignature())
+			&& modifier.equals(mb.getModifier());
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        StringBuilder result = new StringBuilder(32);
+        result.append("\t");
+        result.append(getQualifiedBindingLabel());
+        result.append(": ");
+        result.append(roleMethod.getName());
+        result.append(roleMethod.getSignature());
+        result.append(" <-> ");
+        result.append(modifier);
+        result.append(" ");
+        result.append(baseMethod.getName());
+        result.append(baseMethod.getSignature());
+        if (this.covariantBaseReturn)
+        	result.append('+');
+        return result.toString();
+    }
+
+	/**
+	 * @return
+	 */
+	public boolean hasStaticRoleMethod() {
+		return isStaticRoleMethod;
+	}
+	
+    /**
+     * @return
+     */
+	public boolean hasStaticBaseMethod() {
+		return isStaticBaseMethod;
+	}
+
+	public int getTranslationFlags() {
+		return this.translationFlags;
+	}
+
+	/** For base methods provide a key without the trailing return type to cater for covariance. */ 
+	static String getBaseMethodKey(String baseMethodName, String baseMethodSignature) {
+		int pos= baseMethodSignature.lastIndexOf(')');
+		String baseMethodKey = baseMethodName + '.' + baseMethodSignature.substring(0, pos+1);
+		return baseMethodKey;
+	}
+
+	/** 
+	 * Is the method specified by mName and mSig a match for this method binding?
+	 * @param mName method name
+	 * @param mSig full method signature
+	 * @param strict if true covariance is not supported
+	 */
+	public boolean matchesMethod(String mName, String mSig, boolean strict) {
+		String baseMethodName = getBaseMethodName();
+		String baseMethodSignature = getBaseMethodSignature();
+		if (this.covariantBaseReturn && !strict) {
+			return getBaseMethodKey(mName, mSig).equals(
+				   getBaseMethodKey(baseMethodName, baseMethodSignature));
+		} else {
+			return mName.equals(baseMethodName) 
+				&& mSig.equals(baseMethodSignature);
+		}
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java
new file mode 100644
index 0000000..172c0ae
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java
@@ -0,0 +1,228 @@
+/**********************************************************************
+ * 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: RoleBaseBinding.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.util;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @version $Id: RoleBaseBinding.java 23408 2010-02-03 18:07:35Z stephan $
+ * @author Christine Hundt
+ */
+public class RoleBaseBinding {
+
+	private BoundClass roleClass;
+	private BoundClass baseClass;
+
+	private ListValueHashMap<MethodBinding> roleMethodBindings = new ListValueHashMap<MethodBinding>();
+	private ListValueHashMap<MethodBinding> baseMethodBindings = new ListValueHashMap<MethodBinding>();
+	
+    /**
+     * 
+     */
+    public RoleBaseBinding() {
+    }
+
+    /**
+     * @param _roleClassName
+     * @param _baseClassName
+     * @param teamClassName
+     */
+    public RoleBaseBinding(String _roleClassName, String _baseClassName, String teamClassName) {
+    	roleClass = new BoundClass(_roleClassName, teamClassName);
+    	baseClass = CallinBindingManager.getBoundBaseClass(_baseClassName, teamClassName);
+    }
+
+    /**
+     * @param bindingFileName
+     * @param bindingLineNumber
+     * @param bindingLineOffset
+     * @param bindingLabel
+     * @param roleMethodName
+     * @param roleMethodSignature
+     * @param isStaticRoleMethod
+     * @param wrapperName
+     * @param wrapperSignature
+     * @param modifier
+     * @param baseMethodName
+     * @param baseMethodSignature
+     * @param isStaticBaseMethod
+     * @param baseIsCallin
+     * @param translationFlags
+     * @param liftMethodName
+     * @param liftMethodSignature
+     */
+    public void addMethodBinding(
+            String bindingFileName, int bindingLineNumber, int bindingLineOffset,
+			String bindingLabel, String roleMethodName, String roleMethodSignature,
+			boolean isStaticRoleMethod, String wrapperName, String wrapperSignature, String modifier, 
+			String baseMethodName, String baseMethodSignature, 
+			boolean isStaticBaseMethod, boolean baseIsCallin, boolean covariantBaseReturn,
+			int translationFlags, String liftMethodName, String liftMethodSignature)
+	{
+		MethodBinding mb = new MethodBinding(bindingFileName, bindingLineNumber, bindingLineOffset,
+																		   bindingLabel, roleMethodName, roleMethodSignature, isStaticRoleMethod,
+							   											   wrapperName, wrapperSignature, modifier,
+							   											   baseMethodName, baseMethodSignature, 
+							   											   isStaticBaseMethod, baseIsCallin, covariantBaseReturn, 
+							   											   translationFlags,
+																		   liftMethodName,
+							   											   liftMethodSignature, this);
+		// TODO: check, if the key has to include the 'binding_label'
+		String baseMethodKey = MethodBinding.getBaseMethodKey(baseMethodName, baseMethodSignature);
+		String roleMethodKey = roleMethodName + '.' + roleMethodSignature;
+		roleMethodBindings.put(roleMethodKey, mb);
+		baseMethodBindings.put(baseMethodKey, mb);
+    }
+
+	/**
+	 * @return
+	 */
+	public List<MethodBinding> getBaseMethodBindings() {
+		return baseMethodBindings.getFlattenValues();
+	}
+	
+	/**
+	 * @param baseMethodName
+	 * @param baseMethodSignature
+	 * @return
+	 */
+	public List<MethodBinding> getBaseMethodBindings(String baseMethodName, String baseMethodSignature) {
+		String baseMethodKey = MethodBinding.getBaseMethodKey(baseMethodName, baseMethodSignature);
+		return baseMethodBindings.get(baseMethodKey);
+	}
+
+	/**
+	 * @return
+	 */
+	public List<MethodBinding> getRoleMethodBindings() {
+		return roleMethodBindings.getFlattenValues();
+	}
+	
+	/**
+	 * @param roleMethodName
+	 * @param roleMethodSignature
+	 * @return
+	 */
+	public List<MethodBinding> getRoleMethodBindings(String roleMethodName, String roleMethodSignature) {
+		String roleMethodKey = roleMethodName + '.' + roleMethodSignature;
+		return roleMethodBindings.get(roleMethodKey);
+	}
+	
+	/**
+	 * @param roleMethodName
+	 * @param roleMethodSignature
+	 * @return
+	 */
+	public boolean hasRoleMethodBinding(String roleMethodName, String roleMethodSignature) {
+		String signatureWithoutReturnType = roleMethodSignature.substring(0, roleMethodSignature.lastIndexOf(')') + 1);
+		Set<String> bindingKeys = roleMethodBindings.keySet();
+		Iterator<String> it = bindingKeys.iterator();
+		while (it.hasNext()) {
+			String key = it.next();
+			String keyWithoutReturnType = key.substring(0, key.lastIndexOf(')') + 1);
+			if (keyWithoutReturnType.equals(roleMethodName + '.'
+					+ signatureWithoutReturnType))
+				return true;
+		}
+		return false;
+	}
+	
+	public Set<String> getRoleMethodSignatures() {
+		return roleMethodBindings.keySet();	
+	}
+	
+	/**
+	 * @return
+	 */
+	public BoundClass getRoleClass() {
+		return roleClass;
+	}
+	
+	/**
+	 * @return
+	 */
+	public BoundClass getBaseClass() {
+			return baseClass;
+		}
+	
+    /**
+     * @return
+     */
+    public String getRoleClassName() {
+		return roleClass.getName();
+	}
+
+	/**
+	 * @return
+	 */
+	public String getBaseClassName() {
+		return baseClass.getName();
+	}
+
+	/**
+	 * Collect all base method signatures for this role-base pair.
+	 * @result List <String[] {name, signature}>
+	 */
+	public List<String[]> getBaseSignatures () {
+		List<String[]> result = new LinkedList<String[]>();
+		List<MethodBinding> baseMethodBindingList = getBaseMethodBindings();
+		Iterator<MethodBinding> it = baseMethodBindingList.iterator();
+		while (it.hasNext()) {
+			MethodBinding mb = it.next();
+			result.add(new String [] {
+				mb.getBaseMethodName(),
+				mb.getBaseMethodSignature()
+			});
+		}
+        return result;
+	}
+
+    /**
+     * @param rbb
+     * @return
+     */
+    public boolean equals(RoleBaseBinding rbb) {
+        return roleClass.getName().equals(rbb.getRoleClassName())
+			&& baseClass.getName().equals(rbb.getBaseClassName());
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        StringBuilder out = new StringBuilder(64);
+        out.append(roleClass.getName());
+        out.append(" <-> ");
+        out.append(baseClass.getName());
+	    out.append("\nmethod bindings:\n");
+	    List mbsList = getBaseMethodBindings();
+	    Iterator it = mbsList.iterator();
+	    while (it.hasNext()) {
+			MethodBinding mb = (MethodBinding)it.next();
+			out.append("\n");
+            out.append(mb.getBaseMethodName());
+            out.append(".");
+            out.append(mb.getBaseMethodSignature());
+            out.append(":");
+            out.append(mb.toString());
+	    }
+        return out.toString();
+    }
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java
new file mode 100644
index 0000000..02b9c04
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2008 Technical University Berlin, 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: SuperMethodDescriptor.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * Technical University Berlin - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre.util;
+
+/** Representation of a base-super method call, requiring a special access method. */
+public class SuperMethodDescriptor {
+	public String methodName;
+	public String declaringClass;
+	public String superClass;
+	public String signature;
+	public SuperMethodDescriptor(String methodName, String declaringClass,
+			String superClass, String signature) {
+		super();
+		this.methodName = methodName;
+		this.declaringClass = declaringClass;
+		this.superClass = superClass;
+		this.signature = signature;
+	}
+}
diff --git a/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java
new file mode 100644
index 0000000..100a0a1
--- /dev/null
+++ b/OTRE/OTRE/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java
@@ -0,0 +1,69 @@
+/**********************************************************************
+ * 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: TeamIdDispenser.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.util;
+import java.util.*;
+
+public class TeamIdDispenser {
+
+	private static Map<ClassLoader, TeamIdDispenser> instances = new HashMap<ClassLoader, TeamIdDispenser>();
+    private static TeamIdDispenser defaultInstance = new TeamIdDispenser();
+    
+    static int lastDispensedId = 0;
+    private static HashMap<String, Integer> teamIDs = new HashMap<String, Integer>();
+
+//    @SuppressWarnings("unchecked")
+	private static int produceNextTeamId(String team_name) {
+        lastDispensedId++;
+        Integer teamId = Integer.valueOf(lastDispensedId);
+        teamIDs.put(team_name, teamId);
+        return lastDispensedId;
+    }
+
+    public static int getTeamId(String class_name) {
+        Integer teamId = teamIDs.get(class_name);
+        if (teamId != null)
+        	// the team <class_name> already has a team-id assigned
+        	return teamId.intValue();
+		else return produceNextTeamId(class_name);
+    }
+    
+    // Data shared among different transformers of the same class loader:
+    // REFACTOR: move the following to a better place:
+    private ArrayList<String> clinitAddedClasses = new ArrayList<String>();
+    public static boolean clinitAdded(String class_name, ClassLoader loader) {
+    	TeamIdDispenser instance = getInstanceForLoader(loader);
+    	if (instance.clinitAddedClasses.contains(class_name))
+    		return true;
+		
+    	instance.clinitAddedClasses.add(class_name);
+		return false;	
+    }
+    
+	/**
+	 * Since actual data are stored in an instance, static methods need to retrieve the appropriate
+     * instance regarding the given class loader.
+	 */
+	private static TeamIdDispenser getInstanceForLoader(ClassLoader loader) {
+		if (loader == null)
+			return defaultInstance;
+		
+		TeamIdDispenser instance = instances.get(loader);
+		if (instance == null)
+			instances.put(loader, instance = new TeamIdDispenser());
+		return instance;
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/DoublyWeakHashMap.java b/OTRE/OTRE/src/org/objectteams/DoublyWeakHashMap.java
new file mode 100644
index 0000000..4b72f1e
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/DoublyWeakHashMap.java
@@ -0,0 +1,96 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2010 Stephan Herrmann.
+ * 
+ * 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$
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.objectteams;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * This class defines hash maps where both key and value are weak references.
+ * It is implemented by delegating to a WeakHashMap and additionally
+ * wrapping the value in a WeakReference.
+ * 
+ * @author stephan
+ * @since 0.7.0
+ * @param <K>
+ * @param <V>
+ */
+public class DoublyWeakHashMap<K,V> implements Map<K,V> {
+
+	private WeakHashMap<K, WeakReference<V>> map;
+	
+	public DoublyWeakHashMap() {
+		this.map = new WeakHashMap<K, WeakReference<V>>();
+	}
+	public int size() {
+		return this.map.size();
+	}
+
+	public boolean isEmpty() {
+		return this.map.isEmpty();
+	}
+
+	public boolean containsKey(Object key) {
+		return this.map.containsKey(key);
+	}
+
+	public boolean containsValue(Object value) {
+		return this.map.containsValue(value);
+	}
+
+	public V get(Object key) {
+		return this.map.get(key).get();
+	}
+
+	public V put(K key, V value) {
+		this.map.put(key, new WeakReference<V>(value));
+		return value;
+	}
+
+	public V remove(Object key) {
+		WeakReference<V> value = this.map.remove(key);
+		return (value == null) ? null : value.get();
+	}
+
+	public void putAll(Map<? extends K, ? extends V> t) {
+		for (Entry<? extends K, ? extends V> entry : t.entrySet())
+			this.map.put(entry.getKey(), new WeakReference<V>(entry.getValue()));
+	}
+
+	public void clear() {
+		this.map.clear();
+	}
+
+	public Set<K> keySet() {
+		return this.map.keySet();
+	}
+
+	public Collection<V> values() {
+		ArrayList<V> result = new ArrayList<V>(this.map.size());
+		for (WeakReference<V> valRef : this.map.values())
+			result.add(valRef.get());
+		return result;
+	}
+
+	public Set<java.util.Map.Entry<K, V>> entrySet() {
+		throw new UnsupportedFeatureException("Method entrySet is not implemented for DoublyWeakHashMap");
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/DuplicateRoleException.java b/OTRE/OTRE/src/org/objectteams/DuplicateRoleException.java
new file mode 100644
index 0000000..ae3e851
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/DuplicateRoleException.java
@@ -0,0 +1,48 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: DuplicateRoleException.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.objectteams;
+
+/**
+ * Signal a violation of OTJLD 2.4.1(c).
+ * Also Team.getRole(Object) may throw a DuplicateRoleException if
+ * more than one role is found for the given base object
+ * (in that case those roles are found in different role-caches).
+ * 
+ * 
+ * @author stephan
+ * @version $Id: DuplicateRoleException.java 23408 2010-02-03 18:07:35Z stephan $
+ */
+public class DuplicateRoleException extends RuntimeException {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * @param message
+	 */
+	public DuplicateRoleException(String roleClassName) {
+		super("Failed to create a role instance of type "+roleClassName+"\n"+
+			  "A role for the given base object already exists (OTJLD 2.4.1(c)).");
+	}
+	
+	public DuplicateRoleException(String roleName1, String roleName2) {
+		super("Ambiguous role instances: found a role in hierarchies "+
+				roleName1+" and "+roleName2);
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/IBaseMigratable.java b/OTRE/OTRE/src/org/objectteams/IBaseMigratable.java
new file mode 100644
index 0000000..edc9202
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/IBaseMigratable.java
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2008 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: IBaseMigratable.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.objectteams;
+
+/**
+ * Marker interface: if a role declares to implement this interface
+ * the compiler will generate the method defined herein, and prepare
+ * the role so that the migration will indeed be possible.
+ * 
+ * @author stephan
+ * @since 1.2.5
+ */
+public interface IBaseMigratable {
+	/**
+	 * Migrate the current role to the otherBase.
+	 * 
+	 * @param otherBase new base that this role should adapt, must
+	 *        be of a valid base type for the current role.
+	 */
+	<B> void migrateToBase(B otherBase);
+}
diff --git a/OTRE/OTRE/src/org/objectteams/IBoundBase.java b/OTRE/OTRE/src/org/objectteams/IBoundBase.java
new file mode 100644
index 0000000..9f196bf
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/IBoundBase.java
@@ -0,0 +1,28 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2007-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: IBoundBase.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.objectteams;
+
+/**
+ * Super type for all bound base classes. Purely internal class, not intended for client use.
+ * @author Stephan Herrmann
+ */
+public interface IBoundBase {
+	/** Method to be used by generated code, only (lifting constructor). */
+	void _OT$addRole(Object aRole);
+	/** Method to be used by generated code, only (unregisterRole()). */
+	void _OT$removeRole(Object aRole);
+}
\ No newline at end of file
diff --git a/OTRE/OTRE/src/org/objectteams/IConfined.java b/OTRE/OTRE/src/org/objectteams/IConfined.java
new file mode 100644
index 0000000..8ead4b4
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/IConfined.java
@@ -0,0 +1,24 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004 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: IConfined.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.objectteams;
+
+/** 
+ * Special interface that does not extend Object
+ * 
+ * @author stephan
+ */
+public interface IConfined {}
\ No newline at end of file
diff --git a/OTRE/OTRE/src/org/objectteams/ILiftingParticipant.java b/OTRE/OTRE/src/org/objectteams/ILiftingParticipant.java
new file mode 100644
index 0000000..408d087
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/ILiftingParticipant.java
@@ -0,0 +1,40 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2009 Stephan Herrmann
+ *  
+ * 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: ILiftingParticipant.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.objectteams;
+
+/**
+ * A lifting participant hooks into the lifting process.
+ * 
+ * @author stephan
+ * @since 1.3.1
+ */
+public interface ILiftingParticipant {
+	/**
+	 * This method is called when lifting does not find a suitable role within the
+	 * team's internal role cache. If this method returns a non-null value,
+	 * this value is considered by the runtime as being the desired role 
+	 * (i.e., it must be castable to that role type), and no new role is created. 
+	 * If this method returns null, lifting proceeds as normal, i.e., 
+	 * a fresh role is created using the default lifting constructor.
+	 * 
+	 * @param teamInstance
+	 * @param baseInstance
+	 * @param roleClassName
+	 * @return either null or an instance of the class specified by roleClassName
+	 */
+	Object createRole(ITeam teamInstance, Object baseInstance, String roleClassName);
+}
diff --git a/OTRE/OTRE/src/org/objectteams/ITeam.java b/OTRE/OTRE/src/org/objectteams/ITeam.java
new file mode 100644
index 0000000..84b1cd0
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/ITeam.java
@@ -0,0 +1,204 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2010 Stephan Herrmann.
+ * 
+ * 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: ITeam.java 23408 2010-02-03 18:07:35Z stephan $
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 		Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.objectteams;
+
+/**
+ * Public interface of all team classes.
+ */
+public interface ITeam {
+	
+    /**
+     *  Interface for all role classes that should allow explicit lowering.
+     *  The interface provides a phantom method <pre>&lt;B&gt; B lower()</pre>
+     *  where B is the bound base class of the implementing role class.
+     *  There is no need to implement the method lower, since this is done by the compiler.
+     */
+    public interface ILowerable {
+		// internal method needed for cast and instanceof
+    	ITeam _OT$getTeam();
+    }
+
+	/**
+	 *  This role interface has no properties not even those of java.lang.Object.
+	 */
+	public interface IConfined extends org.objectteams.IConfined {
+		// internal method needed for cast and instanceof
+		ITeam _OT$getTeam(); 
+	}
+
+
+	/**
+	 * Activates the team and therefore all of its callin bindings. 
+	 * This activation applies to the current thread only.
+	 */
+	public abstract void activate();
+
+	/**
+	 * Deactivates the team and therefore all of its callin bindings. 
+	 * This deactivation applies to the current thread only.
+	 */
+	public abstract void deactivate();
+
+	/**
+	 * Activates the team and therefore all of its callin bindings for passed thread. 
+	 * If the constant 'Team.ALL_THREADS' is passed, this activation globally applies to all threads.
+	 */
+	public abstract void activate(Thread thread);
+
+	/**
+	 * Deactivates the team and therefore all of its callin bindings for passed thread. 
+	 * If the constant 'Team.ALL_THREADS' is passed, this deactivation globally applies to all threads.
+	 */
+	public abstract void deactivate(Thread thread);
+
+	/**
+	 * Checks, if the team instance is active for the current thread.
+	 * @return true, if the team is active, false else.
+	 */
+	public abstract boolean isActive();
+
+	/**
+	 * Checks, if the team instance is active for the 'thread'.
+	 * @param thread	The thread for which to check activity.
+	 * @return	true, if the team is active for 'thread', false else.
+	 */
+	public abstract boolean isActive(Thread thread);
+
+	/**
+	 * Does given base object have a role in this team?
+	 * This method will consider roles of any type.
+	 * 
+	 * @param aBase any object, i.e., no checks are performed whether the base object's
+	 * 		class is bound by any role class in this team. 	
+	 * @return
+	 */
+	public abstract boolean hasRole(Object aBase);
+
+	/**
+	 * Does given base object have a role in this team?
+	 * The role must be an instance of the specified role type.
+	 * 
+	 * @param aBase any object, i.e., no checks are performed whether the base object's
+	 * 		class is bound by any role class in this team.
+	 * @param roleClass Class instance specifying the required role type.
+	 *      If this does not specify an existing role class an IllegalArgumentException will be thrown.
+	 *      TODO (SH): is it legal to pass an unbound role class? 	
+	 * @return
+	 */
+	public abstract boolean hasRole(Object aBase, Class<?> roleType);
+
+	/**
+	 * Retrieve a role for a given base object.
+	 * If more than one role exists, a DuplicateRoleException is thrown.
+	 * 
+	 * @param aBase
+	 * @return
+	 */
+	public abstract Object getRole(Object aBase);
+
+	/**
+	 * Retrieve a role for a given base object.
+	 * The role must be an instance of the specified role type.
+	 * 
+	 * @param aBase any object, i.e., no checks are performed whether the base object's
+	 * 		class is bound by any role class in this team.
+	 * @param roleClass Class instance specifying the required role type.
+	 *      If this does not specify an existing role class an IllegalArgumentException will be thrown.
+	 * @return
+	 */
+	public abstract <T> T getRole(Object aBase, Class<T> roleType);
+
+	/**
+	 * Retrieve all bound roles registered in the current team.
+	 * 
+	 * This method uses internal structures of weak references. 
+	 * For that reason it may return role instances which were about to be reclaimed 
+	 * by the garbage collector. 
+	 * If performance permits, it is thus advisable to always call System.gc() 
+	 * prior to calling getAllRoles() in order to achieve deterministic results
+	 * 
+	 * @return a non-null array.
+	 */
+	public abstract Object[] getAllRoles();
+
+	/**
+	 * Retrieve all bound roles registered in the current team that
+	 * are instance of roleType or a subtype thereof.
+	 * 
+	 * This method uses internal structures of weak references. 
+	 * For that reason it may return role instances which were about to be reclaimed 
+	 * by the garbage collector. 
+	 * If performance permits, it is thus advisable to always call System.gc() 
+	 * prior to calling getAllRoles() in order to achieve deterministic results
+	 * 
+	 * @param roleType must be a top-most bound role of this team. 
+	 * @return a non-null array.
+	 */
+	public abstract <T> T[] getAllRoles(Class<T> roleType);
+
+	/**
+	 * Query whether any role instance of this team instance is currently executing a
+	 * method due to a callin binding.
+	 * @return
+	 */
+	public abstract boolean isExecutingCallin();
+
+	/**
+	 * Remove a role from the internal registry, which means that the role will no longer be
+	 * considered during lifting.
+	 *  
+	 * @param aRole
+	 */
+	public abstract void unregisterRole(Object aRole);
+
+	/**
+	 * Remove a role from the internal registry, which means that the role will no longer be
+	 * considered during lifting.
+	 *  
+	 * @param aRole
+	 * @param roleType
+	 */
+	public abstract void unregisterRole(Object aRole, Class<?> roleType);
+
+	/**
+	 * Not API.
+	 * This method saves the activation state of the team  for the current thread.
+	 * If active, it also saves, if the activation was explicit or implicit.
+	 * This method has to be called by the generated code when entering a within block, 
+	 * before the activation.
+	 */
+	public int _OT$saveActivationState();
+	
+	/**
+	 * Not API.
+	 * This method restores the former saved activation state of the team  for the current thread.
+	 * If active, it also restores, if the activation was explicit or implicit.
+	 * This method has to be called by the generated code when leaving a within block 
+	 * (in the finally block).
+	 */
+	public void _OT$restoreActivationState(int old_state);
+	
+	/**
+	 * Not API, for use by TeamThreadManager, only.
+	 */
+	public boolean internalIsActiveSpecificallyFor(Thread t);
+	
+	/**
+	 * Not API, for use by TeamThreadManager, only.
+	 */
+	public void deactivateForEndedThread(Thread thread);
+}
\ No newline at end of file
diff --git a/OTRE/OTRE/src/org/objectteams/ITeamMigratable.java b/OTRE/OTRE/src/org/objectteams/ITeamMigratable.java
new file mode 100644
index 0000000..39be566
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/ITeamMigratable.java
@@ -0,0 +1,36 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2008 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: ITeamMigratable.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.objectteams;
+
+/**
+ * Marker interface: if a role declares to implement this interface
+ * the compiler will generate the method defined herein, and prepare
+ * the role so that the migration will indeed be possible.
+ * Note, that a migratable role does not obey the family guarantee.
+ * 
+ * @author stephan
+ * @since 1.2.5
+ */
+public interface ITeamMigratable {
+	/**
+	 * Migrate the current role to the otherTeam.
+	 * 
+	 * @param otherTeam new team that should adopt this role
+	 * @return the migrated (and re-typed) role (actually of type R<@otherTeam>).  FIXME(SH)
+	 */
+	<R> R migrateToTeam(final ITeam otherTeam);
+}
diff --git a/OTRE/OTRE/src/org/objectteams/IllegalRoleCreationException.java b/OTRE/OTRE/src/org/objectteams/IllegalRoleCreationException.java
new file mode 100644
index 0000000..f745d73
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/IllegalRoleCreationException.java
@@ -0,0 +1,35 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2007-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: IllegalRoleCreationException.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.objectteams;
+
+/**
+ * Exception to be thrown when a bound role is being instantiated but
+ * the constructor does not assign a base object.
+ *  
+ * @author stephan
+ */
+@SuppressWarnings("serial")
+public class IllegalRoleCreationException extends RuntimeException {
+	public IllegalRoleCreationException() {
+		super();
+	}
+	
+	@Override
+	public String getMessage() {
+		return "Cannot instantiate a bound role using a default constructor of its tsuper class";
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/ImplicitTeamActivation.java b/OTRE/OTRE/src/org/objectteams/ImplicitTeamActivation.java
new file mode 100644
index 0000000..09eda96
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/ImplicitTeamActivation.java
@@ -0,0 +1,45 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2009 Stephan Herrmann
+ * 
+ * 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$
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 			Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.objectteams;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This marker annotation enables implicit team activation for the annotated element:
+ * <ul>
+ * <li>If attached to a method the effect is that each call to this method implicitly
+ *     activates the enclosing team.</li>
+ * <li>If attached to a class it has the same effect as annotating all contained methods.</li>
+ * </ul>
+ * See <a href="http://www.objectteams.org/def/1.3/s5.html#s5.3">OTJLD § 5.3</a>.
+ * <p>
+ * This annotation is only evaluated if the property <code>ot.implicit.team.activation</code>
+ * is set to the string <code>ANNOTATED</code>.
+ * </p>
+ * @author stephan
+ * @since 1.4.0
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface ImplicitTeamActivation {
+	/* no members, pure marker annotation. */
+}
diff --git a/OTRE/OTRE/src/org/objectteams/LiftingFailedException.java b/OTRE/OTRE/src/org/objectteams/LiftingFailedException.java
new file mode 100644
index 0000000..99f2dd2
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/LiftingFailedException.java
@@ -0,0 +1,46 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2003-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: LiftingFailedException.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.objectteams;
+
+/**
+ * This exception signals that lifting failed due to unresolved
+ * binding ambiguity.
+ */
+public class LiftingFailedException extends RuntimeException {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private Object base;
+	private String roleType;
+	
+	/**
+	 * @param base the object that should be lifted
+	 * @param roleType the name of the role type for which
+	 *                 lifting was attempted.
+	 */
+	public LiftingFailedException(Object base, String roleType) {
+		this.base = base;
+		this.roleType = roleType;
+	}
+	
+	public String getMessage() {
+		return "\nFailed to lift '" + base + "' of " + base.getClass()
+				+ " to type '" + roleType
+				+ "'\n(See OT/J definition para. 2.3.4(c)).";
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/LiftingVetoException.java b/OTRE/OTRE/src/org/objectteams/LiftingVetoException.java
new file mode 100644
index 0000000..3a9b83a
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/LiftingVetoException.java
@@ -0,0 +1,45 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2003-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: LiftingVetoException.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.objectteams;
+
+/**
+ *  This exception is used by the language implementation
+ *  to signal a failed lifting due to a guard predicate that evaluated to false.
+ *  @author Stephan Herrmann
+ */
+public class LiftingVetoException extends RuntimeException {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	ITeam aTeam = null;
+	Object base = null;
+	
+	public LiftingVetoException(ITeam aTeam, Object base) {
+		this.aTeam = aTeam;
+		this.base = base;
+	}
+	
+    public LiftingVetoException() {
+		super("");
+    }
+    
+	public String toString() {
+		return "Team " + aTeam + " refuses to lift " + base
+				+ "\n(this exception should not be seen in applications).";
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/ResultNotProvidedException.java b/OTRE/OTRE/src/org/objectteams/ResultNotProvidedException.java
new file mode 100644
index 0000000..b6baccb
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/ResultNotProvidedException.java
@@ -0,0 +1,61 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: ResultNotProvidedException.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.objectteams;
+
+/**
+ * @author resix
+ */
+public class ResultNotProvidedException extends RuntimeException {
+
+		/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+		private static final String _bugmsg = 
+		"\nNo base call executed! Result value was uninitialized!\n(see OT/J language definition para. 4.3(e)).";
+
+		/**
+		 * 
+		 */
+		public ResultNotProvidedException() {
+			super(_bugmsg);
+		}
+
+		/**
+		 * @param message
+		 */
+		public ResultNotProvidedException(String message) {
+			super(_bugmsg + "\n" + message);
+			StackTraceElement[] ste = new StackTraceElement[0];
+			setStackTrace(ste);
+		}
+
+		/**
+		 * @param cause
+		 */
+		public ResultNotProvidedException(Throwable cause) {
+			super(_bugmsg + cause.toString());
+		}
+
+		/**
+		 * @param message
+		 * @param cause
+		 */
+		public ResultNotProvidedException(String message, Throwable cause) {
+			super(_bugmsg + message/* +cause.toString() */);
+		}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/RoleCastException.java b/OTRE/OTRE/src/org/objectteams/RoleCastException.java
new file mode 100644
index 0000000..f6608c9
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/RoleCastException.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: RoleCastException.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.objectteams;
+
+/**
+ * This exception is thrown if a cast to a role class fails due to
+ * different enclosing team instances.
+ * @author Stephan Herrmann
+ */
+public class RoleCastException extends ClassCastException {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private static final String MSG = 
+		"Different enclosing team instances (see OT/J language definition para. 1.2.4(b)).";
+
+	/* (non-Javadoc)
+	 * @see java.lang.Throwable#getMessage()
+	 */
+	public String getMessage() {
+		return MSG;
+	}
+}
\ No newline at end of file
diff --git a/OTRE/OTRE/src/org/objectteams/Team.java b/OTRE/OTRE/src/org/objectteams/Team.java
new file mode 100644
index 0000000..c6c5f33
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/Team.java
@@ -0,0 +1,490 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2002-2007 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: Team.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.objectteams;
+
+import java.awt.EventQueue;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.WeakHashMap;
+
+/**
+ *  This is the root class of all team definitions.
+ *  Any class with the <tt>team</tt> modifier implicitly
+ *  inherits from this class.
+ *  
+ */
+public /* team */ class Team implements ITeam {
+	// Technical note: comments starting with //$Debug are intended
+	// for a standalone tool that generates an interface 
+	// which the debugger needs in order to know about line numbers in this class.
+	
+	/*
+	 *  Synchronization: This class supports two levels of synchronization:
+	 *  <ul>
+	 *  <li>Fields of <code>Team</code> are synchronized 
+	 *      using <code>this</code> as the monitor.
+	 *  <li>Those calls that (un)register a team at its base classes are synchronized 
+	 *      via <code>registrationLock</code>
+	 *  </ul>
+	 *  This allows releasing the lock on <code>this</code> before calling to the base class.
+	 *  Note, that the synchronized portion of each initial-wrapper is also synchronized 
+	 *  (against <code>_OT$addTeam/_OT$removeTeam</code>) and that it calls back to
+	 *  the registered teams (method <code>isActive()</code>). 
+	 *  Without <code>registrationLock</code> this situation could easily deadlock:
+	 *  Thread1: <pre>t.activate() -> Base._OT$addTeam()</pre>: owns t, waits for Base.
+	 *  Thread2: <pre>b.bm() (initial wrapper) -> t.isActive()</pre>: owns Base, waits for t. 
+	 */
+	
+	/**
+	 * Internal field used by the runtime to install a lifting participant if one is configured.
+	 */
+	public static ILiftingParticipant _OT$liftingParticipant = null;
+	
+	/**
+	 * Default constructor for debugging purpose.
+	 */
+	public Team() {} //$Debug(TeamConstructor)
+
+	/*
+	 * manual copy-inheritance of a role interface from ITeam.
+	 */
+	public interface ILowerable extends ITeam.ILowerable {}
+
+	/*
+	 * manual copy-inheritance of a role interface from ITeam.
+	 */
+	public interface IConfined extends ITeam.IConfined {}
+	
+	/**
+	 *  Special role type that<ul>
+	 * <li> does not extend java.lang.Object
+	 * <li> may not leak references outside the team.
+	 * </ul>
+	 */
+	protected interface Confined { 
+		/* internal method needed for cast and instanceof
+		 * (this method will be generated for role classes) */
+		ITeam _OT$getTeam();
+	}
+	
+    /** 
+     * This class would have been generated by the OT-compiler.
+     * Don't explicitly use it in client code!
+     */
+    protected class __OT__Confined implements Confined {
+		// internal method needed for cast and instanceof
+    	public ITeam _OT$getTeam() {
+    		return Team.this; //$Debug(ConfinedGetTeam)
+    	}
+    }
+
+	/**
+	 *  Internal function for identifying a Team.
+	 *  Should not be called by client code.
+	 */
+	public int _OT$getID () {return -1;}
+
+    /**
+	 * The constant <code>ALL_THREADS</code> is used for global team (de-)activation.
+	 */
+	public static final Thread ALL_THREADS = new Thread();
+	
+	private static final int _OT$UNREGISTERED = 0;
+	private static final int _OT$REGISTERED = 1;
+	private  int _OT$registrationState = _OT$UNREGISTERED;
+	
+	private boolean _OT$globalActive = false;
+	
+	private ThreadLocal<Integer> _OT$implicitActivationsPerThread = new ThreadLocal<Integer>() {
+		protected synchronized Integer initialValue() {
+			return Integer.valueOf(0);
+		}
+	};
+	
+	private boolean _OT$lazyGlobalActiveFlag = false;
+	
+	/**
+	 * <code>_OT$activatedThreads</code> contains all threads for which this team instance is active.
+	 * key		= activated thread
+	 * value 	= Boolean(true) for explicit activation | Boolean(false) for implicit activation.
+	 */
+	private WeakHashMap<Thread, Boolean> _OT$activatedThreads = new WeakHashMap<Thread, Boolean>();
+	
+	/** This lock is used to protect activate/deactivate methods <strong>including</strong>
+	 *  the calls to doRegistration/doUnregistration. 
+	 */
+	private Object _OT$registrationLock= new Object();
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void activate() {
+		activate(Thread.currentThread());
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void deactivate() {
+		deactivate(Thread.currentThread());
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void activate(Thread thread) {
+		// acquire both locks to avoid incomplete execution:
+		synchronized (this._OT$registrationLock) {
+			synchronized (this) {
+				if (thread.equals(ALL_THREADS)) {
+					_OT$globalActive = true;
+					_OT$lazyGlobalActiveFlag = true;
+					TeamThreadManager.addGlobalActiveTeam(this);
+				} else { // activation only for 'thread':
+					// register 'thread' as active:
+					_OT$activatedThreads.put(thread, Boolean.TRUE);
+				}
+			} // release this before calling synchronized base class methods
+			doRegistration(); //$Debug(ActivateMethod)		
+		}
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void deactivate(Thread thread) {
+		// acquire both locks to avoid incomplete execution:
+		synchronized (this._OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized(this) {
+				if (_OT$globalActive && EventQueue.isDispatchThread()) {
+					System.err.println("Warning: Deactivation for the AWT-Event-Thread is not effective right now!");
+				}
+				if (thread.equals(ALL_THREADS)) {
+					_OT$globalActive = false;
+					TeamThreadManager.removeGlobalActiveTeam(this);
+					// unregister all threads:
+					_OT$activatedThreads.clear();
+					shouldUnregister= true;
+				} else { // deactivation only for 'thread':
+					if (_OT$lazyGlobalActiveFlag) { 
+						// be eager now: activate for all (other) threads:
+						_OT$activateForAllThreads();
+					} 
+					// deactivate for 'thread', no longer active:
+					_OT$activatedThreads.remove(thread);
+					if (!_OT$lazyGlobalActiveFlag  && _OT$activatedThreads.isEmpty()) {
+						shouldUnregister= true;
+					}
+				}
+				_OT$lazyGlobalActiveFlag = false; 
+			} // release this before calling synchronized base class methods
+			if (shouldUnregister) 		//$Debug(DeactivateMethod)
+				doUnregistration();
+		}
+	}
+	
+	public void deactivateForEndedThread(Thread thread) {
+		synchronized (_OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized (this) {
+				_OT$activatedThreads.remove(thread);
+				if (!_OT$lazyGlobalActiveFlag  && _OT$activatedThreads.isEmpty())
+					shouldUnregister= true;				
+			}
+			if (shouldUnregister)
+				doUnregistration();
+		}
+	}
+	
+	private void _OT$activateForAllThreads() {
+		HashSet threads = TeamThreadManager.getExistingThreads();
+		Iterator it = threads.iterator();
+		while (it.hasNext()) {
+			Thread a_thread = (Thread) it.next();
+			activate(a_thread); // use smaller activate version (no ALL_THREADS, no registerAtBases,...
+		}
+	}
+
+	/**
+	 * This method is used for implicit activation in team-level methods.
+	 * Implicit activation only applies to the current thread.
+	 * Don't call it from client code.
+	 */
+	public void _OT$implicitlyActivate() {
+		synchronized (this._OT$registrationLock) {
+			boolean shouldRegister= false;
+			synchronized (this) {
+				// this method is used for debugging purpose (team monitor)
+				Thread currentThread = Thread.currentThread();
+				if (!_OT$activatedThreads.containsKey(currentThread)) {
+					// register 'thread' as active:
+					_OT$activatedThreads.put(currentThread, Boolean.FALSE);
+					shouldRegister= true;
+				}
+				//	increment thread local implicit activaion counter:
+				int implActCount = (_OT$implicitActivationsPerThread.get()).intValue();
+				_OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount + 1 )); 
+			}
+			if (shouldRegister) //$Debug(ImplicitActivateMethod)
+				doRegistration();
+		}
+	}
+	
+	/**
+	 * This method is used for implicitly deactivation in team-level methods.
+	 * It respects explicit activation changes and nested calls to team-level methods.
+	 * Implicit deactivation only applies to the current thread.
+	 * Don't call it from client code.
+	 */
+	public void _OT$implicitlyDeactivate() {
+		synchronized (this._OT$registrationLock) {
+			boolean shouldUnregister= false;
+			synchronized(this) {
+				// this method is used for debugging purpose (team monitor)
+				Thread currentThread = Thread.currentThread();
+				boolean explicitlyActivated = false;
+				if (_OT$activatedThreads.containsKey(currentThread)) {
+					explicitlyActivated = ((Boolean) _OT$activatedThreads.get(currentThread)).booleanValue();
+				}
+				if (!explicitlyActivated 
+						&& !_OT$lazyGlobalActiveFlag // no explicit activation overriding the implicit one 
+						&& ((_OT$implicitActivationsPerThread.get()).intValue() == 1))  // this is the last implicit activation
+				{
+					_OT$activatedThreads.remove(currentThread);
+					if (_OT$activatedThreads.isEmpty()) // there are not other threads for which this theam is active
+					{
+						shouldUnregister= true;
+					}
+				}				
+				// decrement thread local implicit activaion counter:
+				int implActCount = (_OT$implicitActivationsPerThread.get()).intValue();
+				_OT$implicitActivationsPerThread.set(Integer.valueOf(implActCount - 1)); 
+			}
+			if (shouldUnregister) //$Debug(ImplicitDeactivateMethod)
+				doUnregistration();
+		}
+	}
+	
+	/**
+	 * Define whether per-thread activation of this team should be inheritable
+	 * such that the team will be activated automatically for any new threads 
+	 * that are spawned from a thread for which the team is already active at that time.
+	 * 
+	 * @param inheritable whether or not activation should be inheritable to new threads
+	 */
+	public void setInheritableActivation(boolean inheritable) {
+		if (inheritable)
+			TeamThreadManager.registerTeamForActivationInheritance(this);
+		else
+			TeamThreadManager.unRegisterTeamForActivationInheritance(this);
+	}
+	
+	// not API (for use by the TeamThreadManager)
+	public boolean internalIsActiveSpecificallyFor(Thread t) {
+		return this._OT$activatedThreads.containsKey(t);
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isActive() {
+		return isActive(Thread.currentThread());
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isActive(Thread thread) {
+		if (_OT$globalActive && EventQueue.isDispatchThread())
+			return true;
+		if (thread.equals(ALL_THREADS)) {
+			return _OT$globalActive;
+		}
+		if (_OT$lazyGlobalActiveFlag) {
+				return true;
+		} else {
+			//if (!TeamThreadManager.getExistingThreads().contains(thread)) { // this thread is already finished!
+			if (!thread.isAlive()) { // this thread is already finished!
+				throw new IllegalThreadStateException("Called 'isActive(...)' for a thread which is no longer running!");
+			}
+			return _OT$activatedThreads.containsKey(thread);
+		}
+	}
+
+// ***** for restoring the activation state after a within block:	---->*****
+	private static final int _OT$INACTIVE = 0;
+	private static final int _OT$IMPLICIT_ACTIVE = 1;
+	private static final int _OT$EXPLICIT_ACTIVE = 2;
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public synchronized int _OT$saveActivationState() {
+		int old_state = _OT$INACTIVE;
+		if (_OT$lazyGlobalActiveFlag) {
+			old_state = _OT$EXPLICIT_ACTIVE;
+		} else {
+			Thread current_thread = Thread.currentThread();
+			if (_OT$activatedThreads.containsKey(current_thread)) {
+				old_state = _OT$IMPLICIT_ACTIVE;
+				if (((Boolean)_OT$activatedThreads.get(current_thread)).booleanValue()) {
+					old_state = _OT$EXPLICIT_ACTIVE;
+				}
+			}
+		}
+		return old_state;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void _OT$restoreActivationState(int old_state) {
+		synchronized (_OT$registrationLock) {
+			if (old_state == _OT$INACTIVE) // team was inactive before:
+				deactivate();
+			else { // team was active before: has to be reactivated:
+				boolean explicit = (old_state == _OT$EXPLICIT_ACTIVE);
+				synchronized (this) {					
+					_OT$activatedThreads.put(Thread.currentThread(), Boolean.valueOf(explicit));
+				}
+				doRegistration();
+			}
+		}
+	}
+//	 ***** <----for restoring the activation state after a within block.	*****
+	
+
+	private void doRegistration() {
+		if (_OT$registrationState == _OT$UNREGISTERED) {
+			_OT$registerAtBases();
+			_OT$registrationState = _OT$REGISTERED;
+		}
+	}
+	
+	private void doUnregistration() {
+		if (_OT$registrationState == _OT$REGISTERED) {
+			_OT$unregisterFromBases();
+			_OT$registrationState = _OT$UNREGISTERED;
+		}
+	}
+	
+	/**
+	 * This method will be implemented by generated code in subteams.
+	 * It registers the team at every base playing one of its roles. 
+	 * Don't call it from client code.
+	 */
+	public void _OT$registerAtBases() {} 
+
+	/**
+	 * This method will be implemented by generated code in subteams.
+	 * It unregisters the team from every base playing one of its roles. 
+	 * Don't call it from client code.
+	 */
+	public void _OT$unregisterFromBases() {}
+	
+	//public int _OT$activationState = -1; // TODO: remove usage of  this from generated code	
+		
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasRole(Object aBase) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasRole(Object aBase, Class<?> roleType) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+		throw new IllegalArgumentException("No such bound role type in this team: "+roleType.getName());
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object getRole(Object aBase) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+		return null;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T> T getRole(Object aBase, Class<T> roleType) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+		return null;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object[] getAllRoles() {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+		return new Object[0];
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T> T[] getAllRoles(Class<T> roleType) {
+		// overriding method to be generated by the compiler for each team with bound roles. 		
+		throw new IllegalArgumentException("Class org.objectteams.Team has no bound roles.");
+	}
+	
+	/** Internal variable to be set from generated code. */
+	private boolean _OT$isExecutingCallin = false;
+	
+	/**
+	 * Method only for internal use by generated code.
+	 */
+	public boolean _OT$setExecutingCallin(boolean newFlag) {
+		boolean oldVal = _OT$isExecutingCallin;
+		_OT$isExecutingCallin = newFlag;
+		return oldVal;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isExecutingCallin() {
+		return _OT$isExecutingCallin;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	public void unregisterRole(Object aRole) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void unregisterRole(Object aRole, Class<?> roleType) {
+		// overriding method to be generated by the compiler for each team with bound roles. 
+	}
+	
+	@Override
+	protected void finalize() throws Throwable {
+		// nop, hook for the debugger 
+		@SuppressWarnings("unused")
+		int i= 2+3; // Note: body must not be empty for debuggger to be able to stop.
+	} // $Debug(FinalizeMethod)
+}
diff --git a/OTRE/OTRE/src/org/objectteams/TeamThreadManager.java b/OTRE/OTRE/src/org/objectteams/TeamThreadManager.java
new file mode 100644
index 0000000..ce1b174
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/TeamThreadManager.java
@@ -0,0 +1,97 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2006-2008 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: TeamThreadManager.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.objectteams;
+
+import java.util.HashSet;
+import java.util.WeakHashMap;
+
+
+/**
+ * This class is for internal use, only.
+ * 
+ * Maintain information about existing threads as to manage
+ * team activation per thread vs. globally.
+ * 
+ * @author Chistine Hundt
+ * @author Stephan Herrmann
+ */
+public class TeamThreadManager {
+
+	private static Object token = new Object();
+	
+	private static HashSet<ITeam> globalActiveTeams = new HashSet<ITeam>();
+	private static WeakHashMap<ITeam,Object> teamsWithActivationInheritance = new WeakHashMap<ITeam,Object>();
+	private static HashSet<Thread> existingThreads = new HashSet<Thread>();
+	
+	public static boolean newThreadStarted(boolean isMain, Thread parent) {
+		if (!isMain && (new Exception().getStackTrace().length > 3))
+			return false;
+		// workaround for application hang on Mac OS with Apple JVM:
+		Thread currentThread = Thread.currentThread();
+		if (System.getProperty("os.name").startsWith("Mac"))
+			if (currentThread.getName().equals("AWT-Shutdown"))
+				return false;
+
+		ITeam[] globalTeams;
+		ITeam[] inheritableTeams;
+		synchronized (TeamThreadManager.class) {
+			existingThreads.add(currentThread);
+			
+			globalTeams = globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]);
+			inheritableTeams = teamsWithActivationInheritance.keySet().toArray(new ITeam[teamsWithActivationInheritance.size()]);
+		}
+		// activate teams outside synchronized block:
+		for (ITeam t : globalTeams)			
+			t.activate(currentThread); // small version? global -> already registered...!
+		if (parent != null)
+			for (ITeam t : inheritableTeams)
+				if (t.internalIsActiveSpecificallyFor(parent))
+					t.activate(currentThread); // pass activation from parent to child thread
+		return true;
+	}
+	public static void threadEnded() {
+		ITeam[] teamsToDeactivate = internalThreadEnded();
+		// + remove per thread activation:
+		for (ITeam t : teamsToDeactivate) 
+			//t.deactivate(Thread.currentThread()); // small version?
+			t.deactivateForEndedThread(Thread.currentThread());			
+	}
+	private synchronized static ITeam[] internalThreadEnded() {
+		existingThreads.remove(Thread.currentThread());
+		// fetch all global active teams for deactivation:
+		return globalActiveTeams.toArray(new ITeam[globalActiveTeams.size()]);
+	}
+	
+	public synchronized static void addGlobalActiveTeam(ITeam t) {
+		globalActiveTeams.add(t);
+	}
+	
+	public synchronized static void removeGlobalActiveTeam(ITeam t) {
+		globalActiveTeams.remove(t);
+	}
+	
+	public static HashSet<Thread> getExistingThreads() {
+		return existingThreads;
+	}
+	public static void registerTeamForActivationInheritance(ITeam aTeam) {
+		teamsWithActivationInheritance.put(aTeam,token);
+	}
+	public static void unRegisterTeamForActivationInheritance(ITeam aTeam) {
+		teamsWithActivationInheritance.remove(aTeam);
+	}
+
+}
diff --git a/OTRE/OTRE/src/org/objectteams/UnsupportedFeatureException.java b/OTRE/OTRE/src/org/objectteams/UnsupportedFeatureException.java
new file mode 100644
index 0000000..9b1c1ff
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/UnsupportedFeatureException.java
@@ -0,0 +1,60 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2004-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: UnsupportedFeatureException.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.objectteams;
+
+/**
+ * @author resix
+ */
+public class UnsupportedFeatureException extends RuntimeException {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private static final String _bugmsg = "\nThe program encountered an unsupported situation! ";
+
+	/**
+	 * 
+	 */
+	public UnsupportedFeatureException() {
+		super(_bugmsg);
+	}
+
+	/**
+	 * @param message
+	 */
+	public UnsupportedFeatureException(String message) {
+		super(_bugmsg + "\n" + message);
+		StackTraceElement[] ste = new StackTraceElement[0];
+		setStackTrace(ste);
+	}
+
+	/**
+	 * @param cause
+	 */
+	public UnsupportedFeatureException(Throwable cause) {
+		super(_bugmsg + cause.toString());
+	}
+
+	/**
+	 * @param message
+	 * @param cause
+	 */
+	public UnsupportedFeatureException(String message, Throwable cause) {
+		super(_bugmsg + message/*+cause.toString()*/);
+	}
+}
diff --git a/OTRE/OTRE/src/org/objectteams/WrongRoleException.java b/OTRE/OTRE/src/org/objectteams/WrongRoleException.java
new file mode 100644
index 0000000..da84d33
--- /dev/null
+++ b/OTRE/OTRE/src/org/objectteams/WrongRoleException.java
@@ -0,0 +1,57 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ *
+ * Copyright 2003-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: WrongRoleException.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.objectteams;
+
+/**
+ * This exception is thrown by the OT/J infra structure if a role for a given base object
+ * was requested during lifting, but a role with an incompatible type was already
+ * registered for that base object. Can only happen if a compile time warning occurred.
+ * @author Stephan Herrmann
+ */
+public class WrongRoleException extends RuntimeException {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	private Class clazz;
+	private Object base;
+	private Object role;
+
+	/**
+	 * @param clazz
+	 * @param base
+	 * @param role
+	 */
+	public WrongRoleException (Class clazz, Object base, Object role) {
+		this.clazz = clazz;
+		this.base = base;
+		this.role = role;
+	}
+	
+	public String getMessage() {
+		String baseClazz = base.getClass().getName();
+		String roleClazz = role.getClass().getName();
+		return "The compiler has warned you about ambiguous role bindings.\n"
+				+ "Now lifting to " + clazz
+				+ " fails with the following objects\n"
+				+ "(see OT/J language definition para. 2.3.4(d)):\n"
+				+ "Provided:\n  Base object: " + base + "\n" + "  Base type:   "
+				+ baseClazz + "\n" 
+				+ "Found in cache:\n  Role object: " + role + "\n"
+				+ "  Role type:   " + roleClazz;
+	}
+}