Bug 433150 Reorganize structure of runtime bundles / packages
- split runtime bundle into core classes and bundle "otre"
diff --git a/plugins/org.eclipse.objectteams.otre/.classpath b/plugins/org.eclipse.objectteams.otre/.classpath
new file mode 100644
index 0000000..303cd57
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="bcelpatchsrc"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.objectteams.otre/.gitignore b/plugins/org.eclipse.objectteams.otre/.gitignore
new file mode 100644
index 0000000..d6e238c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/.gitignore
@@ -0,0 +1 @@
+/bcelpatchbin
diff --git a/plugins/org.eclipse.objectteams.otre/.project b/plugins/org.eclipse.objectteams.otre/.project
new file mode 100644
index 0000000..191559f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.objectteams.otre</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.objectteams.otre/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.objectteams.otre/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..35a117b
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+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.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/plugins/org.eclipse.objectteams.otre/META-INF/MANIFEST.MF b/plugins/org.eclipse.objectteams.otre/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..77d5729
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.objectteams.otre
+Bundle-Version: 2.3.0.qualifier
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.apache.bcel;bundle-version="[5.2.0,5.3.0)",
+ org.eclipse.objectteams.runtime;bundle-version="[2.3.0,3.0.0)"
+Export-Package: org.eclipse.objectteams.otre;version="2.3.0",
+ org.eclipse.objectteams.otre.bcel;version="2.1.0",
+ org.eclipse.objectteams.otre.jplis;version="2.3.0",
+ org.eclipse.objectteams.otre.util;version="2.0.0"
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.objectteams.otre/about.html b/plugins/org.eclipse.objectteams.otre/about.html
new file mode 100644
index 0000000..66ef6f6
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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>June 15, 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/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java b/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
new file mode 100755
index 0000000..b871166
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/BranchHandle.java
@@ -0,0 +1,123 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2012 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ * 
+ * This file is based on class org.apache.bcel.generic.BranchHandle
+ * originating from the Apache BCEL project which was provided under the 
+ * Apache 2.0 license. Original Copyright from BCEL:
+ * 
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); 
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License. 
+ *
+ */
+package org.apache.bcel.generic;
+
+/**
+ * BranchHandle is returned by specialized InstructionList.append() whenever a
+ * BranchInstruction is appended. This is useful when the target of this
+ * instruction is not known at time of creation and must be set later
+ * via setTarget().
+ *
+ * @see InstructionHandle
+ * @see Instruction
+ * @see InstructionList
+ * @version $Id: BranchHandle.java 386056 2006-03-15 11:31:56Z tcurdt $
+ * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class BranchHandle extends InstructionHandle {
+
+    private BranchInstruction bi; // An alias in fact, but saves lots of casts
+
+
+    private BranchHandle(BranchInstruction i) {
+        super(i);
+        bi = i;
+    }
+
+    /** Factory methods.
+     */
+
+    static final BranchHandle getBranchHandle( BranchInstruction i ) {
+        return new BranchHandle(i);
+    }
+
+
+    /* Override InstructionHandle methods: delegate to branch instruction.
+     * Through this overriding all access to the private i_position field should
+     * be prevented.
+     */
+    public int getPosition() {
+        return bi.position;
+    }
+
+
+    void setPosition( int pos ) {
+        i_position = bi.position = pos;
+    }
+
+
+    protected int updatePosition( int offset, int max_offset ) {
+        int x = bi.updatePosition(offset, max_offset);
+        i_position = bi.position;
+        return x;
+    }
+
+
+    /**
+     * Pass new target to instruction.
+     */
+    public void setTarget( InstructionHandle ih ) {
+        bi.setTarget(ih);
+    }
+
+
+    /**
+     * Update target of instruction.
+     */
+    public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+        bi.updateTarget(old_ih, new_ih);
+    }
+
+
+    /**
+     * @return target of instruction.
+     */
+    public InstructionHandle getTarget() {
+        return bi.getTarget();
+    }
+
+
+    /** 
+     * Set new contents. Old instruction is disposed and may not be used anymore.
+     */
+    public void setInstruction( Instruction i ) {
+        super.setInstruction(i);
+        if (!(i instanceof BranchInstruction)) {
+            throw new ClassGenException("Assigning " + i
+                    + " to branch handle which is not a branch instruction");
+        }
+        bi = (BranchInstruction) i;
+    }
+}
diff --git a/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java b/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
new file mode 100755
index 0000000..11b381f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/bcelpatchsrc/org/apache/bcel/generic/InstructionHandle.java
@@ -0,0 +1,288 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2012 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ * 
+ * This file is based on class org.apache.bcel.classfile.ConstantPool
+ * originating from the Apache BCEL project which was provided under the 
+ * Apache 2.0 license. Original Copyright from BCEL:
+ *
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); 
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License. 
+ *
+ */
+package org.apache.bcel.generic;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.bcel.classfile.Utility;
+
+/**
+ * Instances of this class give users a handle to the instructions contained in
+ * an InstructionList. Instruction objects may be used more than once within a
+ * list, this is useful because it saves memory and may be much faster.
+ *
+ * Within an InstructionList an InstructionHandle object is wrapped
+ * around all instructions, i.e., it implements a cell in a
+ * doubly-linked list. From the outside only the next and the
+ * previous instruction (handle) are accessible. One
+ * can traverse the list via an Enumeration returned by
+ * InstructionList.elements().
+ *
+ * @version $Id: InstructionHandle.java 386056 2006-03-15 11:31:56Z tcurdt $
+ * @author  <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Instruction
+ * @see BranchHandle
+ * @see InstructionList 
+ */
+public class InstructionHandle implements java.io.Serializable {
+
+    InstructionHandle next, prev; // Will be set from the outside
+    Instruction instruction;
+    protected int i_position = -1; // byte code offset of instruction
+    private Set targeters;
+    private Map attributes;
+
+
+    public final InstructionHandle getNext() {
+        return next;
+    }
+
+
+    public final InstructionHandle getPrev() {
+        return prev;
+    }
+
+
+    public final Instruction getInstruction() {
+        return instruction;
+    }
+
+
+    /**
+     * Replace current instruction contained in this handle.
+     * Old instruction is disposed using Instruction.dispose().
+     */
+    public void setInstruction( Instruction i ) { // Overridden in BranchHandle
+        if (i == null) {
+            throw new ClassGenException("Assigning null to handle");
+        }
+        if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
+            throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
+        }
+        if (instruction != null) {
+            instruction.dispose();
+        }
+        instruction = i;
+    }
+
+
+    /**
+     * Temporarily swap the current instruction, without disturbing
+     * anything. Meant to be used by a debugger, implementing
+     * breakpoints. Current instruction is returned.
+     */
+    public Instruction swapInstruction( Instruction i ) {
+        Instruction oldInstruction = instruction;
+        instruction = i;
+        return oldInstruction;
+    }
+
+
+    /*private*/protected InstructionHandle(Instruction i) {
+        setInstruction(i);
+    }
+
+    /** Factory method.
+     */
+    static final InstructionHandle getInstructionHandle( Instruction i ) {
+        return new InstructionHandle(i);
+    }
+
+
+    /**
+     * Called by InstructionList.setPositions when setting the position for every
+     * instruction. In the presence of variable length instructions `setPositions()'
+     * performs multiple passes over the instruction list to calculate the
+     * correct (byte) positions and offsets by calling this function.
+     *
+     * @param offset additional offset caused by preceding (variable length) instructions
+     * @param max_offset the maximum offset that may be caused by these instructions
+     * @return additional offset caused by possible change of this instruction's length
+     */
+    protected int updatePosition( int offset, int max_offset ) {
+        i_position += offset;
+        return 0;
+    }
+
+
+    /** @return the position, i.e., the byte code offset of the contained
+     * instruction. This is accurate only after
+     * InstructionList.setPositions() has been called.
+     */
+    public int getPosition() {
+        return i_position;
+    }
+
+
+    /** Set the position, i.e., the byte code offset of the contained
+     * instruction.
+     */
+    void setPosition( int pos ) {
+        i_position = pos;
+    }
+
+    /**
+     * Delete contents, i.e., remove user access and make handle reusable.
+     */
+    void dispose() {
+        next = prev = null;
+        instruction.dispose();
+        instruction = null;
+        i_position = -1;
+        attributes = null;
+        removeAllTargeters();
+    }
+
+
+    /** Remove all targeters, if any.
+     */
+    public void removeAllTargeters() {
+        if (targeters != null) {
+            targeters.clear();
+        }
+    }
+
+
+    /**
+     * Denote this handle isn't referenced anymore by t.
+     */
+    public void removeTargeter( InstructionTargeter t ) {
+        if (targeters != null) {
+            targeters.remove(t);
+        }
+    }
+
+
+    /**
+     * Denote this handle is being referenced by t.
+     */
+    public void addTargeter( InstructionTargeter t ) {
+        if (targeters == null) {
+            targeters = new HashSet();
+        }
+        //if(!targeters.contains(t))
+        targeters.add(t);
+    }
+
+
+    public boolean hasTargeters() {
+        return (targeters != null) && (targeters.size() > 0);
+    }
+
+
+    /**
+     * @return null, if there are no targeters
+     */
+    public InstructionTargeter[] getTargeters() {
+        if (!hasTargeters()) {
+            return null;
+        }
+        InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
+        targeters.toArray(t);
+        return t;
+    }
+
+
+    /** @return a (verbose) string representation of the contained instruction. 
+     */
+    public String toString( boolean verbose ) {
+        return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
+    }
+
+
+    /** @return a string representation of the contained instruction. 
+     */
+    public String toString() {
+        return toString(true);
+    }
+
+
+    /** Add an attribute to an instruction handle.
+     *
+     * @param key the key object to store/retrieve the attribute
+     * @param attr the attribute to associate with this handle
+     */
+    public void addAttribute( Object key, Object attr ) {
+        if (attributes == null) {
+            attributes = new HashMap(3);
+        }
+        attributes.put(key, attr);
+    }
+
+
+    /** Delete an attribute of an instruction handle.
+     *
+     * @param key the key object to retrieve the attribute
+     */
+    public void removeAttribute( Object key ) {
+        if (attributes != null) {
+            attributes.remove(key);
+        }
+    }
+
+
+    /** Get attribute of an instruction handle.
+     *
+     * @param key the key object to store/retrieve the attribute
+     */
+    public Object getAttribute( Object key ) {
+        if (attributes != null) {
+            return attributes.get(key);
+        }
+        return null;
+    }
+
+
+    /** @return all attributes associated with this handle
+     */
+    public Collection getAttributes() {
+        if (attributes == null) {
+            attributes = new HashMap(3);
+        }
+        return attributes.values();
+    }
+
+
+    /** Convenience method, simply calls accept() on the contained instruction.
+     *
+     * @param v Visitor object
+     */
+    public void accept( Visitor v ) {
+        instruction.accept(v);
+    }
+}
diff --git a/plugins/org.eclipse.objectteams.otre/build.properties b/plugins/org.eclipse.objectteams.otre/build.properties
new file mode 100644
index 0000000..f1ac3c5
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/build.properties
@@ -0,0 +1,9 @@
+customBuildCallbacks=customBuildCallbacks.xml
+customBuildCallbacks.inheritall=true
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.properties,\
+               about.html
+javacProjectSettings = true
diff --git a/plugins/org.eclipse.objectteams.otre/customBuildCallbacks.xml b/plugins/org.eclipse.objectteams.otre/customBuildCallbacks.xml
new file mode 100644
index 0000000..83deba1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/customBuildCallbacks.xml
Binary files differ
diff --git a/plugins/org.eclipse.objectteams.otre/otre-export.jardesc b/plugins/org.eclipse.objectteams.otre/otre-export.jardesc
new file mode 100644
index 0000000..0650e48
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/otre-export.jardesc
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<jardesc>
+    <jar path="/home/stephan/workspaces/otre-export/org.eclipse.objectteams.runtime-head.jar"/>
+    <options buildIfNeeded="true" compress="true" descriptionLocation="/org.eclipse.objectteams.runtime/otre-export.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" 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">
+        <file path="/org.eclipse.objectteams.runtime/about.html"/>
+        <javaElement handleIdentifier="=org.eclipse.objectteams.runtime/src&lt;org.objectteams"/>
+    </selectedElements>
+</jardesc>
diff --git a/plugins/org.eclipse.objectteams.otre/plugin.properties b/plugins/org.eclipse.objectteams.otre/plugin.properties
new file mode 100644
index 0000000..5ad3c96
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/plugin.properties
@@ -0,0 +1,2 @@
+pluginName=Object Teams Runtime (BCEL Weaver)
+providerName=Eclipse.org - Object Teams
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseCallRedirection.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
new file mode 100644
index 0000000..c1357e3
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseCallRedirection.java
@@ -0,0 +1,1465 @@
+/**********************************************************************
+ * 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 org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.*;
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.jplis.JPLISEnhancer;
+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(Object loader) {
+    	super(loader);
+    }
+    
+    /**
+     * @param ce
+     * @param cg
+     */
+    public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+    	factory = new InstructionFactory(cg);
+    	String class_name = cg.getClassName();
+
+        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));
+    	    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+    		}
+    		
+    		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);
+    		}
+    		
+    	}
+    }
+
+	/**
+	 *  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 = newMethodGen(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 = newMethodGen(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());
+
+            short invocationKind = isSuperAccess 
+            						? Constants.INVOKESTATIC
+					   				: Constants.INVOKEVIRTUAL;
+            
+            String boundBaseClassName 		 = mb.getBaseClassName();
+            if (boundBaseClassName.indexOf(OTDT_PREFIX) != -1) {
+            	// if base is a role class, switch now to the interface part to support base-side implicit inheritance:
+				boundBaseClassName = ObjectTeamsTransformation.genRoleInterfaceName(boundBaseClassName);
+				invocationKind = Constants.INVOKEINTERFACE;
+			}
+			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(boundBaseClassName)) {
+				// playedBy has been refined in the sub role;
+				// create a cast to the sub base class:
+				il.append(factory.createCast(baseClass, new ObjectType(boundBaseClassName)));
+			}
+			
+			// --- 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(boundBaseClassName,
+										   baseChainMethodName,
+										   baseChainReturnType,
+										   enhancedBaseArgumentTypes,
+										   invocationKind
+										   ));
+										   
+			boolean resultLiftingNecessary = ((mb.getTranslationFlags()&1)!=0);
+			
+			if (resultLiftingNecessary) { // call the lift-method:
+				// STATIC_PARTS_OK: in role: lift method call
+				String liftMethodName = mb.getLiftMethodName();
+				Type liftMethodReturnType = Type.getReturnType(mb.getLiftMethodSignature());
+				Type[] liftMethodArgs = Type.getArgumentTypes(mb.getLiftMethodSignature());
+				
+				il.append(factory.createCast(baseChainReturnType, baseMethodReturnType));
+                
+				// determine receiver for lift-call:
+                ObjectType liftType = (ObjectType)((liftMethodReturnType instanceof ArrayType)
+			                						? ((ArrayType) liftMethodReturnType).getBasicType()
+			                						: liftMethodReturnType);
+                int liftedDepth = countOccurrences(liftType.getClassName(), '$');
+                int thisNestingDepth = countOccurrences(className, '$');
+                ObjectType liftReceiverType = outerClass; // default;
+                if (liftedDepth == thisNestingDepth) {
+                	// normal case: liftedType is at the same nesting level as "this" 
+                	il.append(InstructionFactory.createThis());
+                	il.append(factory.createGetField(className, "this$" + (thisNestingDepth-1), outerClass)); // access enclosing team-this
+                } else if (liftedDepth == thisNestingDepth+1){
+                	// current role is already the team containing the role to get
+                	liftReceiverType = new ObjectType(className);
+                	il.append(new ALOAD(0));
+                } else {
+                	throw new OTREInternalError("Mismatching nesting levels for lift-call in base-call-surrogate: "+thisNestingDepth+" vs. "+liftedDepth);
+                }
+
+                il.append(new SWAP()); // -> .., liftReceiver, (BaseType)result
+				
+				il.append(factory.createInvoke(liftReceiverType.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							
+	 */
+	@SuppressWarnings("deprecation") // ii.getClassName() is deprecated 
+	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), // deprecated but we're safe because we have not array here (super/tsuper call)
+													 	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		
+	 */
+	@SuppressWarnings("deprecation") // iv.getClassName is deprecated
+	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); // deprecated but we're safe because we have not array here (activate() call)
+		}
+		
+		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(org.apache.bcel.generic.ClassGen)
+ */
+    public void doTransformCode(ClassGen cg) {
+        // nothing to do
+    }
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
new file mode 100644
index 0000000..ad2d6b4
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/BaseMethodTransformation.java
@@ -0,0 +1,2139 @@
+/**********************************************************************
+ * 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.BoundClass;
+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 org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.LineNumber;
+import org.apache.bcel.classfile.LineNumberTable;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.AASTORE;
+import org.apache.bcel.generic.ACONST_NULL;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.ANEWARRAY;
+import org.apache.bcel.generic.ARRAYLENGTH;
+import org.apache.bcel.generic.ATHROW;
+import org.apache.bcel.generic.ArrayType;
+import org.apache.bcel.generic.BasicType;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.DUP;
+import org.apache.bcel.generic.DUP_X1;
+import org.apache.bcel.generic.FieldGen;
+import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.IADD;
+import org.apache.bcel.generic.ICONST;
+import org.apache.bcel.generic.IFNE;
+import org.apache.bcel.generic.IFNONNULL;
+import org.apache.bcel.generic.IF_ICMPLT;
+import org.apache.bcel.generic.IINC;
+import org.apache.bcel.generic.INVOKESPECIAL;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionConstants;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.InvokeInstruction;
+import org.apache.bcel.generic.LDC;
+import org.apache.bcel.generic.LocalVariableGen;
+import org.apache.bcel.generic.MONITOREXIT;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.NOP;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.POP;
+import org.apache.bcel.generic.PUSH;
+import org.apache.bcel.generic.ReturnInstruction;
+import org.apache.bcel.generic.TABLESWITCH;
+import org.apache.bcel.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
+{
+	private static final String AFTER_INIT = "_OT$after_init$";
+	// 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;
+
+	private boolean classNeedsTransformation = false;
+
+	// methods awaiting statements as an initial wrapper:
+    private HashSet<String/*methodName*/> pendingInitialWrappers;
+    // methods awaiting a super call to an existing initial wrapper:
+    private HashSet<String/*methodName*/> pendingSuperDelegationWrappers;
+
+	public boolean useReflection = false;
+
+	public BaseMethodTransformation(Object loader) {
+		super(loader);
+	}
+	/**
+	 *  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();
+    		String method_signature = m.getSignature();
+
+    		if (this.classNeedsTransformation) {
+    			if (pendingInitialWrappers.contains(method_name + '.' + method_signature))
+    				cg.replaceMethod(m, m = generateInitialWrapper(m, class_name, cg.getMajor(), cpg));
+    			else if (pendingSuperDelegationWrappers.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 = newMethodGen(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
+				{ 
+					@SuppressWarnings("deprecation") // type of is (invokespecial) cannot be array type
+					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)) {
+    		// TODO: where to add the role set infrastructure, if only an interface is bound? Implementing classes?
+    		if (cg.containsField(OTConstants.ROLE_SET) == null) { // TODO(SH): this doesn't help for interfaces, do we need to check more?
+    			switch (CallinBindingManager.hasBoundBaseParent(class_name)) {
+    			case NONE:
+	    			ce.addImplements(OTConstants.IBOUND_BASE, cg); // regardless of ifc or class
+	    			//$FALL-THROUGH$
+    			case INTERFACE:
+    				if (!cg.isInterface()) {
+		    			ce.addField(generateRoleSet(cpg, class_name), cg);
+		    			ce.addMethod(generateAddRole(cpg, class_name), cg);
+		    			ce.addMethod(generateRemoveRole(cpg, class_name), cg);
+    				}
+    				break;
+    			case CLASS:
+    				// do nothing, superclass has all the infra structure already
+    				break;
+    			}
+    		}
+    	}
+
+    	if (pendingInitialWrappers == null)
+    		pendingInitialWrappers = new HashSet<String>();
+    	if (pendingSuperDelegationWrappers == null)
+    		pendingSuperDelegationWrappers = new HashSet<String>();
+
+
+    	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);
+			
+    	// if class is already transformed by this transformer
+    	/*
+    	 if (interfaceTransformedClasses.contains(class_name))
+    	 	continue;
+		*/
+			
+    	if(cg.isInterface()) {
+    		// may need to add an interface version of the chaining wrapper, to be called for a base-call
+    		int lastDollar = class_name.lastIndexOf('$');
+    		if (lastDollar != -1) {
+    			// try inserting __OT__ to last type name segment
+	    		String roleClassName = class_name.substring(0, lastDollar+1)+"__OT__"+class_name.substring(lastDollar+1);
+				if (CallinBindingManager.isBoundBaseClass(roleClassName)) {
+			    	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 signature   = m.getSignature();
+						Collection<MethodBinding> bindingsForMethod = CallinBindingManager .
+		    					getBindingForBaseMethod(roleClassName, method_name, signature);
+		    			if (bindingsForMethod!= null) {
+			    			MethodGen chainGen = generateChainingWrapper(class_name, cpg, 
+			    					m.getAccessFlags()|Constants.ACC_ABSTRACT, method_name, signature, null/*argumentNames*/);
+			    			if (cg.containsMethod(chainGen.getName(), chainGen.getSignature()) == null)
+			    				ce.addMethod(chainGen.getMethod(), cg);
+		    			}
+			    	}
+	    		}
+    		}
+
+    		//CallinBindingManager.addBoundBaseInterface(class_name); // <- this is to late, implementing class may be loaded before!!
+    		return; // No transfomations neccessary for interfaces.
+    	}
+
+    	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(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);
+			BoundClass topBase = CallinBindingManager.getTopmostBoundBaseClass(class_name);
+			if (topBase != null && !topBase.getName().equals(class_name)) {
+				// initial wrapper will lock against that super-base, create another field for that class' literal:
+				ce.addField(new FieldGen(Constants.ACC_PROTECTED|Constants.ACC_STATIC, 
+				              			 classType, 
+				              			 OTConstants.CLASS+topBase.getName().replace('.','$'),
+				              			 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;
+    		/*if (bindingsForMethod != null || containsSign(inheritedSigns, m)*/ /*|| containsSign(interfaceInheritedSigns, m)*/ //) {
+    		MethodBinding inheritedBinding = matchingBinding(inheritedBindings, m, false);
+    		String method_key = method_name+'.'+method_signature;
+    		
+    		if (bindingsForMethod != null && INIT.equals(method_name)) {
+    			
+    			//add method '_OT$after_init$' :
+    			mg = getConcretMethodGen(m, class_name, cpg);
+    			MethodGen chainGen = generateAfterConstructorWrapper(class_name, cpg,
+    									mg.getAccessFlags(), method_name, method_signature, mg.getArgumentNames());
+    			Method    chain    = generateAfterConstructorWrapperBody(class_name, cg, cpg, 
+    									mg, method_name, method_signature, chainGen, firstLine);
+													
+    			if (cg.containsMethod(chain.getName(), chain.getSignature()) == null)
+    				ce.addMethod(chain, cg);
+    			
+    			mg = new MethodGen(m, class_name, cpg);
+    			InstructionList il = mg.getInstructionList();
+    			InstructionHandle end = il.getEnd();
+    			if (end.getInstruction() instanceof ReturnInstruction) {
+//    				CodeExceptionGen[] excGens = mg.getExceptionHandlers(); // needed to update exception handlers?
+    				end.setInstruction(new NOP());
+    				InstructionHandle afterInitDispatch = il.append(new NOP());
+    				createInitialDispatchCode(il, class_name, AFTER_INIT, mg, false, Type.VOID, cg.getMajor(), cpg);
+    				InstructionHandle[] instructionHandles = il.getInstructionHandles();
+					for (InstructionHandle ih : instructionHandles) {
+						if (ih == afterInitDispatch) break;
+    					if (ih.getInstruction() instanceof ReturnInstruction) {
+    						ih.setInstruction(new NOP());
+    						il.insert(ih, new GOTO(afterInitDispatch));
+    					}
+    				}
+    				// tidy:
+    		        mg.setMaxStack();
+    		        mg.setMaxLocals();
+    		        Method generatedMethod = mg.getMethod();
+    		        il.dispose();
+    		        ce.addOrReplaceMethod(generatedMethod, cg);
+    			}
+    			continue;
+    		}
+    	
+			if (bindingsForMethod != null || (inheritedBinding != null && !m.isStatic() && !m.isPrivate())) {
+    			
+    			mg = newMethodGen(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 (inheritedBinding != null) {
+                	if (method_signature.equals(inheritedBinding.getBaseMethodSignature()))
+                		pendingSuperDelegationWrappers.add(method_key);
+                	else // override with covariant return: at the VM-level this is a *new* method, need a new initial wrapper
+                		pendingInitialWrappers.add(method_key);
+                }
+    		}
+
+    		/*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' :
+    			mg = getConcretMethodGen(m, class_name, cpg);
+    			MethodGen chainGen = generateChainingWrapper(class_name, cpg,
+    									mg.getAccessFlags(), method_name, method_signature, mg.getArgumentNames());
+    			Method    chain    = generateChainingWrapperBody(class_name, cg, cpg, 
+    									mg, method_name, method_signature, chainGen, firstLine);
+													
+    			if (cg.containsMethod(chain.getName(), chain.getSignature()) == null)
+    				ce.addMethod(chain, cg);
+
+    			pendingInitialWrappers.add(method_key);
+    			pendingSuperDelegationWrappers.remove(method_key); // might have prematurely added this above
+    		}
+    		if (mg == null)
+                if (logging) printLogMessage("No method binding (direct or inherited) found for " //$NON-NLS-1$
+                            + method_name);
+    	}
+    	this.classNeedsTransformation = true;
+    }
+    
+    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)) {
+					@SuppressWarnings("deprecation") // type if is (invokespecial) cannot be array type
+					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();
+			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();
+
+        String  name_chain      = genChainMethName(method_name);
+
+        InstructionList il      = mg.getInstructionList();
+        
+        createInitialDispatchCode(il, class_name, name_chain, mg, m.isStatic(), object, major, cpg);
+		// tidy:
+        mg.setMaxStack();
+        mg.setMaxLocals();
+        Method generatedMethod = mg.getMethod();
+        il.dispose();
+        return generatedMethod;
+	}
+    private void createInitialDispatchCode(InstructionList il,
+    										String class_name,
+    										String name_chain,
+    										MethodGen mg,
+    										boolean isStatic,
+    										Type chainReturnType,
+    										int major,
+    										ConstantPoolGen cpg) 
+    {
+        Type[]  argTypes        = mg.getArgumentTypes();
+        Type    returnType      = mg.getReturnType();
+
+        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) {
+		    BoundClass superBase = CallinBindingManager.getTopmostBoundBaseClass(class_name);
+		    String classNameForLiteral = superBase != null ? superBase.getName() : class_name;
+		    Pair<Integer,InstructionHandle> monitorResult = addClassMonitorEnter(mg, il, class_name, classNameForLiteral, 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(!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 = isStatic?0:1;
+        // chaining wrapper is always public, so never user INVOKESPECIAL:
+        short invocationKind = 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);
+    }
+
+	/**
+	 * 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. 
+	 * @param class_name			the name of the appropriate class
+	 * @param cpg					the ConstantPoolGen of the class
+	 * @param accessFlags			raw flags of the method to add, visibility will however be ignored/set to public inside
+	 * @param method_name			the name of the original method
+	 * @param method_signature	    the signature of the original method
+	 * @param argumentNames			source level argument names, may be null
+	 * @return an new method with an empty instruction list
+	 */
+	MethodGen generateChainingWrapper(String 	 		class_name, 
+								      ConstantPoolGen 	cpg, 
+								      int	   			accessFlags,
+								      String 	 		method_name,
+								      String 	 		method_signature,
+								      String[] 			argumentNames)
+    {
+		Type[] argumentTypes = Type.getArgumentTypes(method_signature);
+		if (argumentNames == null) {
+			argumentNames = new String[argumentTypes.length];
+			for (int i = 0; i < argumentNames.length; i++)
+				argumentNames[i] = "arg"+i;
+		}
+        return new MethodGen(makePublicFlags(accessFlags), // the chaining wrapper has to be 'public' because it will be called by base calls:
+        					 object,  					   // ALWAYS!
+        					 enhanceArgumentTypes(argumentTypes),
+        					 enhanceArgumentNames(argumentNames),
+        					 genChainMethName(method_name),
+        					 class_name,
+        					 new InstructionList(), 
+        					 cpg);
+    }
+	
+	/**
+	 * Create the instructions for the chaining wrapper, which includes dispatch code
+	 * and the termination condition for the recursion.
+	 * @param class_name
+	 * @param cg
+	 * @param cpg
+	 * @param mg
+	 * @param method_name
+	 * @param method_signature
+	 * @param chainMethod
+	 * @param firstLine
+	 * @return
+	 */
+	Method generateChainingWrapperBody(String 	 		class_name,
+			   						   ClassGen  		cg,
+			   						   ConstantPoolGen 	cpg,
+			   						   MethodGen 		mg,
+			   						   String 	 		method_name,
+			   						   String 	 		method_signature, 
+			   						   MethodGen		chainMethod,
+			   						   int 		 		firstLine)
+	{
+		Type 			origReturnType     = mg.getReturnType();
+		Type[]          argumentTypes      = mg.getArgumentTypes();
+        Type 			enhancedReturnType = chainMethod.getReturnType(); 
+        InstructionList il     			   = chainMethod.getInstructionList();
+        
+		// 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;
+    }
+
+	/**
+	 * Generate a chaining wrapper for the original method described by the passed arguments. 
+	 * @param class_name			the name of the appropriate class
+	 * @param cpg					the ConstantPoolGen of the class
+	 * @param accessFlags			raw flags of the method to add, visibility will however be ignored/set to public inside
+	 * @param method_name			the name of the original method
+	 * @param method_signature	    the signature of the original method
+	 * @param argumentNames			source level argument names, may be null
+	 * @return an new method with an empty instruction list
+	 */
+	MethodGen generateAfterConstructorWrapper(String 	 		class_name, 
+								      		  ConstantPoolGen 	cpg, 
+								      		  int	   			accessFlags,
+								      		  String 	 		method_name,
+								      		  String 	 		method_signature,
+								      		  String[] 			argumentNames)
+    {
+		Type[] argumentTypes = Type.getArgumentTypes(method_signature);
+		if (argumentNames == null) {
+			argumentNames = new String[argumentTypes.length];
+			for (int i = 0; i < argumentNames.length; i++)
+				argumentNames[i] = "arg"+i;
+		}
+        return new MethodGen(accessFlags,
+        					 Type.VOID,  					   // ALWAYS!
+        					 enhanceArgumentTypes(argumentTypes),
+        					 enhanceArgumentNames(argumentNames),
+        					 AFTER_INIT,
+        					 class_name,
+        					 new InstructionList(), 
+        					 cpg);
+    }
+	
+	/**
+	 * Create the instructions for the chaining wrapper, which includes dispatch code
+	 * and the termination condition for the recursion.
+	 * @param class_name
+	 * @param cg
+	 * @param cpg
+	 * @param mg
+	 * @param method_name
+	 * @param method_signature
+	 * @param chainMethod
+	 * @param firstLine
+	 * @return
+	 */
+	Method generateAfterConstructorWrapperBody(String 	 		class_name,
+			   						   ClassGen  		cg,
+			   						   ConstantPoolGen 	cpg,
+			   						   MethodGen 		mg,
+			   						   String 	 		method_name,
+			   						   String 	 		method_signature, 
+			   						   MethodGen		chainMethod,
+			   						   int 		 		firstLine)
+	{
+        InstructionList il     			   = chainMethod.getInstructionList();
+       
+        InstructionHandle ih;
+        int ot_team;
+		{
+			LocalVariableGen lg = chainMethod.addLocalVariable("_OT$team", teamType, null, null); //$NON-NLS-1$
+			ot_team = lg.getIndex();
+			// generated: Team _OT$team;
+		}
+
+        il.append(InstructionFactory.createLoad(Type.INT, IDX_ARG));
+        il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG));
+        il.append(new ARRAYLENGTH());
+        IF_ICMPLT recursionNotYetTerminated = new IF_ICMPLT(null);
+        il.append(recursionNotYetTerminated);
+        // generated: if (_OT$teams.length < _OT$idx) {
+     
+		// terminate the recursion:
+        il.append(InstructionFactory.createReturn(Type.VOID));
+        // generated: return;
+
+        ih = il.append(new NOP());
+        recursionNotYetTerminated.setTarget(ih);
+        // generated: ; (end of the if part)
+
+        il.append(InstructionFactory.createLoad(teamArray, TEAMS_ARG));
+        il.append(InstructionFactory.createLoad(Type.INT,  IDX_ARG));
+        il.append(InstructionFactory.createArrayLoad(teamType));
+        il.append(InstructionFactory.createStore(teamType, ot_team));
+        // generated: _OT$team = _OT$teams[_OT$idx];
+
+        // ---------------------------------------------
+        createAfterCtorDispatchCode(chainMethod, il,
+						   class_name, method_name,
+						   method_signature, ot_team, cg, firstLine);
+        // ---------------------------------------------
+        il.append(InstructionFactory.createReturn(Type.VOID));
+        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$
+        }
+    }
+
+	/**
+	 *  Generate the dispatch code by which a chaining wrapper invokes the
+	 *  callin method(s).
+	 *  For constructors we only have one block: 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 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 createAfterCtorDispatchCode(MethodGen chainMethod, InstructionList il,
+							String class_name, String method_name,
+							String method_signature, int ot_team, ClassGen cg, int firstLine)
+    {
+		// no sort by modifier since we only handle "after" here.
+        Collection<MethodBinding> callinsForMethod;
+        callinsForMethod = CallinBindingManager.getBindingForBaseMethod(class_name,
+        																method_name, method_signature);
+        List<MethodBinding> inheritedMethodBindings = CallinBindingManager.getInheritedBaseMethodBindings(class_name, method_name, method_signature);
+        
+        //----------------------------------------------------------------------------------------------
+        if (!chainMethod.isStatic())
+        	callinsForMethod.addAll(inheritedMethodBindings);
+        
+        ListValueHashMap<MethodBinding> afterBindings = new ListValueHashMap<MethodBinding>();
+        
+        Iterator<MethodBinding> it = callinsForMethod.iterator();
+        while (it.hasNext()) {
+        	MethodBinding methodBinding = it.next();
+        	//sourceMapGen.addSourceMapInfo(methodBinding);
+        	// ----> added for precedence purpose:
+        	if (methodBinding.getModifier().equals("after")) { //$NON-NLS-1$
+        		afterBindings.put(methodBinding.getTeamClassName(), methodBinding);
+        	}
+        	// <---
+        }
+        
+        /****************************************************************************/
+        // after callin :
+        if (afterBindings.size() > 0) { //$NON-NLS-1$
+            if(logging) printLogMessage("after bindings will be applied..."); //$NON-NLS-1$
+        	il.append(createSwitch(
+        				  afterBindings,
+        				  chainMethod, ot_team,
+        				  /*NORESULT*/-1, firstLine, cg.getMajor(), false));
+            if(logging) printLogMessage("after bindings: " //$NON-NLS-1$
+        					+ afterBindings); //$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}
+	 *  and {@link org.objectteams.LiftingFailedException LiftingFailedException}
+	 *  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 = CallinBindingManager.sortMethodBindings(entry.getValue(), teamName);
+			//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);
+		mg.addExceptionHandler(il.getStart(), endTry, hdlr, liftingFailed);
+
+		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 teamClassName name of a Team which has a callin to this method.
+	 * @param sortedMBList MethodBindings describing the callins (already processed by CallinBindingManager.sortMethodBindings)
+	 * @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 teamClassName,
+							   List<MethodBinding> sortedMBList, int ot_result, int ot_team,
+							   int major, int firstLine)
+    {	
+
+		MethodBinding mb = sortedMBList.get(0);
+		ConstantPoolGen cpg = mg.getConstantPool();
+
+		// after bindings are processed back-to-front:
+		if (mb.isAfter()) {
+			List<MethodBinding> reverse = new ArrayList<MethodBinding>(sortedMBList.size());
+			for(int i=sortedMBList.size()-1; i>=0; i--)
+				reverse.add(sortedMBList.get(i));
+			sortedMBList = reverse;
+		}
+		
+		Iterator<MethodBinding> it = sortedMBList.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, mg.getClassName(), 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(teamClassName)));
+				// 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(teamClassName,
+											   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, String class_name_this, 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, class_name_this, ((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, class_name_this, 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 teamClassName name of a Team which has a callin to this method.
+	 * @param sortedMBList MethodBindings describing the callins (already processed by CallinBindingManager.sortMethodBindings)
+	 * @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 teamClassName, List<MethodBinding> sortedMBList,
+						   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 = sortedMBList.size() > 1;
+		
+		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 = sortedMBList.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 = sortedMBList.iterator();
+			MethodBinding mb = null; // safe because loop will definitely be entered (mbList.size() > 1)
+			while (mbIterator.hasNext()) {
+				mb = mbIterator.next();
+				matches[caseCounter] = caseCounter;
+				InstructionHandle nextBranch = addition.append(new NOP());
+				// ========== create Cases: ===========
+				addition.append(createSingleReplaceCallin(mg, teamClassName, 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);
+			mg.addExceptionHandler(addition.getStart(), endTry, hdlr, liftingFailed);
+			
+			InstructionHandle nop = addition.append(new NOP());
+			skipHdlr.setTarget(nop);
+			il.append(addition);
+		} else { // only a single replace callin:
+			MethodBinding mb = sortedMBList.get(0); // default, if only one binding exists
+			il.append(createSingleReplaceCallin(mg, teamClassName, 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, mg.getClassName(), 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 (RepositoryAccess.safeSubclassOf(actualObj, 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|Constants.ACC_TRANSIENT, 
+                                   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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ClassEnhancer.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ClassEnhancer.java
new file mode 100644
index 0000000..ce12bb7
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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 org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java
new file mode 100644
index 0000000..a92e184
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ClassLoaderAccess.java
@@ -0,0 +1,69 @@
+/**********************************************************************
+ * This file is part of the "Object Teams Runtime Environment"
+ * 
+ * Copyright 2013 GK Software AG
+ *  
+ * 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
+ * 
+ * Please visit http://www.objectteams.org for updates and contact.
+ * 
+ * Contributors:
+ * 	Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otre;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+
+/**
+ * Generalization over different strategies for obtaining a resource / class on the classpath.
+ * <p>
+ * If a {@link ClassLoader} is provided use its method {@link ClassLoader#getResource(String)} 
+ * and {@link ClassLoader#loadClass(String)}.
+ * </p><p>
+ * Otherwise we need a {@link Method} instance for each kind of access which needs to match
+ * the type of the object passed as "loader". The latter method is used in Equinox settings,
+ * where the "loader" will be an <code>org.osgi.framework.Bundle</code>.
+ * </p><p>
+ * Selecting one of the above strategies happens globally when the system start up,
+ * which implies that {@link #setGetResource(Method)} and {@link #setLoadClass(Method)}
+ * need to be called before any weaving is triggered.
+ * </p>
+ */
+public class ClassLoaderAccess {
+
+	private static Method getResourceMethod;
+	private static Method loadClassMethod;
+
+	public static void setGetResource(Method method) {
+		getResourceMethod = method;
+	}
+	public static void setLoadClass(Method method) {
+		loadClassMethod = method;
+	}
+
+	public static InputStream getResourceAsStream(Object loader, String name) {
+		if (loader instanceof ClassLoader)
+			return ((ClassLoader) loader).getResourceAsStream(name);
+		try {
+			URL url = (URL) getResourceMethod.invoke(loader, name);
+			return url.openStream();
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	public static Class<?> loadClass(Object loader, String name) 
+			throws ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException 
+	{
+		if (loader instanceof ClassLoader)
+			return ((ClassLoader) loader).loadClass(name);
+		else
+			return (Class<?>)loadClassMethod.invoke(loader, name);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/Decapsulation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/Decapsulation.java
new file mode 100644
index 0000000..c9c8ae1
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/Decapsulation.java
@@ -0,0 +1,401 @@
+/**********************************************************************
+ * 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.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 org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.Type;
+
+/**
+ *  For each base method that is bound by callout and has
+ *  insufficient visibility, the visibility is set to public.
+ *  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();
+
+	private HashSet<String/*callout accessed fields*/> generatedFieldCalloutAccessors = new HashSet<String>();
+	private HashSet<String/*super-accessed methods (sign)*/> generatedSuperAccessors  = new HashSet<String>();
+	
+    public Decapsulation(Object loader) {
+    	super(loader);
+    }
+
+	/**
+	 * Main entry for this transformer.
+	 */
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {		
+		String          class_name = cg.getClassName();
+		ConstantPoolGen cpg        = cg.getConstantPool();
+
+		checkReadClassAttributes(ce, cg, class_name, cpg);
+
+
+		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 = this.generatedFieldCalloutAccessors;
+
+		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_" + class_name +"." + 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);
+			}
+		}
+
+		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_"+ class_name +"." + 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);
+			}
+		}
+	}
+
+
+	/**
+	 * 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 = this.generatedSuperAccessors;
+
+		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);
+			}
+		}
+	}
+	
+	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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
new file mode 100644
index 0000000..14c402c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/LiftingParticipantTransformation.java
@@ -0,0 +1,184 @@
+/**********************************************************************
+ * 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 java.lang.reflect.Field;
+
+import org.objectteams.Team;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.BranchInstruction;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.DUP;
+import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.IFNULL;
+import org.apache.bcel.generic.INVOKESPECIAL;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.LDC;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.NEW;
+import org.apache.bcel.generic.NOP;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.POP;
+import org.apache.bcel.generic.Type;
+import org.eclipse.objectteams.otre.jplis.JPLISEnhancer;
+
+/**
+ * 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(Object loader) { super(loader); }
+
+	public void doTransformCode(ClassGen cg) 
+	{
+		if (!classNeedsTeamExtensions(cg)) return;
+
+		synchronized (LiftingParticipantTransformation.class) {
+			try {
+				checkInitParticipant();
+			} catch (Exception e) {
+				new IllegalArgumentException("Lifting participant "+PARTICIPANT_NAME+" is invalid.", e).printStackTrace();
+				PARTICIPANT_NAME = null;
+			}
+			if (PARTICIPANT_NAME == null)
+				return;
+		}
+		
+    	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));
+	    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+    	}
+	}
+
+	private void checkInitParticipant() throws Exception {
+		if (checked) return;
+		checked = true;
+
+		Field participantField = Team.class.getField(LIFTING_PARTICIPANT_FIELD);
+		Object participant = participantField.get(null);
+
+		if (PARTICIPANT_NAME != null) 
+		{
+			// initialize from property "ot.lifting.participant"
+			if (participant != null)
+				throw new IllegalStateException("liftingParticipant already installed.");				
+			// install a shared instance into class Team:
+			Class<?> participantClass = ClassLoaderAccess.loadClass(loader, PARTICIPANT_NAME); 
+			participantField.set(null, participantClass.newInstance());
+		} 
+		else if (participant != null) 
+		{
+			// field was already initialized by a third party
+			
+			// fetch the class name to signal that transformations are needed.
+			PARTICIPANT_NAME = participant.getClass().getName();
+		}
+	}
+
+	private Method weaveLiftingParticipant(Method m, String className, ConstantPoolGen cpg) {
+		MethodGen mg = newMethodGen(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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/OTConstants.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/OTConstants.java
new file mode 100644
index 0000000..1a985cb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/OTConstants.java
@@ -0,0 +1,188 @@
+/**********************************************************************
+ * 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 org.apache.bcel.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.objectteams.LiftingVetoException</tt> */
+    ObjectType liftingFailed = new ObjectType("org.objectteams.LiftingFailedException");
+    /**                            Type <tt>org.eclipse.objectteams.otre.OTREInternalError</tt> */	
+    ObjectType internalError = new ObjectType("org.eclipse.objectteams.otre.OTREInternalError");
+	/**                            Type <tt>org.objectteams.ResultNotProvidedError</tt> */	
+	ObjectType notProvidedError = new ObjectType("org.objectteams.ResultNotProvidedError");
+	/**                            Type <tt>org.objectteams.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";
+	
+	String INIT	= "<init>";
+	
+	// ============ VERSION: ==============
+	public static final int    OT_VERSION_MAJOR = 1;
+    public static final int    OT_VERSION_MINOR = 6;
+    
+    // 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;
+
+    // required compiler revision in the 1.5 (=0.7) stream:
+    public static final int    OT15_REVISION = 0;
+
+    // required compiler revision in the 1.6 (=0.8/2.0) stream:
+    public static final int    OT16_REVISION = 0;
+
+    // ------------------------------------------
+	// ---------- 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$";
+	final static String CLASS 		= "_OT$class_literal$";
+
+	// -----------------------------------------
+	// ---------- 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/OTREInternalError.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/OTREInternalError.java
new file mode 100644
index 0000000..e9bb7c0
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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 submit a bug report at https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Objectteams.\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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
new file mode 100644
index 0000000..daaa278
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ObjectTeamsTransformation.java
@@ -0,0 +1,2269 @@
+/**********************************************************************
+ * 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.jplis.JPLISEnhancer;
+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 org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Attribute;
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantUtf8;
+import org.apache.bcel.classfile.InnerClass;
+import org.apache.bcel.classfile.InnerClasses;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.LineNumberTable;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.classfile.StackMap;
+import org.apache.bcel.classfile.Unknown;
+import org.apache.bcel.generic.*;
+
+/**
+ * Superclass for all transformations in this package.
+ * This class and its subclasses does not directly depend on 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";
+    }
+   
+    /** Common factory for all tranformers.
+	 *	To be initialized once we get a class for transformation. */
+	InstructionFactory factory;
+   
+    /** Which class loader are we working for? */
+    protected Object loader; // standalone: ClassLoader, new equinox.weaving: Bundle
+
+	public ObjectTeamsTransformation(Object loader) {
+		this.loader = loader;
+	}
+
+	// ------------------------------------------
+	// ---------- 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>. */
+	 public 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 = newMethodGen(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 = null;
+    			try {
+    				teamClass = RepositoryAccess.lookupClassFully(nextTeam);
+    			} catch (ClassNotFoundException cfne) {
+    				System.err.println("Config error: Team class '"+nextTeam+ "' in config file '"+ TEAM_CONFIG_FILE+"' can not be found!");
+    				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());
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+    }
+
+	/**
+	 * @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];
+						boolean baseIsInterface = false;
+						if (base_name.charAt(0) == '^') {
+							baseIsInterface = true;
+							base_name = base_name.substring(1);
+						}
+                        if(logging) printLogMessage("**** Binding: " + role_name 
+                                                    + " playedBy " + base_name);
+
+                        //set binding:
+                        CallinBindingManager.addRoleBaseBinding(role_name, base_name, baseIsInterface, 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);
+                			
+                			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 {
+	                		// [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("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
+					// 1.6 stream:
+					if (major == 1 && minor == 6) {
+						// accept all revisions within this stream
+						IS_COMPILER_GREATER_123 = true;
+						IS_COMPILER_13X_PLUS = true;
+						IS_COMPILER_14X_PLUS = true;
+					// 1.5 stream:
+					} else if (major == 1 && minor == 5) {
+						if (revision < OT15_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.4 stream:
+					} else 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);
+						}
+					// other major/minor version?
+					} 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);
+						throw new InternalError("OTRE: Class " + class_name + " has unrecognized version " + major+"."+minor+"."+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("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;	
+	}*/
+    
+    /** Create a MethodGen and remove some unwanted code attributes (which would need special translation which we don't have) */
+    protected static MethodGen newMethodGen(Method m, String class_name, ConstantPoolGen cp) {
+    	MethodGen mg = new MethodGen(m, class_name, cp);
+    	List<Attribute> attributesToRemove = new ArrayList<Attribute>();
+    	for (Attribute attr : mg.getCodeAttributes())
+    		if (attr instanceof Unknown || attr instanceof StackMap)
+    			attributesToRemove.add(attr);
+		for (Attribute attr : attributesToRemove)
+			mg.removeCodeAttribute(attr);
+    	return mg;
+    }
+    
+    /**
+     * 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.removeExceptionHandlers();
+        mg.removeAttributes();
+        mg.removeCodeAttributes();
+        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 = newMethodGen(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());
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+	}
+
+	/** 
+	 * 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)			// must be a team
+				&& ((cg.getAccessFlags() & Constants.ACC_ABSTRACT) == 0)	// and non-abstract
+				&& !(cg.getClassName().equals(OTConstants.teamClassName));	// and not o.o.Team itself.
+	}
+
+	/**
+	 * 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 = newMethodGen(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
+
+		insertBeforeReturn(mg, il, postfix);
+
+		/**
+		 * **** 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)
+	{
+		return addClassMonitorEnter(mg, il, class_name, class_name, major, cpg);
+	}
+	protected Pair<Integer,InstructionHandle> addClassMonitorEnter(MethodGen 		mg, 
+			   InstructionList 	il,
+			   String			class_name_this,
+			   String			class_name_target,
+			   int 				major, 
+			   ConstantPoolGen 	cpg)
+	{
+		int monitor;
+		InstructionHandle ih= 
+			appendClassLiteral(il, class_name_this, class_name_target, 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_this,
+												   String          class_name_target,
+												   int             major,
+												   ConstantPoolGen cpg) 
+	{
+		if (major >= 49) // java 5
+			return il.append(new LDC(cpg.addClass(new ObjectType(class_name_target))));
+		// pre java 5, do it the hard way:
+		// if (_OT$self_class$ != null)
+		// if (ThisClass._OT$class$that$Class != null)
+	    String receiverClass = class_name_this;
+	    String fieldName = class_name_this.equals(class_name_this) ? OTConstants.SELF_CLASS : OTConstants.CLASS+class_name_target;
+	  InstructionHandle start= 
+		il.append(factory.createFieldAccess(receiverClass, fieldName, 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_target)));
+	  	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(receiverClass, fieldName, classType, Constants.PUTSTATIC));
+	
+	  	checkLoaded.setTarget(il.append(new NOP()));
+	  	return start;
+	}
+
+	@SuppressWarnings("unchecked")
+	public static void insertBeforeReturn(MethodGen mg, InstructionList il, InstructionList insertion) {
+		// InstructionFinder is broken see https://issues.apache.org/bugzilla/show_bug.cgi?id=40044
+		// which is fixed in r516724 (2007-03-10) but latest release bcel 5.2 is 6. June 2006.
+//		Iterator<InstructionHandle[]> ihIt = new InstructionFinder(il).search("ReturnInstruction");
+//		while (ihIt.hasNext()) {
+//			InstructionHandle[] ihAr = ihIt.next();
+//			InstructionList insertionCopy = insertion.copy();
+//			if (debugging)
+//				mg.addLineNumber(insertionCopy.getStart(), STEP_OVER_LINENUMBER);
+//			InstructionHandle inserted = il.insert(ihAr[0], insertionCopy); // instruction lists can not be reused
+//			il.redirectBranches(ihAr[0], inserted);// SH: retarget all jumps that targeted at the return instruction
+//		}
+		Iterator<InstructionHandle>ihIt = il.iterator();
+		while (ihIt.hasNext()) {
+			InstructionHandle ihAr = ihIt.next();
+			if (!(ihAr.getInstruction() instanceof ReturnInstruction))
+				continue;
+			InstructionList insertionCopy = insertion.copy();
+			if (debugging)
+				mg.addLineNumber(insertionCopy.getStart(), STEP_OVER_LINENUMBER);
+			InstructionHandle inserted = il.insert(ihAr, insertionCopy); // instruction lists can not be reused
+			il.redirectBranches(ihAr, inserted);// SH: retarget all jumps that targeted at the return instruction
+		}
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/RepositoryAccess.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/RepositoryAccess.java
new file mode 100644
index 0000000..dad2b76
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/RepositoryAccess.java
@@ -0,0 +1,136 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ * 
+ * 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.eclipse.objectteams.otre;
+
+import java.util.HashMap;
+
+import org.apache.bcel.Repository;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.generic.ObjectType;
+import org.eclipse.objectteams.otre.bcel.DietClassLoaderRepository;
+
+/** 
+ * Provides a classloader aware access to one or more class repositories.
+ * All access methods are static, but context is passed by setting a per-thread
+ * current repository using {@link #setClassLoader(ClassLoader)}.
+ * @since 0.7.0 
+ */
+public class RepositoryAccess {
+
+	/** One class repository per class loader. */
+	private static HashMap<Object,DietClassLoaderRepository> repositories = new HashMap<Object,DietClassLoaderRepository>();
+	/** One current repository per thread. */
+	private static ThreadLocal<DietClassLoaderRepository> currentRepository = new ThreadLocal<DietClassLoaderRepository>();
+	 
+	/** 
+	 * Setup a repository for the given class loader and make it the current repository for the current thread.
+	 * @param loader class loader, may be null
+	 * @return the previously active class repository for this thread
+	 */
+	public static synchronized DietClassLoaderRepository setClassLoader(Object loader) {
+		DietClassLoaderRepository clr = null;
+		if (loader != null) { // avoid creating ClassLoaderRepository with null loader
+			clr = repositories.get(loader);
+			if (clr == null)
+				repositories.put(loader, clr = new DietClassLoaderRepository(loader));
+		}
+		DietClassLoaderRepository prev = currentRepository.get();
+		currentRepository.set(clr);
+		return prev;
+	}
+	 
+	/** Reset the class repository for the current thread. */
+	public static synchronized void resetRepository(DietClassLoaderRepository repository) {
+		currentRepository.set(repository);
+	}
+	 
+	public static JavaClass lookupClass(String className)
+	 		throws ClassNotFoundException 
+	{
+		DietClassLoaderRepository clr = currentRepository.get();
+		if (clr != null)
+			return clr.loadClass(className);
+		return Repository.lookupClass(className);
+	}
+	 
+	public static JavaClass lookupClassFully(String className)
+	 		throws ClassNotFoundException 
+	{
+		DietClassLoaderRepository clr = currentRepository.get();
+		if (clr != null)
+			return clr.loadClassFully(className);
+		return Repository.lookupClass(className);
+	}
+
+	public static JavaClass[] getSuperClasses(String className) 
+			throws ClassNotFoundException 
+	{
+		 DietClassLoaderRepository clr = currentRepository.get();
+		 JavaClass jc;
+		 if (clr != null)
+			 jc = clr.loadClass(className);
+		 else
+			 jc = Repository.lookupClass(className);
+		 return jc.getSuperClasses();
+	}
+
+	public static boolean implementationOf(String className, String ifcName) 
+			throws ClassNotFoundException 
+	{
+		DietClassLoaderRepository clr = currentRepository.get();
+		JavaClass jc, ifc;
+		if (clr != null) {
+			jc = clr.loadClass(className);
+			ifc= clr.loadClass(ifcName);
+		} else {
+			jc = Repository.lookupClass(className);
+			ifc= Repository.lookupClass(ifcName);
+		}
+		return jc.implementationOf(ifc);
+	}
+
+	public static boolean safeSubclassOf(ObjectType subClass, ObjectType superClass) {
+		try {
+			String subClassName = subClass.getClassName();
+			String superClassName = superClass.getClassName();
+			return instanceOf(subClassName, superClassName);
+		} catch (ClassNotFoundException e) {
+			// consider classes as incommensurable if they can't both be loaded in the current class loader
+			return false;
+		} catch (ClassCircularityError e) {
+			// assume that circularity was caused by resolving framework classes during class loading
+			return false;
+		}
+	}
+
+	protected static boolean instanceOf(String subClassName, String superClassName) 
+			throws ClassNotFoundException 
+	{
+		DietClassLoaderRepository clr = currentRepository.get();
+		JavaClass subJClass, superJClass;
+		if (clr != null) {
+			subJClass = clr.loadClass(subClassName);
+			superJClass= clr.loadClass(superClassName);
+		} else {
+			subJClass = Repository.lookupClass(subClassName);
+			superJClass= Repository.lookupClass(superClassName);
+		}
+		if (subJClass == null)
+			return false;
+		return subJClass.instanceOf(superJClass);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
new file mode 100644
index 0000000..92faa22
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/StaticSliceBaseTransformation.java
@@ -0,0 +1,764 @@
+/**********************************************************************
+ * 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 java.util.HashMap;
+
+import org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.*;
+import org.eclipse.objectteams.otre.util.*;
+import org.eclipse.objectteams.otre.util.CallinBindingManager.BoundSuperKind;
+
+
+/**
+ * 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(Object loader) { super(loader); }
+	
+	private HashMap<String,String> rejectReasons = new HashMap<String, String>();
+
+	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) == BoundSuperKind.CLASS)
+			return; // team infrastructure already has been added to a super class
+
+		String reason = this.rejectReasons.get(class_name);
+		if (reason != null && !"already has clinit? static void <clinit>()".equals(reason))
+			new IllegalStateException(reason).printStackTrace();
+        ConstantPoolGen cpg = cg.getConstantPool();
+		factory = new InstructionFactory(cpg);
+		addStaticInitializations(cg, cpg);
+     }
+
+	/**
+	 * @param ce
+	 * @param cg
+	 */
+	public void doTransformInterface(ClassEnhancer ce, ClassGen cg) {
+	  try {
+		String class_name = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+		
+		checkReadClassAttributes(ce, cg, class_name, cpg);
+		
+		if (cg.isInterface()) {
+			this.rejectReasons.put(class_name, "is interface");
+			return; // can't add implementation
+		}
+		// IMPLICIT_INHERITANCE
+		if (!CallinBindingManager.isBoundBaseClass(class_name)
+		/*&& !CallinBindingManager.containsBoundBaseInterface(cg.getInterfaceNames())*/) {
+			this.rejectReasons.put(class_name, "not bound base class");
+			if ("org.eclipse.objectteams.otdt.internal.core.compiler.ast.RoleFileCache".equals(class_name))
+				new IllegalStateException("RoleFileCache is not recognized as bound base").printStackTrace();
+			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) == BoundSuperKind.CLASS) {
+			this.rejectReasons.put(class_name, "hasBoundBaseParent");
+			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) {
+			// the clinit-Method only has to be extended by the code transformation of this transformer
+			this.rejectReasons.put(class_name, "already has clinit? "+(clinit==null ? "no" : clinit.toString()));
+			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();
+	  } catch (RuntimeException re) {
+		  re.printStackTrace();
+		  throw re;
+	  } catch (Error err) {
+		  err.printStackTrace();
+		  throw err;
+	  }
+    }
+
+	/* 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);
+
+		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);
+		}
+		
+	  InstructionHandle exit =
+		il.append(InstructionFactory.createReturn(Type.VOID));
+	    earlyExit.setTarget(exit);
+
+
+		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);
+
+		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);
+		}
+
+	  InstructionHandle exit =
+		il.append(InstructionFactory.createReturn(Type.VOID));
+	  	earlyExit.setTarget(exit);
+	  	notFound.setTarget(exit);
+
+		removeTeamMethod.setMaxStack();
+		removeTeamMethod.setMaxLocals();
+		removeTeamMethod.removeNOPs();
+		return removeTeamMethod;
+	}
+
+    /**
+     * Add infrastructure for implicit subclasses to register and be notified. This 'observer' mechanism 
+     * is necessary, because an implicit subclass does not inherit the addition/removal 
+     * of a team at the implicit superclass. 
+	 * @param ce	The ClassEnhancer object to add methods and fields.
+	 * @param cg	The ClassGen object representing the current class. 
+	 */
+	private void addImplicitSubclassNotificationInfrastructure(ClassEnhancer ce, ClassGen cg) {
+
+		ConstantPoolGen cpg = cg.getConstantPool();
+		factory = new InstructionFactory(cpg);
+		String class_name = cg.getClassName();
+		ObjectType linkedListType = new ObjectType("java.util.LinkedList");
+		int accessFlags = Constants.ACC_PROTECTED | Constants.ACC_STATIC;
+		FieldGen teamRegistrationObserversField = new FieldGen(accessFlags, linkedListType, "_OT$teamRegistrationObservers", cpg);
+		ce.addField(teamRegistrationObserversField.getField(), cg);
+		
+/***********************************************************************************************************/
+		
+		InstructionList il = new InstructionList();
+		
+		MethodGen observerRegistrationMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+                                                    Type.VOID,
+                                                    new Type[] { classType },
+                                                    new String[] { "implicitSubClass" },
+                                                    "_OT$registerObserver", class_name,
+                                                    il, cpg);
+
+		il.append(factory.createFieldAccess(class_name, "_OT$teamRegistrationObservers", linkedListType, Constants.GETSTATIC));
+		il.append(InstructionFactory.createLoad(classType, 0));
+		il.append(factory.createInvoke("java.util.LinkedList", "add", Type.BOOLEAN, new Type[] { Type.OBJECT }, Constants.INVOKEVIRTUAL));
+		il.append(new POP());
+		il.append(new RETURN());
+		
+		observerRegistrationMethod.setMaxStack(2);
+		observerRegistrationMethod.setMaxLocals();
+		
+		ce.addMethod(observerRegistrationMethod.getMethod(), cg);
+/***********************************************************************************************************/
+		il = new InstructionList();
+		
+		MethodGen activateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+                                                    												  Type.VOID,
+																									  new Type[] { teamType, Type.INT },
+																									  new String[] { "team", "teamID" },
+																									  "_OT$activateNotify", class_name,
+																									  il, cpg);
+		
+		createNotifyMethodImplementation(activateNotifyMethod, cpg, class_name);
+		
+		ce.addMethod(activateNotifyMethod.getMethod(), cg);
+/***********************************************************************************************************/
+		il = new InstructionList();
+		
+		MethodGen deactivateNotifyMethod = new MethodGen(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+                                                    												  Type.VOID,
+																									  new Type[] { teamType },
+																									  new String[] { "team" },
+																									  "_OT$deactivateNotify", class_name,
+																									  il, cpg);
+		createNotifyMethodImplementation(deactivateNotifyMethod, cpg, class_name);
+
+		ce.addMethod(deactivateNotifyMethod.getMethod(), cg);
+	}
+
+
+	/**
+	 * Create implementation of methods '_OT$activateNotify' and _OT$deactivateNotify'.
+	 * @param notifyMethod	Method which has to be implemented.
+	 * @param cpg					Corresponding constant pool.
+	 * @param class_name	Name of the class for wich to implement the method.
+	 */
+	private void createNotifyMethodImplementation(MethodGen notifyMethod, ConstantPoolGen cpg, String class_name) {
+		boolean isActivateMethod = notifyMethod.getName().equals("_OT$activateNotify");
+//		int methodArgs = isActivateMethod ? 2 : 1;
+
+		int iteratorIdx = isActivateMethod ? 2 : 1;
+		int curClassIdx = isActivateMethod ? 3 : 2;
+		int anotherIdx1 = isActivateMethod ? 4 : 3;
+		int anotherIdx2 = isActivateMethod ? 5 : 4;
+		String methodToInvoke = isActivateMethod ? "_OT$addTeam" : "_OT$removeTeam";
+		
+		InstructionList il = notifyMethod.getInstructionList();
+		il.append(factory.createFieldAccess(class_name,  "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC));
+		BranchInstruction ifnonnull_3 = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
+		il.append(ifnonnull_3);
+		il.append(InstructionFactory.createReturn(Type.VOID));
+		InstructionHandle ih_7 = il.append(factory.createFieldAccess(class_name,  "_OT$teamRegistrationObservers", new ObjectType("java.util.LinkedList"), Constants.GETSTATIC));
+		il.append(factory.createInvoke("java.util.LinkedList", "iterator", new ObjectType("java.util.Iterator"), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		il.append(InstructionFactory.createStore(Type.OBJECT,iteratorIdx));
+		InstructionHandle ih_14 = il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx));
+		il.append(factory.createInvoke("java.util.Iterator", "hasNext", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEINTERFACE));
+		BranchInstruction ifeq_20 = InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
+		il.append(ifeq_20);
+		il.append(InstructionFactory.createLoad(Type.OBJECT,iteratorIdx));
+		il.append(factory.createInvoke("java.util.Iterator", "next", Type.OBJECT, Type.NO_ARGS, Constants.INVOKEINTERFACE));
+		il.append(factory.createCheckCast(classType));
+		il.append(InstructionFactory.createStore(Type.OBJECT,curClassIdx));
+		il.append(InstructionConstants.ACONST_NULL);
+		il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1));
+		InstructionHandle ih_36 = il.append(InstructionFactory.createLoad(Type.OBJECT,curClassIdx));
+		il.append(new PUSH(cpg, methodToInvoke));
+		il.append(new PUSH(cpg,iteratorIdx));
+		il.append((Instruction)factory.createNewArray(classType, (short) 1));
+		il.append(InstructionConstants.DUP);
+		
+		il.append(new PUSH(cpg, 0));
+		il.append(new PUSH(cpg, OTConstants.teamName));
+		il.append(factory.createInvoke("java.lang.Class", "forName", 
+															classType, new Type[] { Type.STRING },
+															 Constants.INVOKESTATIC));
+
+		il.append(InstructionConstants.AASTORE);
+		if (isActivateMethod){ // add the integer argument:
+			il.append(InstructionConstants.DUP);
+			il.append(new PUSH(cpg, 1));
+			il.append(factory.createFieldAccess("java.lang.Integer", "TYPE", classType, Constants.GETSTATIC));
+			il.append(InstructionConstants.AASTORE);
+		}
+		il.append(factory.createInvoke("java.lang.Class", "getMethod", new ObjectType("java.lang.reflect.Method"), new Type[] { Type.STRING, new ArrayType(classType, 1) }, Constants.INVOKEVIRTUAL));
+		InstructionHandle ih_76 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx1));
+		BranchInstruction goto_78 = InstructionFactory.createBranchInstruction(Constants.GOTO, null);
+		il.append(goto_78);
+		InstructionHandle ih_81 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
+		il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
+		il.append(new PUSH(cpg, "activateNotifyMethod not found!"));
+		il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
+		InstructionHandle ih_91 = il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1));
+		BranchInstruction ifnull_93 = InstructionFactory.createBranchInstruction(Constants.IFNULL, null);
+		il.append(ifnull_93);
+		il.append(InstructionFactory.createLoad(Type.OBJECT,anotherIdx1));
+		il.append(InstructionConstants.ACONST_NULL);
+		il.append(new PUSH(cpg,iteratorIdx));
+		il.append((Instruction)factory.createNewArray(Type.OBJECT, (short) 1));
+		il.append(InstructionConstants.DUP);
+		il.append(new PUSH(cpg, 0));
+		il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
+		il.append(InstructionConstants.AASTORE);
+
+		if (isActivateMethod) {	// load the integer argument:
+			il.append(InstructionConstants.DUP);
+			il.append(new PUSH(cpg, 1));
+			il.append(factory.createNew("java.lang.Integer"));
+			il.append(InstructionConstants.DUP);
+			il.append(InstructionFactory.createLoad(Type.INT, 1));
+			il.append(factory.createInvoke("java.lang.Integer", Constants.CONSTRUCTOR_NAME, Type.VOID, new Type[] { Type.INT }, Constants.INVOKESPECIAL));
+			il.append(InstructionConstants.AASTORE);
+		}
+		il.append(factory.createInvoke("java.lang.reflect.Method", "invoke", Type.OBJECT, new Type[] { Type.OBJECT, new ArrayType(Type.OBJECT, 1) }, Constants.INVOKEVIRTUAL));
+		InstructionHandle ih_121 = il.append(InstructionConstants.POP);
+		InstructionHandle ih_122;
+		BranchInstruction goto_122 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
+		ih_122 = il.append(goto_122);
+		InstructionHandle ih_125 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
+		il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
+		il.append(new PUSH(cpg, "Can not call activateNotifyMethod!"));
+		il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
+		BranchInstruction goto_135 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
+		il.append(goto_135);
+		InstructionHandle ih_138 = il.append(InstructionFactory.createStore(Type.OBJECT,anotherIdx2));
+		il.append(factory.createFieldAccess("java.lang.System", "err", new ObjectType("java.io.PrintStream"), Constants.GETSTATIC));
+		il.append(new PUSH(cpg, "InvocationTargetException"));
+		il.append(factory.createInvoke("java.io.PrintStream", "println", Type.VOID, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL));
+		BranchInstruction goto_148 = InstructionFactory.createBranchInstruction(Constants.GOTO, ih_14);
+		il.append(goto_148);
+		InstructionHandle ih_151 = il.append(InstructionFactory.createReturn(Type.VOID));
+		ifnonnull_3.setTarget(ih_7);
+		ifeq_20.setTarget(ih_151);
+		goto_78.setTarget(ih_91);
+		ifnull_93.setTarget(ih_122);
+		notifyMethod.addExceptionHandler(ih_36, ih_76, ih_81, new ObjectType("java.lang.NoSuchMethodException"));
+		notifyMethod.addExceptionHandler(ih_91, ih_121, ih_125, new ObjectType("java.lang.IllegalAccessException"));
+		notifyMethod.addExceptionHandler(ih_91, ih_121, ih_138, new ObjectType("java.lang.reflect.InvocationTargetException"));
+		
+		notifyMethod.setMaxStack();
+		notifyMethod.setMaxLocals();
+	}
+
+	/**
+     * Adds initialization of the team array and the team index array to the static initializer of this class.
+     * If this base class is a role at the same time, then also add initialization of the observer list.
+     * @param cg	The representation of the class.
+     * @param cpg	The constant pool of the class.
+	 */
+	private void addStaticInitializations(ClassGen cg, ConstantPoolGen cpg) {
+		Method clinitMethod = cg.containsMethod(Constants.STATIC_INITIALIZER_NAME, "()V");
+		 /* The clinit method always exists at this moment, because it has been added 
+         * by the interface transformer part of this transformer if necessary.
+         */
+		MethodGen mg = newMethodGen(clinitMethod, cg.getClassName(), cpg);
+		InstructionList il = mg.getInstructionList();
+		// add static initialization for added static fields at start of the <clinit> method:
+		il.insert(inizializeStaticFields(cg.getClassName()));
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		Method newClinit = mg.getMethod();
+		cg.replaceMethod(clinitMethod, newClinit);
+		il.dispose();
+		// Reuse instruction handles
+	}
+	
+    /**
+     * @param class_name
+     * @return
+     */
+    private InstructionList inizializeStaticFields(String class_name) {
+    	// STATIC_PARTS_TODO : in base: static initialization of team fields
+        InstructionList il = new InstructionList();
+        il.append(new ICONST(0));
+        il.append((Instruction)factory.createNewArray(teamType, (short)1));
+        //this are very strange (but necessary!?) casts...
+        il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAMS, teamArray, Constants.PUTSTATIC));
+        //generated: _OT$activeTeams = new Team[0];
+
+        il.append(new ICONST(0));
+        il.append((Instruction)factory.createNewArray(Type.INT, (short)1));
+        //this are very strange (but necessary!?) casts...
+        il.append(factory.createFieldAccess(class_name, _OT_ACTIVE_TEAM_IDS, intArray, Constants.PUTSTATIC));
+        //generated: _OT$activeTeamIDs = new int[0];
+        
+        if (CallinBindingManager.isRole(class_name)) {
+        	ObjectType linkedListType = new ObjectType("java.util.LinkedList");
+        	il.append(factory.createNew(linkedListType));
+        	il.append(new DUP());
+        	il.append(factory.createInvoke("java.util.LinkedList", 
+        								   Constants.CONSTRUCTOR_NAME, 
+        								   Type.VOID, Type.NO_ARGS, 
+        								   Constants.INVOKESPECIAL));
+        								   
+			il.append(factory.createFieldAccess(class_name, 
+												"_OT$teamRegistrationObservers", 
+												linkedListType, Constants.PUTSTATIC ));
+        	
+        	//generated: _OT$teamRegistrationObservers = new LinkedList();
+        }
+        return il;
+    }
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
new file mode 100644
index 0000000..9dc5691
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/SubBoundBaseMethodRedefinition.java
@@ -0,0 +1,169 @@
+/**********************************************************************
+ * 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 org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.*;
+
+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(Object loader) { super(loader); }
+
+	/**
+	 * 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);
+
+
+		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);
+	}
+
+	/**
+	 * 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
new file mode 100644
index 0000000..6bacee9
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/TeamInterfaceImplementation.java
@@ -0,0 +1,987 @@
+/**********************************************************************
+ * 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 org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.*;
+
+import java.util.*;
+
+import org.eclipse.objectteams.otre.jplis.JPLISEnhancer;
+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 {
+
+
+	public TeamInterfaceImplementation(Object loader) {
+		super(loader);
+	}
+
+	/**
+	 * @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 = newMethodGen(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);
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+
+		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 (!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();
+	}
+	
+	/**
+	 * 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 = newMethodGen(method, cg.getClassName(), cpg);
+		InstructionList il = mg.getInstructionList();
+		il.insert(additionalInstructions);
+		mg.setMaxStack();
+		mg.setMaxLocals();
+
+		Method newMethod = mg.getMethod();
+		cg.replaceMethod(method, newMethod);
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+		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) {
+			// 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.teamAdaptsSuperBaseClass(class_name, actBase)) 
+				continue;
+			
+			InstructionHandle startTry = il.append(new ALOAD(0));
+			
+			il.append(factory.createFieldAccess(class_name, "_OT$ID", Type.INT,
+					Constants.GETSTATIC));
+			// Note: the method _OT$addTeam may be found in a super classes (topmostBoundBase),
+			//       but we'll simply leave this lookup to the VM 
+			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.teamAdaptsSuperBaseClass(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.";
+		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));
+		    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+			}
+		}
+	}
+	
+	/**
+	 * 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);
+
+			// --- 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));
+
+			boolean 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ThreadActivation.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ThreadActivation.java
new file mode 100644
index 0000000..4c59ba2
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/ThreadActivation.java
@@ -0,0 +1,184 @@
+/**********************************************************************
+ * 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 org.apache.bcel.classfile.*;
+import org.apache.bcel.generic.*;
+import org.apache.bcel.*;
+import org.eclipse.objectteams.otre.jplis.JPLISEnhancer;
+
+import static org.eclipse.objectteams.otre.ObjectTeamsTransformation.newMethodGen;
+
+/**
+ * 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 RepositoryAccess.implementationOf(class_name, "java.lang.Runnable") || RepositoryAccess.instanceOf(class_name, "java.lang.Thread");
+		} catch (ClassNotFoundException cfne) {
+			if (ObjectTeamsTransformation.WORKAROUND_REPOSITORY) {
+				return false;
+			}
+			else
+				throw new RuntimeException("Could not find class being loaded", cfne); // 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 = newMethodGen(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()));
+
+		ObjectTeamsTransformation.insertBeforeReturn(mg, il, threadDeactivation);
+
+		/** **** 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);
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+        threadActivation.dispose();
+        il.dispose();
+	}
+	// is method a constructor that does not invoke another this()-ctor?
+	@SuppressWarnings("deprecation")
+	private MethodGen isRootCtor(Method method, ClassGen cg) {
+		if (!method.getName().equals("<init>"))
+			return null;
+		String className = cg.getClassName();
+		ConstantPoolGen cpg = cg.getConstantPool();
+		MethodGen mg = newMethodGen(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)) // unsafe due to object/array ambiguity, but we have no array (is an invokespecial!)
+			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());
+    	JPLISEnhancer.requireClassFileVersionLessThan51(cg);
+	    il.dispose();
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/ConstantPool.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/ConstantPool.java
new file mode 100644
index 0000000..eba9fda
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/ConstantPool.java
@@ -0,0 +1,136 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2011 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ * 
+ * This file is based on class org.apache.bcel.classfile.ConstantPool
+ * originating from the Apache BCEL project which was provided under the 
+ * Apache 2.0 license. Original Copyright from BCEL:
+ * 
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.eclipse.objectteams.otre.bcel;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.ClassFormatException;
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantClass;
+import org.apache.bcel.classfile.ConstantDouble;
+import org.apache.bcel.classfile.ConstantFieldref;
+import org.apache.bcel.classfile.ConstantFloat;
+import org.apache.bcel.classfile.ConstantInteger;
+import org.apache.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.bcel.classfile.ConstantLong;
+import org.apache.bcel.classfile.ConstantMethodref;
+import org.apache.bcel.classfile.ConstantNameAndType;
+import org.apache.bcel.classfile.ConstantString;
+import org.apache.bcel.classfile.ConstantUtf8;
+
+/**
+ * Simple gateway to class {@link org.apache.bcel.classfile.ConstantPool}
+ * whose constructor {@link org.apache.bcel.classfile.ConstantPool#ConstantPool(DataInputStream)}
+ * is not visible, unfortunately.
+ */
+@SuppressWarnings("serial")
+public class ConstantPool extends org.apache.bcel.classfile.ConstantPool {
+    
+	static Constant DONT_CARE_CONSTANT = new ConstantInteger(13);
+	static Constant DONT_CARE_CONSTANT_WIDE = new ConstantLong(42);
+
+	ConstantPool(DataInputStream file) throws IOException {
+		super(readConstants(file));
+    }
+	static Constant[] readConstants(DataInputStream file) throws IOException {		
+		byte tag;
+		int constant_pool_count = file.readUnsignedShort();
+		Constant[] constant_pool = new Constant[constant_pool_count];
+		/* constant_pool[0] is unused by the compiler and may be used freely
+		 * by the implementation.
+		 */
+		for (int i = 1; i < constant_pool_count; i++) {
+			constant_pool[i] = readConstant(file);
+			/* Quote from the JVM specification:
+			 * "All eight byte constants take up two spots in the constant pool.
+			 * If this is the n'th byte in the constant pool, then the next item
+			 * will be numbered n+2"
+			 * 
+			 * Thus we have to increment the index counter.
+			 */
+			tag = constant_pool[i].getTag();
+			if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) {
+				i++;
+			}
+		}
+		return constant_pool;
+	}
+
+	static final Constant readConstant(DataInputStream file)
+			throws IOException, ClassFormatException {
+		byte b = file.readByte(); // Read tag byte
+		switch (b) {
+		case Constants.CONSTANT_Class:
+			return new ConstantClass(file.readUnsignedShort());
+		case Constants.CONSTANT_Fieldref:
+			return new ConstantFieldref(file.readUnsignedShort(), file.readUnsignedShort());
+		case Constants.CONSTANT_Methodref:
+			return new ConstantMethodref(file.readUnsignedShort(), file.readUnsignedShort());
+		case Constants.CONSTANT_InterfaceMethodref:
+			return new ConstantInterfaceMethodref(file.readUnsignedShort(), file.readUnsignedShort());
+		case Constants.CONSTANT_String:
+			file.readUnsignedShort(); break;
+		case Constants.CONSTANT_Integer:
+			file.readInt(); break;
+		case Constants.CONSTANT_Float:
+			file.readFloat(); break;
+		case Constants.CONSTANT_Long:
+			file.readLong(); return DONT_CARE_CONSTANT_WIDE;
+		case Constants.CONSTANT_Double:
+			file.readDouble(); return DONT_CARE_CONSTANT_WIDE;
+		case Constants.CONSTANT_NameAndType:
+			return new ConstantNameAndType(file.readUnsignedShort(), file.readUnsignedShort());
+		case Constants.CONSTANT_Utf8:
+			return new ConstantUtf8(file.readUTF());
+		// new in 1.7:
+		case 15: // CONSTANT_MethodHandle
+			file.readByte(); 			// reference_kind
+			file.readUnsignedShort();	// reference_index
+			break;
+		case 16: // CONSTANT_MethodType
+			file.readUnsignedShort();	// descriptor_index
+			break;
+		case 18: // CONSTANT_InvokeDynamic
+			file.readUnsignedShort();	// bootstrap_method_attr_index
+			file.readUnsignedShort();	// name_and_type_index;
+			break;
+		default:
+			throw new ClassFormatException(
+					"Invalid byte tag in constant pool: " + b);
+		}
+		return DONT_CARE_CONSTANT;
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java
new file mode 100644
index 0000000..c67b14a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassLoaderRepository.java
@@ -0,0 +1,90 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2011 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ * 
+ * This file is based on class org.apache.bcel.util.ClassLoaderRepository
+ * originating from the Apache BCEL project which was provided under the 
+ * Apache 2.0 license. Original Copyright from BCEL:
+ * 
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); 
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License. 
+ **********************************************************************/
+package org.eclipse.objectteams.otre.bcel;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.util.ClassLoaderRepository;
+import org.eclipse.objectteams.otre.ClassLoaderAccess;
+
+/**
+ * Class loader repository that retains less memory than BCEL's original.
+ */
+@SuppressWarnings("serial")
+public class DietClassLoaderRepository extends ClassLoaderRepository {
+
+	// repeat a field that is private in the super class:
+	Object dietClassLoaderRepository_loader;
+	
+	public DietClassLoaderRepository(Object loader) {
+		super(loader instanceof ClassLoader ? (ClassLoader) loader : null);
+		dietClassLoaderRepository_loader = loader;
+	}
+
+	@Override
+	public JavaClass loadClass(String className) throws ClassNotFoundException {
+        String classFile = className.replace('.', '/');
+        JavaClass c = findClass(className);
+        if (c != null) {
+            return c;
+        }
+        try {
+            InputStream is = ClassLoaderAccess.getResourceAsStream(dietClassLoaderRepository_loader, classFile + ".class");
+            if (is == null) {
+                throw new ClassNotFoundException(className + " not found.");
+            }
+            DietClassParser parser = new DietClassParser(is, className);
+            c = parser.parse();
+            synchronized(this) {
+           		storeClass(c);
+            }
+            return c;
+        } catch (IOException e) {
+            throw new ClassNotFoundException(e.toString());
+        }
+	}
+	public JavaClass loadClassFully(String className) throws ClassNotFoundException {
+        JavaClass c = findClass(className);
+        if (c != null) { 
+        	if (! (c instanceof DietJavaClass))
+        		return c; // found fully parsed class, OK.
+        	synchronized(this) {
+        		removeClass(c); // force new loading
+        	}
+        }
+		return super.loadClass(className);
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassParser.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassParser.java
new file mode 100644
index 0000000..83380a7
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietClassParser.java
@@ -0,0 +1,143 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2011 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ * 
+ * This file is based on class org.apache.bcel.classfile.ClassParser
+ * originating from the Apache BCEL project which was provided under the 
+ * Apache 2.0 license. Original Copyright from BCEL:
+ * 
+ * Copyright  2000-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.eclipse.objectteams.otre.bcel;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.ClassFormatException;
+import org.apache.bcel.classfile.JavaClass;
+
+/**
+ * Read only structural information from a .class file:
+ * <ul>
+ * <li>class name
+ * <li>access flags
+ * <li>names of super class and super interfaces
+ * </ul>
+ * Also discard the constant pool when done reading. 
+ */
+public final class DietClassParser {
+
+    private DataInputStream file;
+    private String file_name;
+    private int class_name_index, superclass_name_index;
+    private int access_flags; // Access rights of parsed class
+    private boolean is_zip; // Loaded from zip file?
+    private static final int BUFSIZE = 8192;
+
+
+    /**
+     * Parse class from the given stream.
+     *
+     * @param file Input stream
+     * @param file_name File name
+     */
+    public DietClassParser(InputStream file, String file_name) {
+        this.file_name = file_name;
+        String clazz = file.getClass().getName(); // Not a very clean solution ...
+        is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
+        if (file instanceof DataInputStream) {
+            this.file = (DataInputStream) file;
+        } else {
+            this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE));
+        }
+    }
+
+    /**
+     * Parse the given Java class file and return an object that represents
+     * the contained data, i.e., constants, methods, fields and commands.
+     * A <em>ClassFormatException</em> is raised, if the file is not a valid
+     * .class file. (This does not include verification of the byte code as it
+     * is performed by the java interpreter).
+     *
+     * @return Class object representing the parsed class file
+     * @throws  IOException
+     * @throws  ClassFormatException
+     */
+    public JavaClass parse() throws IOException, ClassFormatException {
+        /****************** Read headers ********************************/
+        // Check magic tag of class file
+        if (file.readInt() != 0xCAFEBABE)
+		    throw new ClassFormatException(file_name + " is not a Java .class file");
+        // Get compiler version
+        int minor = file.readUnsignedShort();
+		int major = file.readUnsignedShort();
+        /****************** Read constant pool and related **************/
+        // Read constant pool entries
+        ConstantPool constant_pool = new ConstantPool(file);
+        // Get class information
+        readClassInfo();
+        // Get interface information, i.e., implemented interfaces
+        int[] interfaces = readInterfaces();
+        /****************** Don't read class fields and methods ***************/
+        // Return the information we have gathered in a new object
+        return new DietJavaClass(class_name_index, superclass_name_index, file_name, major, minor,
+                access_flags, constant_pool, interfaces, 
+                is_zip ? JavaClass.ZIP : JavaClass.FILE);
+    }
+
+    /**
+     * Read information about the class and its super class.
+     * @throws  IOException
+     * @throws  ClassFormatException
+     */
+    private final void readClassInfo() throws IOException {
+        access_flags = file.readUnsignedShort();
+        /* Interfaces are implicitely abstract, the flag should be set
+         * according to the JVM specification.
+         */
+        if ((access_flags & Constants.ACC_INTERFACE) != 0) {
+            access_flags |= Constants.ACC_ABSTRACT;
+        }
+        class_name_index = file.readUnsignedShort();
+        superclass_name_index = file.readUnsignedShort();
+    }
+
+    /**
+     * Read information about the interfaces implemented by this class.
+     * @throws  IOException
+     */
+    private int[] readInterfaces() throws IOException {
+        int interfaces_count = file.readUnsignedShort();
+        int[] interfaces = new int[interfaces_count];
+        for (int i = 0; i < interfaces_count; i++) {
+            interfaces[i] = file.readUnsignedShort();
+        }
+        return interfaces;
+    }
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietJavaClass.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietJavaClass.java
new file mode 100644
index 0000000..0eca60a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/bcel/DietJavaClass.java
@@ -0,0 +1,55 @@
+/**********************************************************************
+ * This file is part of "Object Teams Runtime Environment"-Software
+ * 
+ * Copyright 2011 GK Software AG
+ * 
+ * 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
+ * 
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ * 
+ * Contributors:
+ * 	  Stephan Herrmann - Initial API and implementation
+ */
+package org.eclipse.objectteams.otre.bcel;
+
+import org.apache.bcel.classfile.Attribute;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+
+/**
+ * Representation of a class file that reads and retains only structural information:
+ * <ul>
+ * <li>class name
+ * <li>access flags
+ * <li>names of super class and super interfaces
+ * </ul>
+ * Also discard the constant pool when done reading. 
+ */
+@SuppressWarnings("serial")
+public class DietJavaClass extends JavaClass {
+
+	public DietJavaClass(int class_name_index, int superclass_name_index,
+			String file_name, int major, int minor, int access_flags,
+			ConstantPool constant_pool, int[] interfaces, byte source) {
+		super(class_name_index, superclass_name_index, file_name, major, minor, access_flags, constant_pool, interfaces, 
+			  null/*fields*/, null/*methods*/, null/*attributes*/, source);
+		setConstantPool(null);
+	}
+	@Override
+	public Field[] getFields() {
+		throw new UnsupportedOperationException("Class has been parsed in diet mode, fields are not available");
+	}
+	@Override
+	public Method[] getMethods() {
+		throw new UnsupportedOperationException("Class has been parsed in diet mode, methods are not available");
+	}
+	@Override
+	public Attribute[] getAttributes() {
+		throw new UnsupportedOperationException("Class has been parsed in diet mode, attributes are not available");
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
new file mode 100644
index 0000000..29d0c11
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/JPLISEnhancer.java
@@ -0,0 +1,161 @@
+/**********************************************************************
+ * 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.ClassLoaderAccess;
+import org.eclipse.objectteams.otre.OTREInternalError;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.ClassParser;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.classfile.Utility;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.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 Object loader;
+	
+	public JPLISEnhancer(ClassGen cg, Object loader) {
+		this.loader = loader;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.ClassEnhancer#addImplements(java.lang.String, org.apache.bcel.generic.ClassGen)
+	 */
+	public void addImplements(String interfaceName, ClassGen cg) {
+		cg.addInterface(interfaceName);		
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addMethod(org.apache.bcel.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);
+		requireClassFileVersionLessThan51(cg);
+	}
+
+	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);
+		requireClassFileVersionLessThan51(cg);
+	}
+
+	public static void requireClassFileVersionLessThan51(ClassGen cg) {
+		// added methods would be invalid without a stackmap attribute,
+		// work around this by setting the class file to 50.0 (Java6),
+		// where the old verifier is still supported as a fallback.
+		if (cg.getMajor() >= 51)
+			cg.setMajor(50);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#addField(org.apache.bcel.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;
+		InputStream is = null;
+		try {
+			String binaryName = className.replace('.', '/');
+			is = ClassLoaderAccess.getResourceAsStream(this.loader, 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();
+		} finally {
+			if (is != null)
+				try {
+					is.close();
+				} catch (IOException e) {
+					// nothing we can do
+				}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.objectteams.otre.common.ClassEnhancer#decapsulateMethod(org.apache.bcel.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); // no need to remove attributes, code remains unchanged
+
+		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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
new file mode 100644
index 0000000..275d68d
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/ObjectTeamsTransformer.java
@@ -0,0 +1,275 @@
+/**********************************************************************
+ * 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.List;
+
+import org.apache.bcel.classfile.ClassParser;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.generic.ClassGen;
+import org.eclipse.objectteams.otre.BaseCallRedirection;
+import org.eclipse.objectteams.otre.BaseMethodTransformation;
+import org.eclipse.objectteams.otre.Decapsulation;
+import org.eclipse.objectteams.otre.LiftingParticipantTransformation;
+import org.eclipse.objectteams.otre.OTConstants;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.eclipse.objectteams.otre.RepositoryAccess;
+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.bcel.DietClassLoaderRepository;
+import org.eclipse.objectteams.otre.util.AttributeReadingGuard;
+import org.eclipse.objectteams.otre.util.CallinBindingManager;
+
+
+/**
+ * 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,
+		Decapsulation.class,
+		LiftingParticipantTransformation.class,
+		StaticSliceBaseTransformation.class,
+		SubBoundBaseMethodRedefinition.class,
+		TeamInterfaceImplementation.class,
+		ThreadActivation.class
+	};
+
+	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 {
+		return transform((Object)loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+	}
+	
+	public byte[] transform(Object loader, String className, Class<?> classBeingRedefined,
+			ProtectionDomain protectionDomain, byte[] classfileBuffer)
+			throws IllegalClassFormatException
+	{
+		if (warmedUp || loader == null)
+			return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+		synchronized (loader) {
+			try {
+				return internalTransform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+			} finally {
+				warmedUp = true;
+			}		
+		}
+	}
+	public byte[] internalTransform(Object loader, String className, Class<?> classBeingRedefined,
+			ProtectionDomain protectionDomain, byte[] classfileBuffer)
+			throws IllegalClassFormatException
+	{
+		switch(className.charAt(0)) {
+		case 'o':
+			if (   className.startsWith("org/eclipse/objectteams/otre")
+				|| className.startsWith("org/apache/bcel"))
+				// skip OTRE and BCEL classes
+				return null;
+			break;
+		case 's':
+			if (className.startsWith("sun/misc"))
+				// skip, I saw a mysterious deadlock involving sun.misc.Cleaner
+				return null;
+			break;
+		case 'j':
+			if (className.equals("java/util/LinkedHashMap$KeyIterator")) 
+				// skip, I saw class loading circularity caused by accessing this class
+				return null;
+			break;
+		}
+		if (classBeingRedefined != null) {
+			if (!ObjectTeamsTransformation.debugging) {
+				System.out.println("Redefinition!");
+				return null;
+			}
+		}
+		
+		//
+		// One fresh instance of each transformer for a given class:
+		//
+		BaseCallRedirection 				baseCallRedirection 				= new BaseCallRedirection(loader);
+		BaseMethodTransformation 			baseMethodTransformation 			= new BaseMethodTransformation(loader);
+		Decapsulation 						decapsulation 						= new Decapsulation(loader);
+		LiftingParticipantTransformation 	liftingParticipantTransformation	= new LiftingParticipantTransformation(loader);
+		StaticSliceBaseTransformation 		staticSliceBaseTransformation 		= new StaticSliceBaseTransformation(loader);
+		SubBoundBaseMethodRedefinition 		subBoundBaseMethodRedefinition 		= new SubBoundBaseMethodRedefinition(loader);
+		TeamInterfaceImplementation 		teamInterfaceImplementation 		= new TeamInterfaceImplementation(loader);
+		ThreadActivation 					threadActivation					= new ThreadActivation();
+				
+		// tell Repository about the class loader for improved lookupClass()
+		DietClassLoaderRepository prevRepository = RepositoryAccess.setClassLoader(loader);
+		
+		try {
+			InputStream is = new ByteArrayInputStream(classfileBuffer);
+			JavaClass java_class;
+			try {
+				java_class = new ClassParser(is, className).parse();
+			} finally {
+				if (is != null)
+					try {
+						is.close();
+					} catch (IOException e) {
+						// nothing we can do
+					}
+			}
+			//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();
+		}
+			staticSliceBaseTransformation.doTransformInterface(jpe, cg);
+			teamInterfaceImplementation.doTransformInterface(jpe, cg);
+			
+//			subBoundBaseMethodRedefinition.doTransformInterface(jpe, cg);
+//			baseCallRedirection.doTransformInterface(jpe, cg);
+//			decapsulation.doTransformInterface(jpe, cg);
+//			baseMethodTransformation.doTransformInterface(jpe, cg);
+//			staticSliceBaseTransformation.doTransformInterface(jpe, cg);
+//			teamInterfaceImplementation.doTransformInterface(jpe, cg);
+			threadActivation.doTransformInterface(jpe, cg);
+
+			
+//			baseCallRedirection.doTransformCode(cg); // empty method
+			baseMethodTransformation.doTransformCode(cg);
+			liftingParticipantTransformation.doTransformCode(cg);
+			staticSliceBaseTransformation.doTransformCode(cg);
+			teamInterfaceImplementation.doTransformCode(cg);
+			threadActivation.doTransformCode(cg);
+			
+			JavaClass new_java_class = cg.getJavaClass(); 
+			if (dumping) {
+				String binaryName = className.replace('.','/');
+				new_java_class.dump("jplis_dump/" + binaryName + ".class");
+			}
+			return new_java_class.getBytes();
+		} catch (IOException e) {
+			System.err.println("ClassFileTransformer could not parse class file buffer to JavaClass");
+			e.printStackTrace();
+		} catch (RuntimeException re) {
+			re.printStackTrace();
+			throw re;
+		} finally {
+			// restore previous repository:
+			RepositoryAccess.resetRepository(prevRepository);
+		}
+		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, Object loader) 
+			throws ClassFormatError, IOException 
+	{
+		ClassParser   cp  = new ClassParser(file, fileName);
+		ClassGen      cg  = new ClassGen(cp.parse());
+		JPLISEnhancer jpe = new JPLISEnhancer(cg, /*loader (unused)*/null);
+		DietClassLoaderRepository prevRepository = RepositoryAccess.setClassLoader(loader);
+		try {
+			setFirstTransformation(new ObjectTeamsTransformation(loader) {});
+			firstTransformation.checkReadClassAttributes(jpe, cg, cg.getClassName(), cg.getConstantPool());
+		} finally {
+			RepositoryAccess.resetRepository(prevRepository);
+		}
+	}
+	
+	// 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/otreAgent.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/jplis/otreAgent.java
new file mode 100644
index 0000000..ee6077f
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/AnnotationHelper.java
new file mode 100644
index 0000000..0b45daa
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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 org.apache.bcel.classfile.Attribute;
+import org.apache.bcel.classfile.Unknown;
+import org.apache.bcel.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/AttributeReadingGuard.java
new file mode 100644
index 0000000..52a449c
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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<Object, AttributeReadingGuard> instances = new HashMap<Object, 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 token (s.t. like a class loader).
+	 */
+	public static AttributeReadingGuard getInstanceForLoader(Object token) {
+		if (token == null)
+			return defaultInstance;
+		
+		AttributeReadingGuard instance = instances.get(token);
+		if (instance == null)
+			instances.put(token, instance = new AttributeReadingGuard());
+		return instance;
+	}
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/BoundClass.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/BoundClass.java
new file mode 100644
index 0000000..c440414
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/BoundClass.java
@@ -0,0 +1,82 @@
+/**********************************************************************
+ * 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 org.apache.bcel.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 boolean isInterface = false; // currently only for base classes
+
+	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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/BoundMethod.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/BoundMethod.java
new file mode 100644
index 0000000..4a4a8fb
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java
new file mode 100644
index 0000000..9515357
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/CallinBindingManager.java
@@ -0,0 +1,1310 @@
+/**********************************************************************
+ * 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 org.apache.bcel.generic.Type; // just for javadoc.
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.generic.ObjectType;
+
+import org.eclipse.objectteams.otre.OTREInternalError;
+import org.eclipse.objectteams.otre.ObjectTeamsTransformation;
+import org.eclipse.objectteams.otre.RepositoryAccess;
+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 {
+	/** When asking for a bound super type, we may find a super class, a super interface or nothing. */
+	public static enum BoundSuperKind {
+		NONE, CLASS, INTERFACE;
+	}
+
+	// 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>();
+	
+	/**
+	 * 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);
+		// 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);
+			// BoundClass objects are unique per base object, so just take the first binding: 
+			BoundClass currentBaseClass = entry.getValue().getFirst().getBaseClass();
+			if(RepositoryAccess.safeSubclassOf(baseClassType, 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 (RepositoryAccess.safeSubclassOf(currentType, 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
+     * @param baseIsInterface   whether the given base is an interface
+     */
+    public static void addRoleBaseBinding(String roleClassName, String baseClassName, boolean baseIsInterface, String teamClassName) {
+		RoleBaseBinding rbb = roleBindings.get(roleClassName);
+		if (rbb == null) {
+			rbb = new RoleBaseBinding(roleClassName, baseClassName, baseIsInterface, 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 = null;
+		try {
+			baseClass = RepositoryAccess.lookupClass(baseClassName);
+		} catch (ClassNotFoundException e) {
+			// FIXME(SH): where to log?
+			e.printStackTrace();
+		}
+    	if (baseClass != null && baseClass.isInterface()) { 
+    		// 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);
+    }
+    
+    
+	/**
+     * 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 org.apache.bcel.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, false, 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);
+		// 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);
+			if (RepositoryAccess.safeSubclassOf(current, 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);
+		// 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 (RepositoryAccess.safeSubclassOf(current, 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);
+
+		ObjectType subTeamType = new ObjectType(subTeamName);
+		ObjectType superTeamType = new ObjectType(superTeamName);
+		if (RepositoryAccess.safeSubclassOf(subTeamType, 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
+	}
+	
+	/**
+	 * 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 BoundSuperKind hasBoundBaseParent(String baseClassName) {
+		LinkedList<RoleBaseBinding> rbbList = baseBindings.get(baseClassName);
+		if (rbbList != null) {
+			Iterator<RoleBaseBinding> it = rbbList.iterator();
+			while (it.hasNext()) {
+				RoleBaseBinding rbb = it.next();
+				BoundClass baseSuper = rbb.getBaseClass().getSuper();
+				if (baseSuper!=null)
+					return baseSuper.isInterface ? BoundSuperKind.INTERFACE : BoundSuperKind.CLASS;
+			}
+		}
+		// IMPLICIT_INHERITANCE
+		//if (isUnboundSubBase(baseClassName))
+		//	return true;
+		return BoundSuperKind.NONE;
+	}
+	
+	/**
+	 * Returns the name of the topmost bound base class.
+	 * 
+	 * @param baseClassName
+	 * @return a BoundClass representing the topmost bound class or null
+	 */
+	public static BoundClass getTopmostBoundBaseClass(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) {
+				if (bc.getSuper().isInterface)
+					break; // use bc instead of travelling up to super interfaces
+	            bc = bc.getSuper();
+	        }
+			return bc;
+		}
+		return null;
+	}
+
+	/**
+	 * @param teamClassName
+	 * @param baseClassName
+	 * @return
+	 */
+	public static boolean teamAdaptsSuperBaseClass(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 && !bc.isInterface) {
+				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(org.apache.bcel.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>();
+		try {
+			for (JavaClass superTeam : RepositoryAccess.getSuperClasses(teamName))
+				if (paramMappings.get(superTeam.getClassName()) != null)
+					result.add(superTeam.getClassName());
+		} catch (ClassNotFoundException e) {
+			// FIXME(SH): where to log to?
+			e.printStackTrace();
+			// continue, just nothing added to result
+		}
+		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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/DebugUtil.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/DebugUtil.java
new file mode 100644
index 0000000..c6e8d80
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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 org.apache.bcel.generic.*;
+import org.apache.bcel.Constants;
+import java.util.Iterator;
+
+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;
+        Iterator<InstructionHandle> it =  il.iterator();
+        while(it.hasNext()) {
+            Instruction i = it.next().getInstruction();
+            off += i.produceStack(cpg);
+            off -= i.consumeStack(cpg);
+            System.out.print(off);
+            System.out.println("  = "+i);
+        }
+    }
+
+}
diff --git a/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/FieldDescriptor.java
new file mode 100644
index 0000000..30a3dd0
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/ListValueHashMap.java
new file mode 100644
index 0000000..8b7b463
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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<Entry<String,LinkedList<ValueType>>> it = hashMap.entrySet().iterator();
+		while (it.hasNext()) {
+			Entry<String,LinkedList<ValueType>> 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/MethodBinding.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/MethodBinding.java
new file mode 100644
index 0000000..ecc5436
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java
new file mode 100644
index 0000000..0103e2a
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/RoleBaseBinding.java
@@ -0,0 +1,230 @@
+/**********************************************************************
+ * 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 baseIsInterface 
+     * @param teamClassName
+     */
+    public RoleBaseBinding(String _roleClassName, String _baseClassName, boolean baseIsInterface, String teamClassName) {
+    	roleClass = new BoundClass(_roleClassName, teamClassName);
+    	baseClass = CallinBindingManager.getBoundBaseClass(_baseClassName, teamClassName);
+    	baseClass.isInterface = baseIsInterface;
+    }
+
+    /**
+     * @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<MethodBinding> mbsList = getBaseMethodBindings();
+	    Iterator<MethodBinding> it = mbsList.iterator();
+	    while (it.hasNext()) {
+			MethodBinding mb = 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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/SuperMethodDescriptor.java
new file mode 100644
index 0000000..02b9c04
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.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/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java
new file mode 100644
index 0000000..2a12706
--- /dev/null
+++ b/plugins/org.eclipse.objectteams.otre/src/org/eclipse/objectteams/otre/util/TeamIdDispenser.java
@@ -0,0 +1,39 @@
+/**********************************************************************
+ * 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 {
+  
+    static int lastDispensedId = 0;
+    private static HashMap<String, Integer> teamIDs = new HashMap<String, Integer>();
+
+	private static int produceNextTeamId(String team_name) {
+        lastDispensedId++;
+        Integer teamId = Integer.valueOf(lastDispensedId);
+        teamIDs.put(team_name, teamId);
+        return lastDispensedId;
+    }
+
+    synchronized 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);
+    }
+}